Chromium Code Reviews| OLD | NEW |
|---|---|
| (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()) | |
| OLD | NEW |