Optimize binary_op generation to use less stack if possible
This commit is contained in:
parent
56bcad6fc1
commit
79ca8e78b3
|
@ -487,23 +487,64 @@ def compile_ast(node: ASTnode, compile_data: CompileData) -> None:
|
|||
else:
|
||||
assert node.child_rhs.type == 'int'
|
||||
|
||||
# calculate LHS and store it on stack
|
||||
|
||||
old_code = compile_data.code
|
||||
|
||||
# compile LHS
|
||||
compile_data.code = []
|
||||
compile_ast(node.child_lhs, compile_data)
|
||||
compile_data.code.append(Instruction('subq', ['$16', '%rsp']))
|
||||
compile_data.code.append(Instruction('movq', ['%rax', '0(%rsp)']))
|
||||
lhs_code = compile_data.code
|
||||
|
||||
# calculate RHS and store it in RCX
|
||||
# compile RHS
|
||||
compile_data.code = []
|
||||
compile_ast(node.child_rhs, compile_data)
|
||||
if node.child_lhs.type == 'date' and node.child_rhs.type == 'int':
|
||||
# multiply RHS by number of seconds in a day so we can perform arithmetic on dates
|
||||
compile_data.code.append(Instruction('imulq', ['$86400', '%rax', '%rcx']))
|
||||
else:
|
||||
compile_data.code.append(Instruction('movq', ['%rax', '%rcx']))
|
||||
rhs_code = compile_data.code
|
||||
|
||||
# prepare registers, RAX contains LHS and RCX contains RHS
|
||||
# and restore restore stack
|
||||
compile_data.code.append(Instruction('movq', ['0(%rsp)', '%rax']))
|
||||
compile_data.code.append(Instruction('addq', ['$16', '%rsp']))
|
||||
compile_data.code = old_code
|
||||
|
||||
# check if we can use temporary registers instead of stack
|
||||
temp_registers = ['%rcx', '%r8', '%r9', '%r10', '%r11']
|
||||
temp_reg = None
|
||||
for reg in temp_registers:
|
||||
valid = True
|
||||
for instruction in lhs_code:
|
||||
if reg in instruction.operands:
|
||||
valid = False
|
||||
break
|
||||
if valid:
|
||||
temp_reg = reg
|
||||
break
|
||||
|
||||
# check if lhs uses call, this determines whether we need to align stack
|
||||
lhs_call = False
|
||||
for instruction in lhs_code:
|
||||
if instruction.opcode == 'call':
|
||||
lhs_call = True
|
||||
break
|
||||
|
||||
# Add code for RHS calculation
|
||||
compile_data.code += rhs_code
|
||||
if temp_reg is not None:
|
||||
compile_data.code.append(Instruction('movq', ['%rax', temp_reg]))
|
||||
elif not lhs_call:
|
||||
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 temp_reg is not None:
|
||||
compile_data.code.append(Instruction('movq', [temp_reg, '%rcx']))
|
||||
elif not lhs_call:
|
||||
compile_data.code.append(Instruction('popq', ['%rcx']))
|
||||
else:
|
||||
compile_data.code.append(Instruction('movq', ['0(%rsp)', '%rcx']))
|
||||
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':
|
||||
compile_data.code.append(Instruction('imulq', ['$86400', '%rcx']))
|
||||
|
||||
# perform operation
|
||||
if node.value == '+':
|
||||
|
|
Loading…
Reference in New Issue