Fix some indexing problems

This commit is contained in:
Sofia 2026-04-16 23:47:42 +03:00
parent 668e18e8ba
commit 226118bcbb
4 changed files with 75 additions and 44 deletions

View File

@ -256,8 +256,18 @@ namespace AST {
codegen::StackValue IndexAccessExpression::codegen(codegen::Builder& builder, codegen::Scope& scope) { codegen::StackValue IndexAccessExpression::codegen(codegen::Builder& builder, codegen::Scope& scope) {
auto value = this->m_expr->codegen(builder, scope); auto intended_ty = this->m_expr->get_codegen_type(scope);
std::shared_ptr<types::Type> inner_ty{};
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<llvm::Value*> idx_list{ }; std::vector<llvm::Value*> idx_list{ };
idx_list.push_back(llvm::ConstantInt::get(builder.builder->getInt32Ty(), this->m_num)); 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) { if (value.ty->m_kind == types::TypeKind::Pointer) {
auto ptr_ty = dynamic_cast<types::PointerType*>(value.ty.get()); auto ptr_ty = dynamic_cast<types::PointerType*>(value.ty.get());
auto gep_value = builder.builder->CreateGEP(ptr_ty->m_inner->codegen(builder, scope.structs), value.value, idx_list, "GEP"); auto gep_value = builder.builder->CreateGEP(ptr_ty->m_inner->codegen(builder, scope.structs), value.value, idx_list, "ptr_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<types::ArrayType*>(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<types::Type>{
new types::PointerType { array_ty->m_inner->m_const, array_ty->m_inner}
};
if (scope.is_lvalue) { if (scope.is_lvalue) {
return codegen::StackValue{ return codegen::StackValue{
gep_value, gep_value,
ptr_ty, value.ty,
}; };
} }
else { else {
@ -299,6 +291,31 @@ namespace AST {
}; };
} }
} }
else if (value.ty->m_kind == types::TypeKind::Array) {
auto array_ty = dynamic_cast<types::ArrayType*>(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<types::Type>{
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); throw CompileError("Tried indexing a non-pointer", this->m_meta);
} }
@ -345,17 +362,17 @@ namespace AST {
auto gep = builder.builder->CreateStructGEP( auto gep = builder.builder->CreateStructGEP(
ptr_ty->m_inner->codegen(builder, scope.structs), struct_ptr.value, idx); ptr_ty->m_inner->codegen(builder, scope.structs), struct_ptr.value, idx);
auto ptr_ty = std::shared_ptr<types::Type>{
new types::PointerType { field_ty->m_const, field_ty }
};
if (scope.is_lvalue) { if (scope.is_lvalue) {
return codegen::StackValue{ return codegen::StackValue{
gep, gep,
ptr_ty field_ty
}; };
} }
else { else {
auto ptr_ty = std::shared_ptr<types::Type>{
new types::PointerType { field_ty->m_const, field_ty }
};
auto loaded = ptr_ty->load(builder, gep, scope.structs); auto loaded = ptr_ty->load(builder, gep, scope.structs);
return codegen::StackValue{ loaded.first, loaded.second }; return codegen::StackValue{ loaded.first, loaded.second };
} }
@ -458,19 +475,15 @@ namespace AST {
builder.builder->SetInsertPoint(builder.block); builder.builder->SetInsertPoint(builder.block);
if (this->m_type->m_kind == types::TypeKind::Array) { if (this->m_type->m_kind == types::TypeKind::Array) {
auto array_ty = dynamic_cast<types::ArrayType*>(this->m_type.get()); auto raw_llvm_ty = this->m_type->codegen(builder, scope.structs);
if (!array_ty->m_raw) { auto ptr = builder.builder->CreateAlloca(raw_llvm_ty);
auto raw_ty = types::ArrayType{ array_ty->m_inner, array_ty->m_size, true }; if (this->m_expr.has_value()) {
auto raw_llvm_ty = raw_ty.codegen(builder, scope.structs); auto value = this->m_expr->get()->codegen(builder, scope);
auto ptr = builder.builder->CreateAlloca(raw_llvm_ty); builder.builder->CreateStore(value.value, ptr, false);
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;
} }
scope.values[this->m_name] = codegen::StackValue{ ptr, this->m_type };
return;
} }
auto ty = this->m_type->codegen(builder, scope.structs); auto ty = this->m_type->codegen(builder, scope.structs);

View File

@ -176,7 +176,7 @@ std::optional<CompileOutput> compile(std::string_view in_filename) {
builder.mod->print(llvm_ir_dest, nullptr); builder.mod->print(llvm_ir_dest, nullptr);
llvm_ir_dest.flush(); llvm_ir_dest.flush();
// std::cout << llvm_ir_string << std::endl; std::cout << llvm_ir_string << std::endl;
// Print output to obj-file // Print output to obj-file
std::error_code EC; std::error_code EC;

View File

@ -8,6 +8,7 @@ namespace parsing {
static uint32_t struct_id_counter = 0; static uint32_t struct_id_counter = 0;
Result<std::unique_ptr<AST::Expression>, std::string> parse_expression(token::TokenStream& stream, Scope& scope); Result<std::unique_ptr<AST::Expression>, std::string> parse_expression(token::TokenStream& stream, Scope& scope);
Result<std::optional<uint32_t>, std::string> parse_array_postfix(token::TokenStream& stream, bool allow_empty, Scope&);
Result<std::shared_ptr<types::Type>, std::string> parse_type(token::TokenStream& stream, Scope& scope) { Result<std::shared_ptr<types::Type>, std::string> parse_type(token::TokenStream& stream, Scope& scope) {
token::TokenStream inner{ stream }; token::TokenStream inner{ stream };
@ -41,12 +42,23 @@ namespace parsing {
if (counter++ > 0) if (counter++ > 0)
inner.expect(token::Type::Symbol, ";"); inner.expect(token::Type::Symbol, ";");
auto ty = parse_type(inner, scope); auto ty_res = parse_type(inner, scope);
if (!ty.ok()) if (!ty_res.ok())
break; break;
auto ty = ty_res.unwrap();
auto field_name = inner.expect(token::Type::Ident); 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<types::Type>{
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, "}"); inner.expect(token::Type::Symbol, "}");
@ -430,7 +442,7 @@ namespace parsing {
while (array_postfix.ok()) { while (array_postfix.ok()) {
auto postfix = array_postfix.unwrap(); auto postfix = array_postfix.unwrap();
ty = std::shared_ptr<types::Type>{ ty = std::shared_ptr<types::Type>{
new types::ArrayType(ty, *postfix, false) new types::ArrayType(ty, *postfix, true)
}; };
array_postfix = parse_array_postfix(inner, false, scope); array_postfix = parse_array_postfix(inner, false, scope);
} }

8
test.c
View File

@ -15,6 +15,7 @@ struct Otus;
struct Otus { struct Otus {
int field; int field;
int second[2];
}; };
void update(struct Otus potus) { void update(struct Otus potus) {
potus.field = 20; potus.field = 20;
@ -36,14 +37,19 @@ int main() {
printf("first element: %d!\n", somelist[0]); printf("first element: %d!\n", somelist[0]);
printf("first element via ptr: %d!\n", somelist_ptr[0]); printf("first element via ptr: %d!\n", somelist_ptr[0]);
struct Otus otus = { 5 }; struct Otus otus = { 5, { 7, 3 } };
update(otus); update(otus);
printf("first field: %d!\n", otus.field); printf("first field: %d!\n", otus.field);
printf("second field's second element: %d!\n", otus.second[1]);
char hello = 10; char hello = 10;
update_ptr(&hello); update_ptr(&hello);
printf("hello: %d!\n", 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; return 0;
} }