llvm::Value * Generator::visit(For & node) { VarDecl initial(node.variable, nullptr, node.initial); auto counter = initial.accept(this); // create the block. auto function = builder.GetInsertBlock()->getParent(); auto block = llvm::BasicBlock::Create(*context, "forloop", function); auto after = llvm::BasicBlock::Create(*context, "forcont"); auto condition = node.condition->accept(this); // fall to the block. builder.CreateCondBr(condition, block, after); builder.SetInsertPoint(block); createScope(); node.block->accept(this); popScope(); // increment the counter. auto variable = builder.CreateLoad(counter); auto result = builder.CreateAdd(variable, node.increment->accept(this), "counter"); builder.CreateStore(result, counter); // execute again or stop. condition = node.condition->accept(this); builder.CreateCondBr(condition, block, after); // insert the after block. function->getBasicBlockList().push_back(after); builder.SetInsertPoint(after); return nullptr; }
void BWhile::Compile(Compiler& compiler, const vector<ExprPtr>& args) { assert(args.size() == 2); auto& builder = compiler.builder; auto& ctx = compiler.module.getContext(); auto func = builder.GetInsertBlock()->getParent(); auto condBlock = llvm::BasicBlock::Create(ctx, "while", func); auto doBlock = llvm::BasicBlock::Create(ctx, "do", func); auto lastEndLoopBlock = compiler.endLoopBlock; compiler.endLoopBlock = llvm::BasicBlock::Create(ctx, "endwhile"); builder.CreateBr(condBlock); // while builder.SetInsertPoint(condBlock); compiler.Visit(args[0].get()); builder.CreateCondBr(compiler.result, doBlock, compiler.endLoopBlock); compiler.result = nullptr; // do builder.SetInsertPoint(doBlock); compiler.Visit(args[1].get()); compiler.result = nullptr; builder.CreateBr(condBlock); // endloop func->getBasicBlockList().push_back(compiler.endLoopBlock); builder.SetInsertPoint(compiler.endLoopBlock); compiler.endLoopBlock = lastEndLoopBlock; }
llvm::Value * Generator::visit(If & node) { auto condition = node.condition->accept(this); auto function = builder.GetInsertBlock()->getParent(); auto thenBlock = llvm::BasicBlock::Create(*context, "then", function); auto elseBlock = llvm::BasicBlock::Create(*context, "else"); auto mergeBlock = llvm::BasicBlock::Create(*context, "ifcont"); if (node.elseBlock) { builder.CreateCondBr(condition, thenBlock, elseBlock); } else { builder.CreateCondBr(condition, thenBlock, mergeBlock); } builder.SetInsertPoint(thenBlock); createScope(); node.thenBlock->accept(this); popScope(); thenBlock = builder.GetInsertBlock(); if (thenBlock->getTerminator() == nullptr) { builder.CreateBr(mergeBlock); } if (node.elseBlock) { function->getBasicBlockList().push_back(elseBlock); builder.SetInsertPoint(elseBlock); createScope(); node.elseBlock->accept(this); popScope(); builder.CreateBr(mergeBlock); } function->getBasicBlockList().push_back(mergeBlock); builder.SetInsertPoint(mergeBlock); return nullptr; }
void BIf::Compile(Compiler& compiler, const vector<ExprPtr>& args) { assert(args.size() >= 2 && args.size() % 2 == 0); const size_t nclauses = args.size() / 2; auto& builder = compiler.builder; auto& ctx = compiler.module.getContext(); auto func = builder.GetInsertBlock()->getParent(); llvm::AllocaInst* alloc = nullptr; if(args.size() > 2) alloc = builder.CreateAlloca(ToLLVM(*args[1]->value->type, ctx), nullptr, "iftmp"); auto endifBlock = llvm::BasicBlock::Create(ctx, "endif"); for(size_t i = 0; i < nclauses; i++) { auto thenBlock = llvm::BasicBlock::Create(ctx, "then", func); auto contBlock = (i < nclauses - 1) ? llvm::BasicBlock::Create(ctx, "else", func) : endifBlock; // if compiler.Visit(args[i * 2].get()); compiler.result = compiler.Load(compiler.result); builder.CreateCondBr(compiler.result, thenBlock, contBlock); compiler.result = nullptr; // then builder.SetInsertPoint(thenBlock); compiler.Visit(args[i * 2 + 1].get()); if(alloc) builder.CreateStore(compiler.Load(compiler.result), alloc); compiler.result = nullptr; builder.CreateBr(endifBlock); // else or endif builder.SetInsertPoint(contBlock); } func->getBasicBlockList().push_back(endifBlock); if(alloc) compiler.result = builder.CreateLoad(alloc); }
llvm::Value * ForGen::emit(VflModule & module, ForAST & node) { VarDeclAST initial(node.getVariable(), nullptr, node.getInitial()); auto counter = initial.accept(demux); // create the block. auto function = module.getBuilder().GetInsertBlock()->getParent(); auto block = llvm::BasicBlock::Create(llvm::getGlobalContext(), "forloop", function); auto after = llvm::BasicBlock::Create(llvm::getGlobalContext(), "forcont"); auto condition = module.loadIfPtr(demux, node.getCondition()); // fall to the block. module.getBuilder().CreateCondBr(condition, block, after); module.getBuilder().SetInsertPoint(block); module.createScope(); node.getBlock()->accept(demux); module.popScope(); // increment the counter. auto variable = module.getBuilder().CreateLoad(counter); auto result = module.getBuilder().CreateAdd(variable, module.loadIfPtr(demux, node.getIncrement()), "counter"); module.getBuilder().CreateStore(result, counter); // execute again or stop. condition = node.getCondition()->accept(demux); module.getBuilder().CreateCondBr(condition, block, after); // insert the after block. function->getBasicBlockList().push_back(after); module.getBuilder().SetInsertPoint(after); return nullptr; }