Skip to content
Snippets Groups Projects
Commit ec87178c authored by Peter Matta's avatar Peter Matta
Browse files

Generating object files

parent 3b4b04ba
No related branches found
No related tags found
No related merge requests found
...@@ -14,6 +14,7 @@ ...@@ -14,6 +14,7 @@
#include "dusk/Frontend/SourceFile.h" #include "dusk/Frontend/SourceFile.h"
#include "llvm/ADT/ArrayRef.h" #include "llvm/ADT/ArrayRef.h"
#include "llvm/Support/SourceMgr.h" #include "llvm/Support/SourceMgr.h"
#include "llvm/IR/Module.h"
#include <memory> #include <memory>
   
#ifndef DUSK_COMPILER_INSTANCE_H #ifndef DUSK_COMPILER_INSTANCE_H
...@@ -75,6 +76,8 @@ public: ...@@ -75,6 +76,8 @@ public:
virtual void consume(SMDiagnostic &Diagnostic); virtual void consume(SMDiagnostic &Diagnostic);
private: private:
void emitObjectFile(llvm::Module *M);
// Explicitly forbid copying of any kind. // Explicitly forbid copying of any kind.
CompilerInstance(const CompilerInstance &other) = delete; CompilerInstance(const CompilerInstance &other) = delete;
CompilerInstance &operator=(const CompilerInstance &other) = delete; CompilerInstance &operator=(const CompilerInstance &other) = delete;
......
...@@ -118,6 +118,12 @@ public: ...@@ -118,6 +118,12 @@ public:
/// \return \c true on success, \c false if the current scope is already /// \return \c true on success, \c false if the current scope is already
/// a value or function with the same identifier. /// a value or function with the same identifier.
bool declareVal(const Decl *); bool declareVal(const Decl *);
/// \brief Declares a value in current scope.
///
/// \return \c true on success, \c false if the current scope is already
/// a value or function with the same identifier.
bool declareVal(const Decl *, llvm::Function *);
   
/// \brief Declares a function. /// \brief Declares a function.
/// ///
......
...@@ -56,7 +56,7 @@ public: ...@@ -56,7 +56,7 @@ public:
llvm::Module *perform(); llvm::Module *perform();
private: private:
bool prepareGlobals(Context &Ctx, ModuleDecl *M); bool declareFuncs(Context &Ctx, ModuleDecl *M);
}; };
   
} // namespace ir } // namespace ir
......
...@@ -8,10 +8,24 @@ ...@@ -8,10 +8,24 @@
//===----------------------------------------------------------------------===// //===----------------------------------------------------------------------===//
   
#include "dusk/Frontend/CompilerInstance.h" #include "dusk/Frontend/CompilerInstance.h"
#include "dusk/AST/Diagnostics.h" #include "dusk/AST/Diagnostics.h"
#include "dusk/Parse/Parser.h" #include "dusk/Parse/Parser.h"
#include "dusk/Sema/Sema.h" #include "dusk/Sema/Sema.h"
#include "dusk/IRGen/IRGenerator.h" #include "dusk/IRGen/IRGenerator.h"
#include "llvm/IR/Module.h"
#include "llvm/IR/Type.h"
#include "llvm/IR/Verifier.h"
#include "llvm/IR/PassManager.h"
#include "llvm/IR/LegacyPassManager.h"
#include "llvm/Support/FileSystem.h"
#include "llvm/Support/Host.h"
#include "llvm/Support/raw_ostream.h"
#include "llvm/Support/TargetRegistry.h"
#include "llvm/Support/TargetSelect.h"
#include "llvm/Target/TargetMachine.h"
#include "llvm/Target/TargetOptions.h"
#include <string>
   
using namespace dusk; using namespace dusk;
   
...@@ -36,6 +50,8 @@ void CompilerInstance::performCompilation() { ...@@ -36,6 +50,8 @@ void CompilerInstance::performCompilation() {
auto M = Gen.perform(); auto M = Gen.perform();
M->print(llvm::errs(), nullptr); M->print(llvm::errs(), nullptr);
llvm::errs() << "\n"; llvm::errs() << "\n";
emitObjectFile(M);
} }
   
void CompilerInstance::performSema() { void CompilerInstance::performSema() {
...@@ -65,3 +81,56 @@ void CompilerInstance::reset(CompilerInvocation &&I) { ...@@ -65,3 +81,56 @@ void CompilerInstance::reset(CompilerInvocation &&I) {
void CompilerInstance::consume(SMDiagnostic &Diagnostic) { void CompilerInstance::consume(SMDiagnostic &Diagnostic) {
Diagnostic.print("duskc", llvm::errs()); Diagnostic.print("duskc", llvm::errs());
} }
void CompilerInstance::emitObjectFile(llvm::Module *M) {
llvm::InitializeAllTargetInfos();
llvm::InitializeAllTargets();
llvm::InitializeAllTargetMCs();
llvm::InitializeAllAsmParsers();
llvm::InitializeAllAsmPrinters();
std::string Err;
auto Target =
llvm::TargetRegistry::lookupTarget(Invocation.getTargetTriple(), Err);
if (!Target) {
llvm::errs() << Err;
return;
}
auto CPU = "generic";
auto Features = "";
llvm::TargetOptions Opt;
auto RM = Optional<llvm::Reloc::Model>();
auto TargetMachine = Target->createTargetMachine(Invocation.getTargetTriple(),
CPU, Features, Opt, RM);
M->setDataLayout(TargetMachine->createDataLayout());
M->setTargetTriple(Invocation.getTargetTriple());
// Open output file
auto Filename = "output.o"; // Invocation.getOutputFilename();
std::error_code EC;
llvm::raw_fd_ostream dest(Filename, EC, llvm::sys::fs::F_None);
if (EC) {
llvm::errs() << "Could not open file '" << Filename
<< "': " << EC.message();
return;
}
// Emit pass
llvm::legacy::PassManager pass;
auto FileType = llvm::TargetMachine::CGFT_ObjectFile;
if (TargetMachine->addPassesToEmitFile(pass, dest, FileType)) {
llvm::errs() << "TargetMachine can't emit a file of this type";
return;
}
llvm::verifyModule(*M, &llvm::errs());
pass.run(*M);
dest.flush();
}
...@@ -79,6 +79,19 @@ bool Context::declareVal(const Decl *D) { ...@@ -79,6 +79,19 @@ bool Context::declareVal(const Decl *D) {
return true; return true;
} }
   
bool Context::declareVal(const Decl *D, llvm::Function *F) {
// Check if already declared in current scope
if (Impl->isDeclared(D->getName()) || Funcs[D->getName()] != nullptr)
return false;
llvm::IRBuilder<> TmpB(&F->getEntryBlock(), F->getEntryBlock().begin());
auto Ty = llvm::Type::getInt64Ty(Ctx);
auto Var = TmpB.CreateAlloca(Ty, 0, D->getName());
Impl->Values[D->getName()] = Var;
return true;
}
bool Context::declareFunc(const FuncDecl *Fn) { bool Context::declareFunc(const FuncDecl *Fn) {
// Validate that we're in global scope. // Validate that we're in global scope.
assert(Depth == 0 && "Function declaration must be declared in global scope"); assert(Depth == 0 && "Function declaration must be declared in global scope");
......
...@@ -22,7 +22,7 @@ using namespace dusk; ...@@ -22,7 +22,7 @@ using namespace dusk;
using namespace irgen; using namespace irgen;
   
llvm::Value *cast(llvm::Value *V, Context &Ctx, llvm::Type *Ty) { llvm::Value *cast(llvm::Value *V, Context &Ctx, llvm::Type *Ty) {
return Ctx.Builder.CreateBitCast(V, Ty); return Ctx.Builder.CreateIntCast(V, Ty, true);
} }
   
llvm::Value *irgen::codegenExpr(Context &Ctx, NumberLiteralExpr *E) { llvm::Value *irgen::codegenExpr(Context &Ctx, NumberLiteralExpr *E) {
...@@ -121,7 +121,8 @@ llvm::Value *irgen::codegenExpr(Context &Ctx, CallExpr *E) { ...@@ -121,7 +121,8 @@ llvm::Value *irgen::codegenExpr(Context &Ctx, CallExpr *E) {
// Get declared function // Get declared function
auto Fn = Ctx.getFunc(CalleeID->getName()); auto Fn = Ctx.getFunc(CalleeID->getName());
   
auto Args = std::vector<llvm::Value *>(Fn->arg_size()); auto Args = std::vector<llvm::Value *>();
llvm::errs() << Fn->arg_size();
for (auto Arg : ArgsPttrn->getValues()) for (auto Arg : ArgsPttrn->getValues())
Args.push_back(codegenExpr(Ctx, Arg)); Args.push_back(codegenExpr(Ctx, Arg));
return Ctx.Builder.CreateCall(Fn, Args); return Ctx.Builder.CreateCall(Fn, Args);
......
...@@ -10,7 +10,6 @@ ...@@ -10,7 +10,6 @@
#include "GenStmt.h" #include "GenStmt.h"
#include "GenDecl.h" #include "GenDecl.h"
#include "GenExpr.h" #include "GenExpr.h"
#include <iostream>
   
using namespace dusk; using namespace dusk;
using namespace irgen; using namespace irgen;
...@@ -54,10 +53,12 @@ bool irgen::codegenStmt(Context &Ctx, Scope &Scp, BlockStmt *S) { ...@@ -54,10 +53,12 @@ bool irgen::codegenStmt(Context &Ctx, Scope &Scp, BlockStmt *S) {
   
// MARK: - Func statement // MARK: - Func statement
   
void genArgs(Context &Ctx, VarPattern *P) { void genArgs(Context &Ctx, VarPattern *P, llvm::Function *F) {
for (auto Arg : P->getVars()) for (auto Arg : P->getVars())
if (!Ctx.declareVal(Arg)) if (!Ctx.declareVal(Arg, F))
llvm_unreachable("Redefinition of arg"); llvm_unreachable("Redefinition of arg");
for (auto &Arg : F->args())
Ctx.Builder.CreateStore(&Arg, Ctx.getVal(Arg.getName()));
} }
   
bool irgen::codegenStmt(Context &Ctx, Scope &Scp, FuncStmt *S) { bool irgen::codegenStmt(Context &Ctx, Scope &Scp, FuncStmt *S) {
...@@ -69,7 +70,7 @@ bool irgen::codegenStmt(Context &Ctx, Scope &Scp, FuncStmt *S) { ...@@ -69,7 +70,7 @@ bool irgen::codegenStmt(Context &Ctx, Scope &Scp, FuncStmt *S) {
auto BB = llvm::BasicBlock::Create(Ctx, "entry", F); auto BB = llvm::BasicBlock::Create(Ctx, "entry", F);
Ctx.Builder.SetInsertPoint(BB); Ctx.Builder.SetInsertPoint(BB);
Ctx.push(); Ctx.push();
genArgs(Ctx, Args); genArgs(Ctx, Args, F);
codegenStmt(Ctx, Scp_, S->getBody()); codegenStmt(Ctx, Scp_, S->getBody());
Ctx.pop(); Ctx.pop();
return true; return true;
...@@ -103,8 +104,10 @@ bool irgen::codegenStmt(Context &Ctx, Scope &Scp, IfStmt *S) { ...@@ -103,8 +104,10 @@ bool irgen::codegenStmt(Context &Ctx, Scope &Scp, IfStmt *S) {
Ctx.Builder.CreateCondBr(Cond, ThenBB, ElseBB); Ctx.Builder.CreateCondBr(Cond, ThenBB, ElseBB);
genBranch(Ctx, Scp_, ThenBB, S->getThen()); genBranch(Ctx, Scp_, ThenBB, S->getThen());
Ctx.Builder.CreateBr(MergeBB);
if (S->hasElseBlock()) if (S->hasElseBlock())
genBranch(Ctx, Scp_, ElseBB, S->getElse()); genBranch(Ctx, Scp_, ElseBB, S->getElse());
Ctx.Builder.CreateBr(MergeBB);
Ctx.Builder.SetInsertPoint(MergeBB); Ctx.Builder.SetInsertPoint(MergeBB);
return true; return true;
} }
......
...@@ -32,6 +32,7 @@ bool codegenStmt(Context &Ctx, Scope &Scp, IfStmt *S); ...@@ -32,6 +32,7 @@ bool codegenStmt(Context &Ctx, Scope &Scp, IfStmt *S);
bool codegenStmt(Context &Ctx, Scope &Scp, WhileStmt *S); bool codegenStmt(Context &Ctx, Scope &Scp, WhileStmt *S);
bool codegenStmt(Context &Ctx, Scope &Scp, ForStmt *S); bool codegenStmt(Context &Ctx, Scope &Scp, ForStmt *S);
bool codegenStmt(Context &Ctx, Scope &Scp, FuncStmt *S); bool codegenStmt(Context &Ctx, Scope &Scp, FuncStmt *S);
bool codegenStmt(Context &Ctx, Scope &Scp, ExternStmt *S);
} // namespace irgen } // namespace irgen
......
...@@ -20,19 +20,18 @@ ...@@ -20,19 +20,18 @@
using namespace dusk; using namespace dusk;
using namespace irgen; using namespace irgen;
   
IRGenerator::IRGenerator(ASTContext &C, DiagnosticEngine &Diag) IRGenerator::IRGenerator(ASTContext &C, DiagnosticEngine &Diag)
: ASTCtx(C), Diag(Diag), Builder({Ctx}) {} : ASTCtx(C), Diag(Diag), Builder({Ctx}) {}
   
IRGenerator::~IRGenerator() {} IRGenerator::~IRGenerator() {}
   
llvm::Module *IRGenerator::perform() { llvm::Module *IRGenerator::perform() {
auto M = ASTCtx.getRootModule(); auto M = ASTCtx.getRootModule();
Module = std::make_unique<llvm::Module>(M->getName(), Ctx); Module = std::make_unique<llvm::Module>(M->getName(), Ctx);
Context Ctx(this->Ctx, Module.get(), Builder); Context Ctx(this->Ctx, Module.get(), Builder);
Scope Scp; Scope Scp;
prepareGlobals(Ctx, M); declareFuncs(Ctx, M);
for (auto &N : M->getContents()) { for (auto &N : M->getContents()) {
bool R = true; bool R = true;
if (auto D = dynamic_cast<Decl *>(N)) if (auto D = dynamic_cast<Decl *>(N))
...@@ -43,18 +42,15 @@ llvm::Module *IRGenerator::perform() { ...@@ -43,18 +42,15 @@ llvm::Module *IRGenerator::perform() {
R = codegenStmt(Ctx, Scp, S); R = codegenStmt(Ctx, Scp, S);
else else
llvm_unreachable("Unexpected node"); llvm_unreachable("Unexpected node");
if (!R) if (!R)
return nullptr; return nullptr;
} }
return Module.release(); return Module.release();
} }
   
bool IRGenerator::prepareGlobals(Context &Ctx, ModuleDecl *M) { bool IRGenerator::declareFuncs(Context &Ctx, ModuleDecl *M) {
for (auto N : M->getContents()) { for (auto N : M->getContents()) {
if (auto D = dynamic_cast<Decl *>(N))
if (!codegenDecl(Ctx, D))
return false;
if (auto Fn = dynamic_cast<FuncStmt *>(N)) if (auto Fn = dynamic_cast<FuncStmt *>(N))
if (!codegenDecl(Ctx, Fn->getPrototype())) if (!codegenDecl(Ctx, Fn->getPrototype()))
return false; return false;
......
...@@ -62,6 +62,12 @@ bool TypeChecker::postWalkLetDecl(LetDecl *D) { ...@@ -62,6 +62,12 @@ bool TypeChecker::postWalkLetDecl(LetDecl *D) {
if (!D->getType() || !D->getValue()->getType()) if (!D->getType() || !D->getValue()->getType())
return false; return false;
   
if (!D->getType()->isValueType()) {
diagnose(D->getValue()->getLocStart(),
diag::expected_value_type_expression);
return false;
}
// Validate types // Validate types
if (D->getType()->isClassOf(D->getValue()->getType())) { if (D->getType()->isClassOf(D->getValue()->getType())) {
// If types match, declare // If types match, declare
...@@ -86,6 +92,12 @@ bool TypeChecker::postWalkVarDecl(VarDecl *D) { ...@@ -86,6 +92,12 @@ bool TypeChecker::postWalkVarDecl(VarDecl *D) {
if (!D->getType() || (D->hasValue() && !D->getValue()->getType())) if (!D->getType() || (D->hasValue() && !D->getValue()->getType()))
return false; return false;
   
if (!D->getType()->isValueType()) {
diagnose(D->getValue()->getLocStart(),
diag::expected_value_type_expression);
return false;
}
// Validate types // Validate types
if (!D->hasValue() || D->getType()->isClassOf(D->getValue()->getType())) if (!D->hasValue() || D->getType()->isClassOf(D->getValue()->getType()))
// If types match, declare // If types match, declare
......
...@@ -152,4 +152,3 @@ bool TypeChecker::postWalkWhileStmt(WhileStmt *S) { ...@@ -152,4 +152,3 @@ bool TypeChecker::postWalkWhileStmt(WhileStmt *S) {
diagnose(S->getCond()->getLocStart(), diag::expected_value_type_expression); diagnose(S->getCond()->getLocStart(), diag::expected_value_type_expression);
return false; return false;
} }
...@@ -3,7 +3,6 @@ ...@@ -3,7 +3,6 @@
#include "dusk/Frontend/CompilerInstance.h" #include "dusk/Frontend/CompilerInstance.h"
#include "llvm/ADT/StringRef.h" #include "llvm/ADT/StringRef.h"
#include "llvm/Support/CommandLine.h" #include "llvm/Support/CommandLine.h"
#include <iostream>
#include <string> #include <string>
   
using namespace dusk; using namespace dusk;
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment