diff --git a/04_semantics_and_running/main.py b/04_semantics_and_running/main.py index 9c8a863..9a935fb 100644 --- a/04_semantics_and_running/main.py +++ b/04_semantics_and_running/main.py @@ -574,18 +574,27 @@ def compile_ast(node: ASTnode, compile_data: CompileData) -> None: compile_data.code = old_code - # check if we can use temporary registers instead of stack + # If RHS is an 32 bit integer literal, we can use it as an immediate value + register = None + if node.child_rhs.nodetype == 'int_literal' and node.child_rhs.value <= 0x7FFFFFFF: + if node.child_lhs.type != 'date': + register = f'${node.child_rhs.value}' + elif node.child_rhs.value * 86400 <= 0x7FFFFFFF: + register = f'${node.child_rhs.value * 86400}' + + # Otherwise, we need to use a register usable_registers = ['%r8', '%r9', '%r10', '%r11'] - register = '%rcx' - for reg in usable_registers: - valid = True - for instruction in lhs_code: - if reg in instruction.operands: - valid = False + if register is None: + register = '%rcx' + for reg in usable_registers: + valid = True + for instruction in lhs_code: + if reg in instruction.operands: + valid = False + break + if valid: + register = reg break - if valid: - register = reg - break # check if lhs uses call, this determines whether we need to align stack align_stack = False @@ -595,18 +604,21 @@ def compile_ast(node: ASTnode, compile_data: CompileData) -> None: break # Add code for RHS calculation - compile_data.code += rhs_code - if register != '%rcx': - compile_data.code.append(Instruction('movq', ['%rax', register])) - elif not align_stack: - compile_data.code.append(Instruction('pushq', ['%rax'])) + if register[0] == '$': + pass else: - compile_data.code.append(Instruction('subq', ['$16', '%rsp'])) - compile_data.code.append(Instruction('movq', ['%rax', '0(%rsp)'])) + compile_data.code += rhs_code + if register != '%rcx': + compile_data.code.append(Instruction('movq', ['%rax', register])) + elif not align_stack: + compile_data.code.append(Instruction('pushq', ['%rax'])) + else: + compile_data.code.append(Instruction('subq', ['$16', '%rsp'])) + compile_data.code.append(Instruction('movq', ['%rax', '0(%rsp)'])) # Add code for LHS calculation compile_data.code += lhs_code - if register != '%rcx': + if register[0] == '$' or register != '%rcx': pass elif not align_stack: compile_data.code.append(Instruction('popq', [register])) @@ -615,10 +627,11 @@ def compile_ast(node: ASTnode, compile_data: CompileData) -> None: compile_data.code.append(Instruction('addq', ['$16', '%rsp'])) # If we are adding or subtracting dates with integers, multiply the integer by number of seconds in a day - if node.child_lhs.type == 'date' and node.child_rhs.type == 'int': + # If register is immediate, this has already been done + if register[0] != '$' and node.child_lhs.type == 'date' and node.child_rhs.type == 'int': compile_data.code.append(Instruction('imulq', ['$86400', register])) - # perform operation + # Perform operation if node.value == '+': compile_data.code.append(Instruction('addq', [register, '%rax'])) elif node.value == '-': @@ -626,6 +639,10 @@ def compile_ast(node: ASTnode, compile_data: CompileData) -> None: elif node.value == '*': compile_data.code.append(Instruction('imulq', [register, '%rax'])) elif node.value == '/': + # Division by immediate is not possible + if register[0] == '$': + compile_data.code.append(Instruction('movq', [register, '%rcx'])) + register = '%rcx' compile_data.code.append(Instruction('cqo')) compile_data.code.append(Instruction('idivq', [register])) elif node.value == '<': @@ -638,7 +655,7 @@ def compile_ast(node: ASTnode, compile_data: CompileData) -> None: compile_data.code.append(Instruction('movzbq', ['%al', '%rax'])) else: assert False - # if both operands are dates, divide result by number of seconds in a day + # If both operands are dates, divide result by number of seconds in a day if node.child_lhs.type == 'date' and node.child_rhs.type == 'date': assert node.value == '-' compile_data.code.append(Instruction('movq', ['$86400', register]))