public static IReadable Invoke(string scopeName, IReference storage, IntExpression lhs, IntExpression rhs, ActionOnThreeLowRegisters registerAction, ActionOnTwoLowRegistersAndAByte byteAction) { var f = FuncBuilder.Instance; using (f.OpenScope(scopeName)) { var sm = new StorageManager(storage); var lhsResult = lhs.EvaluateTo(sm.ForLhs(rhs)); var rhsResult = rhs.EvaluateTo(sm.ForRhs(lhsResult)); var storageReg = storage.ProposeRegisterOrScratch0(); var lhsReg = lhsResult.ToRegister(f.Scratch0); var rhsRegOrByte = rhsResult.ToRegisterOrByte(f.Scratch1); if (rhsRegOrByte.IsRegister) { registerAction(storageReg, lhsReg, rhsRegOrByte.Register); } else { byteAction(storageReg, lhsReg, rhsRegOrByte.Byte); } storage.FromRegister(storageReg); return(storage); } }
protected IReadable EvaluateToHelper(IReference storage, ActionOnThreeLowRegisters regAction, ActionOnTwoLowRegistersAndAByte byteAction) { var f = FuncBuilder.Instance; using (f.OpenScope("indirectReferenceEval")) { var declarer = f.Declare; var baseStorage = declarer.Int("base"); var offsetStorage = declarer.Int("offset"); var baseResult = baseAddress.EvaluateTo(baseStorage); var offsetResult = offset.EvaluateTo(offsetStorage); var storageReg = storage.ProposeRegisterOrScratch0(); var baseReg = baseResult.ToRegister(f.Scratch0); var offsetRegOrByte = offsetResult.ToRegisterOrUnsignedConstant(exclusiveUpperBoundForConstantOffset, f.Scratch1); if (offsetRegOrByte.IsRegister) { regAction(storageReg, baseReg, offsetRegOrByte.Register); } else { byteAction(storageReg, baseReg, offsetRegOrByte.Byte); } storage.FromRegister(storageReg); return(storage); } }
protected override IReadable EvaluateToHelper(IReference storage) { var emitter=CodeGenerator.Emitter; var myAddress=label.GetLabelAddressBestEffort(); var targetRegister=storage.ProposeRegisterOrScratch0(); emitter.EmitLoadAddress(Format12OpCode.LDADDR_PC, targetRegister, myAddress, wantThumbAdjustment); storage.FromRegister(targetRegister); return storage; }
protected override IReadable EvaluateToHelper(IReference storage) { var emitter=CodeGenerator.Emitter; var exprResult=expr.EvaluateTo(storage); var storageReg=storage.ProposeRegisterOrScratch0(); var exprReg=exprResult.ToRegister(storageReg); emitter.Emit(OpCodes.Format4OpCode.NEG, storageReg, exprReg); storage.FromRegister(storageReg); return storage; }
protected override IReadable EvaluateToHelper(IReference storage) { var emitter = CodeGenerator.Emitter; var exprResult = expr.EvaluateTo(storage); var storageReg = storage.ProposeRegisterOrScratch0(); var exprReg = exprResult.ToRegister(storageReg); emitter.Emit(OpCodes.Format4OpCode.NEG, storageReg, exprReg); storage.FromRegister(storageReg); return(storage); }
protected override IReadable EvaluateToHelper(IReference storage) { var emitter = CodeGenerator.Emitter; var myAddress = label.GetLabelAddressBestEffort(); var targetRegister = storage.ProposeRegisterOrScratch0(); emitter.EmitLoadAddress(Format12OpCode.LDADDR_PC, targetRegister, myAddress, wantThumbAdjustment); storage.FromRegister(targetRegister); return(storage); }
public static void SpecialAssignAny(IReference lhs, Expression rhs) { var f=FuncBuilder.Instance; var lhsWasLivePriorToThisAssignment=f.IsLive(lhs); var rhsReadable=rhs.EvaluateTo(lhs); if(!ReferenceEquals(lhs, rhsReadable)) { var lhsReg=lhs.ProposeRegisterOrScratch0(); var rhsReg=rhsReadable.ToRegister(lhsReg); lhs.FromRegister(rhsReg); } //Don't decide that a variable is live just because it was referenced (or it was used as temporary storage) //in its very-own assignment. if(!lhsWasLivePriorToThisAssignment) { f.UndoNoteRead(new[] {lhs}); } }
protected override IReadable EvaluateToHelper(IReference storage) { var f=FuncBuilder.Instance; using(f.OpenScope(opCode.ToHumanReadable())) { var emitter=CodeGenerator.Emitter; var sm=new StorageManager(storage); var lhsResult=lhs.EvaluateTo(sm.ForLhs(rhs)); var rhsResult=rhs.EvaluateTo(sm.ForRhs(lhsResult)); var storageReg=f.Scratch0; var lhsReg=lhsResult.ToRegister(f.Scratch0); var rhsReg=rhsResult.ToRegister(f.Scratch1); emitter.EmitRegisterMoveIfDifferent(storageReg, lhsReg); emitter.Emit(opCode, storageReg, rhsReg); storage.FromRegister(storageReg); return storage; } }
public static void SpecialAssignAny(IReference lhs, Expression rhs) { var f = FuncBuilder.Instance; var lhsWasLivePriorToThisAssignment = f.IsLive(lhs); var rhsReadable = rhs.EvaluateTo(lhs); if (!ReferenceEquals(lhs, rhsReadable)) { var lhsReg = lhs.ProposeRegisterOrScratch0(); var rhsReg = rhsReadable.ToRegister(lhsReg); lhs.FromRegister(rhsReg); } //Don't decide that a variable is live just because it was referenced (or it was used as temporary storage) //in its very-own assignment. if (!lhsWasLivePriorToThisAssignment) { f.UndoNoteRead(new[] { lhs }); } }
protected override IReadable EvaluateToHelper(IReference storage) { Format4OpCode registerOpCode; Format1OpCode immediateOpCode; if (shiftLeft) { registerOpCode = Format4OpCode.LSL; immediateOpCode = Format1OpCode.LSL; } else { registerOpCode = Format4OpCode.ASR; immediateOpCode = Format1OpCode.ASR; } var f = FuncBuilder.Instance; var emitter = CodeGenerator.Emitter; using (f.OpenScope(registerOpCode.ToHumanReadable())) { var sm = new StorageManager(storage); var lhsResult = lhs.EvaluateTo(sm.ForLhs(rhs)); var rhsResult = rhs.EvaluateTo(sm.ForRhs(lhsResult)); var scratch0 = f.Scratch0; var scratch1 = f.Scratch1; var storageReg = scratch0; var lhsReg = lhsResult.ToRegister(scratch0); var rhsRegOrOffset = rhsResult.ToRegisterOrUint5(scratch1); if (rhsRegOrOffset.IsRegister) { emitter.EmitRegisterMoveIfDifferent(storageReg, lhsReg); emitter.Emit(registerOpCode, storageReg, rhsRegOrOffset.Register); } else { emitter.Emit(immediateOpCode, storageReg, lhsReg, rhsRegOrOffset.Byte); } storage.FromRegister(storageReg); return(storage); } }
protected override IReadable EvaluateToHelper(IReference storage) { var f = FuncBuilder.Instance; using (f.OpenScope(opCode.ToHumanReadable())) { var emitter = CodeGenerator.Emitter; var sm = new StorageManager(storage); var lhsResult = lhs.EvaluateTo(sm.ForLhs(rhs)); var rhsResult = rhs.EvaluateTo(sm.ForRhs(lhsResult)); var storageReg = f.Scratch0; var lhsReg = lhsResult.ToRegister(f.Scratch0); var rhsReg = rhsResult.ToRegister(f.Scratch1); emitter.EmitRegisterMoveIfDifferent(storageReg, lhsReg); emitter.Emit(opCode, storageReg, rhsReg); storage.FromRegister(storageReg); return(storage); } }
public static IReadable Invoke(string scopeName, IReference storage, IntExpression lhs, IntExpression rhs, ActionOnThreeLowRegisters registerAction, ActionOnTwoLowRegistersAndAByte byteAction) { var f=FuncBuilder.Instance; using(f.OpenScope(scopeName)) { var sm=new StorageManager(storage); var lhsResult=lhs.EvaluateTo(sm.ForLhs(rhs)); var rhsResult=rhs.EvaluateTo(sm.ForRhs(lhsResult)); var storageReg=storage.ProposeRegisterOrScratch0(); var lhsReg=lhsResult.ToRegister(f.Scratch0); var rhsRegOrByte=rhsResult.ToRegisterOrByte(f.Scratch1); if(rhsRegOrByte.IsRegister) { registerAction(storageReg, lhsReg, rhsRegOrByte.Register); } else { byteAction(storageReg, lhsReg, rhsRegOrByte.Byte); } storage.FromRegister(storageReg); return storage; } }
protected override IReadable EvaluateToHelper(IReference storage) { Format4OpCode registerOpCode; Format1OpCode immediateOpCode; if(shiftLeft) { registerOpCode=Format4OpCode.LSL; immediateOpCode=Format1OpCode.LSL; } else { registerOpCode=Format4OpCode.ASR; immediateOpCode=Format1OpCode.ASR; } var f=FuncBuilder.Instance; var emitter=CodeGenerator.Emitter; using(f.OpenScope(registerOpCode.ToHumanReadable())) { var sm=new StorageManager(storage); var lhsResult=lhs.EvaluateTo(sm.ForLhs(rhs)); var rhsResult=rhs.EvaluateTo(sm.ForRhs(lhsResult)); var scratch0=f.Scratch0; var scratch1=f.Scratch1; var storageReg=scratch0; var lhsReg=lhsResult.ToRegister(scratch0); var rhsRegOrOffset=rhsResult.ToRegisterOrUint5(scratch1); if(rhsRegOrOffset.IsRegister) { emitter.EmitRegisterMoveIfDifferent(storageReg, lhsReg); emitter.Emit(registerOpCode, storageReg, rhsRegOrOffset.Register); } else { emitter.Emit(immediateOpCode, storageReg, lhsReg, rhsRegOrOffset.Byte); } storage.FromRegister(storageReg); return storage; } }
public void Invoke(FuncPointer fp, IReference optionalResult, params Expression[] arguments) { var callerCaresAboutResult=!ReferenceEquals(optionalResult, null) && !CanProveIsNeverRead(optionalResult); var g=CodeGenerator.Instance; var emitter=CodeGenerator.Emitter; using(this.OpenScope("invokeMethod")) { this.externalMethodWasInvoked=true; //use the caller's storage (if any) as a place to evaluate the func pointer var temp=this.Declare.Int("temp"); var fpReadable=fp.EvaluateTo(optionalResult ?? temp); using(this.OpenScope("params")) { //SUPER HACK: in order to participate in the function calling convention, I need to //relocate any existing variable stored in R0-R3 to the stack int registerMaskToSpill; int registersToSpillStackConsumption; localVariableToInfo.MigrateR0R3ToStack(out registerMaskToSpill, out registersToSpillStackConsumption); //Spill the affected registers to the stack emitter.EmitIfNecessary(Format14OpCode.PUSH, false, (byte)registerMaskToSpill); StackPointer+=registersToSpillStackConsumption; //great! Now make your parameters (which may further adjust the stack) //we only need parameters up to our highest unused argument var parameterLength=arguments.Length; while(parameterLength>0 && arguments[parameterLength-1]==null) { --parameterLength; } var stackPointerBeforePush=StackPointer; var parameters=new IReference[parameterLength]; for(var i=parameterLength-1; i>=0; --i) { Representation representation; if(i<4) { representation=new LowRegister(i); } else { StackPointer+=-4; representation=new StackWordRelativeToZero(StackPointer); } var vi=new LocalVariableInfo(CreateTerminalName("param"+i), representation); var variable=new IntVariable(); localVariableToInfo.Add(variable, vi); parameters[i]=variable; } var additionalStackToAllocate=StackPointer-stackPointerBeforePush; emitter.EmitIfNecessary(Format13OpCode.ADDSP, additionalStackToAllocate); //Now move your arguments to the function parameters for(var i=0; i<parameterLength; ++i) { var parameter=parameters[i]; var argument=arguments[i]; if(!ReferenceEquals(argument, null)) { Assignment.SpecialAssignAny(parameter, arguments[i]); } } //FIRE AWAY, BONGO var branchTargetReg=fpReadable.ToRegister(Scratch0); var targetLabel=g.LookupOrCreateBranchTo(branchTargetReg); var address=targetLabel.GetLabelAddressBestEffort(); emitter.Emit(Format19OpCode.BL, address); //woowee! we are back //R0 has a result... stash it in LR so that our pop logic can restore everything else if(callerCaresAboutResult) { emitter.EmitRegisterMoveIfDifferent(Register.LR, Register.R0); } //fix your stack emitter.EmitIfNecessary(Format13OpCode.ADDSP, -additionalStackToAllocate); StackPointer-=additionalStackToAllocate; //fix your registers emitter.EmitIfNecessary(Format14OpCode.POP, false, (byte)registerMaskToSpill); StackPointer-=registersToSpillStackConsumption; } } //if the caller cares about the result, provide it if(callerCaresAboutResult) { optionalResult.FromRegister(Register.LR); } }
protected IReadable EvaluateToHelper(IReference storage, ActionOnThreeLowRegisters regAction, ActionOnTwoLowRegistersAndAByte byteAction) { var f=FuncBuilder.Instance; using(f.OpenScope("indirectReferenceEval")) { var declarer=f.Declare; var baseStorage=declarer.Int("base"); var offsetStorage=declarer.Int("offset"); var baseResult=baseAddress.EvaluateTo(baseStorage); var offsetResult=offset.EvaluateTo(offsetStorage); var storageReg=storage.ProposeRegisterOrScratch0(); var baseReg=baseResult.ToRegister(f.Scratch0); var offsetRegOrByte=offsetResult.ToRegisterOrUnsignedConstant(exclusiveUpperBoundForConstantOffset, f.Scratch1); if(offsetRegOrByte.IsRegister) { regAction(storageReg, baseReg, offsetRegOrByte.Register); } else { byteAction(storageReg, baseReg, offsetRegOrByte.Byte); } storage.FromRegister(storageReg); return storage; } }
public void Invoke(FuncPointer fp, IReference optionalResult, params Expression[] arguments) { var callerCaresAboutResult = !ReferenceEquals(optionalResult, null) && !CanProveIsNeverRead(optionalResult); var g = CodeGenerator.Instance; var emitter = CodeGenerator.Emitter; using (this.OpenScope("invokeMethod")) { this.externalMethodWasInvoked = true; //use the caller's storage (if any) as a place to evaluate the func pointer var temp = this.Declare.Int("temp"); var fpReadable = fp.EvaluateTo(optionalResult ?? temp); using (this.OpenScope("params")) { //SUPER HACK: in order to participate in the function calling convention, I need to //relocate any existing variable stored in R0-R3 to the stack int registerMaskToSpill; int registersToSpillStackConsumption; localVariableToInfo.MigrateR0R3ToStack(out registerMaskToSpill, out registersToSpillStackConsumption); //Spill the affected registers to the stack emitter.EmitIfNecessary(Format14OpCode.PUSH, false, (byte)registerMaskToSpill); StackPointer += registersToSpillStackConsumption; //great! Now make your parameters (which may further adjust the stack) //we only need parameters up to our highest unused argument var parameterLength = arguments.Length; while (parameterLength > 0 && arguments[parameterLength - 1] == null) { --parameterLength; } var stackPointerBeforePush = StackPointer; var parameters = new IReference[parameterLength]; for (var i = parameterLength - 1; i >= 0; --i) { Representation representation; if (i < 4) { representation = new LowRegister(i); } else { StackPointer += -4; representation = new StackWordRelativeToZero(StackPointer); } var vi = new LocalVariableInfo(CreateTerminalName("param" + i), representation); var variable = new IntVariable(); localVariableToInfo.Add(variable, vi); parameters[i] = variable; } var additionalStackToAllocate = StackPointer - stackPointerBeforePush; emitter.EmitIfNecessary(Format13OpCode.ADDSP, additionalStackToAllocate); //Now move your arguments to the function parameters for (var i = 0; i < parameterLength; ++i) { var parameter = parameters[i]; var argument = arguments[i]; if (!ReferenceEquals(argument, null)) { Assignment.SpecialAssignAny(parameter, arguments[i]); } } //FIRE AWAY, BONGO var branchTargetReg = fpReadable.ToRegister(Scratch0); var targetLabel = g.LookupOrCreateBranchTo(branchTargetReg); var address = targetLabel.GetLabelAddressBestEffort(); emitter.Emit(Format19OpCode.BL, address); //woowee! we are back //R0 has a result... stash it in LR so that our pop logic can restore everything else if (callerCaresAboutResult) { emitter.EmitRegisterMoveIfDifferent(Register.LR, Register.R0); } //fix your stack emitter.EmitIfNecessary(Format13OpCode.ADDSP, -additionalStackToAllocate); StackPointer -= additionalStackToAllocate; //fix your registers emitter.EmitIfNecessary(Format14OpCode.POP, false, (byte)registerMaskToSpill); StackPointer -= registersToSpillStackConsumption; } } //if the caller cares about the result, provide it if (callerCaresAboutResult) { optionalResult.FromRegister(Register.LR); } }