annotate clang/utils/CmpDriver @ 150:1d019706d866

LLVM10
author anatofuz
date Thu, 13 Feb 2020 15:10:13 +0900
parents
children
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
rev   line source
150
anatofuz
parents:
diff changeset
1 #!/usr/bin/env python
anatofuz
parents:
diff changeset
2
anatofuz
parents:
diff changeset
3 """
anatofuz
parents:
diff changeset
4 A simple utility that compares tool invocations and exit codes issued by
anatofuz
parents:
diff changeset
5 compiler drivers that support -### (e.g. gcc and clang).
anatofuz
parents:
diff changeset
6 """
anatofuz
parents:
diff changeset
7
anatofuz
parents:
diff changeset
8 import subprocess
anatofuz
parents:
diff changeset
9
anatofuz
parents:
diff changeset
10 def splitArgs(s):
anatofuz
parents:
diff changeset
11 it = iter(s)
anatofuz
parents:
diff changeset
12 current = ''
anatofuz
parents:
diff changeset
13 inQuote = False
anatofuz
parents:
diff changeset
14 for c in it:
anatofuz
parents:
diff changeset
15 if c == '"':
anatofuz
parents:
diff changeset
16 if inQuote:
anatofuz
parents:
diff changeset
17 inQuote = False
anatofuz
parents:
diff changeset
18 yield current + '"'
anatofuz
parents:
diff changeset
19 else:
anatofuz
parents:
diff changeset
20 inQuote = True
anatofuz
parents:
diff changeset
21 current = '"'
anatofuz
parents:
diff changeset
22 elif inQuote:
anatofuz
parents:
diff changeset
23 if c == '\\':
anatofuz
parents:
diff changeset
24 current += c
anatofuz
parents:
diff changeset
25 current += it.next()
anatofuz
parents:
diff changeset
26 else:
anatofuz
parents:
diff changeset
27 current += c
anatofuz
parents:
diff changeset
28 elif not c.isspace():
anatofuz
parents:
diff changeset
29 yield c
anatofuz
parents:
diff changeset
30
anatofuz
parents:
diff changeset
31 def insertMinimumPadding(a, b, dist):
anatofuz
parents:
diff changeset
32 """insertMinimumPadding(a,b) -> (a',b')
anatofuz
parents:
diff changeset
33
anatofuz
parents:
diff changeset
34 Return two lists of equal length, where some number of Nones have
anatofuz
parents:
diff changeset
35 been inserted into the shorter list such that sum(map(dist, a',
anatofuz
parents:
diff changeset
36 b')) is minimized.
anatofuz
parents:
diff changeset
37
anatofuz
parents:
diff changeset
38 Assumes dist(X, Y) -> int and non-negative.
anatofuz
parents:
diff changeset
39 """
anatofuz
parents:
diff changeset
40
anatofuz
parents:
diff changeset
41 def cost(a, b):
anatofuz
parents:
diff changeset
42 return sum(map(dist, a + [None] * (len(b) - len(a)), b))
anatofuz
parents:
diff changeset
43
anatofuz
parents:
diff changeset
44 # Normalize so a is shortest.
anatofuz
parents:
diff changeset
45 if len(b) < len(a):
anatofuz
parents:
diff changeset
46 b, a = insertMinimumPadding(b, a, dist)
anatofuz
parents:
diff changeset
47 return a,b
anatofuz
parents:
diff changeset
48
anatofuz
parents:
diff changeset
49 # For each None we have to insert...
anatofuz
parents:
diff changeset
50 for i in range(len(b) - len(a)):
anatofuz
parents:
diff changeset
51 # For each position we could insert it...
anatofuz
parents:
diff changeset
52 current = cost(a, b)
anatofuz
parents:
diff changeset
53 best = None
anatofuz
parents:
diff changeset
54 for j in range(len(a) + 1):
anatofuz
parents:
diff changeset
55 a_0 = a[:j] + [None] + a[j:]
anatofuz
parents:
diff changeset
56 candidate = cost(a_0, b)
anatofuz
parents:
diff changeset
57 if best is None or candidate < best[0]:
anatofuz
parents:
diff changeset
58 best = (candidate, a_0, j)
anatofuz
parents:
diff changeset
59 a = best[1]
anatofuz
parents:
diff changeset
60 return a,b
anatofuz
parents:
diff changeset
61
anatofuz
parents:
diff changeset
62 class ZipperDiff(object):
anatofuz
parents:
diff changeset
63 """ZipperDiff - Simple (slow) diff only accommodating inserts."""
anatofuz
parents:
diff changeset
64
anatofuz
parents:
diff changeset
65 def __init__(self, a, b):
anatofuz
parents:
diff changeset
66 self.a = a
anatofuz
parents:
diff changeset
67 self.b = b
anatofuz
parents:
diff changeset
68
anatofuz
parents:
diff changeset
69 def dist(self, a, b):
anatofuz
parents:
diff changeset
70 return a != b
anatofuz
parents:
diff changeset
71
anatofuz
parents:
diff changeset
72 def getDiffs(self):
anatofuz
parents:
diff changeset
73 a,b = insertMinimumPadding(self.a, self.b, self.dist)
anatofuz
parents:
diff changeset
74 for aElt,bElt in zip(a,b):
anatofuz
parents:
diff changeset
75 if self.dist(aElt, bElt):
anatofuz
parents:
diff changeset
76 yield aElt,bElt
anatofuz
parents:
diff changeset
77
anatofuz
parents:
diff changeset
78 class DriverZipperDiff(ZipperDiff):
anatofuz
parents:
diff changeset
79 def isTempFile(self, filename):
anatofuz
parents:
diff changeset
80 if filename[0] != '"' or filename[-1] != '"':
anatofuz
parents:
diff changeset
81 return False
anatofuz
parents:
diff changeset
82 return (filename.startswith('/tmp/', 1) or
anatofuz
parents:
diff changeset
83 filename.startswith('/var/', 1))
anatofuz
parents:
diff changeset
84
anatofuz
parents:
diff changeset
85 def dist(self, a, b):
anatofuz
parents:
diff changeset
86 if a and b and self.isTempFile(a) and self.isTempFile(b):
anatofuz
parents:
diff changeset
87 return 0
anatofuz
parents:
diff changeset
88 return super(DriverZipperDiff, self).dist(a,b)
anatofuz
parents:
diff changeset
89
anatofuz
parents:
diff changeset
90 class CompileInfo:
anatofuz
parents:
diff changeset
91 def __init__(self, out, err, res):
anatofuz
parents:
diff changeset
92 self.commands = []
anatofuz
parents:
diff changeset
93
anatofuz
parents:
diff changeset
94 # Standard out isn't used for much.
anatofuz
parents:
diff changeset
95 self.stdout = out
anatofuz
parents:
diff changeset
96 self.stderr = ''
anatofuz
parents:
diff changeset
97
anatofuz
parents:
diff changeset
98 # FIXME: Compare error messages as well.
anatofuz
parents:
diff changeset
99 for ln in err.split('\n'):
anatofuz
parents:
diff changeset
100 if (ln == 'Using built-in specs.' or
anatofuz
parents:
diff changeset
101 ln.startswith('Target: ') or
anatofuz
parents:
diff changeset
102 ln.startswith('Configured with: ') or
anatofuz
parents:
diff changeset
103 ln.startswith('Thread model: ') or
anatofuz
parents:
diff changeset
104 ln.startswith('gcc version') or
anatofuz
parents:
diff changeset
105 ln.startswith('clang version')):
anatofuz
parents:
diff changeset
106 pass
anatofuz
parents:
diff changeset
107 elif ln.strip().startswith('"'):
anatofuz
parents:
diff changeset
108 self.commands.append(list(splitArgs(ln)))
anatofuz
parents:
diff changeset
109 else:
anatofuz
parents:
diff changeset
110 self.stderr += ln + '\n'
anatofuz
parents:
diff changeset
111
anatofuz
parents:
diff changeset
112 self.stderr = self.stderr.strip()
anatofuz
parents:
diff changeset
113 self.exitCode = res
anatofuz
parents:
diff changeset
114
anatofuz
parents:
diff changeset
115 def captureDriverInfo(cmd, args):
anatofuz
parents:
diff changeset
116 p = subprocess.Popen([cmd,'-###'] + args,
anatofuz
parents:
diff changeset
117 stdin=None,
anatofuz
parents:
diff changeset
118 stdout=subprocess.PIPE,
anatofuz
parents:
diff changeset
119 stderr=subprocess.PIPE)
anatofuz
parents:
diff changeset
120 out,err = p.communicate()
anatofuz
parents:
diff changeset
121 res = p.wait()
anatofuz
parents:
diff changeset
122 return CompileInfo(out,err,res)
anatofuz
parents:
diff changeset
123
anatofuz
parents:
diff changeset
124 def main():
anatofuz
parents:
diff changeset
125 import os, sys
anatofuz
parents:
diff changeset
126
anatofuz
parents:
diff changeset
127 args = sys.argv[1:]
anatofuz
parents:
diff changeset
128 driverA = os.getenv('DRIVER_A') or 'gcc'
anatofuz
parents:
diff changeset
129 driverB = os.getenv('DRIVER_B') or 'clang'
anatofuz
parents:
diff changeset
130
anatofuz
parents:
diff changeset
131 infoA = captureDriverInfo(driverA, args)
anatofuz
parents:
diff changeset
132 infoB = captureDriverInfo(driverB, args)
anatofuz
parents:
diff changeset
133
anatofuz
parents:
diff changeset
134 differ = False
anatofuz
parents:
diff changeset
135
anatofuz
parents:
diff changeset
136 # Compare stdout.
anatofuz
parents:
diff changeset
137 if infoA.stdout != infoB.stdout:
anatofuz
parents:
diff changeset
138 print '-- STDOUT DIFFERS -'
anatofuz
parents:
diff changeset
139 print 'A OUTPUT: ',infoA.stdout
anatofuz
parents:
diff changeset
140 print 'B OUTPUT: ',infoB.stdout
anatofuz
parents:
diff changeset
141 print
anatofuz
parents:
diff changeset
142
anatofuz
parents:
diff changeset
143 diff = ZipperDiff(infoA.stdout.split('\n'),
anatofuz
parents:
diff changeset
144 infoB.stdout.split('\n'))
anatofuz
parents:
diff changeset
145 for i,(aElt,bElt) in enumerate(diff.getDiffs()):
anatofuz
parents:
diff changeset
146 if aElt is None:
anatofuz
parents:
diff changeset
147 print 'A missing: %s' % bElt
anatofuz
parents:
diff changeset
148 elif bElt is None:
anatofuz
parents:
diff changeset
149 print 'B missing: %s' % aElt
anatofuz
parents:
diff changeset
150 else:
anatofuz
parents:
diff changeset
151 print 'mismatch: A: %s' % aElt
anatofuz
parents:
diff changeset
152 print ' B: %s' % bElt
anatofuz
parents:
diff changeset
153
anatofuz
parents:
diff changeset
154 differ = True
anatofuz
parents:
diff changeset
155
anatofuz
parents:
diff changeset
156 # Compare stderr.
anatofuz
parents:
diff changeset
157 if infoA.stderr != infoB.stderr:
anatofuz
parents:
diff changeset
158 print '-- STDERR DIFFERS -'
anatofuz
parents:
diff changeset
159 print 'A STDERR: ',infoA.stderr
anatofuz
parents:
diff changeset
160 print 'B STDERR: ',infoB.stderr
anatofuz
parents:
diff changeset
161 print
anatofuz
parents:
diff changeset
162
anatofuz
parents:
diff changeset
163 diff = ZipperDiff(infoA.stderr.split('\n'),
anatofuz
parents:
diff changeset
164 infoB.stderr.split('\n'))
anatofuz
parents:
diff changeset
165 for i,(aElt,bElt) in enumerate(diff.getDiffs()):
anatofuz
parents:
diff changeset
166 if aElt is None:
anatofuz
parents:
diff changeset
167 print 'A missing: %s' % bElt
anatofuz
parents:
diff changeset
168 elif bElt is None:
anatofuz
parents:
diff changeset
169 print 'B missing: %s' % aElt
anatofuz
parents:
diff changeset
170 else:
anatofuz
parents:
diff changeset
171 print 'mismatch: A: %s' % aElt
anatofuz
parents:
diff changeset
172 print ' B: %s' % bElt
anatofuz
parents:
diff changeset
173
anatofuz
parents:
diff changeset
174 differ = True
anatofuz
parents:
diff changeset
175
anatofuz
parents:
diff changeset
176 # Compare commands.
anatofuz
parents:
diff changeset
177 for i,(a,b) in enumerate(map(None, infoA.commands, infoB.commands)):
anatofuz
parents:
diff changeset
178 if a is None:
anatofuz
parents:
diff changeset
179 print 'A MISSING:',' '.join(b)
anatofuz
parents:
diff changeset
180 differ = True
anatofuz
parents:
diff changeset
181 continue
anatofuz
parents:
diff changeset
182 elif b is None:
anatofuz
parents:
diff changeset
183 print 'B MISSING:',' '.join(a)
anatofuz
parents:
diff changeset
184 differ = True
anatofuz
parents:
diff changeset
185 continue
anatofuz
parents:
diff changeset
186
anatofuz
parents:
diff changeset
187 diff = DriverZipperDiff(a,b)
anatofuz
parents:
diff changeset
188 diffs = list(diff.getDiffs())
anatofuz
parents:
diff changeset
189 if diffs:
anatofuz
parents:
diff changeset
190 print '-- COMMAND %d DIFFERS -' % i
anatofuz
parents:
diff changeset
191 print 'A COMMAND:',' '.join(a)
anatofuz
parents:
diff changeset
192 print 'B COMMAND:',' '.join(b)
anatofuz
parents:
diff changeset
193 print
anatofuz
parents:
diff changeset
194 for i,(aElt,bElt) in enumerate(diffs):
anatofuz
parents:
diff changeset
195 if aElt is None:
anatofuz
parents:
diff changeset
196 print 'A missing: %s' % bElt
anatofuz
parents:
diff changeset
197 elif bElt is None:
anatofuz
parents:
diff changeset
198 print 'B missing: %s' % aElt
anatofuz
parents:
diff changeset
199 else:
anatofuz
parents:
diff changeset
200 print 'mismatch: A: %s' % aElt
anatofuz
parents:
diff changeset
201 print ' B: %s' % bElt
anatofuz
parents:
diff changeset
202 differ = True
anatofuz
parents:
diff changeset
203
anatofuz
parents:
diff changeset
204 # Compare result codes.
anatofuz
parents:
diff changeset
205 if infoA.exitCode != infoB.exitCode:
anatofuz
parents:
diff changeset
206 print '-- EXIT CODES DIFFER -'
anatofuz
parents:
diff changeset
207 print 'A: ',infoA.exitCode
anatofuz
parents:
diff changeset
208 print 'B: ',infoB.exitCode
anatofuz
parents:
diff changeset
209 differ = True
anatofuz
parents:
diff changeset
210
anatofuz
parents:
diff changeset
211 if differ:
anatofuz
parents:
diff changeset
212 sys.exit(1)
anatofuz
parents:
diff changeset
213
anatofuz
parents:
diff changeset
214 if __name__ == '__main__':
anatofuz
parents:
diff changeset
215 main()