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 @@
#include "dusk/Frontend/SourceFile.h"
#include "llvm/ADT/ArrayRef.h"
#include "llvm/Support/SourceMgr.h"
#include "llvm/IR/Module.h"
#include <memory>
 
#ifndef DUSK_COMPILER_INSTANCE_H
......@@ -75,6 +76,8 @@ public:
virtual void consume(SMDiagnostic &Diagnostic);
private:
void emitObjectFile(llvm::Module *M);
// Explicitly forbid copying of any kind.
CompilerInstance(const CompilerInstance &other) = delete;
CompilerInstance &operator=(const CompilerInstance &other) = delete;
......
......@@ -118,6 +118,12 @@ public:
/// \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 *);
/// \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.
///
......
......@@ -56,7 +56,7 @@ public:
llvm::Module *perform();
private:
bool prepareGlobals(Context &Ctx, ModuleDecl *M);
bool declareFuncs(Context &Ctx, ModuleDecl *M);
};
 
} // namespace ir
......
......@@ -8,10 +8,24 @@
//===----------------------------------------------------------------------===//
 
#include "dusk/Frontend/CompilerInstance.h"
#include "dusk/AST/Diagnostics.h"
#include "dusk/Parse/Parser.h"
#include "dusk/Sema/Sema.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;
 
......@@ -36,6 +50,8 @@ void CompilerInstance::performCompilation() {
auto M = Gen.perform();
M->print(llvm::errs(), nullptr);
llvm::errs() << "\n";
emitObjectFile(M);
}
 
void CompilerInstance::performSema() {
......@@ -65,3 +81,56 @@ void CompilerInstance::reset(CompilerInvocation &&I) {
void CompilerInstance::consume(SMDiagnostic &Diagnostic) {
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) {
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) {
// Validate that we're in global scope.
assert(Depth == 0 && "Function declaration must be declared in global scope");
......
......@@ -22,7 +22,7 @@ using namespace dusk;
using namespace irgen;
 
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) {
......@@ -121,7 +121,8 @@ llvm::Value *irgen::codegenExpr(Context &Ctx, CallExpr *E) {
// Get declared function
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())
Args.push_back(codegenExpr(Ctx, Arg));
return Ctx.Builder.CreateCall(Fn, Args);
......
......@@ -10,7 +10,6 @@
#include "GenStmt.h"
#include "GenDecl.h"
#include "GenExpr.h"
#include <iostream>
 
using namespace dusk;
using namespace irgen;
......@@ -54,10 +53,12 @@ bool irgen::codegenStmt(Context &Ctx, Scope &Scp, BlockStmt *S) {
 
// MARK: - Func statement
 
void genArgs(Context &Ctx, VarPattern *P) {
void genArgs(Context &Ctx, VarPattern *P, llvm::Function *F) {
for (auto Arg : P->getVars())
if (!Ctx.declareVal(Arg))
if (!Ctx.declareVal(Arg, F))
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) {
......@@ -69,7 +70,7 @@ bool irgen::codegenStmt(Context &Ctx, Scope &Scp, FuncStmt *S) {
auto BB = llvm::BasicBlock::Create(Ctx, "entry", F);
Ctx.Builder.SetInsertPoint(BB);
Ctx.push();
genArgs(Ctx, Args);
genArgs(Ctx, Args, F);
codegenStmt(Ctx, Scp_, S->getBody());
Ctx.pop();
return true;
......@@ -103,8 +104,10 @@ bool irgen::codegenStmt(Context &Ctx, Scope &Scp, IfStmt *S) {
Ctx.Builder.CreateCondBr(Cond, ThenBB, ElseBB);
genBranch(Ctx, Scp_, ThenBB, S->getThen());
Ctx.Builder.CreateBr(MergeBB);
if (S->hasElseBlock())
genBranch(Ctx, Scp_, ElseBB, S->getElse());
Ctx.Builder.CreateBr(MergeBB);
Ctx.Builder.SetInsertPoint(MergeBB);
return true;
}
......
......@@ -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, ForStmt *S);
bool codegenStmt(Context &Ctx, Scope &Scp, FuncStmt *S);
bool codegenStmt(Context &Ctx, Scope &Scp, ExternStmt *S);
} // namespace irgen
......
......@@ -20,19 +20,18 @@
using namespace dusk;
using namespace irgen;
 
IRGenerator::IRGenerator(ASTContext &C, DiagnosticEngine &Diag)
: ASTCtx(C), Diag(Diag), Builder({Ctx}) {}
 
IRGenerator::~IRGenerator() {}
 
llvm::Module *IRGenerator::perform() {
auto M = ASTCtx.getRootModule();
Module = std::make_unique<llvm::Module>(M->getName(), Ctx);
Context Ctx(this->Ctx, Module.get(), Builder);
Scope Scp;
prepareGlobals(Ctx, M);
declareFuncs(Ctx, M);
for (auto &N : M->getContents()) {
bool R = true;
if (auto D = dynamic_cast<Decl *>(N))
......@@ -43,18 +42,15 @@ llvm::Module *IRGenerator::perform() {
R = codegenStmt(Ctx, Scp, S);
else
llvm_unreachable("Unexpected node");
if (!R)
return nullptr;
}
return Module.release();
}
 
bool IRGenerator::prepareGlobals(Context &Ctx, ModuleDecl *M) {
bool IRGenerator::declareFuncs(Context &Ctx, ModuleDecl *M) {
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 (!codegenDecl(Ctx, Fn->getPrototype()))
return false;
......
......@@ -62,6 +62,12 @@ bool TypeChecker::postWalkLetDecl(LetDecl *D) {
if (!D->getType() || !D->getValue()->getType())
return false;
 
if (!D->getType()->isValueType()) {
diagnose(D->getValue()->getLocStart(),
diag::expected_value_type_expression);
return false;
}
// Validate types
if (D->getType()->isClassOf(D->getValue()->getType())) {
// If types match, declare
......@@ -86,6 +92,12 @@ bool TypeChecker::postWalkVarDecl(VarDecl *D) {
if (!D->getType() || (D->hasValue() && !D->getValue()->getType()))
return false;
 
if (!D->getType()->isValueType()) {
diagnose(D->getValue()->getLocStart(),
diag::expected_value_type_expression);
return false;
}
// Validate types
if (!D->hasValue() || D->getType()->isClassOf(D->getValue()->getType()))
// If types match, declare
......
......@@ -152,4 +152,3 @@ bool TypeChecker::postWalkWhileStmt(WhileStmt *S) {
diagnose(S->getCond()->getLocStart(), diag::expected_value_type_expression);
return false;
}
......@@ -3,7 +3,6 @@
#include "dusk/Frontend/CompilerInstance.h"
#include "llvm/ADT/StringRef.h"
#include "llvm/Support/CommandLine.h"
#include <iostream>
#include <string>
 
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