def method_invocation(element): if element[0].tag == "name": name = name_to_str(element.find("name")) to_file(element) declaration_site = element.env.get_declaration_site_for_method_name( name, argument_list(element)) element.attrib["type"] = element.env.get_type_for_declaration_site( declaration_site) element.declaration = declaration_site elif element[0].tag == "primary": primary_type = element[0].attrib["type"] error_if(is_primitive(primary_type), "Cannot invoke method on primitive " + primary_type) declaration_site = element.env.get_declaration_site_for_class_name( primary_type) identifier = element.find("tok_identifier").text method_declaration = \ declaration_site.env.get_declaration_site_for_method_name( identifier, argument_list(element)) element.attrib["type"] = \ method_declaration.env.get_type_for_declaration_site( method_declaration) element.declaration = method_declaration else: assert False
def check_and_generate(files): init_globals() # reset global state try: out = open("output/out.s", "w") trees = typechecker.check_files(files) initializer_list = [] mega_vtable_offset = 1 type_tag = 0 string_literal_index = 0 for tree in trees: clazz = find_type_decl(tree) clazz.type_tag = type_tag method_list.class_list += [clazz] type_tag += 1 methods = ( tree.findall(".//method") + tree.findall(".//constructor_declaration") + tree.findall(".//abstract_method") ) for method in methods: method.mega_vtable_offset = mega_vtable_offset mega_vtable_offset += 1 method_list.method_list += [method] if "static" in modifiers(method): slot = -2 else: slot = -3 for param in method.findall(".//param"): param.slot = slot slot -= 1 counters.mega_vtable_members = mega_vtable_offset for string_literal in tree.findall(".//string_literal"): string_literal.index = string_literal_index string_literal_index += 1 out.write(instanceof_table(trees)) for tree in trees: CurrentFile.name = tree.filename CurrentFile.mangled_name = CurrentFile.name.replace(".", "_").replace("$", "_").replace("/", "_") CurrentFile.static_slot = 0 for this in tree.findall(".//tok_this"): this.slot = -2 generate(tree) to_file(tree, tree.filename + ".xml") out.write("section .data\n") for clazz in tree.findall(".//class"): out.write(mega_vtable_for_class(clazz)) out.write("section .text\n") initializer_name = "static_init_" + CurrentFile.mangled_name out.write( """ ; global {initializer_name} {initializer_name}: push ebp mov ebp, esp sub esp, {frame_size} """.format( initializer_name=initializer_name, frame_size=CurrentFile.static_slot * 4 ) ) initializer_list.append(initializer_name) for field in tree.findall(".//field"): if "static" in modifiers(field): mangled_name = mangle_field_name(field) out.write( """ ; initializing {mangled_name} {field_assembly} mov eax, {mangled_name} mov ebx, {assigned_value} mov DWORD [eax], ebx """.format( mangled_name=mangled_name, field_assembly=field.assembly, assigned_value=stack_slot_to_operand(field.slot), ) ) out.write( """ leave ret ; done global static initialization """ ) for constructor in tree.findall(".//constructor_declaration"): out.write(constructor.assembly + "\n") for method in tree.findall(".//method"): if method.find("block") is not None: out.write(method.assembly + "\n") out.write("\nsection .data\n") for string_literal in tree.findall(".//string_literal"): string_value = string_literal.get("value") expanded_value = expand_string_literal(string_value) out.write("\n; string literal " + string_value + "\n") out.write("__string_literal_" + str(string_literal.index) + ":\n") out.write("dd _vtable_java_lang_$Array_ ; vtable pointer\n") out.write("dd -3 ; type tag for char\n") out.write("dd " + str(len(expanded_value)) + " ; string length\n") for character in expanded_value: out.write("dd " + str(hex(ord(character))) + "\n") out.write("") out.write("\nsection .bss\n") for field in tree.findall(".//field"): if "static" in modifiers(field): mangled_name = mangle_field_name(field) out.write("""{mangled_name} resb 4""".format(mangled_name=mangled_name) + "\n") out.write("section .text\n") out.write("; prelude\n") out.write("extern __malloc\n") out.write("extern __debexit\n") out.write("extern __exception\n") out.write("extern NATIVEjava.io.OutputStream.nativeWrite\n") out.write("global _start\n") out.write("_start:\n") out.write("call install_segv_handler\n") for initializer in initializer_list: out.write("call " + initializer + "\n") class_name = mangle_class_name(find_type_decl(trees[1]).get("canonical_name")) out.write("call " + class_name + "test_\n") out.write("mov ebx, eax\n") out.write("mov eax, 1\n") out.write("int 0x80 ; invoke exit(1)\n") out.write("; end prelude\n") out.write( """ %define __NR_signal 48 %define SIGSEGV 11 global install_segv_handler install_segv_handler: mov eax, __NR_signal mov ebx, SIGSEGV mov ecx, __exception int 0x80 ret """ ) return 0 except JoosSyntaxException, e: if Testing.testing: return 42 else: out.write("\n" + e.msg + "\n") raise