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) {
auto value = this->m_expr->codegen(builder, scope);
std::shared_ptr<types::Type> 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<llvm::Value*> idx_list{ };
idx_list.push_back(llvm::ConstantInt::get(builder.builder->getInt32Ty(), this->m_num));
@ -265,33 +275,40 @@ namespace AST {
if (value.ty->m_kind == types::TypeKind::Pointer) {
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);
if (scope.is_lvalue) {
return codegen::StackValue{
gep_value,
value.ty,
};
}
else {
auto loaded = ptr_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);
}
// 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}
};
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,
ptr_ty,
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,
@ -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<types::Type>{
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<types::Type>{
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,10 +475,7 @@ namespace AST {
builder.builder->SetInsertPoint(builder.block);
if (this->m_type->m_kind == types::TypeKind::Array) {
auto array_ty = dynamic_cast<types::ArrayType*>(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 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);
@ -471,7 +485,6 @@ namespace AST {
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);

View File

@ -176,7 +176,7 @@ std::optional<CompileOutput> 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;

View File

@ -8,6 +8,7 @@ namespace parsing {
static uint32_t struct_id_counter = 0;
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) {
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<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, "}");
@ -430,7 +442,7 @@ namespace parsing {
while (array_postfix.ok()) {
auto postfix = array_postfix.unwrap();
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);
}

8
test.c
View File

@ -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;
}