/*-------------------- Constructors ---------------------------------*/ /// <summary> /// Create a new finally clause /// </summary> /// <param name="finallyStart">start of finally code</param> /// <param name="finallyEnd">end of finally code</param> public Finally(CILLabel finallyStart, CILLabel finallyEnd) : base(finallyStart,finallyEnd) { }
internal void brfalse(CILLabel label) { buffer.Branch(BranchOp.brfalse, label); }
internal static CILLabel GetLabel(ArrayList labs, uint targetOffset) { CILLabel lab; int i=0; while ((i < labs.Count) && (((CILLabel)labs[i]).offset < targetOffset)) i++; if (i < labs.Count) { if (((CILLabel)labs[i]).offset == targetOffset) // existing label lab = (CILLabel)labs[i]; else { lab = new CILLabel(targetOffset); labs.Insert(i,lab); } } else { lab = new CILLabel(targetOffset); labs.Add(lab); } return lab; }
/*-------------------- Constructors ---------------------------------*/ /// <summary> /// Create a new fault clause /// </summary> /// <param name="faultStart">start of the fault code</param> /// <param name="faultEnd">end of the fault code</param> public Fault(CILLabel faultStart, CILLabel faultEnd) : base(faultStart,faultEnd) { }
/// <summary> /// Add a label to the CIL instructions /// </summary> /// <param name="lab">the label to be added</param> public void CodeLabel(CILLabel lab) { if (lab.Buffer == null) { lab.Buffer = this; } else if (lab.Buffer != this) { throw new DescriptorException("Cannot add a label to two different code buffers"); } AddToBuffer(lab); }
/// <summary> /// Create a new label at this position in the code buffer /// </summary> /// <returns>the label at the current position</returns> public CILLabel NewCodedLabel() { CILLabel lab = new CILLabel(); lab.Buffer = this; AddToBuffer(lab); return lab; }
internal override void GenCode0(CodeGenContext context) { context.newLine(location); if (lhs is ARRAY_ACCESS) // for array access -> need to avoid recomputation of lhs index ((ARRAY_ACCESS)lhs).AssignOp(context, op, rhs); else if (lhs is CVAR && op == "||") { CILLabel alreadyDefined1 = new CILLabel(); CILLabel alreadyDefined2 = new CILLabel(); CILLabel alreadyDefined3 = new CILLabel(); Node lhsDefined = new DEFINED(lhs, location); lhsDefined.GenCode(context); context.brtrue(alreadyDefined1); lhs.Assign(context, rhs); context.br(alreadyDefined2); context.CodeLabel(alreadyDefined1); lhs.Assign(context, METHOD_CALL.Create(lhs, op, rhs, location)); context.CodeLabel(alreadyDefined2); } else lhs.Assign(context, METHOD_CALL.Create(lhs, op, rhs, location)); }
/*-------------------- Constructors ---------------------------------*/ /// <summary> /// Create a new catch clause /// </summary> /// <param name="except">the exception to be caught</param> /// <param name="handlerStart">start of the handler code</param> /// <param name="handlerEnd">end of the handler code</param> public Catch(Class except, CILLabel handlerStart, CILLabel handlerEnd) : base(handlerStart,handlerEnd) { exceptType = except; }
// ----------------------------------------------------------------- internal void CodeLabel(CILLabel label) { buffer.CodeLabel(label); }
internal void Goto(CILLabel label) { Clause top = Clause.None; if (blocks.Count > 0) top = blocks.Peek(); if (top == Clause.Try || top == Clause.Catch) leave(label); else if (top == Clause.Finally) endfinally(); else br(label); }
internal void bge(CILLabel label) { buffer.Branch(BranchOp.bge, label); }
internal void bne(CILLabel label) { buffer.Branch(BranchOp.bne_un, label); }
internal void brtrue(CILLabel label) { buffer.Branch(BranchOp.brtrue, label); }
public void SetDests(CILLabel[] dests) { cases = dests; }
////////////////////////////////////////////////////////////////////////// // Switch ////////////////////////////////////////////////////////////////////////// private void tableswitch() { int count = u2(); CILLabel[] labels = new CILLabel[count]; for (int i=0; i<count; ++i) labels[i] = jumps.add(u2()); code.Switch(labels); }
/*-------------------- Constructors ---------------------------------*/ /// <summary> /// Create a new try block /// </summary> /// <param name="start">start label for the try block</param> /// <param name="end">end label for the try block</param> public TryBlock(CILLabel start, CILLabel end) : base(start,end) { }
private void catchEnd() { PERWAPI.TryBlock lastTry = (PERWAPI.TryBlock)errBlocks.Pop(); if (dotnetErr != null) { // use a filter if we need to "dual-check" for native exception code.EndFilterBlock(filterStart, lastTry); dotnetErr = null; filterStart = null; } else { // this is the normal catch block code.EndCatchBlock(emitter.findType(exType) as PERWAPI.Class, lastTry); } }
/// <summary> /// Add a branch instruction /// </summary> /// <param name="inst">the branch instruction</param> /// <param name="lab">the label that is the target of the branch</param> public void Branch(BranchOp inst, CILLabel lab) { Debug.Assert(lab != null); AddToBuffer(new BranchInstr(inst,lab)); }
private void catchErrStart() { exType = "System.Exception"; for (int i=0; i<tryJump.Length; i++) if (startPos == tryJump[i]) { FTypeRef typeRef = pod.typeRef(tryErr[i]); dotnetErr = Fan.Sys.Err.fanToDotnet(typeRef.nname()); if (!typeRef.isErr()) exType = typeRef.nname() + "/Val"; break; } // close try block errBlocks.Push(getLastTryBlock()); // use a filter if we need to "dual-check" for native exception if (dotnetErr != null) { code.CodeLabel(filterStart = code.NewLabel()); CILLabel match = code.NewLabel(); CILLabel endfilter = code.NewLabel(); // check native type first code.Inst(Op.dup); code.TypeInst(TypeOp.isinst, emitter.findType(dotnetErr)); code.Inst(Op.ldnull); code.Branch(BranchOp.bne_un_s, match); // then check Fantom type code.Inst(Op.dup); code.TypeInst(TypeOp.isinst, emitter.findType(exType)); code.Inst(Op.ldnull); code.Branch(BranchOp.bne_un_s, match); // no match code.Inst(Op.pop); // pop exception off stack code.IntInst(IntOp.ldc_i4, 0); code.Branch(BranchOp.br_s, endfilter); // match code.CodeLabel(match); code.Inst(Op.pop); // pop exception off stack code.IntInst(IntOp.ldc_i4, 1); // endfilter code.CodeLabel(endfilter); code.Inst(Op.endfilter); } // start handler block code.StartBlock(); // there is already a System.Exception on the stack, but // we need to map into a sys::Err type if (parent.ErrMake == null) parent.ErrMake = emitter.findMethod("Fan.Sys.Err", "make", new string[] { "System.Exception" }, "Fan.Sys.Err"); code.MethInst(MethodOp.call, parent.ErrMake); cast(); }
/// <summary> /// Mark this position as the end of the last started block and /// make it a filter block. This filter block is associated with the /// specified try block. The format is: /// filterLab: ... /// ... /// filterHandler : ... /// ... /// </summary> /// <param name="filterLab">the label where the filter code is</param> /// <param name="tryBlock">the try block associated with this filter block</param> public void EndFilterBlock(CILLabel filterLab, TryBlock tryBlock) { Filter filBlock = new Filter(filterLab,(CILLabel)blockStack.Pop(),NewCodedLabel()); tryBlock.AddHandler(filBlock); }
/*-------------------- Constructors ---------------------------------*/ public BranchInstr(BranchOp inst, CILLabel dst) : base((uint)inst) { dest = dst; shortVer = (inst < BranchOp.br) || (inst == BranchOp.leave_s); if (shortVer) size++; else size += 4; }
/// <summary> /// Add a switch instruction /// </summary> /// <param name="labs">the target labels for the switch</param> public void Switch(CILLabel[] labs) { AddToBuffer(new SwitchInstr(labs)); }
public void SetDest(CILLabel lab) { dest = lab; }
/*-------------------- Constructors ---------------------------------*/ public CodeBlock(CILLabel start, CILLabel end) { this.start = start; this.end = end; }
internal void MakeTargetLabel(ArrayList labs) { uint targetOffset = (uint)(offset + size + target); dest = CILInstructions.GetLabel(labs,targetOffset); }
/*-------------------- Constructors ---------------------------------*/ /// <summary> /// Create a new filter clause /// </summary> /// <param name="filterLabel">the label where the filter code starts</param> /// <param name="handlerStart">the start of the handler code</param> /// <param name="handlerEnd">the end of the handler code</param> public Filter(CILLabel filterLabel, CILLabel handlerStart, CILLabel handlerEnd) : base(handlerStart,handlerEnd) { this.filterLabel = filterLabel; }
/*-------------------- Constructors ---------------------------------*/ public SwitchInstr(CILLabel[] dsts) : base(0x45) { cases = dsts; if (cases != null) numCases = (uint)cases.Length; size += 4 + (numCases * 4); }
/*-------------------- Constructors ---------------------------------*/ public HandlerBlock(CILLabel start, CILLabel end) : base(start,end) { }
internal void leave(CILLabel label) { buffer.Branch(BranchOp.leave, label); }