/// <summary> /// Pops an element from the stack. /// </summary> /// <returns>The popped element.</returns> public StackElement Pop() { int index = mStack.Count - 1; StackElement top = mStack[index]; mStack.RemoveAt(index); mPhi.RemoveAt(index); return(top); }
/// <summary> /// Creates a new StackElement from an existing one. /// </summary> /// <param name="other">The existing one.</param> public StackElement(StackElement other) { Type = other.Type; ILType = other.ILType; Value = other.Value; }
/// <summary> /// Pushes an element on the stack. /// </summary> /// <param name="element">The element.</param> public void Push(StackElement element) { mPhi.Add(0); mStack.Add(element); }
/// <summary> /// Insert an element at start. /// </summary> /// <param name="element">The element.</param> public void InsertAtStart(StackElement element) { mStack.Insert(0, element); mPhi.Insert(0, 0); }
/// <summary> /// Update stack with phi nodes. /// </summary> /// <param name="builder">The builder.</param> /// <param name="srcStack">The source stack.</param> /// <param name="oldBlock">The old block.</param> /// <param name="newBlock">The new block.</param> /// <param name="refers">The amount of references to the new block.</param> public void Update(BuilderRef builder, ILStack srcStack, BasicBlockRef oldBlock, BasicBlockRef newBlock, int refers) { // If there's only one reference to this branch, there's only one way to get here. // That means the stack elements only depend on one other branch, therefor we don't need to build phi nodes. if (refers == 1) { for (int i = 0; i < srcStack.Count; i++) { Push(new StackElement(srcStack[i])); } } // Multiple references. else { // We got three possible cases here: // 1. #deststack = #srcstack => build phi nodes for every element. // 2. #deststack > #srcstack => build phi nodes for the top elements of the srcstack. // 3. #deststack < #srcstack => build phi nodes for the top elements and put the rest on the stack as independent values. int dstOffset = Count - 1; int difference = 0; // Case 3. if (Count < srcStack.Count) { difference = srcStack.Count - Count; // Push independent values on the stack start. for (int i = difference - 1; i >= 0; i--) { InsertAtStart(srcStack[i]); oldBlocks.Insert(0, oldBlock); } } difference += srcStack.GetDependentCount(); for (int i = srcStack.Count - 1; i >= difference; i--) { // Not a phi node yet. Transform to a phi node. if (mPhi[dstOffset] == 0) { StackElement element = mStack[dstOffset]; ValueRef oldValue = element.Value; LLVM.PositionBuilderAtEnd(builder, newBlock); element.Value = LLVM.BuildPhi(builder, element.Type, "phi"); LLVM.PositionBuilderAtEnd(builder, oldBlock); LLVM.AddIncoming(element.Value, new ValueRef[] { oldValue }, new BasicBlockRef[] { oldBlocks[i] }); } ValueRef phi = mStack[dstOffset].Value; // We might need to cast the incoming value to the phi type. // This is because it is possible that an integer type of a smaller type is pushed on the stack. // by IL, for example in "branch on condition". TypeRef phiType = LLVM.TypeOf(phi); ValueRef incomingValue = srcStack[i].Value; // Cast if not the same type. if (srcStack[i].Type != phiType) { CastHelper.HelpIntAndPtrCast(builder, ref incomingValue, ref srcStack[i].Type, phiType, "phicast"); } // Add new incoming from source stack. LLVM.AddIncoming(phi, new ValueRef[] { incomingValue }, new BasicBlockRef[] { oldBlock }); mPhi[dstOffset]++; dstOffset--; } } }