123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512 |
- #include "CodegenVisitor.h"
- #include "CodeGeneration.h"
- #include "Type.h"
- #include "Builtin.h"
- #include "ErrorReporting.h"
- #include <llvm/IR/Constants.h>
- #include <llvm/IR/IRBuilder.h>
- #include <llvm/IR/DataLayout.h>
- #include <llvm/Support/raw_os_ostream.h>
- using namespace qlow;
- llvm::Value* ExpressionCodegenVisitor::visit(sem::LocalVariableExpression& lve, llvm::IRBuilder<>& builder)
- {
- assert(lve.var->allocaInst != nullptr);
- if (llvm::dyn_cast<llvm::AllocaInst>(lve.var->allocaInst)) {
- llvm::Type* returnType = lve.context.getLlvmType(lve.type, builder.getContext());
- llvm::Value* val = builder.CreateLoad(returnType, lve.var->allocaInst);
- return val;
- }
- else {
- return lve.var->allocaInst;
- }
- }
- llvm::Value* ExpressionCodegenVisitor::visit(sem::UnaryOperation& unop, llvm::IRBuilder<>& builder)
- {
- using llvm::Value;
- auto value = unop.arg->accept(*this, builder);
- auto& type = unop.arg->type;
-
- if (type == sem::NO_TYPE)
- throw "invalid type to negate";
-
- return nullptr;
- }
- llvm::Value* ExpressionCodegenVisitor::visit(sem::BinaryOperation& binop, llvm::IRBuilder<>& builder)
- {
- using llvm::Value;
- using sem::Type;
- auto left = binop.left->accept(*this, builder);
- auto right = binop.right->accept(*this, builder);
-
- auto& leftType = binop.left->type;
- auto& rightType = binop.right->type;
-
- sem::Method* operation = binop.operationMethod;
-
- if (operation != nullptr) {
-
- if (sem::NativeMethod* nm = dynamic_cast<sem::NativeMethod*>(operation); nm) {
- return nm->generateCode(builder, {left, right});
- }
- else
- throw "only native operations supported at the moment";
- }
- else {
- throw "internal error: operation method null";
- }
-
-
- if (left == nullptr) {
- printf("WOW: %s\n", binop.left->toString().c_str());
- }
-
- Value* implicitelyCastedRight = right;
-
-
-
-
-
-
-
- }
- llvm::Value* ExpressionCodegenVisitor::visit(sem::CastExpression& cast, llvm::IRBuilder<>& builder)
- {
-
- return nullptr;
- }
- llvm::Value* ExpressionCodegenVisitor::visit(sem::NewExpression& nexpr, llvm::IRBuilder<>& builder)
- {
- using llvm::Value;
-
- sem::Context& semCtxt = nexpr.context;
- sem::TypeId type = nexpr.type;
- const llvm::DataLayout& layout = builder.GetInsertBlock()->getModule()->getDataLayout();
- llvm::Type* llvmTy = semCtxt.getLlvmType(type, builder.getContext())->getPointerElementType();
- auto allocSize = layout.getTypeAllocSize(llvmTy);
- auto size = llvm::ConstantInt::get(builder.getContext(), llvm::APInt(32, allocSize, false));
- auto mallocCall = llvm::CallInst::CreateMalloc(builder.GetInsertBlock(), size->getType(), llvmTy, size, nullptr, nullptr, "");
-
- builder.GetInsertBlock()->getInstList().push_back(llvm::cast<llvm::Instruction>(mallocCall));
- return mallocCall;
- }
- llvm::Value* ExpressionCodegenVisitor::visit(sem::NewArrayExpression& naexpr, llvm::IRBuilder<>& builder)
- {
- using llvm::Value;
-
- return nullptr;
- }
- llvm::Value* ExpressionCodegenVisitor::visit(sem::MethodCallExpression& call, llvm::IRBuilder<>& builder)
- {
- using llvm::Value;
- sem::Context& semCtxt = call.context;
- if (call.arguments.size() != call.callee->arguments.size()) {
- throw "wrong number of arguments";
- }
-
- std::vector<Value*> arguments;
-
- if (call.target != nullptr) {
- auto* target = call.target->accept(*this, builder);
- #ifdef DEBUGGING
- Printer::getInstance() << "creating 'this' argument";
- #endif
-
- arguments.push_back(target);
- }
-
- for (size_t i = 0; i < call.arguments.size(); i++) {
-
- auto& arg = call.arguments[i];
- auto value = arg->accept(*this, builder);
-
- if (arg->type != call.callee->arguments[i]->type) {
- throw "argument type mismatch";
- }
-
- arguments.push_back(value);
- }
-
- llvm::CallInst* callInst = builder.CreateCall(call.callee->llvmNode, arguments);
- return callInst;
- }
- llvm::Value* ExpressionCodegenVisitor::visit(sem::FieldAccessExpression& access, llvm::IRBuilder<>& builder)
- {
- using llvm::Value;
- using llvm::Type;
- sem::Context& semCtxt = access.context;
-
- Type* type = semCtxt.getLlvmType(access.target->type, builder.getContext());
-
- if (type == nullptr)
- throw "no access type";
- if (type->isPointerTy()) {
- type = type->getPointerElementType();
- }
-
- llvm::Value* target = access.target->accept(fg.lvalueVisitor, fg);
- llvm::raw_os_ostream os(Printer::getInstance());
- type->print(os);
- os << "\n";
- os.flush();
- int structIndex = access.accessed->llvmStructIndex;
- llvm::ArrayRef<Value*> indexList = {
- llvm::ConstantInt::get(builder.getContext(), llvm::APInt(32, structIndex, false)),
- llvm::ConstantInt::get(builder.getContext(), llvm::APInt(32, 0, false))
- };
- Value* ptr = builder.CreateGEP(type, target, indexList);
- return builder.CreateLoad(ptr);
-
-
-
-
-
- return llvm::ConstantInt::get(builder.getContext(),
- llvm::APInt(32, 0, false));
- }
- llvm::Value* ExpressionCodegenVisitor::visit(sem::AddressExpression& node, llvm::IRBuilder<>& builder)
- {
- using llvm::Value;
- Value* lvalue = node.target->accept(fg.lvalueVisitor, fg);
-
-
- if (auto* allocaInst = llvm::dyn_cast<llvm::AllocaInst>(lvalue)) {
- return lvalue;
- }
- else {
- return lvalue;
- }
- }
- llvm::Value* ExpressionCodegenVisitor::visit(sem::IntConst& node, llvm::IRBuilder<>& builder)
- {
- return llvm::ConstantInt::get(builder.getContext(),
- llvm::APInt(64, std::to_string(node.value), 10));
- }
- llvm::Value* ExpressionCodegenVisitor::visit(sem::ThisExpression& thisExpr, llvm::IRBuilder<>& builder)
- {
- return thisExpr.allocaInst;
- }
- llvm::Value* LValueVisitor::visit(sem::Expression& e, qlow::gen::FunctionGenerator& fg)
- {
- throw "cannot construct lvalue from expression";
- }
- llvm::Value* LValueVisitor::visit(sem::LocalVariableExpression& lve, qlow::gen::FunctionGenerator& fg)
- {
- assert(lve.var->allocaInst != nullptr);
-
- if (llvm::dyn_cast<llvm::AllocaInst>(lve.var->allocaInst)) {
- return lve.var->allocaInst;
-
-
- }
- else if (llvm::dyn_cast<llvm::PointerType> (lve.var->allocaInst->getType())) {
- return lve.var->allocaInst;
- }
- else {
- return lve.var->allocaInst;
-
- }
- }
- llvm::Value* LValueVisitor::visit(sem::FieldAccessExpression& access, qlow::gen::FunctionGenerator& fg)
- {
-
-
- using llvm::Value;
- using llvm::Type;
- sem::Context& semCtxt = access.context;
-
- Type* type = semCtxt.getLlvmType(access.target->type, fg.builder.getContext());
-
- if (type == nullptr)
- throw "no access type";
- if (type->isPointerTy()) {
- type = type->getPointerElementType();
- }
-
- llvm::Value* target = access.target->accept(fg.expressionVisitor, fg.builder);
-
- int structIndex = access.accessed->llvmStructIndex;
- llvm::ArrayRef<Value*> indexList = {
- llvm::ConstantInt::get(fg.builder.getContext(), llvm::APInt(32, structIndex, false)),
- llvm::ConstantInt::get(fg.builder.getContext(), llvm::APInt(32, 0, false))
- };
- Value* ptr = fg.builder.CreateGEP(type, target, indexList);
- return ptr;
- }
- llvm::Value* StatementVisitor::visit(sem::DoEndBlock& assignment,
- qlow::gen::FunctionGenerator& fg)
- {
- for (auto& statement : assignment.statements) {
- statement->accept(*this, fg);
- }
- return nullptr;
- }
- llvm::Value* StatementVisitor::visit(sem::IfElseBlock& ifElseBlock,
- qlow::gen::FunctionGenerator& fg)
- {
- using llvm::Value;
- using llvm::BasicBlock;
-
- fg.builder.SetInsertPoint(fg.getCurrentBlock());
- auto condition = ifElseBlock.condition->accept(fg.expressionVisitor, fg.builder);
-
- llvm::Function* function = fg.getCurrentBlock()->getParent();
-
- BasicBlock* thenB = BasicBlock::Create(fg.getContext(), "then", function);
- BasicBlock* elseB = BasicBlock::Create(fg.getContext(), "else", function);
- BasicBlock* merge = BasicBlock::Create(fg.getContext(), "merge", function);
-
- Value* boolCond = fg.builder.CreateIntCast(condition, llvm::Type::getInt1Ty(fg.getContext()), false);
-
- fg.builder.CreateCondBr(boolCond, thenB, elseB);
-
- fg.pushBlock(thenB);
- ifElseBlock.ifBlock->accept(*this, fg);
- fg.builder.SetInsertPoint(thenB);
- if (!thenB->getTerminator())
- fg.builder.CreateBr(merge);
- fg.popBlock();
- fg.pushBlock(elseB);
- ifElseBlock.elseBlock->accept(*this, fg);
- fg.builder.SetInsertPoint(elseB);
- if (!elseB->getTerminator())
- fg.builder.CreateBr(merge);
- fg.popBlock();
- fg.popBlock();
- fg.pushBlock(merge);
- return nullptr;
- }
- llvm::Value* StatementVisitor::visit(sem::WhileBlock& whileBlock,
- qlow::gen::FunctionGenerator& fg)
- {
- using llvm::Value;
- using llvm::BasicBlock;
-
- fg.builder.SetInsertPoint(fg.getCurrentBlock());
-
- llvm::Function* function = fg.getCurrentBlock()->getParent();
-
- BasicBlock* startloop = BasicBlock::Create(fg.getContext(), "startloop", function);
- BasicBlock* body = BasicBlock::Create(fg.getContext(), "loopbody", function);
- BasicBlock* merge = BasicBlock::Create(fg.getContext(), "merge", function);
-
-
-
- fg.builder.CreateBr(startloop);
- fg.pushBlock(startloop);
- fg.builder.SetInsertPoint(startloop);
- auto condition = whileBlock.condition->accept(fg.expressionVisitor, fg.builder);
- Value* boolCond = fg.builder.CreateIntCast(condition, llvm::Type::getInt1Ty(fg.getContext()), false);
- fg.builder.CreateCondBr(condition, body, merge);
- fg.popBlock();
-
- fg.pushBlock(body);
- whileBlock.body->accept(*this, fg);
- fg.builder.SetInsertPoint(body);
- fg.builder.CreateBr(startloop);
- fg.popBlock();
- fg.pushBlock(merge);
- return nullptr;
- }
- llvm::Value* StatementVisitor::visit(sem::AssignmentStatement& assignment,
- qlow::gen::FunctionGenerator& fg)
- {
- Printer& printer = Printer::getInstance();
- fg.builder.SetInsertPoint(fg.getCurrentBlock());
-
- auto val = assignment.value->accept(fg.expressionVisitor, fg.builder);
- auto target = assignment.target->accept(fg.lvalueVisitor, fg);
-
- return fg.builder.CreateStore(val, target);
-
-
- }
- llvm::Value* StatementVisitor::visit(sem::ReturnStatement& returnStatement,
- qlow::gen::FunctionGenerator& fg)
- {
- fg.builder.SetInsertPoint(fg.getCurrentBlock());
- auto val = returnStatement.value->accept(fg.expressionVisitor, fg.builder);
- fg.builder.CreateRet(val);
- return val;
- }
- llvm::Value* StatementVisitor::visit(sem::FeatureCallStatement& fc, gen::FunctionGenerator& fg)
- {
- llvm::Module* module = fg.getModule();
- fg.builder.SetInsertPoint(fg.getCurrentBlock());
-
-
- return fc.expr->accept(fg.expressionVisitor, fg.builder);
-
-
-
- }
- llvm::Value* CastGenerator::generateCast(llvm::Value* toCast,
- llvm::IRBuilder<>& b)
- {
-
- return nullptr;
- }
|