def type_tag_of_subtree(subtree, if_array_then_contents=False): if isarray(collect_token_text(subtree)): if if_array_then_contents: subtree = subtree[0] if subtree.tag == "primitive_type": return {"short": -1, "int": -2, "char": -3, "byte": -4, "boolean": -5}[collect_token_text(subtree)] return subtree.env.findclass(name_to_str(subtree)).type_tag
def comparison_expression(subtree): if subtree[1].tag == "tok_instanceof": instanceof_expression(subtree) return label_no = new_label_no() zero_case = "EQUALITY_ZERO_" + str(label_no) one_case = "EQUALITY_ONE_" + str(label_no) final = "EQUALITY_FINAL_" + str(label_no) lhs_location = subtree[0].slot rhs_location = subtree[2].slot subtree.slot = generate_new_stack_slot(subtree) jump_if_zero_location = one_case jump = "" cmp_expression = "" if collect_token_text(subtree[1]) == "==": jump = "JZ" elif subtree[1].tag == "tok_gt": jump = "JG" elif subtree[1].tag == "tok_lt": jump = "JL" elif subtree[1].tag == "tok_lteq": jump = "JLE" elif subtree[1].tag == "tok_gteq": jump = "JGE" elif collect_token_text(subtree[1]) == "!=": jump = "JNZ" subtree.assembly = """ ; equality expression mov eax, {lhs} mov ebx, {rhs} sub eax, ebx {jump} .{jump_if_zero_location} .{zero_case}: mov {result}, {false} JMP .{final_location} .{one_case}: mov {result}, {true} .{final_location}: ;end equality expression """.format( lhs=stack_slot_to_operand(lhs_location), rhs=stack_slot_to_operand(rhs_location), result=stack_slot_to_operand(subtree.slot), cmp_expression=cmp_expression, jump_if_zero_location=jump_if_zero_location, final_location=final, zero_case=zero_case, one_case=one_case, jump=jump, false=false, true=true, )
def array_creation_expression(element): base_name = collect_token_text(element[1]) if element.find(".//dim_expr") is not None: base_name += "[]" if element.find(".//dim_expr/expression") is not None: type_str = element.find(".//dim_expr/expression").attrib["type"] error_if(not is_integral_primitive(type_str), "dim_expr require integral type") element.attrib["type"] = element.env.canonicalize_name(base_name)
def constructor_declaration(subtree): mangled_name = mangle_fn_name(subtree) constructor_body = subtree.find("constructor_body") error_if(constructor_body is None, "No constructor body") superclass = subtree.env.findclass("this").superclass superclass_mangled_name = mangle_class_name(superclass.get("canonical_name")) superclass_constructor = superclass_mangled_name + mangle_class_name(superclass.get("name")) fields = subtree.env.findclass("this").findall(".//field") field_initializers = "" for field in fields: if "static" not in modifiers(field) and field.find("expression") is not None: if not hasattr(field.find("expression"), "assembly"): generate(field.find("expression")) field_initializers += field.find("expression").assembly + "\n" field_initializers += """ ; field_initializer mov eax, DWORD [ebp + 8] ; this -> eax add eax, {field_location} mov ebx, {value} mov DWORD [eax], ebx ; end_field_initializer """.format( field_location=field.env.find_nonlocal(collect_token_text(field.find("variable"))).field_offset * 4, value=stack_slot_to_operand(field.find("expression").slot), ) chained_constructor_call = """ ;initialize fields {field_initializers} ; call superclass default constructor push DWORD [ebp + 8] call {superclass_constructor} """.format( superclass_constructor=superclass_constructor, field_initializers=field_initializers ) this_class = subtree.env.findclass("this") if this_class.get("canonical_name") == "java.lang.Object": chained_constructor_call = field_initializers subtree.assembly = method_declaration_asm( constructor_body.assembly, mangled_name, subtree, chained_constructor_call ) subtree.assembly += """ mov eax, {this_ptr} leave ret ; end constructor {name} """.format( this_ptr=stack_slot_to_operand(this), name=mangled_name )
def multiplicative_expression(subtree): lhs_location = subtree[0].slot rhs_location = subtree[2].slot new_stack_slot = generate_new_stack_slot(subtree) operator_type = collect_token_text(subtree[1]) result = operator = "" if operator_type == "*": operator = "imul" result = "eax" check = "" elif operator_type == "/": operator = "idiv" result = "eax" label_no = new_label_no() check = """ sub ebx, 0 jne .{okay_label} call __exception .{okay_label}: """.format( okay_label="DIV0_CHECK_" + str(label_no) ) elif operator_type == "%": operator = "idiv" result = "edx" check = "" else: error_if(True, "Unknown argument to mulitplicative expression") subtree.assembly = """ ; multiplicative {dbg} mov edx, {lhs} mov eax, edx sar edx, 31 mov ebx, {rhs} {check} {op} ebx mov {nss}, {result} ; end multiplicative """.format( nss=stack_slot_to_operand(new_stack_slot), lhs=stack_slot_to_operand(lhs_location), rhs=stack_slot_to_operand(rhs_location), result=result, check=check, op=operator, imul_part=operator == "imul" and ", edx" or "", dbg=collect_debug_text(subtree), ) subtree.slot = new_stack_slot
def additive_expression(subtree): lhs_slot = subtree[0].slot rhs_slot = subtree[2].slot result_slot = generate_new_stack_slot(subtree) lhs_type = subtree[0].get("type") rhs_type = subtree[2].get("type") if "java.lang.String" in [lhs_type, rhs_type]: (lhs_slot, lhs_assembly) = generate_promotion_to_string(subtree[0]) (rhs_slot, rhs_assembly) = generate_promotion_to_string(subtree[2]) assembly = """ ; string additive expression {lhs_assembly} {rhs_assembly} mov eax, {lhs_slot} mov ebx, {rhs_slot} push ebx push eax call java_lang_String_concat_java_lang_String_ mov {result_slot}, eax """.format( lhs_assembly=lhs_assembly, rhs_assembly=rhs_assembly, rhs_slot=stack_slot_to_operand(rhs_slot), lhs_slot=stack_slot_to_operand(lhs_slot), result_slot=stack_slot_to_operand(result_slot), ) subtree.assembly = assembly subtree.slot = result_slot return operator_type = collect_token_text(subtree[1]) operator = "" if operator_type == "+": operator = "add" elif operator_type == "-": operator = "sub" else: error_if(True, "Unknown additive_expression operator_type") subtree.assembly = binary_operator_assembly(lhs_slot, rhs_slot, operator, result_slot, collect_debug_text(subtree)) subtree.slot = result_slot
def cast_expression(element): if element[1].tag == "name": expression_being_cast = element.find("unary_expression_not_plus_minus") cast_type = element.env.canonicalize_name(name_to_str(element[1])) if element.find("dims"): cast_type += "[]" elif element[1].tag == "expression": # Expression case cast_type = element[1].attrib["type"] expression_being_cast = element[-1] else: # Primitive cast case cast_type = collect_token_text(element[1]) if element[2].tag == "dims": cast_type += "[]" expression_being_cast = element[-1] error_if(not element.env.can_be_cast(expression_being_cast.attrib["type"], cast_type), "TODO(thurn): This is an error.") element.attrib["type"] = cast_type
def reference_type(element): name_string = collect_token_text(element) canonical_name = element.env.canonicalize_name(name_string) element.attrib["type"] = canonical_name
def mangle_field_name(field_decl): return mangle_class_name(classof(field_decl)) + "_" + collect_token_text(field_decl.find("./variable")) + "_"