diff --git a/src/codegen.cpp b/src/codegen.cpp index 37b6533..33fe17f 100644 --- a/src/codegen.cpp +++ b/src/codegen.cpp @@ -32,7 +32,8 @@ namespace AST { std::shared_ptr StringLiteralExpression::get_codegen_type(codegen::Scope&) { auto stack_type = new types::ArrayType{ std::make_unique(types::FundamentalTypeKind::Char), - static_cast(this->m_value.size()) + 1 + static_cast(this->m_value.size()) + 1, + true }; return std::shared_ptr {stack_type}; } @@ -40,7 +41,8 @@ namespace AST { codegen::StackValue StringLiteralExpression::codegen(codegen::Builder& builder, codegen::Scope& scope) { auto stack_type = new types::ArrayType{ std::make_unique(types::FundamentalTypeKind::Char), - static_cast(this->m_value.size()) + 1 + static_cast(this->m_value.size()) + 1, + true }; auto str = llvm::StringRef{ this->m_value.c_str() }; @@ -264,58 +266,45 @@ namespace AST { if (value.ty->m_kind == types::TypeKind::Pointer) { auto ptr_ty = dynamic_cast(value.ty.get()); - 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, scope.structs), value.value, idx_list, "GEP"); - if (scope.is_lvalue) { - return codegen::StackValue{ - gep_value, - value.ty, - }; - } - else { - auto loaded = value.ty->load(builder, gep_value, scope.structs); - return codegen::StackValue{ - loaded.first, - loaded.second - }; - } - } - else if (ptr_ty->m_inner->m_kind == types::TypeKind::Array) { - // 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, scope.structs), value.value, idx_list, "GEP"); - if (scope.is_lvalue) { - return codegen::StackValue{ - gep_value, - value.ty, - }; - } - else { - auto inner_ptr_ty = types::PointerType{ arr_ty->m_inner }; - auto loaded = inner_ptr_ty.load(builder, gep_value, scope.structs); - return codegen::StackValue{ - loaded.first, - loaded.second - }; - } + 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, + value.ty, + }; } else { - 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, - value.ty, - }; - } - else { - auto loaded = value.ty->load(builder, gep_value, scope.structs); - return codegen::StackValue{ - loaded.first, - loaded.second - }; - } + auto loaded = value.ty->load(builder, gep_value, scope.structs); + return codegen::StackValue{ + loaded.first, + loaded.second + }; + } + } + else if (value.ty->m_kind == types::TypeKind::Array) { + auto array_ty = dynamic_cast(value.ty.get()); + if (array_ty->m_raw) { + throw CompileError("Tried indexing a raw array", this->m_meta); + } + + auto gep_value = builder.builder->CreateGEP(array_ty->m_inner->codegen(builder, scope.structs), value.value, idx_list, "GEP"); + + auto ptr_ty = std::shared_ptr{ + new types::PointerType { array_ty->m_inner} + }; + + if (scope.is_lvalue) { + return codegen::StackValue{ + gep_value, + ptr_ty, + }; + } + else { + auto loaded = ptr_ty->load(builder, gep_value, scope.structs); + return codegen::StackValue{ + loaded.first, + loaded.second + }; } } @@ -476,6 +465,22 @@ namespace AST { builder.builder->SetInsertPoint(builder.block); + if (this->m_type->m_kind == types::TypeKind::Array) { + auto array_ty = dynamic_cast(this->m_type.get()); + if (!array_ty->m_raw) { + auto raw_ty = types::ArrayType{ array_ty->m_inner, array_ty->m_size, true }; + auto raw_llvm_ty = raw_ty.codegen(builder, scope.structs); + auto ptr = builder.builder->CreateAlloca(raw_llvm_ty); + if (this->m_expr.has_value()) { + auto value = this->m_expr->get()->codegen(builder, scope); + builder.builder->CreateStore(value.value, ptr, false); + } + + scope.values[this->m_name] = codegen::StackValue{ ptr, this->m_type }; + return; + } + } + auto ty = this->m_type->codegen(builder, scope.structs); auto ptr = builder.builder->CreateAlloca(ty); if (this->m_expr.has_value()) { @@ -552,32 +557,34 @@ namespace AST { int counter = 0; for (auto& param : this->m_params) { - if (param.second->m_kind == types::TypeKind::Pointer) { - auto ty = param_ty_ptrs[counter]; - auto arg = function->getArg(counter++); - if (param.first) { - arg->setName(*param.first); - inner_scope.values[*param.first] = codegen::StackValue{ - arg, - ty, - }; + if (param.second->m_kind == types::TypeKind::Array) { + auto array_ty = dynamic_cast(param.second.get()); + if (!array_ty->m_raw) { + auto ty = param_ty_ptrs[counter]; + auto arg = function->getArg(counter++); + if (param.first) { + arg->setName(*param.first); + inner_scope.values[*param.first] = codegen::StackValue{ + arg, + ty, + }; + } + continue; } } - else { - builder.builder->SetInsertPoint(BB); - 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]} + builder.builder->SetInsertPoint(BB); + 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]} + }; + auto arg = function->getArg(counter++); + builder.builder->CreateStore(arg, arg_ptr); + if (param.first) { + arg->setName(*param.first); + inner_scope.values[*param.first] = codegen::StackValue{ + arg_ptr, + param_ty_ptr, }; - auto arg = function->getArg(counter++); - builder.builder->CreateStore(arg, arg_ptr); - if (param.first) { - arg->setName(*param.first); - inner_scope.values[*param.first] = codegen::StackValue{ - arg_ptr, - param_ty_ptr, - }; - } } } @@ -637,7 +644,9 @@ namespace types { } llvm::Type* ArrayType::codegen(codegen::Builder& builder, codegen::TypeMap& structs) { - return llvm::ArrayType::get(this->m_inner->codegen(builder, structs), this->m_size); + if (this->m_raw) + return llvm::ArrayType::get(this->m_inner->codegen(builder, structs), this->m_size); + return llvm::PointerType::get(*builder.context, 0); } llvm::Type* StructType::codegen(codegen::Builder& builder, codegen::TypeMap& structs) { diff --git a/src/parsing.cpp b/src/parsing.cpp index f27f90a..f3c5365 100644 --- a/src/parsing.cpp +++ b/src/parsing.cpp @@ -392,7 +392,7 @@ namespace parsing { auto postfix = array_postfix.unwrap(); if (postfix) { ty = std::shared_ptr{ - new types::ArrayType(ty, *postfix) + new types::ArrayType(ty, *postfix, false) }; } else { @@ -511,7 +511,7 @@ namespace parsing { auto array_postfix = postfix.unwrap(); if (array_postfix) { param_ty = std::shared_ptr{ - new types::PointerType(param_ty) + new types::ArrayType(param_ty, *array_postfix, false) }; } else { diff --git a/src/typechecker.cpp b/src/typechecker.cpp index 9c88c5a..4d040be 100644 --- a/src/typechecker.cpp +++ b/src/typechecker.cpp @@ -138,7 +138,7 @@ namespace AST { auto char_ty = std::shared_ptr{ new types::FundamentalType{ types::FundamentalTypeKind::Char } }; - auto ptr_ty = new types::ArrayType{ char_ty, static_cast(this->m_value.size()) + 1 }; + auto ptr_ty = new types::ArrayType{ char_ty, static_cast(this->m_value.size()) + 1, true }; return std::shared_ptr{ptr_ty}; } @@ -449,7 +449,8 @@ namespace AST { this->m_ty = std::shared_ptr{ new types::ArrayType{ array_ty->m_inner, - static_cast(this->m_expressions.size()) + static_cast(this->m_expressions.size()), + true } }; } @@ -503,7 +504,8 @@ namespace AST { this->m_ty = std::shared_ptr{ new types::ArrayType{ std::make_shared(types::FundamentalTypeKind::Void), - 0 + 0, + true } }; return this->m_ty; @@ -518,7 +520,8 @@ namespace AST { this->m_ty = std::shared_ptr{ new types::ArrayType{ first_expr_ty, - static_cast(this->m_expressions.size()) + static_cast(this->m_expressions.size()), + true } }; return this->m_ty; diff --git a/src/types.h b/src/types.h index c649cd4..706e1e3 100644 --- a/src/types.h +++ b/src/types.h @@ -87,9 +87,10 @@ namespace types { public: std::shared_ptr m_inner; uint32_t m_size; + bool m_raw; - ArrayType(std::shared_ptr inner, uint32_t size) - : Type(TypeKind::Array), m_inner{ std::move(inner) }, m_size{ size } { + ArrayType(std::shared_ptr inner, uint32_t size, bool raw) + : Type(TypeKind::Array), m_inner{ std::move(inner) }, m_size{ size }, m_raw{ raw } { } virtual ~ArrayType() override = default; virtual std::string formatted() override; diff --git a/test.c b/test.c index 59f59f1..377779e 100644 --- a/test.c +++ b/test.c @@ -20,6 +20,10 @@ struct Otus { int field; }; +void update_ptr(char* ptr) { + *ptr = 50; +} + int main() { char text[29] = "10th fibonacci number is %d!"; printf(text, fibonacci(10)); @@ -35,5 +39,9 @@ int main() { printf(" first field: %d!", otus.field); + char hello = 10; + update_ptr(&hello); + printf(" hello: %d!", hello); + return 0; } \ No newline at end of file