#include "Compiler.hpp" #include #include #include #include #include #include #include #include namespace wg { /*explicit*/ Compiler::Compiler() { } /*virtual*/ Compiler::~Compiler() { } void Compiler::gen() { auto target_triple = llvm::sys::getDefaultTargetTriple(); llvm::InitializeAllTargetInfos(); llvm::InitializeAllTargets(); llvm::InitializeAllTargetMCs(); llvm::InitializeAllAsmParsers(); llvm::InitializeAllAsmPrinters(); std::string err; auto target = llvm::TargetRegistry::lookupTarget(target_triple, err); if (!target) { llvm::errs() << err; abort(); } auto cpu = "generic"; auto features = ""; llvm::TargetOptions opt; auto rm = std::optional(); auto target_machine = target->createTargetMachine(target_triple, cpu, features, opt, rm); m_module->setDataLayout(target_machine->createDataLayout()); m_module->setTargetTriple(target_triple); auto filename = "output.o"; std::error_code ec; llvm::raw_fd_ostream dest(filename, ec, llvm::sys::fs::OF_None); WG_ASSERT(!ec, "cannot write output file."); llvm::legacy::PassManager pass; auto file_type = llvm::CodeGenFileType::CGFT_ObjectFile; if (target_machine->addPassesToEmitFile(pass, dest, nullptr, file_type)) { llvm::errs() << "Target machine cannot emit a file of this type"; } pass.run(*m_module); dest.flush(); m_module->print(llvm::outs(), nullptr); } llvm::Value* Compiler::compile(std::shared_ptr node) { switch (node->type()) { case NODE_PROG: { auto* block = llvm::BasicBlock::Create(*m_context, "entry"); m_builder->SetInsertPoint(block); for (size_t i=0; isize(); i++) { compile(node->child(i)); } return block; } break; case NODE_ADD: { auto* lhs = compile(node->child(0)); auto* rhs = compile(node->child(1)); return m_builder->CreateAdd(lhs, rhs); } break; case NODE_SUB: { auto* lhs = compile(node->child(0)); auto* rhs = compile(node->child(1)); return m_builder->CreateSub(lhs, rhs); } break; case NODE_MUL: { auto* lhs = compile(node->child(0)); auto* rhs = compile(node->child(1)); return m_builder->CreateMul(lhs, rhs); } break; case NODE_DIV: { auto* lhs = compile(node->child(0)); auto* rhs = compile(node->child(1)); return m_builder->CreateSDiv(lhs, rhs); } break; case NODE_MOD: { auto* lhs = compile(node->child(0)); auto* rhs = compile(node->child(1)); return m_builder->CreateSRem(lhs, rhs); } break; case NODE_INT: { return llvm::ConstantInt::get(*m_context, llvm::APInt(32, 0, true)); } break; default: WG_ASSERT(false, std::string() + "cannot compile unknown node '" + NodeTypeStr[node->type()] + "'"); } } }