public BuildFAdd ( |
||
lhs | ||
rhs | ||
varName | string | |
리턴 |
public override Value CodeGen(IRBuilder builder) { Value l = this.LHS.CodeGen(builder); Value r = this.RHS.CodeGen(builder); if(l.IsNull || r.IsNull) return Value.Null; switch(this.Op) { case '+': return builder.BuildFAdd(l, r); case '-': return builder.BuildFSub(l, r); case '*': return builder.BuildFMul(l, r); case '<': // Convert bool 0/1 to double 0.0 or 1.0 return builder.BuildFCmpAndPromote(l, LLVMRealPredicate.RealULT, r, TypeRef.CreateDouble()); } // If it wasn't a builtin binary operator, it must be a user defined one. Emit // a call to it. Function f = CodeGenManager.Module.GetFunction("binary" + this.Op); Debug.Assert(f != null); Value[] ops = new Value[] { l, r }; return builder.BuildCall(f, ops, "binop"); }
public override Value CodeGen(IRBuilder builder) { Value l = this.LHS.CodeGen(builder); Value r = this.RHS.CodeGen(builder); if(l.IsNull || r.IsNull) return Value.Null; switch(this.Op) { case '+': return builder.BuildFAdd(l, r); case '-': return builder.BuildFSub(l, r); case '*': return builder.BuildFMul(l, r); case '<': // Convert bool 0/1 to double 0.0 or 1.0 return builder.BuildFCmpAndPromote(l, LLVMRealPredicate.RealULT, r, TypeRef.CreateDouble()); } CodeGenManager.ErrorOutput.WriteLine("Unknown binary operator."); return Value.Null; }
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) { // Output this as: // var = alloca double // ... // start = startexpr // store start -> var // goto loop // loop: // ... // bodyexpr // ... // loopend: // step = stepexpr // endcond = endexpr // // curvar = load var // nextvar = curvar + step // store nextvar -> var // br endcond, loop, endloop // outloop: BasicBlock startBlock = builder.GetInsertPoint(); Function func = startBlock.GetParent(); Value alloca = builder.BuildEntryBlockAlloca(func, TypeRef.CreateDouble(), this.VarName); Value startV = this.Start.CodeGen(builder); if(startV.IsNull) return startV; builder.BuildStore(startV, alloca); BasicBlock loopBB = func.AppendBasicBlock("loop"); builder.BuildBr(loopBB); builder.SetInsertPoint(loopBB); /* 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] = alloca; /* 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); // Compute the end condition Value endCond = this.End.CodeGen(builder); endCond = builder.BuildFCmp(endCond, LLVMRealPredicate.RealONE, Value.CreateConstDouble(0), "loopcond"); Value curvar = builder.BuildLoad(alloca, VarName); Value nextVar = builder.BuildFAdd(curvar, stepV, "nextvar"); builder.BuildStore(nextVar, alloca); BasicBlock loopEndBB = builder.GetInsertPoint(); BasicBlock afterBB = func.AppendBasicBlock("afterloop"); builder.BuildCondBr(endCond, loopBB, afterBB); builder.SetInsertPoint(afterBB); if(!oldVal.IsNull) CodeGenManager.NamedValues[this.VarName] = oldVal; else CodeGenManager.NamedValues.Remove(this.VarName); return Value.CreateConstDouble(0); }