From 124a18a48659a41bf10de348fd70ae4e5c053015 Mon Sep 17 00:00:00 2001 From: Christoffer Lerno Date: Sun, 29 Jan 2023 17:17:18 +0100 Subject: [PATCH] Fix bug with enum associated values. --- src/compiler/llvm_codegen_expr.c | 14 +-- src/version.h | 2 +- .../enum_associated_values_other.c3t | 85 +++++++++++++++++++ 3 files changed, 94 insertions(+), 7 deletions(-) create mode 100644 test/test_suite/enumerations/enum_associated_values_other.c3t diff --git a/src/compiler/llvm_codegen_expr.c b/src/compiler/llvm_codegen_expr.c index 8c70b8309..387057a7b 100644 --- a/src/compiler/llvm_codegen_expr.c +++ b/src/compiler/llvm_codegen_expr.c @@ -1088,24 +1088,26 @@ static inline void llvm_emit_bitaccess(GenContext *c, BEValue *be_value, Expr *e llvm_extract_bitvalue(c, be_value, parent, expr->access_expr.ref); } -static inline void llvm_emit_access_addr(GenContext *context, BEValue *be_value, Expr *expr) +static inline void llvm_emit_access_addr(GenContext *c, BEValue *be_value, Expr *expr) { Expr *parent = expr->access_expr.parent; - llvm_emit_expr(context, be_value, parent); + llvm_emit_expr(c, be_value, parent); Decl *member = expr->access_expr.ref; Type *flat_type = type_flatten_distinct_optional(parent->type); if (flat_type->type_kind == TYPE_ENUM) { - llvm_value_rvalue(context, be_value); - LLVMTypeRef value_type = llvm_get_type(context, type_get_array(member->type, vec_size(flat_type->decl->enums.values))); + llvm_value_rvalue(c, be_value); + if (!member->backend_ref) llvm_get_typeid(c, parent->type); + assert(member->backend_ref); + LLVMTypeRef value_type = llvm_get_type(c, type_get_array(member->type, vec_size(flat_type->decl->enums.values))); AlignSize align = LLVMGetAlignment(member->backend_ref); AlignSize alignment; - LLVMValueRef ptr = llvm_emit_array_gep_raw_index(context, member->backend_ref, value_type, be_value->value, align, &alignment); + LLVMValueRef ptr = llvm_emit_array_gep_raw_index(c, member->backend_ref, value_type, be_value->value, align, &alignment); llvm_value_set_address(be_value, ptr, member->type, alignment); return; } - llvm_emit_member_addr(context, be_value, type_lowering(parent->type)->decl, member); + llvm_emit_member_addr(c, be_value, type_lowering(parent->type)->decl, member); } diff --git a/src/version.h b/src/version.h index 7895006b9..bad77db80 100644 --- a/src/version.h +++ b/src/version.h @@ -1 +1 @@ -#define COMPILER_VERSION "0.4.33" \ No newline at end of file +#define COMPILER_VERSION "0.4.34" \ No newline at end of file diff --git a/test/test_suite/enumerations/enum_associated_values_other.c3t b/test/test_suite/enumerations/enum_associated_values_other.c3t new file mode 100644 index 000000000..7c6d45c7b --- /dev/null +++ b/test/test_suite/enumerations/enum_associated_values_other.c3t @@ -0,0 +1,85 @@ +// #target: macos-x64 +module test; +import std::io; +import abc; + +fn void main(String[] args) +{ + typeid y = Abc.typeid; + int* x = &abc::dabc; + Foo a = Foo.DEF; + String z = a.val; + io::printfln("%s", z); +} + +module abc; +int dabc; + +struct Abc { int x; } +enum Foo : int(String val) +{ + ABC("hello"), + DEF("world") +} + +/* #expect: abc.ll + +@"ct$abc_Abc" = linkonce constant %.introspect { i8 10, i64 4, i64 0, i64 1, [0 x i64] zeroinitializer }, align 8 +@.enum.0 = internal constant [4 x i8] c"ABC\00", align 1 +@.enum.1 = internal constant [4 x i8] c"DEF\00", align 1 +@"ct$int" = linkonce constant %.introspect { i8 2, i64 4, i64 0, i64 0, [0 x i64] zeroinitializer }, align 8 +@"ct$abc_Foo" = linkonce constant { i8, i64, i64, i64, [2 x %"char[]"] } { i8 8, i64 4, i64 ptrtoint (ptr @"ct$int" to i64), i64 2, [2 x %"char[]"] [%"char[]" { ptr @.enum.0, i64 3 }, %"char[]" { ptr @.enum.1, i64 3 }] }, align 8 +@.str = private unnamed_addr constant [6 x i8] c"hello\00", align 1 +@.str.1 = private unnamed_addr constant [6 x i8] c"world\00", align 1 +@"abc_Foo$val" = linkonce constant [2 x %"char[]"] [%"char[]" { ptr @.str, i64 5 }, %"char[]" { ptr @.str.1, i64 5 }], align 8 +@abc_dabc = global i32 0, align 4 + +// #expect: test.ll + + +@"ct$abc_Abc" = linkonce constant %.introspect { i8 10, i64 4, i64 0, i64 1, [0 x i64] zeroinitializer }, align 8 +@abc_dabc = external global i32, align 4 +@.enum.0 = internal constant [4 x i8] c"ABC\00", align 1 +@.enum.1 = internal constant [4 x i8] c"DEF\00", align 1 +@"ct$int" = linkonce constant %.introspect { i8 2, i64 4, i64 0, i64 0, [0 x i64] zeroinitializer }, align 8 +@"ct$abc_Foo" = linkonce constant { i8, i64, i64, i64, [2 x %"char[]"] } { i8 8, i64 4, i64 ptrtoint (ptr @"ct$int" to i64), i64 2, [2 x %"char[]"] [%"char[]" { ptr @.enum.0, i64 3 }, %"char[]" { ptr @.enum.1, i64 3 }] }, align 8 +@.str = private unnamed_addr constant [6 x i8] c"hello\00", align 1 +@.str.1 = private unnamed_addr constant [6 x i8] c"world\00", align 1 +@"abc_Foo$val" = linkonce constant [2 x %"char[]"] [%"char[]" { ptr @.str, i64 5 }, %"char[]" { ptr @.str.1, i64 5 }], align 8 +@.str.2 = private unnamed_addr constant [3 x i8] c"%s\00", align 1 +@"ct$char" = linkonce constant %.introspect { i8 3, i64 1, i64 0, i64 0, [0 x i64] zeroinitializer }, align 8 +@"ct$sa$char" = linkonce constant %.introspect { i8 16, i64 16, i64 ptrtoint (ptr @"ct$char" to i64), i64 0, [0 x i64] zeroinitializer }, align 8 + +define void @test_main(ptr %0, i64 %1) #0 { +entry: + %args = alloca %"char[][]", align 8 + %y = alloca i64, align 8 + %x = alloca ptr, align 8 + %a = alloca i32, align 4 + %z = alloca %"char[]", align 8 + %retparam = alloca i64, align 8 + %varargslots = alloca [1 x %variant], align 16 + %2 = getelementptr inbounds { ptr, i64 }, ptr %args, i32 0, i32 0 + store ptr %0, ptr %2, align 8 + %3 = getelementptr inbounds { ptr, i64 }, ptr %args, i32 0, i32 1 + store i64 %1, ptr %3, align 8 + store i64 ptrtoint (ptr @"ct$abc_Abc" to i64), ptr %y, align 8 + store ptr @abc_dabc, ptr %x, align 8 + store i32 1, ptr %a, align 4 + %4 = load i32, ptr %a, align 4 + %5 = getelementptr inbounds [2 x %"char[]"], ptr @"abc_Foo$val", i32 0, i32 %4 + call void @llvm.memcpy.p0.p0.i32(ptr align 8 %z, ptr align 8 %5, i32 16, i1 false) + %6 = insertvalue %variant undef, ptr %z, 0 + %7 = insertvalue %variant %6, i64 ptrtoint (ptr @"ct$sa$char" to i64), 1 + %8 = getelementptr inbounds [1 x %variant], ptr %varargslots, i64 0, i64 0 + store %variant %7, ptr %8, align 16 + %9 = call i64 @std_io_printfn(ptr %retparam, ptr @.str.2, i64 2, ptr %varargslots, i64 1) + %not_err = icmp eq i64 %9, 0 + br i1 %not_err, label %after_check, label %voiderr + +after_check: ; preds = %entry + br label %voiderr + +voiderr: ; preds = %after_check, %entry + ret void +} \ No newline at end of file