Пример #1
0
        private FuncBuilder(Namespace ns, FuncBuilderHints builderHints, ActionOnFuncBuilder action)
        {
            Instance=this;
              this.namespaceAndNextIndex=new NamespaceAndNextIndex(ns, 0);
              this.BuilderHints=builderHints;

              var pt=builderHints.PassTraits;
              this.Scratch0=pt.Scratch0;
              this.Scratch1=pt.Scratch1;

              var emitter=CodeGenerator.Emitter;

              var passTraits=BuilderHints.PassTraits;
              var preserveLr=passTraits.PreserveLinkRegister;
              var regsToPreserve=passTraits.RegisterMask&0xf0;
              emitter.EmitIfNecessary(Format14OpCode.PUSH, preserveLr, (byte)regsToPreserve);
              if(preserveLr) {
            StackPointer+=-4;
              }
              while(regsToPreserve!=0) {
            StackPointer+=-4;
            regsToPreserve&=(regsToPreserve-1);
              }
              this.EndOfVariableRegion=StackPointer;

              var avo=passTraits.AllocatedVariableOffset;
              emitter.EmitIfNecessary(Format13OpCode.ADDSP, avo);
              StackPointer+=avo;

              this.TheExitLabel=DeclareLabel("leave");

              action(this);

              TheExitLabel.Mark();
              StackPointer+=-avo;
              emitter.EmitIfNecessary(Format13OpCode.ADDSP, -avo);

              regsToPreserve=passTraits.RegisterMask&0xf0;
              emitter.EmitIfNecessary(Format14OpCode.POP, false, (byte)regsToPreserve);

              Register bxRegister;
              if(passTraits.PreserveLinkRegister) {
            bxRegister=new LowRegister(1);
            emitter.EmitIfNecessary(Format14OpCode.POP, false, 1<<1);
              } else {
            bxRegister=Register.LR;
              }
              emitter.Emit(Format5OpCode.BX, null, bxRegister);

              if(inflightUtterances.Count>0) {
            var allUtterances="";
            foreach(string utterance in inflightUtterances.Values) {
              if(allUtterances.Length>0) {
            allUtterances+=",";
              }
              allUtterances+=utterance;
            }
            throw new Exception(allUtterances);
              }
        }
Пример #2
0
        public override LowRegister ToRegister(LowRegister storageReg)
        {
            var emitter=CodeGenerator.Emitter;

              var address=StorageLabel.GetLabelAddressBestEffort();
              emitter.Emit(Format6OpCode.LDR, storageReg, address);
              return storageReg;
        }
Пример #3
0
 public static LowRegister ToRegister(this IReadable self, LowRegister writeableReg)
 {
     //special case for IntConstant
       var ic=self as IntConstant;
       return !ReferenceEquals(ic, null)
     ? ic.ToRegisterHelper(writeableReg)
     : ((IReference)self).GetRepresentation().ToRegister(writeableReg);
 }
Пример #4
0
 public static RegisterOrByte ToRegisterOrUnsignedConstant(this IReadable self, int exclusiveUpperBound, LowRegister writeableReg)
 {
     //special case for IntConstant
       var ic=self as IntConstant;
       return !ReferenceEquals(ic, null)
     ? ic.ToRegisterOrUnsignedConstantHelper(writeableReg, exclusiveUpperBound)
     : RegisterOrByte.Create(((IReference)self).GetRepresentation().ToRegister(writeableReg));
 }
Пример #5
0
        public static LowRegister ToRegister(this IReadable self, LowRegister writeableReg)
        {
            //special case for IntConstant
            var ic = self as IntConstant;

            return(!ReferenceEquals(ic, null)
        ? ic.ToRegisterHelper(writeableReg)
        : ((IReference)self).GetRepresentation().ToRegister(writeableReg));
        }
Пример #6
0
        public override LowRegister ToRegister(LowRegister storageReg)
        {
            var emitter = CodeGenerator.Emitter;

            var address = StorageLabel.GetLabelAddressBestEffort();

            emitter.Emit(Format6OpCode.LDR, storageReg, address);
            return(storageReg);
        }
 private LowRegister AllocateRegisterIfPossible(LowRegister register)
 {
     if(numberOfRegistersLeft!=0) {
     if(register!=null && TryAllocate(register.Index)) {
       return register;
     }
     for(var i=0; i<32; ++i) {
       if(TryAllocate(i)) {
     return new LowRegister(i);
       }
     }
       }
       return null;
 }
Пример #8
0
 public LowRegister ToRegisterHelper(LowRegister writeableReg)
 {
     var emitter=CodeGenerator.Emitter;
       if(value>=0 && value<256) {
     emitter.Emit(Format3OpCode.MOV, writeableReg, (byte)value);
       } else if(value<0 && value>-256) {
     emitter.Emit(Format3OpCode.MOV, writeableReg, 0);
     emitter.Emit(Format3OpCode.SUB, writeableReg, (byte)(-value));
       } else {
     var label=CodeGenerator.Instance.AllocateInlineConstant(value);
     var address=label.GetLabelAddressBestEffort();
     emitter.Emit(Format6OpCode.LDR, writeableReg, address);
       }
       return writeableReg;
 }
Пример #9
0
   public PassTraits(bool preserveLinkRegister, LowRegister scratch0, LowRegister scratch1, bool scratch0Used, bool scratch1Used,
 int registerMaskExcludingScratch, int allocatedVariableOffset)
   {
       PreserveLinkRegister=preserveLinkRegister;
         Scratch0=scratch0;
         Scratch1=scratch1;
         Scratch0Used=scratch0Used;
         Scratch1Used=scratch1Used;
         RegisterMask=registerMaskExcludingScratch;
         if(Scratch0Used) {
       RegisterMask|=1<<(Scratch0.Index);
         }
         if(Scratch1Used) {
       RegisterMask|=1<<(Scratch1.Index);
         }
         AllocatedVariableOffset=allocatedVariableOffset;
   }
Пример #10
0
 public void Emit(Format6OpCode opCode, LowRegister rd, int target)
 {
     var offset=(uint)(target-((CurrentAddress+4)&~2));
       CheckRange(target, 0, 1023, 3);
       var fluentComment="LDR ".MyConcat(rd, ",[PC, #0x", ((short)target).ToHex(), "]");
       var offsetBits=offset>>2;
       EmitHelper(rd, 6, fluentComment, 9, 5, rd.Index, 3, (int)offsetBits, 8);
 }
Пример #11
0
 public void Emit(Format8OpCode opCode, LowRegister rsd, LowRegister rb, LowRegister ro)
 {
     var fluentComment=opCode.ToHumanReadable().MyConcat(" ", rsd, ",[", rb, ",", ro, "]");
       EmitHelper(rsd, 7, fluentComment, 5, 4, (int)opCode, 2, 1, 1, ro.Index, 3, rb.Index, 3, rsd.Index, 3);
 }
Пример #12
0
 private void EmitBXInstructions()
 {
     for(var registerIndex=0; registerIndex<registerIndexToLabelWhereItsBXInstructionIs.Length; ++registerIndex) {
     var label=registerIndexToLabelWhereItsBXInstructionIs[registerIndex];
     if(label!=null) {
       label.Mark();
       var register=new LowRegister(registerIndex);
       emitter.Emit(Format5OpCode.BX, null, register);
     }
       }
 }
Пример #13
0
 public abstract LowRegister ToRegister(LowRegister proposal);
Пример #14
0
   private void Format2Helper(Format2OpCode opCode, int immediateBit,
 LowRegister rd, LowRegister rs, int rnBits, string suffix)
   {
       var fluentComment=opCode.ToHumanReadable().MyConcat(" ", rd, ",", rs, ",", suffix);
         EmitHelper(rd, 2, fluentComment, 3, 5, immediateBit, 1, (int)opCode, 1, rnBits, 3, rs.Index, 3, rd.Index, 3);
   }
Пример #15
0
        public static RegisterOrByte ToRegisterOrUnsignedConstant(this IReadable self, int exclusiveUpperBound, LowRegister writeableReg)
        {
            //special case for IntConstant
            var ic = self as IntConstant;

            return(!ReferenceEquals(ic, null)
        ? ic.ToRegisterOrUnsignedConstantHelper(writeableReg, exclusiveUpperBound)
        : RegisterOrByte.Create(((IReference)self).GetRepresentation().ToRegister(writeableReg)));
        }
Пример #16
0
 public void Emit(Format3OpCode opCode, LowRegister rd, byte value)
 {
     var fluentComment=opCode.ToHumanReadable().MyConcat(" ", rd, ",#", value);
       EmitHelper(rd, 3, fluentComment, 1, 3, (int)opCode, 2, rd.Index, 3, value, 8);
 }
Пример #17
0
 public void Emit(Format12OpCode opCode, LowRegister rd, int target)
 {
     var offset=target-((CurrentAddress+4)&~2);
       CheckRange(offset, 0, 1023, 3);
       var fluentComment=opCode.ToHumanReadable().MyConcat(" ", rd, ",#0x", ((short)target).ToHex());
       var offsetBits=(offset>>2)&0xff;
       EmitHelper(rd, 12, fluentComment, 10, 4, (int)opCode, 1, rd.Index, 3, offsetBits, 8);
 }
Пример #18
0
 public static RegisterOrByte ToRegisterOrUint5(this IReadable self, LowRegister writeableReg)
 {
     return(self.ToRegisterOrUnsignedConstant(32, writeableReg));
 }
Пример #19
0
 public void Emit(Format2OpCode opCode, LowRegister rd, LowRegister rs, LowRegister rn)
 {
     Format2Helper(opCode, 0, rd, rs, rn.Index, rn.ToString());
 }
Пример #20
0
 public override LowRegister ToRegister(LowRegister proposal)
 {
     throw new NotImplementedException();
 }
Пример #21
0
 public override LowRegister ToRegister(LowRegister proposal)
 {
     return(this);
 }
Пример #22
0
 public override LowRegister ToRegister(LowRegister proposal)
 {
     CodeGenerator.Emitter.Emit(Format11OpCode.LDR, proposal, (uint)CalculateOffset());
       return proposal;
 }
Пример #23
0
 public void Emit(Format9OpCode opCode, LowRegister rsd, LowRegister rb, byte offset)
 {
     CheckRange(offset, 0, 31);
       var multiplier=(opCode==Format9OpCode.LDR || opCode==Format9OpCode.STR) ? "*4" : "";
       var fluentComment=opCode.ToHumanReadable().MyConcat(" ", rsd, ",[", rb, ",#", offset+multiplier, "]");
       EmitHelper(rsd, 9, fluentComment, 3, 3, (int)opCode, 2, offset, 5, rb.Index, 3, rsd.Index, 3);
 }
Пример #24
0
        public FuncBuilderHints RunOptimizer(bool scratch0Used, bool scratch1Used, out bool runAgain)
        {
            var liveLocalNonParameterVariableNames=new Hashtable();
              var usedRegisterMask=0;
              foreach(TerminalName variableName in liveLocalVariableNames.Keys) {
            var rep=(Representation)pinnedVariables[variableName];
            if(rep==null) {
              liveLocalNonParameterVariableNames.Add(variableName, null);
            } else {
              var register=rep as Register;
              if(register!=null) {
            usedRegisterMask|=1<<register.Index;
              }
            }
              }
              var allocableRegisterMask=((1<<Traits.NumAllocableRegisters)-1)&~usedRegisterMask;

              var result=VariableAllocator.Run(liveLocalNonParameterVariableNames.Keys,
            allocableRegisterMask,
            BuilderHints.VariableNameToRepresentation);

              var allUsedExcludingScratch=usedRegisterMask|result.UsedRegisterMask;

              //The reason for this is that scratch0 and scratch1 must not interfere with the calling convention
              var startingPoint=externalMethodWasInvoked ? 4 : 0;
              LowRegister scratch0=null;
              for(var i=startingPoint; i<Traits.NumLowRegisters; ++i) {
            if((allUsedExcludingScratch&(1<<i))==0) {
              var register=new LowRegister(i);
              if(scratch0==null) {
            scratch0=register;
              } else {
            var pt=new PassTraits(this.externalMethodWasInvoked, scratch0, register,
              scratch0Used, scratch1Used, allUsedExcludingScratch, result.AllocatedVariableOffset);
            runAgain=result.RunAgain || !pt.EqualTo(BuilderHints.PassTraits);
            return BuilderHints.CloneSetValues(liveLocalVariableNames.AsReadOnlyDictionary(),
              result.VariableNameToRepresentation, pt);
              }
            }
              }
              throw new Exception("never");
        }
Пример #25
0
 public void Emit(Format11OpCode opCode, LowRegister rd, uint unsigned10BitOffset)
 {
     CheckRange((int)unsigned10BitOffset, 0, 1023, 3);
       var fluentComment=opCode.ToHumanReadable().MyConcat(" ", rd, ",[SP,#", unsigned10BitOffset, "]");
       var offsetBits=(unsigned10BitOffset>>2)&0xff;
       EmitHelper(rd, 11, fluentComment, 9, 4, (int)opCode, 1, rd.Index, 3, (int)offsetBits, 8);
 }
Пример #26
0
 public override LowRegister ToRegister(LowRegister proposal)
 {
     return this;
 }
Пример #27
0
 public void EmitLoadAddress(Format12OpCode opCode, LowRegister targetRegister, int target, bool thumbAdjustment)
 {
     var offset=target-((CurrentAddress+4)&~2);
       if(offset>=0) {
     Emit(opCode, targetRegister, target);
     if(thumbAdjustment) {
       Emit(Format3OpCode.ADD, targetRegister, 1);
     }
       } else {
     //While the Format12 instruction will clear the 1 bit of the PC, this code does not
     var remainder=-(target-(CurrentAddress+4));
     if(thumbAdjustment) {
       --remainder;
     }
     Emit(Format5OpCode.MOV, targetRegister, Register.PC);
     while(remainder!=0) {
       var amountToUse=Math.Min(remainder, 255);
       Emit(Format3OpCode.SUB, targetRegister, (byte)remainder);
       remainder-=amountToUse;
     }
       }
 }
Пример #28
0
 public override LowRegister ToRegister(LowRegister proposal)
 {
     throw new NotImplementedException();
 }
Пример #29
0
 public void Emit(Format1OpCode opCode, LowRegister rd, LowRegister rs, byte immediate)
 {
     CheckRange(immediate, 0, 31);
       var fluentComment=opCode.ToHumanReadable().MyConcat(" ", rd, ",", rs, ",#", immediate);
       EmitHelper(rd, 1, fluentComment, 0, 3, (int)opCode, 2, immediate, 5, rs.Index, 3, rd.Index, 3);
 }
Пример #30
0
        private static LowRegister ProposeRegisterForValue(IReadable valueResult, LowRegister baseReg, LowRegister offsetReg)
        {
            var f=FuncBuilder.Instance;
              var scratch0=f.Scratch0;

              if(baseReg.Index!=scratch0.Index) {
            return scratch0;
              }

              var scratch1=f.Scratch1;
              if(offsetReg.Index!=scratch1.Index) {
            return scratch1;
              }
              var reference=valueResult as IReference;
              if(reference!=null) {
            var lowRegister=reference.GetRepresentation() as LowRegister;
            if(lowRegister!=null) {
              return lowRegister;
            }
              }
              return null;
        }
Пример #31
0
 public void Emit(Format2OpCode opCode, LowRegister rd, LowRegister rs, byte immediate3Bit)
 {
     CheckRange(immediate3Bit, 0, 7);
       Format2Helper(opCode, 1, rd, rs, immediate3Bit, "#"+immediate3Bit);
 }
Пример #32
0
 public RegisterOrByte ToRegisterOrUnsignedConstantHelper(LowRegister writeable, int exclusiveUpperBound)
 {
     return value>=0 && value<exclusiveUpperBound
     ? RegisterOrByte.Create((byte)value)
     : RegisterOrByte.Create(ToRegisterHelper(writeable));
 }
Пример #33
0
 public void Emit(Format4OpCode opCode, LowRegister rd, LowRegister rs)
 {
     var fluentComment=opCode.ToHumanReadable().MyConcat(" ", rd, ",", rs);
       EmitHelper(rd, 4, fluentComment, 16, 6, (int)opCode, 4, rs.Index, 3, rd.Index, 3);
 }
Пример #34
0
 public abstract LowRegister ToRegister(LowRegister proposal);
Пример #35
0
 public static RegisterOrByte ToRegisterOrUint5(this IReadable self, LowRegister writeableReg)
 {
     return self.ToRegisterOrUnsignedConstant(32, writeableReg);
 }
Пример #36
0
 public Label LookupOrCreateBranchTo(LowRegister register)
 {
     var regIndex=register.Index;
       var label=registerIndexToLabelWhereItsBXInstructionIs[regIndex];
       if(label==null) {
     label=DeclareStaticLabel("bxTo"+register);
     registerIndexToLabelWhereItsBXInstructionIs[regIndex]=label;
       }
       return label;
 }
Пример #37
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);
              }
        }
Пример #38
0
 public override LowRegister ToRegister(LowRegister proposal)
 {
     CodeGenerator.Emitter.Emit(Format11OpCode.LDR, proposal, (uint)CalculateOffset());
     return(proposal);
 }