Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(365)

Side by Side Diff: tools/generate-x32-sources.py

Issue 18014003: Add X32 port into V8 (Closed) Base URL: http://v8.googlecode.com/svn/branches/bleeding_edge/
Patch Set: Created 7 years, 5 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
(Empty)
1 #!/usr/bin/env python
2 #
danno 2013/07/17 13:33:21 As discussed offline, this file shouldn't be added
3 # Copyright 2012 the V8 project authors. All rights reserved.
4 # Redistribution and use in source and binary forms, with or without
5 # modification, are permitted provided that the following conditions are
6 # met:
7 #
8 # * Redistributions of source code must retain the above copyright
9 # notice, this list of conditions and the following disclaimer.
10 # * Redistributions in binary form must reproduce the above
11 # copyright notice, this list of conditions and the following
12 # disclaimer in the documentation and/or other materials provided
13 # with the distribution.
14 # * Neither the name of Google Inc. nor the names of its
15 # contributors may be used to endorse or promote products derived
16 # from this software without specific prior written permission.
17 #
18 # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
19 # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
20 # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
21 # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
22 # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
23 # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
24 # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
25 # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
26 # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
27 # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
28 # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29
30 import sys
31 import os
32
33 # This script generates the x32 sources from annoated x64 codes.
34 # <Usage>:
35 # ./generate-x32-source.py {debug|release} output_file_names input_file_names
36 #
37 # The annotations include:
38 # __a (argument) : Replace (n + 1) * kPointerSize with 1 * kHWRegSize +
39 # n * kPointerSize and __a with __ or remove "__a ".
40 # The size of return address is kHWRegSize for X32, the current X64 codes
41 # assume return address size is kPointerSize, so we replace the argument
42 # access offset with the right value.
43 #
44 # __k (keep) : Keep the current line unchanged and replace __k with __
45 # or remove "__k ".
46 # We need to use 64-bit instructions for X32 when:
47 # 1) Load/Store 64-bit value.
48 # 2) Load/Store double into heap number field
49 # 3) Use push/pop for return address and FP register
50 # 4) Get signed index register for SIB access
51 #
52 # __q (quad) : Replace kPointerSize with kHWRegSize and __q with __
53 # or remove "__q ".
54 # We need to use quadword for X32 when:
55 # 1) Pass arguments to the C++ runtime, we need 8-byte in the stack
56 # according to X32 ABI (https://sites.google.com/site/x32abi/)
57 # 2) Access a stack slot when skipping return address or FP
58 # 3) Compute size of state in the deoptimization process as we store state
59 # as quadword in the stack
60 #
61 # __n : Replace RelocInfo::NONE64 with RelocInfo::NONE32.
62 #
63 # __s (quad, keep) : Combine __k and __q. It is used when storing a register
64 # to the runtime stack for RegExp.
65 #
66 # After handling the annotations, if not __k or __s, the rest of the line will
67 # be processed according to the operator_handlers (see below).
68
69 argument_replacements = {
70 "1 * kPointerSize" : "1 * kHWRegSize",
71 "2 * kPointerSize" : "1 * kHWRegSize + 1 * kPointerSize",
72 "3 * kPointerSize" : "1 * kHWRegSize + 2 * kPointerSize",
73 "4 * kPointerSize" : "1 * kHWRegSize + 3 * kPointerSize",
74 "5 * kPointerSize" : "1 * kHWRegSize + 4 * kPointerSize",
75 "6 * kPointerSize" : "1 * kHWRegSize + 5 * kPointerSize",
76 "i * kPointerSize" : "1 * kHWRegSize + (i - 1) * kPointerSize",
77 "argc * kPointerSize" : "1 * kHWRegSize + (argc - 1) * kPointerSize",
78 "(argc - 0) * kPointerSize" : "1 * kHWRegSize + (argc - 1) * kPointerSize",
79 "(argc + 1) * kPointerSize" : "1 * kHWRegSize + argc * kPointerSize",
80 "(argc_ + 1) * kPointerSize" : "1 * kHWRegSize + argc_ * kPointerSize",
81 }
82
83 def HandleArgument(line):
84 result = line
85 if result.find("times_pointer_size, 0)") != -1:
86 result = result.replace("times_pointer_size, 0)", \
87 "times_pointer_size, kPointerSize)")
88 else:
89 for argument in argument_replacements:
90 if result.find(argument) != -1:
91 result = result.replace(argument, argument_replacements[argument])
92 break
93
94 return (True, result)
95
96 def HandleKeep(line):
97 return (False, line)
98
99 def HandleQuad(line):
100 result = line
101 result = result.replace("kPointerSize", "kHWRegSize")
102 return (True, result)
103
104 def HandleNone64(line):
105 result = line
106 result = result.replace("RelocInfo::NONE64", "RelocInfo::NONE32")
107 return (True, result)
108
109 def HandleQuadKeep(line):
110 (cont, result) = HandleQuad(line)
111 return HandleKeep(result)
112
113 annotation_handlers = {
114 " __a" : [" ", HandleArgument],
115 " __k" : [" ", HandleKeep],
116 " __q" : [" ", HandleQuad],
117 " __n" : [" ", HandleNone64],
118 " __s" : [" ", HandleQuadKeep],
119 }
120
121 def Replace(line, key):
122 return line.replace(key, operator_handlers[key][0])
123
124 def HandlePushPop(line, key):
125 if line.find("push(rbp)") == -1 and line.find("pop(rbp)") == -1:
126 return Replace(line, key)
127 else:
128 return line
129
130 def HandleMovQ(line, key):
131 result = line
132 if result.find("xmm") == -1 and result.find("double_scratch") == -1 and \
133 result.find("V8_UINT64_C") == -1 and result.find("V8_INT64_C") == -1:
134 result = Replace(result, key)
135 if result.find("kZapValue") != -1 and result.find("NONE64") != -1:
136 result = result.replace("int64_t", "int32_t")
137 result = result.replace("NONE64", "NONE32")
138 return result
139
140 operator_handlers = {
141 "movq(" : ("movl(", HandleMovQ),
142 "push(" : ("Push(", HandlePushPop),
143 "pop(" : ("Pop(", HandlePushPop),
144 "push_imm32(" : ("Push_imm32(", Replace),
145 " cmovq(" : (" cmovl(", Replace),
146 " xchg(" : (" xchgl(", Replace),
147 " addq(" : (" addl(", Replace),
148 " sbbq(" : (" sbbl(", Replace),
149 " cmpq(" : (" cmpl(", Replace),
150 " and_(" : (" andl(", Replace),
151 " decq(" : (" decl(", Replace),
152 " cqo(" : (" cdq(", Replace),
153 " idivq(" : (" idivl(", Replace),
154 " imul(" : (" imull(", Replace),
155 " incq(" : (" incl(", Replace),
156 " lea(" : (" leal(", Replace),
157 " neg(" : (" negl(", Replace),
158 " not_(" : (" notl(", Replace),
159 " or_(" : (" orl(", Replace),
160 " rol(" : (" roll(", Replace),
161 " ror(" : (" rorl(", Replace),
162 " sar(" : (" sarl(", Replace),
163 " sar_cl(" : (" sarl_cl(", Replace),
164 " shl(" : (" shll(", Replace),
165 " shl_cl(" : (" shll_cl(", Replace),
166 " shr(" : (" shrl(", Replace),
167 " shr_cl(" : (" shrl_cl(", Replace),
168 " subq(" : (" subl(", Replace),
169 " testq(" : (" testl(", Replace),
170 " xor_(" : (" xorl(", Replace),
171 " movzxbq(" : (" movzxbl(", Replace),
172 " repmovsq(" : (" repmovsl(", Replace),
173 }
174
175 def HandleAnnotations(line, debug):
176 cont = True
177 result = line
178 for annotation in annotation_handlers:
179 if result.find(annotation) != -1:
180 if result.find(annotation + " ") != -1:
181 if result.find("#define" + annotation + " __") != -1:
182 # Add a new line to keep debugging easier if debug
183 result = "\n" if debug else ""
184 annotation_handlers[annotation][0] = " __"
185 else:
186 (cont, result) = annotation_handlers[annotation][1](result)
187 if annotation_handlers[annotation][0] == " ":
188 result = result.replace(annotation + " ", \
189 annotation_handlers[annotation][0])
190 else:
191 result = result.replace(annotation, \
192 annotation_handlers[annotation][0])
193 else:
194 if result.find("#define") != -1 or result.find("#undef") != -1:
195 # Add a new line to keep debugging easier if debug
196 result = "\n" if debug else ""
197 annotation_handlers[annotation][0] = " "
198 break
199
200 return (cont, result)
201
202 comment_replacements = {
203 "rbp[24]" : "rbp[20]",
204 "rbp[32]" : "rbp[24]",
205 "rbp[-n-8]" : "rbp[-n-4]",
206 "rsp[16]" : "rsp[12]",
207 "rsp[24]" : "rsp[16]",
208 "rsp[32]" : "rsp[20]",
209 "rsp[40]" : "rsp[24]",
210 "rsp[48]" : "rsp[28]",
211 "rsp[56]" : "rsp[32]",
212 "rsp[argc * 8] " : "rsp[(argc - 1) * 4 + 8]",
213 "rsp[kFastApiCallArguments * 8] " : \
214 "rsp[(kFastApiCallArguments - 1) * 4 + 8]",
215 "rsp[8 * argc] " : "rsp[(argc - 1) * 4 + 8]",
216 "rsp[8 * n] " : "rsp[(n - 1) * 4 + 8]",
217 "rsp[8 * num_arguments] " : "rsp[(num_arguments - 1) * 4 + 8]",
218 "rsp[8 * (argc + 1)]" : "rsp[argc * 4 + 8] ",
219 "rsp[kFastApiCallArguments * 8 + 8]" : "rsp[kFastApiCallArguments * 4 + 8] ",
220 "rsp[8 * (n + 1)]" : "rsp[n * 4 + 8] ",
221 "rsp[(argc + 1) * 8]" : "rsp[argc * 4 + 8] ",
222 "rsp[(argc + 6) * 8] " : "rsp[(argc + 5) * 4 + 8]",
223 "rsp[(argc + 7) * 8] " : "rsp[(argc + 6) * 4 + 8]",
224 "rsp[(argc - n) * 8] " : "rsp[(argc - n - 1) * 4 + 8]",
225 }
226
227 def HandleComment(line):
228 result = line
229 return result
230 ####### Temporarily disable the comment handling##################
231 for comment in comment_replacements:
232 if result.find(comment) != -1:
233 result = result.replace(comment, comment_replacements[comment])
234 break
235
236 return result
237
238 def ProcessLine(line, is_assembler, debug):
239 if line.find("#include") != -1:
240 result = line.replace("x64", "x32")
241 else:
242 result = line.replace("X64", "X32")
243 if not is_assembler:
244 (cont, result) = HandleAnnotations(result, debug)
245 if cont:
246 for key in operator_handlers:
247 if result.find(key) != -1:
248 handler = operator_handlers[key][1]
249 result = handler(result, key)
250 break
251
252 return result
253
254
255 def ProcessLines(lines_in, lines_out, line_number, is_assembler, debug):
256 line_in = lines_in[line_number]
257
258 if line_in.find("#ifdef V8_TARGET_ARCH_X32") != -1:
259 # Process codes inside #ifdef V8_TARGET_ARCH_X32 lines #endif
260 # If debug, keep the #ifdef and #endif, otherwise remove them
261 begin = line_number
262 if debug:
263 lines_out.append(line_in)
264
265 line_number += 1;
266 line_in = lines_in[line_number]
267 while (line_in.find("#endif")) == -1:
268 lines_out.append(line_in)
269 line_number += 1;
270 line_in = lines_in[line_number]
271
272 if debug:
273 lines_out.append(line_in)
274
275 return line_number - begin + 1
276 elif line_in.find("#ifndef V8_TARGET_ARCH_X32") != -1:
277 # Process codes inside #ifndef V8_TARGET_ARCH_X32 x64_lines #endif or
278 # #ifndef V8_TARGET_ARCH_X32 x64_lines #else x32_lines #endif
279 # If debug, keep all, otherwise remove #ifdef, x64_lines, #else and #endif
280 begin = line_number
281 if debug:
282 lines_out.append(line_in)
283
284 line_number += 1;
285 line_in = lines_in[line_number]
286 while (line_in.find("#else")) == -1 and (line_in.find("#endif")) == -1:
287 if debug:
288 lines_out.append(line_in)
289 line_number += 1;
290 line_in = lines_in[line_number]
291 if (line_in.find("#else")) != -1:
292 if debug:
293 lines_out.append(line_in)
294 line_number += 1;
295 line_in = lines_in[line_number]
296 while (line_in.find("#endif")) == -1:
297 lines_out.append(line_in)
298 line_number += 1;
299 line_in = lines_in[line_number]
300 if debug:
301 lines_out.append(line_in)
302
303 return line_number - begin + 1
304 elif (line_in.find("rsp[") != -1 or line_in.find("rbp[") != -1) \
305 and line_in.find("//") !=-1:
306 line_out = HandleComment(line_in)
307 lines_out.append(line_out)
308 return 1
309 else:
310 line_out = ProcessLine(line_in, is_assembler, debug)
311 lines_out.append(line_out)
312 return 1
313
314 def ProcessFile(name, debug):
315 f_in = open(name, "r")
316 lines_in = f_in.readlines()
317 f_in.close()
318
319 # Replace x64 with x32 to form the name "../../src/x32/code-stubs-x32.[h|cc]"
320 # Create x32 folder if it does not exist
321 out_filename = name.replace("x64", "x32")
322 if not os.path.exists(os.path.dirname(out_filename)):
323 os.makedirs(os.path.dirname(out_filename))
324
325 # Process lines of the input file
326 is_assembler = name.find("assembler-x64") == 14
327 lines_out = []
328 line_number = 0
329 total_lines = len(lines_in)
330 while line_number < total_lines:
331 line_number += ProcessLines(lines_in, lines_out, line_number, \
332 is_assembler, debug)
333
334 # Write generated contents into output file
335 f_out = open(out_filename, "w")
336 for item in lines_out:
337 f_out.write(item)
338 f_out.close()
339
340 return 0
341
342 def Main():
343 argc = len(sys.argv)
344 if (argc == 1):
345 print("Usage: %s {debug|release} output_file_names input_file_names" % \
346 sys.argv[0])
347 return 1
348
349 mode = sys.argv[1].lower()
350 if mode != "debug" and mode != 'release':
351 print("{debug|release} mode is expected")
352 return 1
353 debug = True if mode == "debug" else False
354
355 if (argc == 2):
356 print("%s: No output file names and input file names" % sys.argv[0])
357 return 1
358
359 if (argc % 2 == 1):
360 print("%s: The number of output files should be equal with input files" % \
361 sys.argv[0])
362 return 1
363
364 input_start = argc/2 + 1
365 x64_source_lists = sys.argv[input_start:]
366
367 for item in x64_source_lists:
368 ProcessFile(item, debug)
369
370 if __name__ == '__main__':
371 sys.exit(Main())
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698