Make a bunch of tweaks, make fibonacci sequence compile
This commit is contained in:
parent
e653734f86
commit
5abcd6e00a
16
.vscode/launch.json
vendored
Normal file
16
.vscode/launch.json
vendored
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
{
|
||||||
|
// Use IntelliSense to learn about possible attributes.
|
||||||
|
// Hover to view descriptions of existing attributes.
|
||||||
|
// For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
|
||||||
|
"version": "0.2.0",
|
||||||
|
"configurations": [
|
||||||
|
{
|
||||||
|
"type": "lldb",
|
||||||
|
"request": "launch",
|
||||||
|
"name": "Debug",
|
||||||
|
"program": "${workspaceFolder}/build/llvm_c_compiler",
|
||||||
|
"args": [],
|
||||||
|
"cwd": "${workspaceFolder}"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
@ -33,9 +33,10 @@ namespace AST {
|
|||||||
return value->second;
|
return value->second;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
|
auto loaded = value->second.ty->load(builder, value->second.value);
|
||||||
return codegen::StackValue{
|
return codegen::StackValue{
|
||||||
builder.builder->CreateLoad(value->second.ty->codegen(builder), value->second.value),
|
loaded.first,
|
||||||
value->second.ty
|
loaded.second
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -82,9 +83,14 @@ namespace AST {
|
|||||||
for (auto& arg : this->m_args) {
|
for (auto& arg : this->m_args) {
|
||||||
args.push_back(arg->codegen(builder, scope).value);
|
args.push_back(arg->codegen(builder, scope).value);
|
||||||
}
|
}
|
||||||
auto function = this->m_fn_expr->codegen(builder, scope);
|
auto with_lvalue = scope.with_lvalue();
|
||||||
|
auto function = this->m_fn_expr->codegen(builder, with_lvalue);
|
||||||
|
|
||||||
builder.builder->CreateCall(dyn_cast<llvm::FunctionType>(function.ty->codegen(builder)), function.value);
|
auto value = builder.builder->CreateCall(llvm::dyn_cast<llvm::FunctionType>(function.ty->codegen(builder)), function.value, args, "call");
|
||||||
|
return codegen::StackValue{
|
||||||
|
value,
|
||||||
|
*function.ty->return_type(),
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
void ReturnStatement::codegen(codegen::Builder& builder, codegen::Scope& scope) {
|
void ReturnStatement::codegen(codegen::Builder& builder, codegen::Scope& scope) {
|
||||||
@ -158,33 +164,41 @@ namespace AST {
|
|||||||
|
|
||||||
|
|
||||||
void Function::codegen(codegen::Builder& builder, codegen::Scope& scope) {
|
void Function::codegen(codegen::Builder& builder, codegen::Scope& scope) {
|
||||||
codegen::Scope inner_scope{ scope };
|
|
||||||
|
|
||||||
auto ret_ty = this->m_return_ty->codegen(builder);
|
auto ret_ty = this->m_return_ty->codegen(builder);
|
||||||
std::vector<llvm::Type*> params{};
|
|
||||||
|
std::shared_ptr<types::Type> ret_ty_ptr{ std::move(this->m_return_ty) };
|
||||||
|
std::vector<std::shared_ptr<types::Type>> param_ty_ptrs{};
|
||||||
|
|
||||||
for (auto& param : this->m_params) {
|
for (auto& param : this->m_params) {
|
||||||
params.push_back(param.second->codegen(builder));
|
param_ty_ptrs.push_back(std::move(param.second));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
auto fn_ty_ptr = std::shared_ptr<types::Type>{ new types::FunctionType{ ret_ty_ptr, param_ty_ptrs } };
|
||||||
|
|
||||||
auto fn_ty = llvm::FunctionType::get(ret_ty, params, false);
|
auto fn_ty = fn_ty_ptr->codegen(builder);
|
||||||
auto function = llvm::Function::Create(
|
auto function = llvm::Function::Create(
|
||||||
fn_ty,
|
llvm::dyn_cast<llvm::FunctionType>(fn_ty),
|
||||||
llvm::GlobalValue::LinkageTypes::ExternalLinkage,
|
llvm::GlobalValue::LinkageTypes::ExternalLinkage,
|
||||||
this->m_name,
|
this->m_name,
|
||||||
builder.mod.get()
|
builder.mod.get()
|
||||||
);
|
);
|
||||||
|
|
||||||
|
scope.values[this->m_name] = codegen::StackValue{ function, fn_ty_ptr };
|
||||||
|
|
||||||
auto BB = llvm::BasicBlock::Create(*builder.context, "entry", function, nullptr);
|
auto BB = llvm::BasicBlock::Create(*builder.context, "entry", function, nullptr);
|
||||||
builder.block = BB;
|
builder.block = BB;
|
||||||
|
|
||||||
|
codegen::Scope inner_scope{ scope };
|
||||||
|
|
||||||
int counter = 0;
|
int counter = 0;
|
||||||
for (auto& param : this->m_params) {
|
for (auto& param : this->m_params) {
|
||||||
|
auto param_ty_ptr = param_ty_ptrs[counter];
|
||||||
auto arg = function->getArg(counter++);
|
auto arg = function->getArg(counter++);
|
||||||
arg->setName(param.first);
|
arg->setName(param.first);
|
||||||
inner_scope.values[param.first] = codegen::StackValue{
|
inner_scope.values[param.first] = codegen::StackValue{
|
||||||
arg,
|
arg,
|
||||||
std::move(param.second),
|
param_ty_ptr,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -209,4 +223,20 @@ namespace types {
|
|||||||
return builder.builder->getVoidTy();
|
return builder.builder->getVoidTy();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
llvm::Type* FunctionType::codegen(codegen::Builder& builder) {
|
||||||
|
std::vector<llvm::Type*> params{};
|
||||||
|
|
||||||
|
for (auto& param : this->m_param_tys) {
|
||||||
|
params.push_back(param->codegen(builder));
|
||||||
|
}
|
||||||
|
|
||||||
|
auto ret_ty = this->m_ret_ty->codegen(builder);
|
||||||
|
|
||||||
|
return llvm::FunctionType::get(ret_ty, params, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
llvm::Type* PointerType::codegen(codegen::Builder& builder) {
|
||||||
|
return llvm::PointerType::get(this->m_inner->codegen(builder), 0);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
@ -46,10 +46,19 @@ namespace types {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::optional<std::shared_ptr<Type>> FundamentalType::return_type() {
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
|
||||||
|
std::pair<llvm::Value*, std::shared_ptr<Type>> FundamentalType::load(codegen::Builder& builder, llvm::Value* ptr) {
|
||||||
|
auto self = std::make_shared<FundamentalType>(*this);
|
||||||
|
return std::pair(ptr, self);
|
||||||
|
}
|
||||||
|
|
||||||
llvm::Value* FundamentalType::add(codegen::Builder& builder, llvm::Value* lhs, llvm::Value* rhs) {
|
llvm::Value* FundamentalType::add(codegen::Builder& builder, llvm::Value* lhs, llvm::Value* rhs) {
|
||||||
switch (this->m_ty) {
|
switch (this->m_ty) {
|
||||||
case FundamentalTypeKind::Int:
|
case FundamentalTypeKind::Int:
|
||||||
return builder.builder->CreateAdd(lhs, rhs);
|
return builder.builder->CreateAdd(lhs, rhs, "add");
|
||||||
default:
|
default:
|
||||||
throw std::runtime_error("Invalid type for add");
|
throw std::runtime_error("Invalid type for add");
|
||||||
}
|
}
|
||||||
@ -58,7 +67,7 @@ namespace types {
|
|||||||
llvm::Value* FundamentalType::sub(codegen::Builder& builder, llvm::Value* lhs, llvm::Value* rhs) {
|
llvm::Value* FundamentalType::sub(codegen::Builder& builder, llvm::Value* lhs, llvm::Value* rhs) {
|
||||||
switch (this->m_ty) {
|
switch (this->m_ty) {
|
||||||
case FundamentalTypeKind::Int:
|
case FundamentalTypeKind::Int:
|
||||||
return builder.builder->CreateSub(lhs, rhs);
|
return builder.builder->CreateSub(lhs, rhs, "sub");
|
||||||
default:
|
default:
|
||||||
throw std::runtime_error("Invalid type");
|
throw std::runtime_error("Invalid type");
|
||||||
}
|
}
|
||||||
@ -67,7 +76,7 @@ namespace types {
|
|||||||
llvm::Value* FundamentalType::lt(codegen::Builder& builder, llvm::Value* lhs, llvm::Value* rhs) {
|
llvm::Value* FundamentalType::lt(codegen::Builder& builder, llvm::Value* lhs, llvm::Value* rhs) {
|
||||||
switch (this->m_ty) {
|
switch (this->m_ty) {
|
||||||
case FundamentalTypeKind::Int:
|
case FundamentalTypeKind::Int:
|
||||||
return builder.builder->CreateCmp(llvm::CmpInst::Predicate::ICMP_SLT, lhs, rhs);
|
return builder.builder->CreateCmp(llvm::CmpInst::Predicate::ICMP_SLT, lhs, rhs, "cmp");
|
||||||
default:
|
default:
|
||||||
throw std::runtime_error("Invalid type");
|
throw std::runtime_error("Invalid type");
|
||||||
}
|
}
|
||||||
@ -81,4 +90,77 @@ namespace types {
|
|||||||
throw std::runtime_error("Invalid type");
|
throw std::runtime_error("Invalid type");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::string FunctionType::formatted() {
|
||||||
|
std::stringstream out{ "" };
|
||||||
|
out << "(";
|
||||||
|
|
||||||
|
int counter = 0;
|
||||||
|
for (auto& param : this->m_param_tys) {
|
||||||
|
if (counter++ > 0)
|
||||||
|
out << ", ";
|
||||||
|
out << param->formatted();
|
||||||
|
}
|
||||||
|
|
||||||
|
out << ") -> " << this->m_ret_ty->formatted();
|
||||||
|
return out.str();
|
||||||
|
}
|
||||||
|
|
||||||
|
std::optional<std::shared_ptr<Type>> FunctionType::return_type() {
|
||||||
|
return this->m_ret_ty;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::pair<llvm::Value*, std::shared_ptr<Type>> FunctionType::load(codegen::Builder& builder, llvm::Value* ptr) {
|
||||||
|
auto self = std::make_shared<FunctionType>(*this);
|
||||||
|
return std::pair(ptr, self);
|
||||||
|
}
|
||||||
|
|
||||||
|
llvm::Value* FunctionType::add(codegen::Builder& builder, llvm::Value* lhs, llvm::Value* rhs) {
|
||||||
|
throw std::runtime_error("Invalid operation for functions");
|
||||||
|
}
|
||||||
|
|
||||||
|
llvm::Value* FunctionType::sub(codegen::Builder& builder, llvm::Value* lhs, llvm::Value* rhs) {
|
||||||
|
throw std::runtime_error("Invalid operation for functions");
|
||||||
|
}
|
||||||
|
|
||||||
|
llvm::Value* FunctionType::lt(codegen::Builder& builder, llvm::Value* lhs, llvm::Value* rhs) {
|
||||||
|
throw std::runtime_error("Invalid operation for functions");
|
||||||
|
}
|
||||||
|
|
||||||
|
llvm::Value* FunctionType::gt(codegen::Builder& builder, llvm::Value* lhs, llvm::Value* rhs) {
|
||||||
|
throw std::runtime_error("Invalid operation for functions");
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string PointerType::formatted() {
|
||||||
|
std::stringstream out{ "" };
|
||||||
|
out << this->m_inner << "*";
|
||||||
|
return out.str();
|
||||||
|
}
|
||||||
|
|
||||||
|
std::optional<std::shared_ptr<Type>> PointerType::return_type() {
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
|
||||||
|
std::pair<llvm::Value*, std::shared_ptr<Type>> PointerType::load(codegen::Builder& builder, llvm::Value* ptr) {
|
||||||
|
return std::pair(
|
||||||
|
builder.builder->CreateLoad(this->m_inner->codegen(builder), ptr),
|
||||||
|
this->m_inner
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
llvm::Value* PointerType::add(codegen::Builder& builder, llvm::Value* lhs, llvm::Value* rhs) {
|
||||||
|
throw std::runtime_error("Invalid operation for pointers");
|
||||||
|
}
|
||||||
|
|
||||||
|
llvm::Value* PointerType::sub(codegen::Builder& builder, llvm::Value* lhs, llvm::Value* rhs) {
|
||||||
|
throw std::runtime_error("Invalid operation for pointers");
|
||||||
|
}
|
||||||
|
|
||||||
|
llvm::Value* PointerType::lt(codegen::Builder& builder, llvm::Value* lhs, llvm::Value* rhs) {
|
||||||
|
throw std::runtime_error("Invalid operation for pointers");
|
||||||
|
}
|
||||||
|
|
||||||
|
llvm::Value* PointerType::gt(codegen::Builder& builder, llvm::Value* lhs, llvm::Value* rhs) {
|
||||||
|
throw std::runtime_error("Invalid operation for pointers");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
44
src/types.h
44
src/types.h
@ -28,6 +28,8 @@ namespace types {
|
|||||||
virtual ~Type() = default;
|
virtual ~Type() = default;
|
||||||
virtual std::string formatted() = 0;
|
virtual std::string formatted() = 0;
|
||||||
virtual llvm::Type* codegen(codegen::Builder& builder) = 0;
|
virtual llvm::Type* codegen(codegen::Builder& builder) = 0;
|
||||||
|
virtual std::pair<llvm::Value*, std::shared_ptr<Type>> load(codegen::Builder& builder, llvm::Value* ptr) = 0;
|
||||||
|
virtual std::optional<std::shared_ptr<Type>> return_type() = 0;
|
||||||
virtual llvm::Value* add(codegen::Builder& builder, llvm::Value* lhs, llvm::Value* rhs) = 0;
|
virtual llvm::Value* add(codegen::Builder& builder, llvm::Value* lhs, llvm::Value* rhs) = 0;
|
||||||
virtual llvm::Value* sub(codegen::Builder& builder, llvm::Value* lhs, llvm::Value* rhs) = 0;
|
virtual llvm::Value* sub(codegen::Builder& builder, llvm::Value* lhs, llvm::Value* rhs) = 0;
|
||||||
virtual llvm::Value* lt(codegen::Builder& builder, llvm::Value* lhs, llvm::Value* rhs) = 0;
|
virtual llvm::Value* lt(codegen::Builder& builder, llvm::Value* lhs, llvm::Value* rhs) = 0;
|
||||||
@ -42,6 +44,48 @@ namespace types {
|
|||||||
virtual ~FundamentalType() override = default;
|
virtual ~FundamentalType() override = default;
|
||||||
virtual std::string formatted() override;
|
virtual std::string formatted() override;
|
||||||
virtual llvm::Type* codegen(codegen::Builder& builder) override;
|
virtual llvm::Type* codegen(codegen::Builder& builder) override;
|
||||||
|
virtual std::pair<llvm::Value*, std::shared_ptr<Type>> load(codegen::Builder& builder, llvm::Value* ptr) override;
|
||||||
|
virtual std::optional<std::shared_ptr<Type>> return_type() override;
|
||||||
|
virtual llvm::Value* add(codegen::Builder& builder, llvm::Value* lhs, llvm::Value* rhs) override;
|
||||||
|
virtual llvm::Value* sub(codegen::Builder& builder, llvm::Value* lhs, llvm::Value* rhs) override;
|
||||||
|
virtual llvm::Value* lt(codegen::Builder& builder, llvm::Value* lhs, llvm::Value* rhs) override;
|
||||||
|
virtual llvm::Value* gt(codegen::Builder& builder, llvm::Value* lhs, llvm::Value* rhs) override;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
class FunctionType : public Type {
|
||||||
|
private:
|
||||||
|
std::shared_ptr<Type> m_ret_ty;
|
||||||
|
std::vector<std::shared_ptr<Type>> m_param_tys;
|
||||||
|
public:
|
||||||
|
FunctionType(std::shared_ptr<Type> ret_ty, std::vector<std::shared_ptr<Type>> param_tys)
|
||||||
|
: m_ret_ty{ std::move(ret_ty) }, m_param_tys{ std::move(param_tys) } {
|
||||||
|
}
|
||||||
|
virtual ~FunctionType() override = default;
|
||||||
|
virtual std::string formatted() override;
|
||||||
|
virtual llvm::Type* codegen(codegen::Builder& builder) override;
|
||||||
|
virtual std::pair<llvm::Value*, std::shared_ptr<Type>> load(codegen::Builder& builder, llvm::Value* ptr) override;
|
||||||
|
virtual std::optional<std::shared_ptr<Type>> return_type() override;
|
||||||
|
virtual llvm::Value* add(codegen::Builder& builder, llvm::Value* lhs, llvm::Value* rhs) override;
|
||||||
|
virtual llvm::Value* sub(codegen::Builder& builder, llvm::Value* lhs, llvm::Value* rhs) override;
|
||||||
|
virtual llvm::Value* lt(codegen::Builder& builder, llvm::Value* lhs, llvm::Value* rhs) override;
|
||||||
|
virtual llvm::Value* gt(codegen::Builder& builder, llvm::Value* lhs, llvm::Value* rhs) override;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
class PointerType : public Type {
|
||||||
|
private:
|
||||||
|
std::shared_ptr<Type> m_inner;
|
||||||
|
public:
|
||||||
|
PointerType(std::shared_ptr<Type> inner)
|
||||||
|
: m_inner{ std::move(inner) } {
|
||||||
|
}
|
||||||
|
virtual ~PointerType() override = default;
|
||||||
|
virtual std::string formatted() override;
|
||||||
|
virtual llvm::Type* codegen(codegen::Builder& builder) override;
|
||||||
|
virtual std::pair<llvm::Value*, std::shared_ptr<Type>> load(codegen::Builder& builder, llvm::Value* ptr) override;
|
||||||
|
virtual std::optional<std::shared_ptr<Type>> return_type() override;
|
||||||
virtual llvm::Value* add(codegen::Builder& builder, llvm::Value* lhs, llvm::Value* rhs) override;
|
virtual llvm::Value* add(codegen::Builder& builder, llvm::Value* lhs, llvm::Value* rhs) override;
|
||||||
virtual llvm::Value* sub(codegen::Builder& builder, llvm::Value* lhs, llvm::Value* rhs) override;
|
virtual llvm::Value* sub(codegen::Builder& builder, llvm::Value* lhs, llvm::Value* rhs) override;
|
||||||
virtual llvm::Value* lt(codegen::Builder& builder, llvm::Value* lhs, llvm::Value* rhs) override;
|
virtual llvm::Value* lt(codegen::Builder& builder, llvm::Value* lhs, llvm::Value* rhs) override;
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user