Compile test.c using LLVM
This commit is contained in:
parent
74a3914fdf
commit
c314ca4cb7
@ -15,7 +15,7 @@ separate_arguments(LLVM_DEFINITIONS_LIST NATIVE_COMMAND ${LLVM_DEFINITIONS})
|
|||||||
add_definitions(${LLVM_DEFINITIONS_LIST})
|
add_definitions(${LLVM_DEFINITIONS_LIST})
|
||||||
|
|
||||||
# Executable
|
# Executable
|
||||||
add_executable(${PROJECT_NAME} src/main.cpp src/tokens.cpp src/parsing.cpp src/ast.cpp)
|
add_executable(${PROJECT_NAME} src/main.cpp src/tokens.cpp src/parsing.cpp src/ast.cpp src/codegen.cpp)
|
||||||
target_compile_features(${PROJECT_NAME} PRIVATE cxx_std_20)
|
target_compile_features(${PROJECT_NAME} PRIVATE cxx_std_20)
|
||||||
|
|
||||||
# Find the libraries that correspond to the LLVM components
|
# Find the libraries that correspond to the LLVM components
|
||||||
|
|||||||
24
src/ast.h
24
src/ast.h
@ -1,6 +1,8 @@
|
|||||||
#ifndef AST_H
|
#ifndef AST_H
|
||||||
#define AST_H
|
#define AST_H
|
||||||
|
|
||||||
|
#include "codegen.h"
|
||||||
|
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
#include <memory>
|
#include <memory>
|
||||||
@ -11,12 +13,21 @@ namespace AST {
|
|||||||
virtual std::string formatted() = 0;
|
virtual std::string formatted() = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
class Expression : public Node {};
|
class Expression : public Node {
|
||||||
|
public:
|
||||||
|
virtual llvm::Value* codegen(codegen::Builder& builder) = 0;
|
||||||
|
};
|
||||||
|
|
||||||
class Type {
|
class Type {
|
||||||
public:
|
public:
|
||||||
virtual std::string formatted() = 0;
|
virtual std::string formatted() = 0;
|
||||||
|
virtual llvm::Type* codegen(codegen::Builder& builder) = 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
class Statement : public Node {
|
||||||
|
public:
|
||||||
|
virtual void codegen(codegen::Builder& builder) = 0;
|
||||||
};
|
};
|
||||||
class Statement : public Node {};
|
|
||||||
|
|
||||||
class IntLiteralExpression : public Expression {
|
class IntLiteralExpression : public Expression {
|
||||||
private:
|
private:
|
||||||
@ -24,6 +35,7 @@ namespace AST {
|
|||||||
public:
|
public:
|
||||||
IntLiteralExpression(int value) : m_value{ value } {}
|
IntLiteralExpression(int value) : m_value{ value } {}
|
||||||
virtual std::string formatted() override;
|
virtual std::string formatted() override;
|
||||||
|
virtual llvm::Value* codegen(codegen::Builder& builder) override;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
@ -33,9 +45,13 @@ namespace AST {
|
|||||||
public:
|
public:
|
||||||
ReturnStatement(std::unique_ptr<Expression> expr) : m_expr{ std::move(expr) } {}
|
ReturnStatement(std::unique_ptr<Expression> expr) : m_expr{ std::move(expr) } {}
|
||||||
virtual std::string formatted() override;
|
virtual std::string formatted() override;
|
||||||
|
virtual void codegen(codegen::Builder& builder) override;
|
||||||
};
|
};
|
||||||
|
|
||||||
class TopLevelStatement : public Node {};
|
class TopLevelStatement : public Node {
|
||||||
|
public:
|
||||||
|
virtual void codegen(codegen::Builder& builder) = 0;
|
||||||
|
};
|
||||||
|
|
||||||
class Function : public TopLevelStatement {
|
class Function : public TopLevelStatement {
|
||||||
private:
|
private:
|
||||||
@ -55,6 +71,7 @@ namespace AST {
|
|||||||
, m_statements{ std::move(statements) } {
|
, m_statements{ std::move(statements) } {
|
||||||
}
|
}
|
||||||
virtual std::string formatted() override;
|
virtual std::string formatted() override;
|
||||||
|
virtual void codegen(codegen::Builder& builder) override;
|
||||||
};
|
};
|
||||||
|
|
||||||
enum class FundamentalTypeKind {
|
enum class FundamentalTypeKind {
|
||||||
@ -67,6 +84,7 @@ namespace AST {
|
|||||||
public:
|
public:
|
||||||
FundamentalType(FundamentalTypeKind kind) : m_ty{ kind } {}
|
FundamentalType(FundamentalTypeKind kind) : m_ty{ kind } {}
|
||||||
virtual std::string formatted() override;
|
virtual std::string formatted() override;
|
||||||
|
virtual llvm::Type* codegen(codegen::Builder& builder) override;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
58
src/codegen.cpp
Normal file
58
src/codegen.cpp
Normal file
@ -0,0 +1,58 @@
|
|||||||
|
#include "codegen.h"
|
||||||
|
#include "ast.h"
|
||||||
|
|
||||||
|
#include <llvm/IR/Module.h>
|
||||||
|
#include <llvm/IR/Verifier.h>
|
||||||
|
#include <memory>
|
||||||
|
#include <iostream>
|
||||||
|
|
||||||
|
namespace AST {
|
||||||
|
llvm::Value* IntLiteralExpression::codegen(codegen::Builder& builder) {
|
||||||
|
auto ty = builder.builder->getInt32Ty();
|
||||||
|
return llvm::ConstantInt::get(ty, this->m_value);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ReturnStatement::codegen(codegen::Builder& builder) {
|
||||||
|
if (!builder.block)
|
||||||
|
return;
|
||||||
|
|
||||||
|
builder.builder->SetInsertPoint(builder.block.get());
|
||||||
|
|
||||||
|
auto value = this->m_expr->codegen(builder);
|
||||||
|
builder.builder->CreateRet(value);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Function::codegen(codegen::Builder& builder) {
|
||||||
|
auto ret_ty = this->m_return_ty->codegen(builder);
|
||||||
|
std::vector<llvm::Type*> params{};
|
||||||
|
|
||||||
|
|
||||||
|
auto fn_ty = llvm::FunctionType::get(ret_ty, params, false);
|
||||||
|
auto function = llvm::Function::Create(
|
||||||
|
fn_ty,
|
||||||
|
llvm::GlobalValue::LinkageTypes::ExternalLinkage,
|
||||||
|
this->m_name,
|
||||||
|
builder.mod.get()
|
||||||
|
);
|
||||||
|
auto BB = std::unique_ptr<llvm::BasicBlock>{ llvm::BasicBlock::Create(*builder.context, "entry", function, nullptr) };
|
||||||
|
builder.block = std::move(BB);
|
||||||
|
|
||||||
|
for (auto& statement : this->m_statements) {
|
||||||
|
statement->codegen(builder);
|
||||||
|
}
|
||||||
|
|
||||||
|
llvm::verifyFunction(*function);
|
||||||
|
|
||||||
|
// unique_ptr is not really supposed to free the block
|
||||||
|
builder.block.release();
|
||||||
|
}
|
||||||
|
|
||||||
|
llvm::Type* FundamentalType::codegen(codegen::Builder& builder) {
|
||||||
|
switch (this->m_ty) {
|
||||||
|
case FundamentalTypeKind::Int:
|
||||||
|
return builder.builder->getInt32Ty();
|
||||||
|
default:
|
||||||
|
return builder.builder->getVoidTy();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
17
src/codegen.h
Normal file
17
src/codegen.h
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
#ifndef CODEGEN_H
|
||||||
|
#define CODEGEN_H
|
||||||
|
|
||||||
|
#include <memory>
|
||||||
|
#include <llvm/IR/LLVMContext.h>
|
||||||
|
#include <llvm/IR/IRBuilder.h>
|
||||||
|
|
||||||
|
namespace codegen {
|
||||||
|
struct Builder {
|
||||||
|
std::unique_ptr<llvm::LLVMContext> context;
|
||||||
|
std::unique_ptr<llvm::Module> mod;
|
||||||
|
std::unique_ptr<llvm::IRBuilder<>> builder;
|
||||||
|
std::unique_ptr<llvm::BasicBlock> block;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
40
src/main.cpp
40
src/main.cpp
@ -61,11 +61,45 @@ int main() {
|
|||||||
}
|
}
|
||||||
stream.expect(token::Type::Eof);
|
stream.expect(token::Type::Eof);
|
||||||
|
|
||||||
for (int i = 0; i < statements.size(); i++) {
|
|
||||||
if (statements[i])
|
auto LLVMContext = std::make_unique<llvm::LLVMContext>();
|
||||||
std::cout << statements[i]->formatted() << std::endl;
|
auto LLVMModule = std::make_unique<llvm::Module>("test.c", *LLVMContext);
|
||||||
|
auto LLVMBuilder = std::make_unique<llvm::IRBuilder<>>(*LLVMContext);
|
||||||
|
|
||||||
|
codegen::Builder builder{
|
||||||
|
std::move(LLVMContext),
|
||||||
|
std::move(LLVMModule),
|
||||||
|
std::move(LLVMBuilder),
|
||||||
|
{}
|
||||||
|
};
|
||||||
|
|
||||||
|
for (auto& tls : statements) {
|
||||||
|
std::cout << tls->formatted() << std::endl;
|
||||||
|
tls->codegen(builder);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
llvm::InitializeAllTargetInfos();
|
||||||
|
llvm::InitializeAllTargets();
|
||||||
|
llvm::InitializeAllTargetMCs();
|
||||||
|
llvm::InitializeAllAsmParsers();
|
||||||
|
llvm::InitializeAllAsmPrinters();
|
||||||
|
|
||||||
|
auto TargetTriple = llvm::sys::getDefaultTargetTriple();
|
||||||
|
std::string Error;
|
||||||
|
auto Target = llvm::TargetRegistry::lookupTarget(TargetTriple, Error);
|
||||||
|
|
||||||
|
llvm::TargetOptions opt;
|
||||||
|
auto TargetMachine = Target->createTargetMachine(TargetTriple, "generic", "", opt, llvm::Reloc::PIC_);
|
||||||
|
builder.mod->setDataLayout(TargetMachine->createDataLayout());
|
||||||
|
|
||||||
|
std::string ir_output;
|
||||||
|
llvm::raw_string_ostream dest{ ir_output };
|
||||||
|
|
||||||
|
builder.mod->print(dest, nullptr);
|
||||||
|
dest.flush();
|
||||||
|
|
||||||
|
std::cout << ir_output << std::endl;
|
||||||
|
|
||||||
// LLVM Hello World
|
// LLVM Hello World
|
||||||
// llvm_hello_world();
|
// llvm_hello_world();
|
||||||
|
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user