diff --git a/src/codegen.cpp b/src/codegen.cpp index 63d270f..7c9f557 100644 --- a/src/codegen.cpp +++ b/src/codegen.cpp @@ -256,8 +256,18 @@ namespace AST { codegen::StackValue IndexAccessExpression::codegen(codegen::Builder& builder, codegen::Scope& scope) { - auto value = this->m_expr->codegen(builder, scope); - std::shared_ptr inner_ty{}; + auto intended_ty = this->m_expr->get_codegen_type(scope); + + codegen::StackValue value; + if (intended_ty->m_kind != types::TypeKind::Pointer) { + auto lvalued = scope.with_lvalue(); + value = this->m_expr->codegen(builder, lvalued); + } + else { + value = this->m_expr->codegen(builder, scope); + } + + std::cout << intended_ty->formatted() << std::endl; std::vector idx_list{ }; idx_list.push_back(llvm::ConstantInt::get(builder.builder->getInt32Ty(), this->m_num)); @@ -265,30 +275,12 @@ namespace AST { if (value.ty->m_kind == types::TypeKind::Pointer) { auto ptr_ty = dynamic_cast(value.ty.get()); - auto gep_value = builder.builder->CreateGEP(ptr_ty->m_inner->codegen(builder, scope.structs), value.value, idx_list, "GEP"); - - 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->m_const, array_ty->m_inner} - }; + auto gep_value = builder.builder->CreateGEP(ptr_ty->m_inner->codegen(builder, scope.structs), value.value, idx_list, "ptr_gep"); if (scope.is_lvalue) { return codegen::StackValue{ gep_value, - ptr_ty, + value.ty, }; } else { @@ -299,6 +291,31 @@ namespace AST { }; } } + 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, "array_gep"); + + if (scope.is_lvalue) { + return codegen::StackValue{ + gep_value, + array_ty->m_inner, + }; + } + else { + auto ptr_ty = std::shared_ptr{ + new types::PointerType { array_ty->m_inner->m_const, array_ty->m_inner} + }; + auto loaded = ptr_ty->load(builder, gep_value, scope.structs); + return codegen::StackValue{ + loaded.first, + loaded.second + }; + } + } throw CompileError("Tried indexing a non-pointer", this->m_meta); } @@ -345,17 +362,17 @@ namespace AST { auto gep = builder.builder->CreateStructGEP( ptr_ty->m_inner->codegen(builder, scope.structs), struct_ptr.value, idx); - auto ptr_ty = std::shared_ptr{ - new types::PointerType { field_ty->m_const, field_ty } - }; if (scope.is_lvalue) { return codegen::StackValue{ gep, - ptr_ty + field_ty }; } else { + auto ptr_ty = std::shared_ptr{ + new types::PointerType { field_ty->m_const, field_ty } + }; auto loaded = ptr_ty->load(builder, gep, scope.structs); return codegen::StackValue{ loaded.first, loaded.second }; } @@ -458,19 +475,15 @@ 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 raw_llvm_ty = this->m_type->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); diff --git a/src/main.cpp b/src/main.cpp index 0b3f096..f9ff086 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -176,7 +176,7 @@ std::optional compile(std::string_view in_filename) { builder.mod->print(llvm_ir_dest, nullptr); llvm_ir_dest.flush(); - // std::cout << llvm_ir_string << std::endl; + std::cout << llvm_ir_string << std::endl; // Print output to obj-file std::error_code EC; diff --git a/src/parsing.cpp b/src/parsing.cpp index ef01829..01046b0 100644 --- a/src/parsing.cpp +++ b/src/parsing.cpp @@ -8,6 +8,7 @@ namespace parsing { static uint32_t struct_id_counter = 0; Result, std::string> parse_expression(token::TokenStream& stream, Scope& scope); + Result, std::string> parse_array_postfix(token::TokenStream& stream, bool allow_empty, Scope&); Result, std::string> parse_type(token::TokenStream& stream, Scope& scope) { token::TokenStream inner{ stream }; @@ -41,12 +42,23 @@ namespace parsing { if (counter++ > 0) inner.expect(token::Type::Symbol, ";"); - auto ty = parse_type(inner, scope); - if (!ty.ok()) + auto ty_res = parse_type(inner, scope); + if (!ty_res.ok()) break; + auto ty = ty_res.unwrap(); auto field_name = inner.expect(token::Type::Ident); - fields.push_back(types::StructField{ field_name.content, ty.unwrap() }); + + auto array_postfix = parse_array_postfix(inner, false, scope); + while (array_postfix.ok()) { + auto postfix = array_postfix.unwrap(); + ty = std::shared_ptr{ + new types::ArrayType(ty, *postfix, true) + }; + array_postfix = parse_array_postfix(inner, false, scope); + } + + fields.push_back(types::StructField{ field_name.content, ty }); } inner.expect(token::Type::Symbol, "}"); @@ -430,7 +442,7 @@ namespace parsing { while (array_postfix.ok()) { auto postfix = array_postfix.unwrap(); ty = std::shared_ptr{ - new types::ArrayType(ty, *postfix, false) + new types::ArrayType(ty, *postfix, true) }; array_postfix = parse_array_postfix(inner, false, scope); } diff --git a/test.c b/test.c index 612d2fd..439473d 100644 --- a/test.c +++ b/test.c @@ -15,6 +15,7 @@ struct Otus; struct Otus { int field; + int second[2]; }; void update(struct Otus potus) { potus.field = 20; @@ -36,14 +37,19 @@ int main() { printf("first element: %d!\n", somelist[0]); printf("first element via ptr: %d!\n", somelist_ptr[0]); - struct Otus otus = { 5 }; + struct Otus otus = { 5, { 7, 3 } }; update(otus); printf("first field: %d!\n", otus.field); + printf("second field's second element: %d!\n", otus.second[1]); char hello = 10; update_ptr(&hello); printf("hello: %d!\n", hello); + char twod_array[5][5]; + twod_array[0][0] = 50; + printf("2d array: %d!\n", twod_array[0][0]); + return 0; } \ No newline at end of file