Optimize binary_op generation to use less stack if possible
This commit is contained in:
		
							parent
							
								
									56bcad6fc1
								
							
						
					
					
						commit
						79ca8e78b3
					
				| 
						 | 
					@ -487,24 +487,65 @@ def compile_ast(node: ASTnode, compile_data: CompileData) -> None:
 | 
				
			||||||
            else:
 | 
					            else:
 | 
				
			||||||
                assert node.child_rhs.type == 'int'
 | 
					                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_ast(node.child_lhs, compile_data)
 | 
				
			||||||
 | 
					            lhs_code = compile_data.code
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            # compile RHS
 | 
				
			||||||
 | 
					            compile_data.code = []
 | 
				
			||||||
 | 
					            compile_ast(node.child_rhs, compile_data)
 | 
				
			||||||
 | 
					            rhs_code = compile_data.code
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            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('subq', ['$16', '%rsp']))
 | 
				
			||||||
                compile_data.code.append(Instruction('movq', ['%rax', '0(%rsp)']))
 | 
					                compile_data.code.append(Instruction('movq', ['%rax', '0(%rsp)']))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            # calculate RHS and store it in RCX
 | 
					            # Add code for LHS calculation
 | 
				
			||||||
            compile_ast(node.child_rhs, compile_data)
 | 
					            compile_data.code += lhs_code
 | 
				
			||||||
            if node.child_lhs.type == 'date' and node.child_rhs.type == 'int':
 | 
					            if temp_reg is not None:
 | 
				
			||||||
                # multiply RHS by number of seconds in a day so we can perform arithmetic on dates
 | 
					                compile_data.code.append(Instruction('movq', [temp_reg, '%rcx']))
 | 
				
			||||||
                compile_data.code.append(Instruction('imulq', ['$86400', '%rax', '%rcx']))
 | 
					            elif not lhs_call:
 | 
				
			||||||
 | 
					                compile_data.code.append(Instruction('popq', ['%rcx']))
 | 
				
			||||||
            else:
 | 
					            else:
 | 
				
			||||||
                compile_data.code.append(Instruction('movq', ['%rax', '%rcx']))
 | 
					                compile_data.code.append(Instruction('movq', ['0(%rsp)', '%rcx']))
 | 
				
			||||||
 | 
					 | 
				
			||||||
            # 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.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
 | 
					            # perform operation
 | 
				
			||||||
            if node.value == '+':
 | 
					            if node.value == '+':
 | 
				
			||||||
                compile_data.code.append(Instruction('addq', ['%rcx', '%rax']))
 | 
					                compile_data.code.append(Instruction('addq', ['%rcx', '%rax']))
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
		Reference in New Issue