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;
|
||||
}
|
||||
else {
|
||||
auto loaded = value->second.ty->load(builder, value->second.value);
|
||||
return codegen::StackValue{
|
||||
builder.builder->CreateLoad(value->second.ty->codegen(builder), value->second.value),
|
||||
value->second.ty
|
||||
loaded.first,
|
||||
loaded.second
|
||||
};
|
||||
}
|
||||
}
|
||||
@ -82,9 +83,14 @@ namespace AST {
|
||||
for (auto& arg : this->m_args) {
|
||||
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) {
|
||||
@ -158,33 +164,41 @@ namespace AST {
|
||||
|
||||
|
||||
void Function::codegen(codegen::Builder& builder, codegen::Scope& scope) {
|
||||
codegen::Scope inner_scope{ scope };
|
||||
|
||||
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) {
|
||||
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(
|
||||
fn_ty,
|
||||
llvm::dyn_cast<llvm::FunctionType>(fn_ty),
|
||||
llvm::GlobalValue::LinkageTypes::ExternalLinkage,
|
||||
this->m_name,
|
||||
builder.mod.get()
|
||||
);
|
||||
|
||||
scope.values[this->m_name] = codegen::StackValue{ function, fn_ty_ptr };
|
||||
|
||||
auto BB = llvm::BasicBlock::Create(*builder.context, "entry", function, nullptr);
|
||||
builder.block = BB;
|
||||
|
||||
codegen::Scope inner_scope{ scope };
|
||||
|
||||
int counter = 0;
|
||||
for (auto& param : this->m_params) {
|
||||
auto param_ty_ptr = param_ty_ptrs[counter];
|
||||
auto arg = function->getArg(counter++);
|
||||
arg->setName(param.first);
|
||||
inner_scope.values[param.first] = codegen::StackValue{
|
||||
arg,
|
||||
std::move(param.second),
|
||||
param_ty_ptr,
|
||||
};
|
||||
}
|
||||
|
||||
@ -209,4 +223,20 @@ namespace types {
|
||||
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) {
|
||||
switch (this->m_ty) {
|
||||
case FundamentalTypeKind::Int:
|
||||
return builder.builder->CreateAdd(lhs, rhs);
|
||||
return builder.builder->CreateAdd(lhs, rhs, "add");
|
||||
default:
|
||||
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) {
|
||||
switch (this->m_ty) {
|
||||
case FundamentalTypeKind::Int:
|
||||
return builder.builder->CreateSub(lhs, rhs);
|
||||
return builder.builder->CreateSub(lhs, rhs, "sub");
|
||||
default:
|
||||
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) {
|
||||
switch (this->m_ty) {
|
||||
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:
|
||||
throw std::runtime_error("Invalid type");
|
||||
}
|
||||
@ -81,4 +90,77 @@ namespace types {
|
||||
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 std::string formatted() = 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* 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;
|
||||
@ -42,6 +44,48 @@ namespace types {
|
||||
virtual ~FundamentalType() 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 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* 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;
|
||||
|
||||
Loading…
Reference in New Issue
Block a user