private List <Expression> ExtractFromFunctionCall(FunctionCall funCall) { funCall.Arguments = funCall.Arguments.Select((argument, i) => { if (argument is AST.Variable variableArgument) { var isModifiedByAnotherArgument = funCall .Arguments .Skip(i + 1) .Any(followingArgument => this.variableAccess.Modifies[followingArgument] .Contains(variableArgument.Declaration)); if (isModifiedByAnotherArgument) { var tmpDeclaration = new VariableDeclaration(argument.InputRange, argument.Type, "tmp", argument) { IntermediateVariable = new VirtualRegister() }; var tmpVariable = new AST.Variable(tmpDeclaration.InputRange, "tmp") { Declaration = tmpDeclaration, Type = argument.Type }; var instructionBlock = new InstructionBlock( tmpDeclaration.InputRange, new List <Expression> { tmpDeclaration }); return((Expression) new BlockWithResult( tmpDeclaration.InputRange, instructionBlock, tmpVariable) { Type = tmpVariable.Type }); } } var instructions = this.ExtractTemporaryVariables(argument); return(new BlockWithResult( funCall.InputRange, new InstructionBlock(funCall.InputRange, instructions), argument) { Type = argument.Type }); }).ToList(); return(new List <Expression>()); }
private List <Expression> ExtractFromOperationNode(BinaryOperation operationNode) { // In (A op B) // We'd like to compute A before B if both A and B use variable x and at least one of them modifies it var modifiedVariablesLeft = this.variableAccess.Modifies[operationNode.LeftValue]; var modifiedVariablesRight = this.variableAccess.Modifies[operationNode.RightValue]; var usedVariablesLeft = this.variableAccess.Accesses[operationNode.LeftValue]; var usedVariablesRight = this.variableAccess.Accesses[operationNode.RightValue]; operationNode.LeftValue = this.ReplaceWithBlock(operationNode.LeftValue); var result = new List <Expression>(); if (modifiedVariablesLeft.Any(x => usedVariablesRight.Contains(x)) || modifiedVariablesRight.Any(x => usedVariablesLeft.Contains(x))) { var tmpDecl = new VariableDeclaration( operationNode.LeftValue.InputRange, operationNode.LeftValue.Type, "tmp", operationNode.LeftValue) { IntermediateVariable = new VirtualRegister() }; var tmpVar = new AST.Variable(tmpDecl.InputRange, "tmp") { Declaration = tmpDecl }; result.Add(tmpDecl); operationNode.LeftValue = tmpVar; } operationNode.RightValue = this.ReplaceWithBlock(operationNode.RightValue); return(result); }