From 51a548f321f6d20c55add6fde1f8df5c118068d9 Mon Sep 17 00:00:00 2001 From: Harrand Date: Fri, 17 May 2024 17:39:37 +0100 Subject: [PATCH] [cpp] very basic codegen for struct types --- cpp/src/codegen.cpp | 101 ++++++++++++++++++++++++++++++++++++++++++++ cpp/src/semal.cpp | 10 ++--- cpp/src/semal.hpp | 8 ++-- 3 files changed, 110 insertions(+), 9 deletions(-) diff --git a/cpp/src/codegen.cpp b/cpp/src/codegen.cpp index 72fac43..9c91406 100644 --- a/cpp/src/codegen.cpp +++ b/cpp/src/codegen.cpp @@ -114,6 +114,79 @@ namespace code } }; + llvm::Type* as_llvm_type(const type& ty, const semal::output& semal_input) + { + diag::assert_that(!ty.is_undefined(), error_code::ice, "undefined type made it to codegen!"); + if(ty.is_pointer()) + { + return llvm::PointerType::get(*ctx, 0); + } + if(ty.is_struct()) + { + const semal::struct_t* structdata = semal_input.try_find_struct(ty.name()); + diag::assert_that(structdata != nullptr, error_code::type, "struct type \"{}\" was not found within semantic analysis state, which is weird as it was recognised as a struct type. perhaps semantic analysis bug?", ty.name()); + diag::assert_that(structdata->userdata != nullptr, error_code::ice, "found struct named \"{}\" but its userdata ptr is null, meaning it has not been codegen'd and i currently need it while evaluating something else.", ty.name()); + return static_cast(structdata->userdata); + } + if(ty.is_primitive()) + { + switch(ty.as_primitive()) + { + case primitive_type::i64: + [[fallthrough]]; + case primitive_type::u64: + return llvm::Type::getInt64Ty(*ctx); + break; + + case primitive_type::i32: + [[fallthrough]]; + case primitive_type::u32: + return llvm::Type::getInt32Ty(*ctx); + break; + + case primitive_type::i16: + [[fallthrough]]; + case primitive_type::u16: + return llvm::Type::getInt16Ty(*ctx); + break; + + case primitive_type::i8: + [[fallthrough]]; + case primitive_type::u8: + return llvm::Type::getInt8Ty(*ctx); + break; + + case primitive_type::u0: + return llvm::Type::getVoidTy(*ctx); + break; + + case primitive_type::boolean: + return llvm::Type::getInt1Ty(*ctx); + break; + + case primitive_type::f64: + return llvm::Type::getDoubleTy(*ctx); + break; + case primitive_type::f32: + return llvm::Type::getFloatTy(*ctx); + break; + case primitive_type::f16: + return llvm::Type::getHalfTy(*ctx); + break; + + default: + diag::error(error_code::ice, "unrecognised primitive type \"{}\" used in source", ty.name()); + return nullptr; + break; + } + } + // todo: implement + diag::error(error_code::ice, "could not convert type \"{}\" to its corresponding llvm::Type*", ty.name()); + return nullptr; + } + + void codegen_struct(const semal::struct_t& structdata, const semal::output& semal_input); + output generate(const ast& tree, const semal::output& input, std::string module_name) { diag::assert_that(program == nullptr && builder == nullptr, error_code::ice, "previous codegen state has not been erased and you want me to move onto codegening another file..."); @@ -126,9 +199,37 @@ namespace code builder = std::make_unique>(*ctx); // todo: codegen logic goes here. + for(const auto& [structname, structdata] : input.struct_decls) + { + codegen_struct(structdata, input); + } llvm::verifyModule(*program); ret.codegen_handle = program.get(); return ret; } + + // top level codegen bits. not thinking of nodes very much yet. + + void codegen_struct(const semal::struct_t& structdata, const semal::output& semal_input) + { + if(structdata.userdata != nullptr) + { + // already codegen'd. stop. + return; + } + + std::vector llvm_data_members; + for(const struct_type::data_member& member : structdata.ty.data_members) + { + if(member.ty->is_struct()) + { + struct_type memty = member.ty->as_struct(); + codegen_struct(*semal_input.try_find_struct(memty.name.c_str()), semal_input); + } + llvm_data_members.push_back(as_llvm_type(*member.ty, semal_input)); + } + llvm::StructType* llvm_ty = llvm::StructType::create(llvm_data_members, structdata.ty.name, false); + structdata.userdata = llvm_ty; + } } \ No newline at end of file diff --git a/cpp/src/semal.cpp b/cpp/src/semal.cpp index 9382d2b..3f146fe 100644 --- a/cpp/src/semal.cpp +++ b/cpp/src/semal.cpp @@ -148,7 +148,7 @@ namespace semal this->struct_decls[structdata.ty.name] = structdata; } - const function_t* output::try_find_function(const char* name) const + const function_t* output::try_find_function(std::string_view name) const { for(const auto& [fnname, funcdata] : this->functions) { @@ -193,7 +193,7 @@ namespace semal return nullptr; } - const local_variable_t* output::try_find_global_variable(const char* name) const + const local_variable_t* output::try_find_global_variable(std::string_view name) const { for(const auto& [varname, gvar] : this->global_variables) { @@ -205,7 +205,7 @@ namespace semal return nullptr; } - const local_variable_t* output::try_find_local_variable(const ast::path_t& context, const char* name) const + const local_variable_t* output::try_find_local_variable(const ast::path_t& context, std::string_view name) const { ast::path_const_view_t cv = context; const scope_reference* current_scope = &this->variables; @@ -213,7 +213,7 @@ namespace semal { for(std::size_t idx : context) { - auto iter = current_scope->variables.find(name); + auto iter = current_scope->variables.find(name.data()); if(iter != current_scope->variables.end()) { return &iter->second; @@ -225,7 +225,7 @@ namespace semal } - const struct_t* output::try_find_struct(const char* name) const + const struct_t* output::try_find_struct(std::string_view name) const { for(const auto& [structname, structdata] : this->struct_decls) { diff --git a/cpp/src/semal.hpp b/cpp/src/semal.hpp index 27b0589..d52af82 100644 --- a/cpp/src/semal.hpp +++ b/cpp/src/semal.hpp @@ -76,11 +76,11 @@ namespace semal void register_local_variable(local_variable_t gvar); void register_struct(struct_t structdata); - const function_t* try_find_function(const char* name) const; + const function_t* try_find_function(std::string_view name) const; const function_t* try_find_parent_function(const ast& tree, ast::path_t path) const; - const local_variable_t* try_find_global_variable(const char* name) const; - const local_variable_t* try_find_local_variable(const ast::path_t& context, const char* name) const; - const struct_t* try_find_struct(const char* name) const; + const local_variable_t* try_find_global_variable(std::string_view) const; + const local_variable_t* try_find_local_variable(const ast::path_t& context, std::string_view name) const; + const struct_t* try_find_struct(std::string_view name) const; type get_type_from_payload(const ast::node::payload_t& payload, const ast& tree, const ast::path_t& path) const; };