diff --git a/src/builder.h b/src/builder.h index dc68830..f403e61 100644 --- a/src/builder.h +++ b/src/builder.h @@ -1,6 +1,8 @@ #ifndef BUILDER_H #define BUILDER_H +#include + #include #include @@ -11,6 +13,8 @@ namespace codegen { std::unique_ptr> builder; llvm::BasicBlock* block; }; + + typedef std::map TypeMap; } #endif \ No newline at end of file diff --git a/src/casting.cpp b/src/casting.cpp index 3372473..6d21ca7 100644 --- a/src/casting.cpp +++ b/src/casting.cpp @@ -32,13 +32,15 @@ namespace types { if (target_ty->is_signed()) { casts.push_back(CastDefinition{ source_ty, target_ty, allow_implicit, [](codegen::Builder& builder, std::shared_ptr 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 { casts.push_back(CastDefinition{ source_ty, target_ty, allow_implicit, [](codegen::Builder& builder, std::shared_ptr 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 CastDefinition{ casted_ty, target_ty, true, [](codegen::Builder&, std::shared_ptr, llvm::Value* value) { - // auto ptr_ty = dynamic_cast(target.get()); - - // std::vector 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; } }; } diff --git a/src/codegen.cpp b/src/codegen.cpp index 135282c..aacd07f 100644 --- a/src/codegen.cpp +++ b/src/codegen.cpp @@ -11,7 +11,7 @@ namespace codegen { 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; } - codegen::StackValue IntLiteralExpression::codegen(codegen::Builder& builder, codegen::Scope&) { - auto ty = this->m_ty->codegen(builder); + codegen::StackValue IntLiteralExpression::codegen(codegen::Builder& builder, codegen::Scope& scope) { + auto ty = this->m_ty->codegen(builder, scope.structs); return codegen::StackValue{ llvm::ConstantInt::get(ty, this->m_value), @@ -56,7 +56,7 @@ namespace AST { } else { 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{stack_type}, }; } @@ -83,7 +83,7 @@ namespace AST { return value->second; } 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{ loaded.first, loaded.second @@ -160,7 +160,7 @@ namespace AST { } auto function = this->m_fn_expr->codegen(builder, scope); - auto value = builder.builder->CreateCall(llvm::dyn_cast(function.ty->codegen(builder)), function.value, args, "call"); + auto value = builder.builder->CreateCall(llvm::dyn_cast(function.ty->codegen(builder, scope.structs)), function.value, args, "call"); return codegen::StackValue{ value, *function.ty->return_type(), @@ -226,7 +226,7 @@ namespace AST { codegen::StackValue DerefExpression::codegen(codegen::Builder& builder, codegen::Scope& scope) { auto value = this->m_expr->codegen(builder, scope); 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{ loaded.first, loaded.second @@ -267,7 +267,7 @@ namespace AST { if (ptr_ty->m_inner->m_kind == types::TypeKind::Pointer) { auto inner_ptr_ty = dynamic_cast(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) { return codegen::StackValue{ gep_value, @@ -275,7 +275,7 @@ namespace AST { }; } else { - auto loaded = value.ty->load(builder, gep_value); + auto loaded = value.ty->load(builder, gep_value, scope.structs); return codegen::StackValue{ loaded.first, loaded.second @@ -287,7 +287,7 @@ namespace AST { // Must be an array otherwise auto arr_ty = dynamic_cast(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) { return codegen::StackValue{ gep_value, @@ -296,7 +296,7 @@ namespace AST { } else { 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{ loaded.first, loaded.second @@ -304,7 +304,7 @@ namespace AST { } } 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) { return codegen::StackValue{ gep_value, @@ -312,7 +312,7 @@ namespace AST { }; } else { - auto loaded = value.ty->load(builder, gep_value); + auto loaded = value.ty->load(builder, gep_value, scope.structs); return codegen::StackValue{ loaded.first, loaded.second @@ -331,7 +331,7 @@ namespace AST { } 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) { auto array_ty = dynamic_cast(this->m_ty.get()); @@ -341,7 +341,7 @@ namespace AST { std::vector indices{}; indices.push_back(llvm::ConstantInt::get(builder.builder->getInt32Ty(), counter++)); 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); } @@ -353,7 +353,7 @@ namespace AST { return codegen::StackValue{ array_ptr, ptr_ty }; } 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 }; } } @@ -387,7 +387,7 @@ namespace AST { 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); if (this->m_expr.has_value()) { auto value = this->m_expr->get()->codegen(builder, scope); @@ -445,7 +445,7 @@ namespace AST { auto fn_ty_ptr = std::shared_ptr{ 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( llvm::dyn_cast(fn_ty), llvm::GlobalValue::LinkageTypes::ExternalLinkage, @@ -476,7 +476,7 @@ namespace AST { } else { 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{ new types::PointerType { param_ty_ptrs[counter]} }; @@ -506,7 +506,7 @@ namespace AST { } namespace types { - llvm::Type* FundamentalType::codegen(codegen::Builder& builder) { + llvm::Type* FundamentalType::codegen(codegen::Builder& builder, codegen::TypeMap&) { switch (this->m_ty) { case FundamentalTypeKind::Int: 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 params{}; 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); } - llvm::Type* PointerType::codegen(codegen::Builder& builder) { + llvm::Type* PointerType::codegen(codegen::Builder& builder, codegen::TypeMap&) { return llvm::PointerType::get(*builder.context, 0); } - llvm::Type* ArrayType::codegen(codegen::Builder& builder) { - return llvm::ArrayType::get(this->m_inner->codegen(builder), this->m_size); + llvm::Type* ArrayType::codegen(codegen::Builder& builder, codegen::TypeMap& structs) { + 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 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]; } } \ No newline at end of file diff --git a/src/codegen.h b/src/codegen.h index f15989c..611f670 100644 --- a/src/codegen.h +++ b/src/codegen.h @@ -22,7 +22,9 @@ namespace codegen { std::vector& binops; std::vector& casts; + TypeMap structs; std::map values; + bool is_lvalue; Scope with_lvalue(); diff --git a/src/main.cpp b/src/main.cpp index 9dd13f4..db3b9f8 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -124,6 +124,7 @@ std::optional compile(std::string_view in_filename) { codegen::Scope cg_scope{ .binops = typecheck_state.binops, .casts = typecheck_state.casts, + .structs = {}, .values = {}, .is_lvalue = false, }; diff --git a/src/types.cpp b/src/types.cpp index aeb85c0..69726bf 100644 --- a/src/types.cpp +++ b/src/types.cpp @@ -4,6 +4,7 @@ #include "types.h" #include "binops.h" +#include "builder.h" namespace types { int operator_precedence(BinOp& op) { @@ -63,7 +64,7 @@ namespace types { return false; } - std::pair> FundamentalType::load(codegen::Builder&, llvm::Value* ptr) { + std::pair> FundamentalType::load(codegen::Builder&, llvm::Value* ptr, codegen::TypeMap&) { auto self = std::make_shared(*this); return std::pair(ptr, self); } @@ -118,7 +119,7 @@ namespace types { return this->m_ret_ty; } - std::pair> FunctionType::load(codegen::Builder&, llvm::Value* ptr) { + std::pair> FunctionType::load(codegen::Builder&, llvm::Value* ptr, codegen::TypeMap&) { auto self = std::make_shared(*this); return std::pair(ptr, self); } @@ -133,9 +134,9 @@ namespace types { return out.str(); } - std::pair> PointerType::load(codegen::Builder& builder, llvm::Value* ptr) { + std::pair> PointerType::load(codegen::Builder& builder, llvm::Value* ptr, codegen::TypeMap& structs) { 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 ); } @@ -151,7 +152,7 @@ namespace types { return out.str(); } - std::pair> ArrayType::load(codegen::Builder&, llvm::Value* ptr) { + std::pair> ArrayType::load(codegen::Builder&, llvm::Value* ptr, codegen::TypeMap&) { auto self = std::make_shared(*this); return std::pair(ptr, self); } @@ -160,18 +161,59 @@ namespace types { return this->m_size * this->m_inner->size(); } - bool types_equal(std::shared_ptr type1, std::shared_ptr type2) { - // if (type1->m_kind == TypeKind::Array && type2->m_kind == TypeKind::Pointer) { - // auto ty1 = dynamic_cast(type1.get()); - // auto ty2 = dynamic_cast(type2.get()); - // return types_equal(ty1->m_inner, ty2->m_inner); - // } - // else if (type1->m_kind == TypeKind::Pointer && type2->m_kind == TypeKind::Array) { - // auto ty1 = dynamic_cast(type1.get()); - // auto ty2 = dynamic_cast(type2.get()); - // return types_equal(ty1->m_inner, ty2->m_inner); - // } + std::string StructType::formatted() { + std::stringstream out{ "" }; + out << "struct "; + if (this->m_name) { + out << *this->m_name << " "; + } + if (this->m_fields) { + out << "{ "; + int counter = 0; + for (auto& field : *this->m_fields) { + if (counter++ > 0) + out << ", "; + out << field.first << ": " << field.second->formatted() << " "; + } + out << "}"; + } + return out.str(); + } + + std::pair> StructType::load(codegen::Builder&, llvm::Value* ptr, codegen::TypeMap&) { + auto self = std::make_shared(*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> StructRef::load(codegen::Builder&, llvm::Value* ptr, codegen::TypeMap&) { + auto self = std::make_shared(*this); + return std::pair(ptr, self); + } + + uint32_t StructRef::size() { + return this->m_referred->size(); + } + + bool types_equal(std::shared_ptr type1, std::shared_ptr type2) { if (type1->m_kind != type2->m_kind) return false; diff --git a/src/types.h b/src/types.h index 24a820f..604d85f 100644 --- a/src/types.h +++ b/src/types.h @@ -29,8 +29,8 @@ namespace types { Type(TypeKind kind) : m_kind{ kind } {} virtual ~Type() = default; virtual std::string formatted() = 0; - virtual llvm::Type* codegen(codegen::Builder& builder) = 0; - virtual std::pair> load(codegen::Builder& builder, llvm::Value* ptr) = 0; + virtual llvm::Type* codegen(codegen::Builder& builder, codegen::TypeMap& structs) = 0; + virtual std::pair> load(codegen::Builder& builder, llvm::Value* ptr, codegen::TypeMap& structs) = 0; virtual std::optional> return_type(); virtual bool is_signed(); virtual uint32_t size() = 0; @@ -42,8 +42,8 @@ namespace types { FundamentalType(FundamentalTypeKind kind) : Type(TypeKind::Fundamental), m_ty{ kind } {} virtual ~FundamentalType() override = default; virtual std::string formatted() override; - virtual llvm::Type* codegen(codegen::Builder& builder) override; - virtual std::pair> load(codegen::Builder& builder, llvm::Value* ptr) override; + virtual llvm::Type* codegen(codegen::Builder& builder, codegen::TypeMap& structs) override; + virtual std::pair> load(codegen::Builder& builder, llvm::Value* ptr, codegen::TypeMap& structs) override; virtual bool is_signed() override; virtual uint32_t size() override; }; @@ -62,8 +62,8 @@ namespace types { } virtual ~FunctionType() override = default; virtual std::string formatted() override; - virtual llvm::Type* codegen(codegen::Builder& builder) override; - virtual std::pair> load(codegen::Builder& builder, llvm::Value* ptr) override; + virtual llvm::Type* codegen(codegen::Builder& builder, codegen::TypeMap& structs) override; + virtual std::pair> load(codegen::Builder& builder, llvm::Value* ptr, codegen::TypeMap& structs) override; virtual std::optional> return_type() override; virtual uint32_t size() override; }; @@ -77,8 +77,8 @@ namespace types { } virtual ~PointerType() override = default; virtual std::string formatted() override; - virtual llvm::Type* codegen(codegen::Builder& builder) override; - virtual std::pair> load(codegen::Builder& builder, llvm::Value* ptr) override; + virtual llvm::Type* codegen(codegen::Builder& builder, codegen::TypeMap& structs) override; + virtual std::pair> load(codegen::Builder& builder, llvm::Value* ptr, codegen::TypeMap& structs) override; virtual uint32_t size() override; }; @@ -92,8 +92,40 @@ namespace types { } virtual ~ArrayType() override = default; virtual std::string formatted() override; - virtual llvm::Type* codegen(codegen::Builder& builder) override; - virtual std::pair> load(codegen::Builder& builder, llvm::Value* ptr) override; + virtual llvm::Type* codegen(codegen::Builder& builder, codegen::TypeMap& structs) override; + virtual std::pair> load(codegen::Builder& builder, llvm::Value* ptr, codegen::TypeMap& structs) override; + virtual uint32_t size() override; + }; + + typedef std::pair> StructField; + + class StructType : public Type { + public: + std::optional m_name; + std::optional> m_fields; + + StructType(std::optional name, std::optional> 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> 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 m_referred; + + StructRef(std::string name, std::shared_ptr 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> load(codegen::Builder& builder, llvm::Value* ptr, codegen::TypeMap& structs) override; virtual uint32_t size() override; };