Esempio n. 1
0
 public void MigrateR0R3ToStack(out int registerMaskToSpill, out int stackConsumption)
 {
     var outermost=this.variables;
       var variableNamesToMigrate=new ArrayList[4];
       for(var i=0; i<4; ++i) {
     variableNamesToMigrate[i]=new ArrayList();
       }
       for(var self=this.inner; self!=null; self=self.inner) {
     foreach(DictionaryEntry kvp in self.variables) {
       var vi=(LocalVariableInfo)kvp.Value;
       var register=vi.Representation as LowRegister;
       if(register!=null) {
     var index=register.Index;
     if(index<4) {
       variableNamesToMigrate[index].Add(kvp);
     }
       }
     }
       }
       registerMaskToSpill=0;
       stackConsumption=0;
       var f=FuncBuilder.Instance;
       for(var i=3; i>=0; --i) {
     foreach(DictionaryEntry de in variableNamesToMigrate[i]) {
       var variable=(IReference)de.Key;
       var vi=(LocalVariableInfo)de.Value;
       stackConsumption-=4;
       var newVariableInfo=new LocalVariableInfo(vi.Name, new StackWordRelativeToZero(f.StackPointer+stackConsumption));
       outermost.CheckedAdd(variable, newVariableInfo);
       registerMaskToSpill|=(1<<i);
     }
       }
 }
Esempio n. 2
0
        public void MigrateR0R3ToStack(out int registerMaskToSpill, out int stackConsumption)
        {
            var outermost = this.variables;
            var variableNamesToMigrate = new ArrayList[4];

            for (var i = 0; i < 4; ++i)
            {
                variableNamesToMigrate[i] = new ArrayList();
            }
            for (var self = this.inner; self != null; self = self.inner)
            {
                foreach (DictionaryEntry kvp in self.variables)
                {
                    var vi       = (LocalVariableInfo)kvp.Value;
                    var register = vi.Representation as LowRegister;
                    if (register != null)
                    {
                        var index = register.Index;
                        if (index < 4)
                        {
                            variableNamesToMigrate[index].Add(kvp);
                        }
                    }
                }
            }
            registerMaskToSpill = 0;
            stackConsumption    = 0;
            var f = FuncBuilder.Instance;

            for (var i = 3; i >= 0; --i)
            {
                foreach (DictionaryEntry de in variableNamesToMigrate[i])
                {
                    var variable = (IReference)de.Key;
                    var vi       = (LocalVariableInfo)de.Value;
                    stackConsumption -= 4;
                    var newVariableInfo = new LocalVariableInfo(vi.Name, new StackWordRelativeToZero(f.StackPointer + stackConsumption));
                    outermost.CheckedAdd(variable, newVariableInfo);
                    registerMaskToSpill |= (1 << i);
                }
            }
        }
Esempio n. 3
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);
              }
        }
Esempio n. 4
0
 public void Add(IReference variable, LocalVariableInfo localVariableInfo)
 {
     variables.CheckedAdd(variable, localVariableInfo);
 }
Esempio n. 5
0
 public void Add(IReference variable, LocalVariableInfo localVariableInfo)
 {
     variables.CheckedAdd(variable, localVariableInfo);
 }