diff --git a/cmdargs.cc b/cmdargs.cc index 47e72f5..029d945 100644 --- a/cmdargs.cc +++ b/cmdargs.cc @@ -4,7 +4,7 @@ #include #include -const std::string usage = "Usage: clox [script]\n"; +const std::string usage = "Usage: clox [source]\n"; CmdArgs::CmdArgs(int argc, char** argv) { lexOutput = false; diff --git a/main.cc b/main.cc index 65602ce..83fc7f6 100644 --- a/main.cc +++ b/main.cc @@ -3,6 +3,7 @@ #include #include "cmdargs.h" +#include "object.h" #include "parser.h" #include "scanner.h" @@ -25,6 +26,8 @@ int run(const string& s) { cout << endl; } if (options->printIR()) l.mod->print(llvm::outs(), nullptr); + l.mod->print(llvm::errs(), nullptr); + compile(v); return 0; } diff --git a/object.cc b/object.cc new file mode 100644 index 0000000..48a1892 --- /dev/null +++ b/object.cc @@ -0,0 +1,62 @@ +#include "object.h" + +#include "llvm/IR/LegacyPassManager.h" +#include "llvm/Support/FileSystem.h" +#include "llvm/Support/Host.h" +#include "llvm/Support/TargetRegistry.h" +#include "llvm/Support/TargetSelect.h" +#include "llvm/Support/raw_ostream.h" +#include "llvm/Target/TargetMachine.h" +#include "llvm/Target/TargetOptions.h" + +using namespace llvm; + +void compile(CodeGenVisitor v) { + auto TargetTriple = sys::getDefaultTargetTriple(); + InitializeAllTargetInfos(); + InitializeAllTargets(); + InitializeAllTargetMCs(); + InitializeAllAsmParsers(); + InitializeAllAsmPrinters(); + std::string Error; + + auto Target = TargetRegistry::lookupTarget(TargetTriple, Error); + + // Print an error and exit if we couldn't find the requested target. + // This generally occurs if we've forgotten to initialise the + // TargetRegistry or we have a bogus target triple. + if (!Target) { + errs() << Error; + return; + } + + auto CPU = "generic"; + auto Features = ""; + + TargetOptions opt; + auto RM = Optional(); + auto TargetMachine = + Target->createTargetMachine(TargetTriple, CPU, Features, opt, RM); + v.getMod()->setDataLayout(TargetMachine->createDataLayout()); + v.getMod()->setTargetTriple(TargetTriple); + + auto Filename = "output.o"; + std::error_code EC; + raw_fd_ostream dest(Filename, EC, sys::fs::OF_None); + + if (EC) { + errs() << "Could not open file: " << EC.message(); + return; + } + + legacy::PassManager pass; + auto FileType = CGFT_ObjectFile; + + if (TargetMachine->addPassesToEmitFile(pass, dest, nullptr, FileType)) { + errs() << "TargetMachine can't emit a file of this type"; + return; + } + + pass.run(*v.getMod()); + dest.flush(); +} diff --git a/object.h b/object.h new file mode 100644 index 0000000..7f089ab --- /dev/null +++ b/object.h @@ -0,0 +1,3 @@ +#pragma once +#include "visitor.h" +void compile(CodeGenVisitor v); diff --git a/visitor.h b/visitor.h index e530702..05efa51 100644 --- a/visitor.h +++ b/visitor.h @@ -98,6 +98,8 @@ class CodeGenVisitor : public DeclVisitor { : scope(scope), l(l), terminate(false){}; CodeGenVisitor wrap(); CodeGenVisitor wrapWithTrace(Trace* r); + auto getMod() { return l.mod; } + auto getCtx() { return l.ctx; } virtual void visit(Declaration* d) override; virtual void visit(ExprStmt* st) override;