Add Struct and StructRef-types
This commit is contained in:
parent
5fc58ea1c5
commit
bca18b4f1b
@ -1,6 +1,8 @@
|
|||||||
#ifndef BUILDER_H
|
#ifndef BUILDER_H
|
||||||
#define BUILDER_H
|
#define BUILDER_H
|
||||||
|
|
||||||
|
#include <map>
|
||||||
|
|
||||||
#include <llvm/IR/LLVMContext.h>
|
#include <llvm/IR/LLVMContext.h>
|
||||||
#include <llvm/IR/IRBuilder.h>
|
#include <llvm/IR/IRBuilder.h>
|
||||||
|
|
||||||
@ -11,6 +13,8 @@ namespace codegen {
|
|||||||
std::unique_ptr<llvm::IRBuilder<>> builder;
|
std::unique_ptr<llvm::IRBuilder<>> builder;
|
||||||
llvm::BasicBlock* block;
|
llvm::BasicBlock* block;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
typedef std::map<std::string, llvm::Type*> TypeMap;
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
@ -32,13 +32,15 @@ namespace types {
|
|||||||
if (target_ty->is_signed()) {
|
if (target_ty->is_signed()) {
|
||||||
casts.push_back(CastDefinition{ source_ty, target_ty, allow_implicit,
|
casts.push_back(CastDefinition{ source_ty, target_ty, allow_implicit,
|
||||||
[](codegen::Builder& builder, std::shared_ptr<Type> target, llvm::Value* value) {
|
[](codegen::Builder& builder, std::shared_ptr<Type> target, llvm::Value* value) {
|
||||||
return builder.builder->CreateSExtOrTrunc(value, target->codegen(builder), "cast");
|
codegen::TypeMap empty {};
|
||||||
|
return builder.builder->CreateSExtOrTrunc(value, target->codegen(builder, empty), "cast");
|
||||||
} });
|
} });
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
casts.push_back(CastDefinition{ source_ty, target_ty, allow_implicit,
|
casts.push_back(CastDefinition{ source_ty, target_ty, allow_implicit,
|
||||||
[](codegen::Builder& builder, std::shared_ptr<Type> target, llvm::Value* value) {
|
[](codegen::Builder& builder, std::shared_ptr<Type> target, llvm::Value* value) {
|
||||||
return builder.builder->CreateZExtOrTrunc(value, target->codegen(builder), "cast");
|
codegen::TypeMap empty {};
|
||||||
|
return builder.builder->CreateZExtOrTrunc(value, target->codegen(builder, empty), "cast");
|
||||||
} });
|
} });
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -60,14 +62,6 @@ namespace types {
|
|||||||
return {};
|
return {};
|
||||||
return CastDefinition{ casted_ty, target_ty, true,
|
return CastDefinition{ casted_ty, target_ty, true,
|
||||||
[](codegen::Builder&, std::shared_ptr<Type>, llvm::Value* value) {
|
[](codegen::Builder&, std::shared_ptr<Type>, llvm::Value* value) {
|
||||||
// auto ptr_ty = dynamic_cast<types::PointerType*>(target.get());
|
|
||||||
|
|
||||||
// std::vector<llvm::Value*> indices {};
|
|
||||||
// indices.push_back(llvm::ConstantInt::get(
|
|
||||||
// builder.builder->getInt32Ty(),
|
|
||||||
// 0
|
|
||||||
// ));
|
|
||||||
// return builder.builder->CreateGEP(ptr_ty->m_inner->codegen(builder), value, indices, "arraydecay");
|
|
||||||
return value;
|
return value;
|
||||||
} };
|
} };
|
||||||
}
|
}
|
||||||
|
|||||||
@ -11,7 +11,7 @@
|
|||||||
|
|
||||||
namespace codegen {
|
namespace codegen {
|
||||||
Scope Scope::with_lvalue() {
|
Scope Scope::with_lvalue() {
|
||||||
return Scope{ this->binops, this->casts, this->values, true };
|
return Scope{ this->binops, this->casts, this->structs, this->values, true };
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -20,8 +20,8 @@ namespace AST {
|
|||||||
return this->m_ty;
|
return this->m_ty;
|
||||||
}
|
}
|
||||||
|
|
||||||
codegen::StackValue IntLiteralExpression::codegen(codegen::Builder& builder, codegen::Scope&) {
|
codegen::StackValue IntLiteralExpression::codegen(codegen::Builder& builder, codegen::Scope& scope) {
|
||||||
auto ty = this->m_ty->codegen(builder);
|
auto ty = this->m_ty->codegen(builder, scope.structs);
|
||||||
|
|
||||||
return codegen::StackValue{
|
return codegen::StackValue{
|
||||||
llvm::ConstantInt::get(ty, this->m_value),
|
llvm::ConstantInt::get(ty, this->m_value),
|
||||||
@ -56,7 +56,7 @@ namespace AST {
|
|||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
return codegen::StackValue{
|
return codegen::StackValue{
|
||||||
builder.builder->CreateLoad(stack_type->codegen(builder), global_str, "literal"),
|
builder.builder->CreateLoad(stack_type->codegen(builder, scope.structs), global_str, "literal"),
|
||||||
std::unique_ptr<types::Type>{stack_type},
|
std::unique_ptr<types::Type>{stack_type},
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
@ -83,7 +83,7 @@ namespace AST {
|
|||||||
return value->second;
|
return value->second;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
auto loaded = value->second.ty->load(builder, value->second.value);
|
auto loaded = value->second.ty->load(builder, value->second.value, scope.structs);
|
||||||
return codegen::StackValue{
|
return codegen::StackValue{
|
||||||
loaded.first,
|
loaded.first,
|
||||||
loaded.second
|
loaded.second
|
||||||
@ -160,7 +160,7 @@ namespace AST {
|
|||||||
}
|
}
|
||||||
auto function = this->m_fn_expr->codegen(builder, scope);
|
auto function = this->m_fn_expr->codegen(builder, scope);
|
||||||
|
|
||||||
auto value = builder.builder->CreateCall(llvm::dyn_cast<llvm::FunctionType>(function.ty->codegen(builder)), function.value, args, "call");
|
auto value = builder.builder->CreateCall(llvm::dyn_cast<llvm::FunctionType>(function.ty->codegen(builder, scope.structs)), function.value, args, "call");
|
||||||
return codegen::StackValue{
|
return codegen::StackValue{
|
||||||
value,
|
value,
|
||||||
*function.ty->return_type(),
|
*function.ty->return_type(),
|
||||||
@ -226,7 +226,7 @@ namespace AST {
|
|||||||
codegen::StackValue DerefExpression::codegen(codegen::Builder& builder, codegen::Scope& scope) {
|
codegen::StackValue DerefExpression::codegen(codegen::Builder& builder, codegen::Scope& scope) {
|
||||||
auto value = this->m_expr->codegen(builder, scope);
|
auto value = this->m_expr->codegen(builder, scope);
|
||||||
if (value.ty->m_kind == types::TypeKind::Pointer) {
|
if (value.ty->m_kind == types::TypeKind::Pointer) {
|
||||||
auto loaded = value.ty->load(builder, value.value);
|
auto loaded = value.ty->load(builder, value.value, scope.structs);
|
||||||
return codegen::StackValue{
|
return codegen::StackValue{
|
||||||
loaded.first,
|
loaded.first,
|
||||||
loaded.second
|
loaded.second
|
||||||
@ -267,7 +267,7 @@ namespace AST {
|
|||||||
if (ptr_ty->m_inner->m_kind == types::TypeKind::Pointer) {
|
if (ptr_ty->m_inner->m_kind == types::TypeKind::Pointer) {
|
||||||
auto inner_ptr_ty = dynamic_cast<types::PointerType*>(ptr_ty->m_inner.get());
|
auto inner_ptr_ty = dynamic_cast<types::PointerType*>(ptr_ty->m_inner.get());
|
||||||
|
|
||||||
auto gep_value = builder.builder->CreateGEP(inner_ptr_ty->m_inner->codegen(builder), value.value, idx_list, "GEP");
|
auto gep_value = builder.builder->CreateGEP(inner_ptr_ty->m_inner->codegen(builder, scope.structs), value.value, idx_list, "GEP");
|
||||||
if (scope.is_lvalue) {
|
if (scope.is_lvalue) {
|
||||||
return codegen::StackValue{
|
return codegen::StackValue{
|
||||||
gep_value,
|
gep_value,
|
||||||
@ -275,7 +275,7 @@ namespace AST {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
auto loaded = value.ty->load(builder, gep_value);
|
auto loaded = value.ty->load(builder, gep_value, scope.structs);
|
||||||
return codegen::StackValue{
|
return codegen::StackValue{
|
||||||
loaded.first,
|
loaded.first,
|
||||||
loaded.second
|
loaded.second
|
||||||
@ -287,7 +287,7 @@ namespace AST {
|
|||||||
|
|
||||||
// Must be an array otherwise
|
// Must be an array otherwise
|
||||||
auto arr_ty = dynamic_cast<types::ArrayType*>(ptr_ty->m_inner.get());
|
auto arr_ty = dynamic_cast<types::ArrayType*>(ptr_ty->m_inner.get());
|
||||||
auto gep_value = builder.builder->CreateGEP(arr_ty->m_inner->codegen(builder), value.value, idx_list, "GEP");
|
auto gep_value = builder.builder->CreateGEP(arr_ty->m_inner->codegen(builder, scope.structs), value.value, idx_list, "GEP");
|
||||||
if (scope.is_lvalue) {
|
if (scope.is_lvalue) {
|
||||||
return codegen::StackValue{
|
return codegen::StackValue{
|
||||||
gep_value,
|
gep_value,
|
||||||
@ -296,7 +296,7 @@ namespace AST {
|
|||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
auto inner_ptr_ty = types::PointerType{ arr_ty->m_inner };
|
auto inner_ptr_ty = types::PointerType{ arr_ty->m_inner };
|
||||||
auto loaded = inner_ptr_ty.load(builder, gep_value);
|
auto loaded = inner_ptr_ty.load(builder, gep_value, scope.structs);
|
||||||
return codegen::StackValue{
|
return codegen::StackValue{
|
||||||
loaded.first,
|
loaded.first,
|
||||||
loaded.second
|
loaded.second
|
||||||
@ -304,7 +304,7 @@ namespace AST {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
auto gep_value = builder.builder->CreateGEP(ptr_ty->m_inner->codegen(builder), value.value, idx_list, "GEP");
|
auto gep_value = builder.builder->CreateGEP(ptr_ty->m_inner->codegen(builder, scope.structs), value.value, idx_list, "GEP");
|
||||||
if (scope.is_lvalue) {
|
if (scope.is_lvalue) {
|
||||||
return codegen::StackValue{
|
return codegen::StackValue{
|
||||||
gep_value,
|
gep_value,
|
||||||
@ -312,7 +312,7 @@ namespace AST {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
auto loaded = value.ty->load(builder, gep_value);
|
auto loaded = value.ty->load(builder, gep_value, scope.structs);
|
||||||
return codegen::StackValue{
|
return codegen::StackValue{
|
||||||
loaded.first,
|
loaded.first,
|
||||||
loaded.second
|
loaded.second
|
||||||
@ -331,7 +331,7 @@ namespace AST {
|
|||||||
}
|
}
|
||||||
|
|
||||||
codegen::StackValue ListInitializerExpression::codegen(codegen::Builder& builder, codegen::Scope& scope) {
|
codegen::StackValue ListInitializerExpression::codegen(codegen::Builder& builder, codegen::Scope& scope) {
|
||||||
auto array_ptr = builder.builder->CreateAlloca(this->m_ty->codegen(builder));
|
auto array_ptr = builder.builder->CreateAlloca(this->m_ty->codegen(builder, scope.structs));
|
||||||
|
|
||||||
if (this->m_ty->m_kind == types::TypeKind::Array) {
|
if (this->m_ty->m_kind == types::TypeKind::Array) {
|
||||||
auto array_ty = dynamic_cast<types::ArrayType*>(this->m_ty.get());
|
auto array_ty = dynamic_cast<types::ArrayType*>(this->m_ty.get());
|
||||||
@ -341,7 +341,7 @@ namespace AST {
|
|||||||
std::vector<llvm::Value*> indices{};
|
std::vector<llvm::Value*> indices{};
|
||||||
indices.push_back(llvm::ConstantInt::get(builder.builder->getInt32Ty(), counter++));
|
indices.push_back(llvm::ConstantInt::get(builder.builder->getInt32Ty(), counter++));
|
||||||
auto gep = builder.builder->CreateGEP(
|
auto gep = builder.builder->CreateGEP(
|
||||||
array_ty->m_inner->codegen(builder), array_ptr, indices, "GEP");
|
array_ty->m_inner->codegen(builder, scope.structs), array_ptr, indices, "GEP");
|
||||||
builder.builder->CreateStore(expr->codegen(builder, scope).value, gep);
|
builder.builder->CreateStore(expr->codegen(builder, scope).value, gep);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -353,7 +353,7 @@ namespace AST {
|
|||||||
return codegen::StackValue{ array_ptr, ptr_ty };
|
return codegen::StackValue{ array_ptr, ptr_ty };
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
auto loaded = ptr_ty->load(builder, array_ptr);
|
auto loaded = ptr_ty->load(builder, array_ptr, scope.structs);
|
||||||
return codegen::StackValue{ loaded.first, loaded.second };
|
return codegen::StackValue{ loaded.first, loaded.second };
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -387,7 +387,7 @@ namespace AST {
|
|||||||
|
|
||||||
builder.builder->SetInsertPoint(builder.block);
|
builder.builder->SetInsertPoint(builder.block);
|
||||||
|
|
||||||
auto ty = this->m_type->codegen(builder);
|
auto ty = this->m_type->codegen(builder, scope.structs);
|
||||||
auto ptr = builder.builder->CreateAlloca(ty);
|
auto ptr = builder.builder->CreateAlloca(ty);
|
||||||
if (this->m_expr.has_value()) {
|
if (this->m_expr.has_value()) {
|
||||||
auto value = this->m_expr->get()->codegen(builder, scope);
|
auto value = this->m_expr->get()->codegen(builder, scope);
|
||||||
@ -445,7 +445,7 @@ namespace AST {
|
|||||||
|
|
||||||
auto fn_ty_ptr = std::shared_ptr<types::Type>{ new types::FunctionType{ ret_ty_ptr, param_ty_ptrs, this->m_is_vararg } };
|
auto fn_ty_ptr = std::shared_ptr<types::Type>{ new types::FunctionType{ ret_ty_ptr, param_ty_ptrs, this->m_is_vararg } };
|
||||||
|
|
||||||
auto fn_ty = fn_ty_ptr->codegen(builder);
|
auto fn_ty = fn_ty_ptr->codegen(builder, scope.structs);
|
||||||
auto function = llvm::Function::Create(
|
auto function = llvm::Function::Create(
|
||||||
llvm::dyn_cast<llvm::FunctionType>(fn_ty),
|
llvm::dyn_cast<llvm::FunctionType>(fn_ty),
|
||||||
llvm::GlobalValue::LinkageTypes::ExternalLinkage,
|
llvm::GlobalValue::LinkageTypes::ExternalLinkage,
|
||||||
@ -476,7 +476,7 @@ namespace AST {
|
|||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
builder.builder->SetInsertPoint(BB);
|
builder.builder->SetInsertPoint(BB);
|
||||||
auto arg_ptr = builder.builder->CreateAlloca(param_ty_ptrs[counter]->codegen(builder));
|
auto arg_ptr = builder.builder->CreateAlloca(param_ty_ptrs[counter]->codegen(builder, scope.structs));
|
||||||
auto param_ty_ptr = std::shared_ptr<types::Type>{
|
auto param_ty_ptr = std::shared_ptr<types::Type>{
|
||||||
new types::PointerType { param_ty_ptrs[counter]}
|
new types::PointerType { param_ty_ptrs[counter]}
|
||||||
};
|
};
|
||||||
@ -506,7 +506,7 @@ namespace AST {
|
|||||||
}
|
}
|
||||||
|
|
||||||
namespace types {
|
namespace types {
|
||||||
llvm::Type* FundamentalType::codegen(codegen::Builder& builder) {
|
llvm::Type* FundamentalType::codegen(codegen::Builder& builder, codegen::TypeMap&) {
|
||||||
switch (this->m_ty) {
|
switch (this->m_ty) {
|
||||||
case FundamentalTypeKind::Int:
|
case FundamentalTypeKind::Int:
|
||||||
return builder.builder->getInt32Ty();
|
return builder.builder->getInt32Ty();
|
||||||
@ -521,23 +521,44 @@ namespace types {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
llvm::Type* FunctionType::codegen(codegen::Builder& builder) {
|
llvm::Type* FunctionType::codegen(codegen::Builder& builder, codegen::TypeMap& structs) {
|
||||||
std::vector<llvm::Type*> params{};
|
std::vector<llvm::Type*> params{};
|
||||||
|
|
||||||
for (auto& param : this->m_param_tys) {
|
for (auto& param : this->m_param_tys) {
|
||||||
params.push_back(param->codegen(builder));
|
params.push_back(param->codegen(builder, structs));
|
||||||
}
|
}
|
||||||
|
|
||||||
auto ret_ty = this->m_ret_ty->codegen(builder);
|
auto ret_ty = this->m_ret_ty->codegen(builder, structs);
|
||||||
|
|
||||||
return llvm::FunctionType::get(ret_ty, params, this->m_vararg);
|
return llvm::FunctionType::get(ret_ty, params, this->m_vararg);
|
||||||
}
|
}
|
||||||
|
|
||||||
llvm::Type* PointerType::codegen(codegen::Builder& builder) {
|
llvm::Type* PointerType::codegen(codegen::Builder& builder, codegen::TypeMap&) {
|
||||||
return llvm::PointerType::get(*builder.context, 0);
|
return llvm::PointerType::get(*builder.context, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
llvm::Type* ArrayType::codegen(codegen::Builder& builder) {
|
llvm::Type* ArrayType::codegen(codegen::Builder& builder, codegen::TypeMap& structs) {
|
||||||
return llvm::ArrayType::get(this->m_inner->codegen(builder), this->m_size);
|
return llvm::ArrayType::get(this->m_inner->codegen(builder, structs), this->m_size);
|
||||||
|
}
|
||||||
|
|
||||||
|
llvm::Type* StructType::codegen(codegen::Builder& builder, codegen::TypeMap& structs) {
|
||||||
|
if (this->m_fields) {
|
||||||
|
std::vector<llvm::Type*> fields{};
|
||||||
|
for (auto& field : *this->m_fields) {
|
||||||
|
fields.push_back(field.second->codegen(builder, structs));
|
||||||
|
}
|
||||||
|
|
||||||
|
auto ty = llvm::StructType::get(*builder.context, fields);
|
||||||
|
if (this->m_name)
|
||||||
|
ty->setName(*this->m_name);
|
||||||
|
return ty;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
return llvm::StructType::get(*builder.context);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
llvm::Type* StructRef::codegen(codegen::Builder&, codegen::TypeMap& structs) {
|
||||||
|
return structs[this->m_name];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -22,7 +22,9 @@ namespace codegen {
|
|||||||
std::vector<types::BinopDefinition>& binops;
|
std::vector<types::BinopDefinition>& binops;
|
||||||
std::vector<types::CastDefinition>& casts;
|
std::vector<types::CastDefinition>& casts;
|
||||||
|
|
||||||
|
TypeMap structs;
|
||||||
std::map<std::string, StackValue> values;
|
std::map<std::string, StackValue> values;
|
||||||
|
|
||||||
bool is_lvalue;
|
bool is_lvalue;
|
||||||
|
|
||||||
Scope with_lvalue();
|
Scope with_lvalue();
|
||||||
|
|||||||
@ -124,6 +124,7 @@ std::optional<CompileOutput> compile(std::string_view in_filename) {
|
|||||||
codegen::Scope cg_scope{
|
codegen::Scope cg_scope{
|
||||||
.binops = typecheck_state.binops,
|
.binops = typecheck_state.binops,
|
||||||
.casts = typecheck_state.casts,
|
.casts = typecheck_state.casts,
|
||||||
|
.structs = {},
|
||||||
.values = {},
|
.values = {},
|
||||||
.is_lvalue = false,
|
.is_lvalue = false,
|
||||||
};
|
};
|
||||||
|
|||||||
@ -4,6 +4,7 @@
|
|||||||
|
|
||||||
#include "types.h"
|
#include "types.h"
|
||||||
#include "binops.h"
|
#include "binops.h"
|
||||||
|
#include "builder.h"
|
||||||
|
|
||||||
namespace types {
|
namespace types {
|
||||||
int operator_precedence(BinOp& op) {
|
int operator_precedence(BinOp& op) {
|
||||||
@ -63,7 +64,7 @@ namespace types {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::pair<llvm::Value*, std::shared_ptr<Type>> FundamentalType::load(codegen::Builder&, llvm::Value* ptr) {
|
std::pair<llvm::Value*, std::shared_ptr<Type>> FundamentalType::load(codegen::Builder&, llvm::Value* ptr, codegen::TypeMap&) {
|
||||||
auto self = std::make_shared<FundamentalType>(*this);
|
auto self = std::make_shared<FundamentalType>(*this);
|
||||||
return std::pair(ptr, self);
|
return std::pair(ptr, self);
|
||||||
}
|
}
|
||||||
@ -118,7 +119,7 @@ namespace types {
|
|||||||
return this->m_ret_ty;
|
return this->m_ret_ty;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::pair<llvm::Value*, std::shared_ptr<Type>> FunctionType::load(codegen::Builder&, llvm::Value* ptr) {
|
std::pair<llvm::Value*, std::shared_ptr<Type>> FunctionType::load(codegen::Builder&, llvm::Value* ptr, codegen::TypeMap&) {
|
||||||
auto self = std::make_shared<FunctionType>(*this);
|
auto self = std::make_shared<FunctionType>(*this);
|
||||||
return std::pair(ptr, self);
|
return std::pair(ptr, self);
|
||||||
}
|
}
|
||||||
@ -133,9 +134,9 @@ namespace types {
|
|||||||
return out.str();
|
return out.str();
|
||||||
}
|
}
|
||||||
|
|
||||||
std::pair<llvm::Value*, std::shared_ptr<Type>> PointerType::load(codegen::Builder& builder, llvm::Value* ptr) {
|
std::pair<llvm::Value*, std::shared_ptr<Type>> PointerType::load(codegen::Builder& builder, llvm::Value* ptr, codegen::TypeMap& structs) {
|
||||||
return std::pair(
|
return std::pair(
|
||||||
builder.builder->CreateLoad(this->m_inner->codegen(builder), ptr),
|
builder.builder->CreateLoad(this->m_inner->codegen(builder, structs), ptr),
|
||||||
this->m_inner
|
this->m_inner
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@ -151,7 +152,7 @@ namespace types {
|
|||||||
return out.str();
|
return out.str();
|
||||||
}
|
}
|
||||||
|
|
||||||
std::pair<llvm::Value*, std::shared_ptr<Type>> ArrayType::load(codegen::Builder&, llvm::Value* ptr) {
|
std::pair<llvm::Value*, std::shared_ptr<Type>> ArrayType::load(codegen::Builder&, llvm::Value* ptr, codegen::TypeMap&) {
|
||||||
auto self = std::make_shared<ArrayType>(*this);
|
auto self = std::make_shared<ArrayType>(*this);
|
||||||
return std::pair(ptr, self);
|
return std::pair(ptr, self);
|
||||||
}
|
}
|
||||||
@ -160,18 +161,59 @@ namespace types {
|
|||||||
return this->m_size * this->m_inner->size();
|
return this->m_size * this->m_inner->size();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool types_equal(std::shared_ptr<types::Type> type1, std::shared_ptr<types::Type> type2) {
|
std::string StructType::formatted() {
|
||||||
// if (type1->m_kind == TypeKind::Array && type2->m_kind == TypeKind::Pointer) {
|
std::stringstream out{ "" };
|
||||||
// auto ty1 = dynamic_cast<ArrayType*>(type1.get());
|
out << "struct ";
|
||||||
// auto ty2 = dynamic_cast<PointerType*>(type2.get());
|
if (this->m_name) {
|
||||||
// return types_equal(ty1->m_inner, ty2->m_inner);
|
out << *this->m_name << " ";
|
||||||
// }
|
}
|
||||||
// else if (type1->m_kind == TypeKind::Pointer && type2->m_kind == TypeKind::Array) {
|
if (this->m_fields) {
|
||||||
// auto ty1 = dynamic_cast<PointerType*>(type1.get());
|
out << "{ ";
|
||||||
// auto ty2 = dynamic_cast<ArrayType*>(type2.get());
|
int counter = 0;
|
||||||
// return types_equal(ty1->m_inner, ty2->m_inner);
|
for (auto& field : *this->m_fields) {
|
||||||
// }
|
if (counter++ > 0)
|
||||||
|
out << ", ";
|
||||||
|
out << field.first << ": " << field.second->formatted() << " ";
|
||||||
|
}
|
||||||
|
out << "}";
|
||||||
|
}
|
||||||
|
|
||||||
|
return out.str();
|
||||||
|
}
|
||||||
|
|
||||||
|
std::pair<llvm::Value*, std::shared_ptr<Type>> StructType::load(codegen::Builder&, llvm::Value* ptr, codegen::TypeMap&) {
|
||||||
|
auto self = std::make_shared<StructType>(*this);
|
||||||
|
return std::pair(ptr, self);
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t StructType::size() {
|
||||||
|
uint32_t size{ 0 };
|
||||||
|
if (this->m_fields) {
|
||||||
|
for (auto& field : *this->m_fields) {
|
||||||
|
size += field.second->size();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return size;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
std::string StructRef::formatted() {
|
||||||
|
std::stringstream out{ "" };
|
||||||
|
out << "struct(ref) " << this->m_name;
|
||||||
|
return out.str();
|
||||||
|
}
|
||||||
|
|
||||||
|
std::pair<llvm::Value*, std::shared_ptr<Type>> StructRef::load(codegen::Builder&, llvm::Value* ptr, codegen::TypeMap&) {
|
||||||
|
auto self = std::make_shared<StructRef>(*this);
|
||||||
|
return std::pair(ptr, self);
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t StructRef::size() {
|
||||||
|
return this->m_referred->size();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool types_equal(std::shared_ptr<types::Type> type1, std::shared_ptr<types::Type> type2) {
|
||||||
if (type1->m_kind != type2->m_kind)
|
if (type1->m_kind != type2->m_kind)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
|
|||||||
52
src/types.h
52
src/types.h
@ -29,8 +29,8 @@ namespace types {
|
|||||||
Type(TypeKind kind) : m_kind{ kind } {}
|
Type(TypeKind kind) : m_kind{ kind } {}
|
||||||
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, codegen::TypeMap& structs) = 0;
|
||||||
virtual std::pair<llvm::Value*, std::shared_ptr<Type>> load(codegen::Builder& builder, llvm::Value* ptr) = 0;
|
virtual std::pair<llvm::Value*, std::shared_ptr<Type>> load(codegen::Builder& builder, llvm::Value* ptr, codegen::TypeMap& structs) = 0;
|
||||||
virtual std::optional<std::shared_ptr<Type>> return_type();
|
virtual std::optional<std::shared_ptr<Type>> return_type();
|
||||||
virtual bool is_signed();
|
virtual bool is_signed();
|
||||||
virtual uint32_t size() = 0;
|
virtual uint32_t size() = 0;
|
||||||
@ -42,8 +42,8 @@ namespace types {
|
|||||||
FundamentalType(FundamentalTypeKind kind) : Type(TypeKind::Fundamental), m_ty{ kind } {}
|
FundamentalType(FundamentalTypeKind kind) : Type(TypeKind::Fundamental), m_ty{ kind } {}
|
||||||
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, codegen::TypeMap& structs) override;
|
||||||
virtual std::pair<llvm::Value*, std::shared_ptr<Type>> load(codegen::Builder& builder, llvm::Value* ptr) override;
|
virtual std::pair<llvm::Value*, std::shared_ptr<Type>> load(codegen::Builder& builder, llvm::Value* ptr, codegen::TypeMap& structs) override;
|
||||||
virtual bool is_signed() override;
|
virtual bool is_signed() override;
|
||||||
virtual uint32_t size() override;
|
virtual uint32_t size() override;
|
||||||
};
|
};
|
||||||
@ -62,8 +62,8 @@ namespace types {
|
|||||||
}
|
}
|
||||||
virtual ~FunctionType() override = default;
|
virtual ~FunctionType() 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, codegen::TypeMap& structs) override;
|
||||||
virtual std::pair<llvm::Value*, std::shared_ptr<Type>> load(codegen::Builder& builder, llvm::Value* ptr) override;
|
virtual std::pair<llvm::Value*, std::shared_ptr<Type>> load(codegen::Builder& builder, llvm::Value* ptr, codegen::TypeMap& structs) override;
|
||||||
virtual std::optional<std::shared_ptr<Type>> return_type() override;
|
virtual std::optional<std::shared_ptr<Type>> return_type() override;
|
||||||
virtual uint32_t size() override;
|
virtual uint32_t size() override;
|
||||||
};
|
};
|
||||||
@ -77,8 +77,8 @@ namespace types {
|
|||||||
}
|
}
|
||||||
virtual ~PointerType() override = default;
|
virtual ~PointerType() 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, codegen::TypeMap& structs) override;
|
||||||
virtual std::pair<llvm::Value*, std::shared_ptr<Type>> load(codegen::Builder& builder, llvm::Value* ptr) override;
|
virtual std::pair<llvm::Value*, std::shared_ptr<Type>> load(codegen::Builder& builder, llvm::Value* ptr, codegen::TypeMap& structs) override;
|
||||||
virtual uint32_t size() override;
|
virtual uint32_t size() override;
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -92,8 +92,40 @@ namespace types {
|
|||||||
}
|
}
|
||||||
virtual ~ArrayType() override = default;
|
virtual ~ArrayType() 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, codegen::TypeMap& structs) override;
|
||||||
virtual std::pair<llvm::Value*, std::shared_ptr<Type>> load(codegen::Builder& builder, llvm::Value* ptr) override;
|
virtual std::pair<llvm::Value*, std::shared_ptr<Type>> load(codegen::Builder& builder, llvm::Value* ptr, codegen::TypeMap& structs) override;
|
||||||
|
virtual uint32_t size() override;
|
||||||
|
};
|
||||||
|
|
||||||
|
typedef std::pair<std::string, std::shared_ptr<types::Type>> StructField;
|
||||||
|
|
||||||
|
class StructType : public Type {
|
||||||
|
public:
|
||||||
|
std::optional<std::string> m_name;
|
||||||
|
std::optional<std::vector<StructField>> m_fields;
|
||||||
|
|
||||||
|
StructType(std::optional<std::string> name, std::optional<std::vector<StructField>> fields)
|
||||||
|
: Type(TypeKind::Array), m_name{ name }, m_fields{ fields } {
|
||||||
|
}
|
||||||
|
virtual ~StructType() override = default;
|
||||||
|
virtual std::string formatted() override;
|
||||||
|
virtual llvm::Type* codegen(codegen::Builder& builder, codegen::TypeMap& structs) override;
|
||||||
|
virtual std::pair<llvm::Value*, std::shared_ptr<Type>> load(codegen::Builder& builder, llvm::Value* ptr, codegen::TypeMap& structs) override;
|
||||||
|
virtual uint32_t size() override;
|
||||||
|
};
|
||||||
|
|
||||||
|
class StructRef : public Type {
|
||||||
|
public:
|
||||||
|
std::string m_name;
|
||||||
|
std::shared_ptr<types::Type> m_referred;
|
||||||
|
|
||||||
|
StructRef(std::string name, std::shared_ptr<types::Type> referred)
|
||||||
|
: Type(TypeKind::Array), m_name{ name }, m_referred{ referred } {
|
||||||
|
}
|
||||||
|
virtual ~StructRef() override = default;
|
||||||
|
virtual std::string formatted() override;
|
||||||
|
virtual llvm::Type* codegen(codegen::Builder& builder, codegen::TypeMap& structs) override;
|
||||||
|
virtual std::pair<llvm::Value*, std::shared_ptr<Type>> load(codegen::Builder& builder, llvm::Value* ptr, codegen::TypeMap& structs) override;
|
||||||
virtual uint32_t size() override;
|
virtual uint32_t size() override;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user