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"); }
static void Main(string[] args) { var context = new LLVMContext(); var module = new Module("NoName", context); var builder = new IRBuilder(context); var t = builder.getInt32Ty(); var funcType = FunctionType.get(t, false); var main = Function.Create(funcType, GlobalValue.LinkageTypes.ExternalLinkage, "main", module); var entry = BasicBlock.Create(context, "entrypoint", main); builder.SetInsertPoint(entry); var hello = builder.CreateGlobalStringPtr("Hello, World!"); var putsType = FunctionType.get(builder.getInt32Ty(), new[] { builder.getInt8Ty().getPointerTo(0) }, false); var putsFunc = module.getOrInsertFunction("puts", putsType); builder.CreateCall(putsFunc, hello); var variable = builder.CreateAlloca(t); var val = ConstantInt.get(t, 127); builder.CreateStore(val, variable); builder.CreateRetVoid(); var pm = new PassManager(); var os = new raw_fd_ostream("code.ll"); pm.add(Passes.createPrintModulePass(os)); pm.run(module); os.close(); Console.ReadKey(); }
public override Value CodeGen(IRBuilder builder) { Value value = Value.Null; if(!CodeGenManager.NamedValues.TryGetValue(this.Name, out value)) CodeGenManager.ErrorOutput.WriteLine("Unknown variable name."); return value; }
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; }
/// <summary> /// Generates the BrainF runtime environment. /// </summary> private void GenerateHeader() { this.module = new Module(this.context, "BrainF"); // === Function prototypes ========================================= Function memsetFunction = Intrinsic.GetDecleration(this.module, IntrinsicType.memset, Type.GetInteger8PointerType(this.context), Type.GetInteger32Type(this.context)); // declare i32 @getchar() this.getcharFunction = (Function)this.module.GetOrInsertFunction("getchar", new FunctionType(Type.GetInteger32Type(this.context))); // declare i32 @putchar(i32) this.putcharFunction = (Function)this.module.GetOrInsertFunction("putchar", new FunctionType(Type.GetInteger32Type(this.context), Type.GetInteger32Type(this.context))); // === Function header ============================================= // define void @brainf() this.brainfFunction = (Function)this.module.GetOrInsertFunction("brainf", new FunctionType(Type.GetVoidType(this.context))); this.builder = new IRBuilder(new BasicBlock( this.context, this.brainfFunction, "brainf")); // %arr = malloc i8, i32 %d Constant valMemory = new Constant(this.context, 32, this.totalMemory); BasicBlock bb = this.builder.GetInsertBlock(); Type intType = Type.GetInteger32Type(this.context); Type byteType = Type.GetInteger8Type(this.context); Constant allocsize = new Constant(byteType); allocsize.TruncOrBitCast(intType); Instruction pointerArray = CallInstruction.CreateMalloc(bb, intType, byteType, allocsize, valMemory, "arr"); bb.PushBack(pointerArray); // call void @llvm.memset. CallInstruction memsetCall = this.builder.CreateCall( memsetFunction, pointerArray, new Constant(this.context, 8, 0), valMemory, new Constant(this.context, 32, 1), new Constant(this.context, 1, 0)); memsetCall.TailCall = false; // this.currentHead = this.builder.CreateGEP( pointerArray, new Constant(this.context, 32, this.totalMemory / 2), "head"); // Footer this.endBlock = new BasicBlock(this.context, this.brainfFunction, "brainf"); this.endBlock.PushBack(CallInstruction.CreateFree(pointerArray, this.endBlock)); ReturnInstruction.Create(this.context, this.endBlock); }
public override Value CodeGen(IRBuilder builder) { return Value.CreateConstReal(TypeRef.CreateDouble(), this.Val); }
public Function CodeGen(IRBuilder builder) { CodeGenManager.NamedValues.Clear(); Function func = this.Proto.CodeGen(builder); if(func == null) return null; // Create a new basic block to start insertion into. BasicBlock bb = func.AppendBasicBlock("entry"); builder.SetInsertPoint(bb); Value retVal = Body.CodeGen(builder); if(!retVal.IsNull) { builder.BuildReturn(retVal); // Validate the generated code, checking for consistency. func.Validate(LLVMVerifierFailureAction.PrintMessageAction); return func; } // Error reading body, remove function. func.Delete(); return null; }
public Function CodeGen(IRBuilder builder) { List<TypeRef> args = new List<TypeRef>(); this.Args.ForEach(a => args.Add(TypeRef.CreateDouble())); Function func = new Function(CodeGenManager.Module, this.Name, TypeRef.CreateDouble(), args.ToArray()); func.SetLinkage(LLVMLinkage.ExternalLinkage); // If F conflicted, there was already something named 'Name'. If it has a // body, don't allow redefinition or reextern. if(func.IsDuplicate()) { // Delete the one we just made and get the existing one. func.Delete(); func = CodeGenManager.Module.GetFunction(this.Name); // If F already has a body, reject this. if(func.HasBody) { CodeGenManager.ErrorOutput.WriteLine("redefinition of function."); return null; } // If F took a different number of args, reject. if(func.ArgCount != this.Args.Count) { CodeGenManager.ErrorOutput.WriteLine("redefinition of function with different # args."); return null; } } // Set names for all arguments. for(int i = 0; i < func.ArgCount; ++i) { Value val = func.GetParameter((uint)i); val.Name = this.Args[i]; CodeGenManager.NamedValues[this.Args[i]] = val; } return func; }
public abstract Value CodeGen(IRBuilder builder);
public override Value CodeGen(IRBuilder builder) { // Look up the name in the global module table. Function func = CodeGenManager.Module.GetFunction(this.Callee); if(func == null) { CodeGenManager.ErrorOutput.WriteLine("Unknown function referenced."); return Value.Null; } // If argument mismatch error. if(func.ArgCount != Args.Count) { CodeGenManager.ErrorOutput.WriteLine("Incorrect # arguments passed."); return Value.Null; } List<Value> args = new List<Value>(); foreach(var arg in this.Args) { Value val = arg.CodeGen(builder); if(val.IsNull) return Value.Null; args.Add(val); } return builder.BuildCall(func, args.ToArray()); }
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; }
public Function CodeGen(IRBuilder builder, PassManager passManager) { CodeGenManager.NamedValues.Clear(); Function func = this.Proto.CodeGen(builder); if(func == null) return null; // If this is an operator, install it. if(this.Proto.IsBinaryOp) CodeGenManager.BinopPrecendence[Proto.OperatorName] = Proto.Precedence; // Create a new basic block to start insertion into. BasicBlock bb = func.AppendBasicBlock("entry"); builder.SetInsertPoint(bb); Proto.CreateArgAllocas(func, builder); Value retVal = Body.CodeGen(builder); if(!retVal.IsNull) { builder.BuildReturn(retVal); // Validate the generated code, checking for consistency. func.Validate(LLVMVerifierFailureAction.PrintMessageAction); // Optimize the function. passManager.Run(func); return func; } // Error reading body, remove function. func.Delete(); return null; }
public void CreateArgAllocas(Function function, IRBuilder builder) { for(int i = 0; i < function.ArgCount; ++i) { Value alloca = builder.BuildEntryBlockAlloca(function, TypeRef.CreateDouble(), this.Args[i]); builder.BuildStore(function.GetParameter((uint)i), alloca); CodeGenManager.NamedValues[this.Args[i]] = alloca; } }
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); }
public override Value CodeGen(IRBuilder builder) { Value operandV = this.Operand.CodeGen(builder); if(operandV.IsNull) return operandV; Function f = CodeGenManager.Module.GetFunction("unary" + this.Op); Debug.Assert(f != null); Value[] ops = new Value[] { operandV }; return builder.BuildCall(f, ops, "unop"); }