Make a bunch of tweaks, make fibonacci sequence compile

This commit is contained in:
Sofia 2026-04-10 19:55:34 +03:00
parent e653734f86
commit 5abcd6e00a
5 changed files with 188 additions and 18 deletions

16
.vscode/launch.json vendored Normal file
View 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}"
}
]
}

View File

@ -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);
}
} }

View File

@ -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");
}
} }

View File

@ -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;

8
test.c
View File

@ -1,11 +1,9 @@
int fibonacci(int n) { int fibonacci(int n) {
if (n < 2) if (n < 2)
return 0; return 1;
return fibonacci(n - 1); return fibonacci(n - 1) + fibonacci(n - 2);
} }
int main() { int main() {
int a = 5; return fibonacci(10);
a = 15 + 20;
return a - 30;
} }