Ejemplo n.º 1
0
        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);
            }
        }
Ejemplo n.º 2
0
        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);
            }
        }
Ejemplo n.º 3
0
        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;
        }
Ejemplo n.º 4
0
        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;
        }
Ejemplo n.º 5
0
        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);
        }
Ejemplo n.º 6
0
        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);
        }
Ejemplo n.º 7
0
 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});
       }
 }
Ejemplo n.º 8
0
        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;
              }
        }
Ejemplo n.º 9
0
        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 });
            }
        }
Ejemplo n.º 10
0
        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);
            }
        }
Ejemplo n.º 11
0
        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);
            }
        }
Ejemplo n.º 12
0
        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;
              }
        }
Ejemplo n.º 13
0
        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;
              }
        }
Ejemplo n.º 14
0
        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);
              }
        }
Ejemplo n.º 15
0
        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;
              }
        }
Ejemplo n.º 16
0
        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);
            }
        }