public BuildPhi ( |
||
type | ||
name | string | |
incoming | ||
return |
public override Value CodeGen(IRBuilder builder) { Value startV = this.Start.CodeGen(builder); if(startV.IsNull) return startV; BasicBlock startBlock = builder.GetInsertPoint(); Function func = startBlock.GetParent(); BasicBlock loopBB = func.AppendBasicBlock("loop"); builder.BuildBr(loopBB); builder.SetInsertPoint(loopBB); Value variable = builder.BuildPhi(TypeRef.CreateDouble(), this.VarName, new PhiIncoming(startV, startBlock)); /* Within the loop, the variable is defined equal to the PHI node. If it * shadows an existing variable, we have to restore it, so save it * now. */ Value oldVal = Value.Null; CodeGenManager.NamedValues.TryGetValue(this.VarName, out oldVal); CodeGenManager.NamedValues[this.VarName] = variable; /* Emit the body of the loop. This, like any other expr, can change the * current BB. Note that we ignore the value computed by the body, but * don't allow an error */ Body.CodeGen(builder); // Emit the step value; Value stepV = Value.Null; if(this.Step != null) stepV = this.Step.CodeGen(builder); else stepV = Value.CreateConstDouble(1); Value nextVar = builder.BuildFAdd(variable, stepV, "nextvar"); // Compute the end condition Value endCond = this.End.CodeGen(builder); endCond = builder.BuildFCmp(endCond, LLVMRealPredicate.RealONE, Value.CreateConstDouble(0), "loopcond"); BasicBlock loopEndBB = builder.GetInsertPoint(); BasicBlock afterBB = func.AppendBasicBlock("afterloop"); builder.BuildCondBr(endCond, loopBB, afterBB); builder.SetInsertPoint(afterBB); builder.AddPhiIncoming(variable, nextVar, loopEndBB); if(!oldVal.IsNull) CodeGenManager.NamedValues[this.VarName] = oldVal; return Value.CreateConstDouble(0); }
public override Value CodeGen(IRBuilder builder) { Value condV = this.Cond.CodeGen(builder); if(condV.IsNull) return condV; condV = builder.BuildFCmp(condV, LLVMRealPredicate.RealONE, Value.CreateConstDouble(0)); BasicBlock startBlock = builder.GetInsertPoint(); Function func = startBlock.GetParent(); BasicBlock thenBB = func.AppendBasicBlock("then"); builder.SetInsertPoint(thenBB); Value thenV = this.Then.CodeGen(builder); if(thenV.IsNull) return thenV; /* Codegen of 'then' can change the current block, update then_bb for the * phi. We create a new name because one is used for the phi node, and the * other is used for the conditional branch. */ BasicBlock newThenBB = builder.GetInsertPoint(); // Emit else block BasicBlock elseBB = func.AppendBasicBlock("else"); func.AppendBasicBlock(elseBB); builder.SetInsertPoint(elseBB); Value elseV = this.Else.CodeGen(builder); if(elseV.IsNull) return elseV; // Codegen of 'Else' can change the current block, update ElseBB for the PHI. BasicBlock newElseBB = builder.GetInsertPoint(); // Emit merge block BasicBlock mergeBB = func.AppendBasicBlock("ifcont"); func.AppendBasicBlock(mergeBB); builder.SetInsertPoint(mergeBB); PhiIncoming incoming = new PhiIncoming(); incoming.Add(thenV, thenBB); incoming.Add(elseV, elseBB); Value phi = builder.BuildPhi(TypeRef.CreateDouble(), "iftmp", incoming); builder.SetInsertPoint(startBlock); builder.BuildCondBr(condV, thenBB, elseBB); builder.SetInsertPoint(thenBB); builder.BuildBr(mergeBB); builder.SetInsertPoint(elseBB); builder.BuildBr(mergeBB); builder.SetInsertPoint(mergeBB); return phi; }