diff --git a/releasenotes.md b/releasenotes.md index 75ff6bc73..8a506c3de 100644 --- a/releasenotes.md +++ b/releasenotes.md @@ -33,6 +33,7 @@ - Place output in `out` by default for projects. Use temp folder for building at the command line. - Allow absolute paths for `$embed`. - Add `@try` and `@try_catch`. +- Assignment evaluation order now right->left, following C++17 and possibly C23. ### Fixes - mkdir/rmdir would not work properly with substring paths on non-windows platforms. diff --git a/src/compiler/llvm_codegen_expr.c b/src/compiler/llvm_codegen_expr.c index abee7fdef..b64f0a63c 100644 --- a/src/compiler/llvm_codegen_expr.c +++ b/src/compiler/llvm_codegen_expr.c @@ -106,17 +106,16 @@ Expr *expr_remove_recast(Expr *expr) return expr; } -BEValue llvm_emit_assign_expr(GenContext *c, BEValue *ref, Expr *expr, LLVMValueRef optional, bool is_init) +BEValue llvm_emit_assign_expr(GenContext *c, BEValue *ref, Expr *ref_expr, Expr *expr, LLVMValueRef optional, bool is_init) { - ASSERT(llvm_value_is_addr(ref)); - - assert((optional || !IS_OPTIONAL(expr)) && "Assumed an optional address if it's an optional expression."); + ASSERT(ref_expr || llvm_value_is_addr(ref)); expr = expr_remove_recast(expr); // Special optimization of handling of optional if (expr->expr_kind == EXPR_OPTIONAL) { + assert(!ref_expr); PUSH_CLEAR_CATCH(); BEValue result; @@ -125,6 +124,9 @@ BEValue llvm_emit_assign_expr(GenContext *c, BEValue *ref, Expr *expr, LLVMValue llvm_value_rvalue(c, &result); + assert((optional || !IS_OPTIONAL(expr)) && "Assumed an optional address if it's an optional expression."); + + LLVMValueRef err_val = result.value; // Store it in the optional llvm_store_to_ptr(c, optional, &result); @@ -147,6 +149,7 @@ BEValue llvm_emit_assign_expr(GenContext *c, BEValue *ref, Expr *expr, LLVMValue if (IS_OPTIONAL(expr)) { + assert(!ref_expr); assign_block = llvm_basic_block_new(c, "after_assign"); ASSERT(optional); if (c->catch.fault) @@ -168,10 +171,12 @@ BEValue llvm_emit_assign_expr(GenContext *c, BEValue *ref, Expr *expr, LLVMValue if (type_flat_is_vector(expr->type)) { llvm_emit_expr(c, &value, expr); + if (ref_expr) llvm_emit_expr(c, ref, ref_expr); llvm_store(c, ref, &value); } else if (expr_is_const_initializer(expr)) { + if (ref_expr) llvm_emit_expr(c, ref, ref_expr); llvm_emit_const_initialize_reference(c, ref, expr); value = *ref; } @@ -179,15 +184,18 @@ BEValue llvm_emit_assign_expr(GenContext *c, BEValue *ref, Expr *expr, LLVMValue { if (is_init) { + assert(!ref_expr); llvm_emit_initialize_reference(c, ref, expr); } else { BEValue val; - AlignSize alignment = type_alloca_alignment(ref->type); - LLVMValueRef temp = llvm_emit_alloca(c, llvm_get_type(c, ref->type), alignment, ".assign_list"); - llvm_value_set_address(c, &val, temp, ref->type, alignment); + Type *type = ref_expr ? type_lowering(ref_expr->type) : ref->type; + AlignSize alignment = type_alloca_alignment(type); + LLVMValueRef temp = llvm_emit_alloca(c, llvm_get_type(c, type), alignment, ".assign_list"); + llvm_value_set_address(c, &val, temp, type, alignment); llvm_emit_initialize_reference(c, &val, expr); + if (ref_expr) llvm_emit_expr(c, ref, ref_expr); llvm_store(c, ref, &val); } value = *ref; @@ -196,11 +204,13 @@ BEValue llvm_emit_assign_expr(GenContext *c, BEValue *ref, Expr *expr, LLVMValue { if (expr->expr_kind == EXPR_CALL) { - llvm_emit_call_expr(c, &value, expr, ref); + llvm_emit_call_expr(c, &value, expr, ref_expr ? NULL : ref); + if (ref_expr) llvm_emit_expr(c, ref, ref_expr); } else { llvm_emit_expr(c, &value, expr); + if (ref_expr) llvm_emit_expr(c, ref, ref_expr); } if (!c->current_block) goto AFTER_STORE; if (value.type != type_void) llvm_store(c, ref, &value); @@ -215,6 +225,7 @@ AFTER_STORE:; if (assign_block) { + assert(!ref_expr); llvm_emit_br(c, assign_block); if (rejump_block) { @@ -4493,19 +4504,18 @@ static void llvm_emit_binary_expr(GenContext *c, BEValue *be_value, Expr *expr) if (binary_op == BINARYOP_ASSIGN) { Expr *left = exprptr(expr->binary_expr.left); - llvm_emit_expr(c, be_value, left); - ASSERT(llvm_value_is_addr(be_value)); - LLVMValueRef optional_ref = NULL; // If the LHS is an identifier, then we're assigning the optional value to that. if (left->expr_kind == EXPR_IDENTIFIER) { - optional_ref = decl_optional_ref(left->ident_expr); - be_value->kind = BE_ADDRESS; + llvm_value_set_decl(c, be_value, left->ident_expr); + *be_value = llvm_emit_assign_expr(c, be_value, NULL, exprptr(expr->binary_expr.right), decl_optional_ref(left->ident_expr), false); + return; } + *be_value = llvm_emit_assign_expr(c, be_value, left, exprptr(expr->binary_expr.right), NULL, false); + // Emit the result. - *be_value = llvm_emit_assign_expr(c, be_value, exprptr(expr->binary_expr.right), optional_ref, false); return; } diff --git a/src/compiler/llvm_codegen_internal.h b/src/compiler/llvm_codegen_internal.h index 961a8932d..9c90d197b 100644 --- a/src/compiler/llvm_codegen_internal.h +++ b/src/compiler/llvm_codegen_internal.h @@ -542,7 +542,7 @@ void llvm_emit_compound_stmt(GenContext *c, Ast *ast); LLVMValueRef llvm_emit_const_bitstruct(GenContext *c, ConstInitializer *initializer); void llvm_emit_function_body(GenContext *c, Decl *decl); void llvm_emit_dynamic_functions(GenContext *c, Decl **funcs); -BEValue llvm_emit_assign_expr(GenContext *c, BEValue *ref, Expr *expr, LLVMValueRef optional, bool is_init); +BEValue llvm_emit_assign_expr(GenContext *c, BEValue *ref, Expr *ref_expr, Expr *expr, LLVMValueRef optional, bool is_init); INLINE void llvm_emit_exprid(GenContext *c, BEValue *value, ExprId expr); INLINE void llvm_emit_statement_chain(GenContext *c, AstId current); void llvm_emit_initialize_reference_temporary_const(GenContext *c, BEValue *ref, ConstInitializer *initializer); diff --git a/src/compiler/llvm_codegen_stmt.c b/src/compiler/llvm_codegen_stmt.c index a802008ba..cc73e79f0 100644 --- a/src/compiler/llvm_codegen_stmt.c +++ b/src/compiler/llvm_codegen_stmt.c @@ -144,7 +144,7 @@ void llvm_emit_local_decl(GenContext *c, Decl *decl, BEValue *value) llvm_value_set_decl_address(c, value, decl); // Pretend to be normal. value->kind = BE_ADDRESS; - BEValue res = llvm_emit_assign_expr(c, value, decl->var.init_expr, decl->var.optional_ref, true); + BEValue res = llvm_emit_assign_expr(c, value, NULL, decl->var.init_expr, decl->var.optional_ref, true); if (!is_optional && res.value) { *value = res; diff --git a/src/compiler/sema_expr.c b/src/compiler/sema_expr.c index a92ff9a88..fef01bc98 100644 --- a/src/compiler/sema_expr.c +++ b/src/compiler/sema_expr.c @@ -6726,10 +6726,14 @@ static bool sema_expr_analyse_assign(SemaContext *context, Expr *expr, Expr *lef } if (left->expr_kind == EXPR_SUBSCRIPT_ASSIGN) { + Decl *temp = decl_new_generated_var(right->type, VARDECL_LOCAL, right->span); + Expr *expr_rh = expr_generate_decl(temp, right); Expr **args = NULL; vec_add(args, exprptr(left->subscript_assign_expr.index)); - vec_add(args, right); - return sema_insert_method_call(context, expr, declptr(left->subscript_assign_expr.method), exprptr(left->subscript_assign_expr.expr), args, false); + vec_add(args, expr_variable(temp)); + if (!sema_insert_method_call(context, expr, declptr(left->subscript_assign_expr.method), exprptr(left->subscript_assign_expr.expr), args, false)) return false; + expr_rewrite_two(expr, expr_rh, expr_copy(expr)); + return true; } if (left->expr_kind == EXPR_BITACCESS) { diff --git a/test/test_suite/clang/2002-07.c3t b/test/test_suite/clang/2002-07.c3t index 6ece2a552..a5bdd1789 100644 --- a/test/test_suite/clang/2002-07.c3t +++ b/test/test_suite/clang/2002-07.c3t @@ -319,16 +319,13 @@ fn int strcmp(char *s1, char *s2) { @.str = private unnamed_addr constant [7 x i8] c"\00", align 1 @.str.11 = private unnamed_addr constant [14 x i8] c"Hello world!\0A\00", align 1 -; Function Attrs: declare ptr @malloc(i32) #0 -; Function Attrs: define ptr @foo.passThroughList(ptr %0) #0 { entry: ret ptr %0 } -; Function Attrs: define void @foo.foo() #0 { entry: %0 = load i32, ptr @foo.foo.10, align 4 @@ -339,7 +336,6 @@ entry: ret void } -; Function Attrs: define void @foo.insertIntoListTail(ptr %0, i32 %1) #0 { entry: %l = alloca ptr, align 8 @@ -360,9 +356,9 @@ loop.body: ; preds = %loop.cond br label %loop.cond loop.exit: ; preds = %loop.cond - %6 = load ptr, ptr %l, align 8 - %7 = call ptr @malloc(i32 16) - store ptr %7, ptr %6, align 8 + %6 = call ptr @malloc(i32 16) + %7 = load ptr, ptr %l, align 8 + store ptr %6, ptr %7, align 8 %8 = load ptr, ptr %l, align 8 %9 = load ptr, ptr %8, align 8 store i32 %1, ptr %9, align 8 @@ -373,7 +369,6 @@ loop.exit: ; preds = %loop.cond ret void } -; Function Attrs: define ptr @foo.findData(ptr %0, i32 %1) #0 { entry: %i2nb = icmp eq ptr %0, null @@ -397,10 +392,8 @@ if.exit2: ; preds = %if.exit ret ptr %4 } -; Function Attrs: declare void @foundIt() #0 -; Function Attrs: define void @foo.doListStuff() #0 { entry: %myList = alloca ptr, align 8 @@ -443,7 +436,6 @@ if.exit6: ; preds = %if.then5, %if.exit3 ret void } -; Function Attrs: define i32 @foo.floatcomptest(ptr %0, ptr %1, ptr %2, ptr %3) #0 { entry: %4 = load double, ptr %0, align 8 @@ -463,7 +455,6 @@ or.phi: ; preds = %or.rhs, %entry ret i32 %zext } -; Function Attrs: define ptr @foo.memset_impl(ptr %0, i32 %1, i32 %2) #0 { entry: %len = alloca i32, align 4 @@ -480,9 +471,9 @@ loop.cond: ; preds = %loop.body, %entry br i1 %neq, label %loop.body, label %loop.exit loop.body: ; preds = %loop.cond + %trunc = trunc i32 %1 to i8 %4 = load i64, ptr %dstp, align 8 %intptr = inttoptr i64 %4 to ptr - %trunc = trunc i32 %1 to i8 store i8 %trunc, ptr %intptr, align 1 %5 = load i64, ptr %dstp, align 8 %add = add i64 %5, 1 @@ -496,7 +487,6 @@ loop.exit: ; preds = %loop.cond ret ptr %0 } -; Function Attrs: define internal ptr @foo.localmalloc(i32 %0) #0 { entry: %blah = alloca ptr, align 8 @@ -516,7 +506,6 @@ if.exit: ; preds = %entry ret ptr null } -; Function Attrs: define void @foo.testRetStruct(ptr noalias sret(%PBVTest) align 8 %0, float %1, double %2, i32 %3) #0 { entry: %t = alloca %PBVTest, align 8 @@ -530,10 +519,8 @@ entry: ret void } -; Function Attrs: declare void @testRetStruct2(ptr noalias sret(%PBVTest) align 8) #0 -; Function Attrs: define double @foo.callRetStruct(float %0, double %1, i32 %2) #0 { entry: %t = alloca %PBVTest, align 8 @@ -547,10 +534,8 @@ entry: ret double %fadd2 } -; Function Attrs: declare i32 @fp(i32, ptr) #0 -; Function Attrs: define void @foo.__bb_exit_func() #0 { entry: %0 = load ptr, ptr @foo.ext, align 8 @@ -570,17 +555,14 @@ cond.phi: ; preds = %cond.rhs, %cond.lhs ret void } -; Function Attrs: declare i32 @puts(ptr) #0 -; Function Attrs: define i32 @foo.ptrFunc(ptr %0, i32 %1) #0 { entry: %2 = call i32 %0(i32 %1) ret i32 %2 } -; Function Attrs: define zeroext i8 @foo.ptrFunc2(ptr byval([30 x ptr]) align 8 %0, i32 %1) #0 { entry: %sext = sext i32 %1 to i64 @@ -591,13 +573,10 @@ entry: ret i8 %trunc } -; Function Attrs: declare zeroext i8 @smallArgs2(i8 zeroext, i8 zeroext, i64, i8 zeroext, i8 zeroext) #0 -; Function Attrs: declare i32 @someFuncA() #0 -; Function Attrs: define zeroext i8 @foo.smallArgs(i8 zeroext %0, i8 zeroext %1, i8 zeroext %2, i8 zeroext %3) #0 { entry: %4 = call i32 @someFuncA() @@ -612,7 +591,6 @@ entry: ret i8 %5 } -; Function Attrs: define internal i32 @foo.f0(ptr byval(%Quad) align 8 %0, i32 %1) #0 { entry: %r = alloca %Quad, align 8 @@ -620,19 +598,19 @@ entry: br i1 %i2b, label %if.then, label %if.exit if.then: ; preds = %entry - %ptradd = getelementptr inbounds i8, ptr %r, i64 4 - %ptradd1 = getelementptr inbounds i8, ptr %0, i64 4 - call void @llvm.memcpy.p0.p0.i32(ptr align 4 %ptradd, ptr align 4 %ptradd1, i32 4, i1 false) + %ptradd = getelementptr inbounds i8, ptr %0, i64 4 + %ptradd1 = getelementptr inbounds i8, ptr %r, i64 4 + call void @llvm.memcpy.p0.p0.i32(ptr align 4 %ptradd1, ptr align 4 %ptradd, i32 4, i1 false) br label %if.exit if.exit: ; preds = %if.then, %entry - %ptradd2 = getelementptr inbounds i8, ptr %0, i64 8 - %ptradd3 = getelementptr inbounds i8, ptr %r, i64 4 - store ptr %ptradd3, ptr %ptradd2, align 8 - %ptradd4 = getelementptr inbounds i8, ptr %0, i64 20 - %ptradd5 = getelementptr inbounds i8, ptr %0, i64 16 - store i8 1, ptr %ptradd5, align 8 - store i32 1, ptr %ptradd4, align 4 + %ptradd2 = getelementptr inbounds i8, ptr %r, i64 4 + %ptradd3 = getelementptr inbounds i8, ptr %0, i64 8 + store ptr %ptradd2, ptr %ptradd3, align 8 + %ptradd4 = getelementptr inbounds i8, ptr %0, i64 16 + store i8 1, ptr %ptradd4, align 8 + %ptradd5 = getelementptr inbounds i8, ptr %0, i64 20 + store i32 1, ptr %ptradd5, align 4 store i32 1, ptr %0, align 8 %ptradd6 = getelementptr inbounds i8, ptr %0, i64 4 %ptradd7 = getelementptr inbounds i8, ptr %ptradd6, i64 2 @@ -649,7 +627,6 @@ if.exit: ; preds = %if.then, %entry ret i32 %sub } -; Function Attrs: define i32 @foo.f1(ptr %0, i32 %1) #0 { entry: %r = alloca %Quad, align 8 @@ -661,10 +638,10 @@ if.then: ; preds = %entry br label %if.exit if.exit: ; preds = %if.then, %entry - %ptradd = getelementptr inbounds i8, ptr %0, i64 20 - %ptradd1 = getelementptr inbounds i8, ptr %0, i64 16 - store i8 1, ptr %ptradd1, align 8 - store i32 1, ptr %ptradd, align 4 + %ptradd = getelementptr inbounds i8, ptr %0, i64 16 + store i8 1, ptr %ptradd, align 8 + %ptradd1 = getelementptr inbounds i8, ptr %0, i64 20 + store i32 1, ptr %ptradd1, align 4 store i32 1, ptr %0, align 8 %ptradd2 = getelementptr inbounds i8, ptr %0, i64 4 %ptradd3 = getelementptr inbounds i8, ptr %ptradd2, i64 2 @@ -681,7 +658,6 @@ if.exit: ; preds = %if.then, %entry ret i32 %sub } -; Function Attrs: define i32 @foo.badFunc(float %0) #0 { entry: %result = alloca i32, align 4 @@ -698,10 +674,8 @@ if.exit: ; preds = %if.then, %entry ret i32 %1 } -; Function Attrs: declare i32 @ef1(ptr, ptr, ptr) #0 -; Function Attrs: define i32 @foo.func(i32 %0, i64 %1) #0 { entry: %result = alloca i32, align 4 @@ -718,7 +692,6 @@ entry: ret i32 %4 } -; Function Attrs: define signext i16 @foo.funFunc(i64 %0, i8 zeroext %1) #0 { entry: %zext = zext i8 %1 to i64 @@ -727,13 +700,11 @@ entry: ret i16 %trunc } -; Function Attrs: define i32 @foo.castTest(i32 %0) #0 { entry: ret i32 %0 } -; Function Attrs: define double @foo.testAdd(double %0, float %1) #0 { entry: %fpfpext = fpext float %1 to double @@ -742,7 +713,6 @@ entry: ret double %fadd1 } -; Function Attrs: define i32 @foo.funcZ(i32 %0, i32 %1) #0 { entry: %i = alloca i32, align 4 @@ -778,7 +748,6 @@ loop.exit: ; preds = %loop.cond ret i32 %mul4 } -; Function Attrs: define i32 @foo.sumArray(ptr %0, i32 %1) #0 { entry: %i = alloca i32, align 4 @@ -810,7 +779,6 @@ loop.exit: ; preds = %loop.cond ret i32 %7 } -; Function Attrs: define i32 @foo.arrayParam(ptr %0) #0 { entry: %ptradd = getelementptr inbounds i8, ptr %0, i64 200 @@ -822,7 +790,6 @@ entry: ret i32 %2 } -; Function Attrs: define i32 @foo.arrayToSum() #0 { entry: %a = alloca [100 x i32], align 16 @@ -838,10 +805,10 @@ loop.cond: ; preds = %loop.body, %entry loop.body: ; preds = %loop.cond %1 = load i32, ptr %i, align 4 - %sext = sext i32 %1 to i64 - %ptroffset = getelementptr inbounds [4 x i8], ptr %a, i64 %sext + %mul = mul i32 %1, 4 %2 = load i32, ptr %i, align 4 - %mul = mul i32 %2, 4 + %sext = sext i32 %2 to i64 + %ptroffset = getelementptr inbounds [4 x i8], ptr %a, i64 %sext store i32 %mul, ptr %ptroffset, align 4 %3 = load i32, ptr %i, align 4 %add = add i32 %3, 1 @@ -887,7 +854,6 @@ loop.exit: ; preds = %loop.cond ret i32 0 } -; Function Attrs: define double @foo.mathFunc(double %0, double %1, double %2, double %3, double %4, double %5, double %6, double %7, double %8, double %9, double %10, double %11, double %12, double %13, double %14, double %15, double %16) #0 { entry: %fadd = fadd double %0, %1 @@ -909,7 +875,6 @@ entry: ret double %fadd15 } -; Function Attrs: define void @foo.strcpy(ptr %0, ptr %1) #0 { entry: %s1 = alloca ptr, align 8 @@ -919,14 +884,14 @@ entry: br label %loop.cond loop.cond: ; preds = %loop.body, %entry - %2 = load ptr, ptr %s1, align 8 + %2 = load ptr, ptr %s2, align 8 %ptradd_any = getelementptr i8, ptr %2, i64 1 - store ptr %ptradd_any, ptr %s1, align 8 - %3 = load ptr, ptr %s2, align 8 + store ptr %ptradd_any, ptr %s2, align 8 + %3 = load ptr, ptr %s1, align 8 %ptradd_any1 = getelementptr i8, ptr %3, i64 1 - store ptr %ptradd_any1, ptr %s2, align 8 - %4 = load i8, ptr %3, align 1 - store i8 %4, ptr %2, align 1 + store ptr %ptradd_any1, ptr %s1, align 8 + %4 = load i8, ptr %2, align 1 + store i8 %4, ptr %3, align 1 %i2b = icmp ne i8 %4, 0 br i1 %i2b, label %loop.body, label %loop.exit @@ -964,14 +929,14 @@ loop.exit: ; preds = %loop.cond br label %loop.cond2 loop.cond2: ; preds = %loop.body6, %loop.exit - %5 = load ptr, ptr %s1, align 8 + %5 = load ptr, ptr %s2, align 8 %ptradd_any3 = getelementptr i8, ptr %5, i64 1 - store ptr %ptradd_any3, ptr %s1, align 8 - %6 = load ptr, ptr %s2, align 8 + store ptr %ptradd_any3, ptr %s2, align 8 + %6 = load ptr, ptr %s1, align 8 %ptradd_any4 = getelementptr i8, ptr %6, i64 1 - store ptr %ptradd_any4, ptr %s2, align 8 - %7 = load i8, ptr %6, align 1 - store i8 %7, ptr %5, align 1 + store ptr %ptradd_any4, ptr %s1, align 8 + %7 = load i8, ptr %5, align 1 + store i8 %7, ptr %6, align 1 %i2b5 = icmp ne i8 %7, 0 br i1 %i2b5, label %loop.body6, label %loop.exit7 diff --git a/test/test_suite/contracts/ensure_with_void_2098.c3t b/test/test_suite/contracts/ensure_with_void_2098.c3t index c3f8161c2..bacf016ea 100644 --- a/test/test_suite/contracts/ensure_with_void_2098.c3t +++ b/test/test_suite/contracts/ensure_with_void_2098.c3t @@ -29,6 +29,7 @@ entry: %taddr9 = alloca i64, align 8 %varargslots10 = alloca [2 x %any], align 16 %indirectarg13 = alloca %"any[]", align 8 + %add = add i32 %1, 1 %checknull = icmp eq ptr %0, null %2 = call i1 @llvm.expect.i1(i1 %checknull, i1 false) br i1 %2, label %panic, label %checkok @@ -41,7 +42,6 @@ checkok: ; preds = %entry br i1 %6, label %panic1, label %checkok3 checkok3: ; preds = %checkok - %add = add i32 %1, 1 store i32 %add, ptr %0, align 4 %checknull4 = icmp eq ptr %0, null %7 = call i1 @llvm.expect.i1(i1 %checknull4, i1 false) diff --git a/test/test_suite/debug_symbols/ct_foreach.c3t b/test/test_suite/debug_symbols/ct_foreach.c3t index 7c43baf93..b5f7bc0a0 100644 --- a/test/test_suite/debug_symbols/ct_foreach.c3t +++ b/test/test_suite/debug_symbols/ct_foreach.c3t @@ -41,7 +41,7 @@ entry: !15 = !{!16} !16 = !DISubrange(count: 1, lowerBound: 0) !17 = !DILocation(line: 5, column: 10, scope: !8) -!18 = !DILocation(line: 7, column: 18, scope: !8) +!18 = !DILocation(line: 7, column: 12, scope: !8) !19 = distinct !DISubprogram(name: "main", linkageName: "test.main", scope: !7, file: !7, line: 11, type: !9, scopeLine: 11, flags: DIFlagPrototyped, spFlags: DISPFlagDefinition, unit: !6) !20 = !DILocation(line: 12, column: 3, scope: !19) !21 = distinct !DISubprogram(name: "_$main", linkageName: "main", scope: !7, file: !7, line: 11, type: !22, scopeLine: 11, flags: DIFlagPrototyped, spFlags: DISPFlagDefinition, unit: !6, retainedNodes: !11) diff --git a/test/test_suite/debug_symbols/defer_macro.c3t b/test/test_suite/debug_symbols/defer_macro.c3t index 2bbb2c46c..479344f64 100644 --- a/test/test_suite/debug_symbols/defer_macro.c3t +++ b/test/test_suite/debug_symbols/defer_macro.c3t @@ -380,22 +380,22 @@ entry: %arg = alloca ptr, align 8 %len = alloca i64, align 8 %ptr = alloca ptr, align 8 - %len18 = alloca i64, align 8 + %len16 = alloca i64, align 8 store ptr null, ptr %.cachedtype, align 8 store i32 %0, ptr %.anon, align 4 - !140 + store ptr %1, ptr %.anon1, align 8 - !140 + %2 = load i32, ptr %.anon, align 4 store i32 %2, ptr %argc, align 4 %3 = load ptr, ptr %.anon1, align 8 store ptr %3, ptr %argv, align 8 - !145 + %4 = load i32, ptr %argc, align 4 store i32 %4, ptr %argc2, align 4 %5 = load ptr, ptr %argv, align 8 store ptr %5, ptr %argv3, align 8 - !148 + %6 = load i32, ptr %argc2, align 4, !dbg !150 %sext = sext i32 %6 to i64, !dbg !150 store i64 %sext, ptr %elements, align 8 @@ -507,38 +507,37 @@ loop.body: ; preds = %loop.cond store ptr %37, ptr %arg, align 8, !dbg !179 store i64 0, ptr %len, align 8, !dbg !182 - %38 = load ptr, ptr %list5, align 8, !dbg !183 - %39 = load i32, ptr %i, align 4, !dbg !184 - %sext15 = sext i32 %39 to i64, !dbg !184 - %ptroffset16 = getelementptr inbounds [16 x i8], ptr %38, i64 %sext15, !dbg !184 - %40 = load ptr, ptr %arg, align 8, !dbg !185 - %41 = load ptr, ptr %arg, align 8 - store ptr %41, ptr %ptr, align 8 + %38 = load ptr, ptr %arg, align 8, !dbg !183 + %39 = load ptr, ptr %arg, align 8 + store ptr %39, ptr %ptr, align 8 + store i64 0, ptr %len16, align 8, !dbg !188 + br label %loop.cond17, !dbg !189 - store i64 0, ptr %len18, align 8, !dbg !190 - br label %loop.cond19, !dbg !191 +loop.cond17: ; preds = %loop.body19, %loop.body + %40 = load ptr, ptr %ptr, align 8, !dbg !190 + %41 = load i64, ptr %len16, align 8, !dbg !192 + %ptradd18 = getelementptr inbounds i8, ptr %40, i64 %41, !dbg !192 + %42 = load i8, ptr %ptradd18, align 1, !dbg !192 + %i2b = icmp ne i8 %42, 0, !dbg !192 + br i1 %i2b, label %loop.body19, label %loop.exit, !dbg !192 -loop.cond19: ; preds = %loop.body21, %loop.body - %42 = load ptr, ptr %ptr, align 8, !dbg !192 - %43 = load i64, ptr %len18, align 8, !dbg !194 - %ptradd20 = getelementptr inbounds i8, ptr %42, i64 %43, !dbg !194 - %44 = load i8, ptr %ptradd20, align 1, !dbg !194 - %i2b = icmp ne i8 %44, 0, !dbg !194 - br i1 %i2b, label %loop.body21, label %loop.exit, !dbg !194 +loop.body19: ; preds = %loop.cond17 + %43 = load i64, ptr %len16, align 8, !dbg !193 + %add20 = add i64 %43, 1, !dbg !193 + store i64 %add20, ptr %len16, align 8, !dbg !193 + br label %loop.cond17, !dbg !193 -loop.body21: ; preds = %loop.cond19 - %45 = load i64, ptr %len18, align 8, !dbg !195 - %add22 = add i64 %45, 1, !dbg !195 - store i64 %add22, ptr %len18, align 8, !dbg !195 - br label %loop.cond19, !dbg !195 - -loop.exit: ; preds = %loop.cond19 - %46 = load i64, ptr %len18, align 8, !dbg !196 - %add23 = add i64 0, %46, !dbg !196 - %size24 = sub i64 %add23, 0, !dbg !196 - %47 = insertvalue %"char[]" undef, ptr %40, 0, !dbg !196 - %48 = insertvalue %"char[]" %47, i64 %size24, 1, !dbg !196 - store %"char[]" %48, ptr %ptroffset16, align 8, !dbg !196 +loop.exit: ; preds = %loop.cond17 + %44 = load i64, ptr %len16, align 8, !dbg !194 + %add21 = add i64 0, %44, !dbg !194 + %size22 = sub i64 %add21, 0, !dbg !194 + %45 = insertvalue %"char[]" undef, ptr %38, 0, !dbg !194 + %46 = insertvalue %"char[]" %45, i64 %size22, 1, !dbg !194 + %47 = load ptr, ptr %list5, align 8, !dbg !195 + %48 = load i32, ptr %i, align 4, !dbg !196 + %sext23 = sext i32 %48 to i64, !dbg !196 + %ptroffset24 = getelementptr inbounds [16 x i8], ptr %47, i64 %sext23, !dbg !196 + store %"char[]" %46, ptr %ptroffset24, align 8, !dbg !196 %49 = load i32, ptr %i, align 4, !dbg !197 %add25 = add i32 %49, 1, !dbg !197 store i32 %add25, ptr %i, align 4, !dbg !197 @@ -681,6 +680,7 @@ no_match: ; preds = %compare !72 = !DILocation(line: 35, column: 49, scope: !66) !73 = !DILocalVariable(name: "name", arg: 3, scope: !66, file: !7, line: 35, type: !39) !74 = !DILocation(line: 35, column: 63, scope: !66) +!75 = !76 = distinct !DISubprogram(name: "new", linkageName: "new", scope: !77, file: !77 !77 = !DIFile(filename: "mem.c3", directory: !78 = !DILocation(line: 37, column: 9, scope: !66) diff --git a/test/test_suite/expressions/assign_eval_order.c3t b/test/test_suite/expressions/assign_eval_order.c3t new file mode 100644 index 000000000..39328a75d --- /dev/null +++ b/test/test_suite/expressions/assign_eval_order.c3t @@ -0,0 +1,59 @@ +// #target: macos-x64 +module test; +import std; + +DString x; +fn int[2] a() +{ + x.append("a"); + return { 1, 2 }; +} +fn int idx() +{ + x.append("i"); + return 0; +} +fn int abc() +{ + x.append("abc"); + return 1; +} +fn List{int} l() +{ + List{int} l; + l.push(2); + return l; +} + +fn int main(String[] args) +{ + l()[idx()] = abc(); + a()[idx()] = abc(); + return 0; +} + +/* #expect: test.ll + +define i32 @test.main(ptr %0, i64 %1) #0 { +entry: + %args = alloca %"char[][]", align 8 + %sretparam = alloca %List, align 8 + %result = alloca [2 x i32], align 4 + store ptr %0, ptr %args, align 8 + %ptradd = getelementptr inbounds i8, ptr %args, i64 8 + store i64 %1, ptr %ptradd, align 8 + %2 = call i32 @test.abc() + call void @test.l(ptr sret(%List) align 8 %sretparam) + %3 = call i32 @test.idx() + %sext = sext i32 %3 to i64 + call void @"std_collections_list$int$.List.set"(ptr %sretparam, i64 %sext, i32 %2) + %4 = call i32 @test.abc() + %5 = call i64 @test.a() + store i64 %5, ptr %result, align 4 + %6 = call i32 @test.idx() + %sext1 = sext i32 %6 to i64 + %ptroffset = getelementptr inbounds [4 x i8], ptr %result, i64 %sext1 + store i32 %4, ptr %ptroffset, align 4 + ret i32 0 +} + diff --git a/test/test_suite/expressions/overload_through_overload.c3t b/test/test_suite/expressions/overload_through_overload.c3t index 475742914..124029108 100644 --- a/test/test_suite/expressions/overload_through_overload.c3t +++ b/test/test_suite/expressions/overload_through_overload.c3t @@ -63,12 +63,14 @@ entry: %result3 = alloca %Abc, align 4 %result4 = alloca %Abc, align 4 %c = alloca %Container, align 4 + %.anon = alloca %Abc, align 4 %result5 = alloca %Abc, align 4 %result6 = alloca %Abc, align 4 %result7 = alloca %Abc, align 4 - %result9 = alloca %Abc, align 4 + %.anon9 = alloca %Abc, align 4 %result10 = alloca %Abc, align 4 %result11 = alloca %Abc, align 4 + %result12 = alloca %Abc, align 4 call void @llvm.memcpy.p0.p0.i32(ptr align 4 %a, ptr align 4 @.__const, i32 4, i1 false) call void @llvm.memcpy.p0.p0.i32(ptr align 4 %b, ptr align 4 @.__const.1, i32 4, i1 false) store i32 0, ptr %y, align 4 @@ -115,7 +117,8 @@ entry: %21 = load i32, ptr %b, align 4 %22 = call i32 @test.Abc.add(i32 %20, i32 %21) store i32 %22, ptr %result6, align 4 - %23 = load i32, ptr %result6, align 4 + call void @llvm.memcpy.p0.p0.i32(ptr align 4 %.anon, ptr align 4 %result6, i32 4, i1 false) + %23 = load i32, ptr %.anon, align 4 %24 = call i32 @test.Container.set(ptr %c, i32 0, i32 %23) store i32 %24, ptr %result7, align 4 %25 = load i32, ptr %c, align 4 @@ -123,15 +126,16 @@ entry: call void @llvm.assume(i1 %eq8) %26 = load i32, ptr %c, align 4 %27 = call i32 @test.Container.get(i32 %26, i32 0) - store i32 %27, ptr %result9, align 4 + store i32 %27, ptr %result10, align 4 %28 = load i32, ptr %b, align 4 - %29 = call i32 @test.Abc.sub_self(ptr %result9, i32 %28) - store i32 %29, ptr %result10, align 4 - %30 = load i32, ptr %result10, align 4 + %29 = call i32 @test.Abc.sub_self(ptr %result10, i32 %28) + store i32 %29, ptr %result11, align 4 + call void @llvm.memcpy.p0.p0.i32(ptr align 4 %.anon9, ptr align 4 %result11, i32 4, i1 false) + %30 = load i32, ptr %.anon9, align 4 %31 = call i32 @test.Container.set(ptr %c, i32 0, i32 %30) - store i32 %31, ptr %result11, align 4 + store i32 %31, ptr %result12, align 4 %32 = load i32, ptr %c, align 4 - %eq12 = icmp eq i32 %32, 5 - call void @llvm.assume(i1 %eq12) + %eq13 = icmp eq i32 %32, 5 + call void @llvm.assume(i1 %eq13) ret i32 0 } diff --git a/test/test_suite/macros/userland_bitcast.c3t b/test/test_suite/macros/userland_bitcast.c3t index 6f425e337..23cb51e5d 100644 --- a/test/test_suite/macros/userland_bitcast.c3t +++ b/test/test_suite/macros/userland_bitcast.c3t @@ -113,14 +113,14 @@ loop.cond: ; preds = %loop.body, %entry br i1 %lt, label %loop.body, label %loop.exit loop.body: ; preds = %loop.cond - %2 = load ptr, ptr %to, align 8 + %2 = load ptr, ptr %b, align 8 %3 = load i64, ptr %i, align 8 %ptroffset = getelementptr inbounds [2 x i8], ptr %2, i64 %3 - %4 = load ptr, ptr %b, align 8 + %4 = load ptr, ptr %to, align 8 %5 = load i64, ptr %i, align 8 %ptroffset4 = getelementptr inbounds [2 x i8], ptr %4, i64 %5 - %6 = load i16, ptr %ptroffset4, align 2 - store i16 %6, ptr %ptroffset, align 2 + %6 = load i16, ptr %ptroffset, align 2 + store i16 %6, ptr %ptroffset4, align 2 %7 = load i64, ptr %i, align 8 %add = add i64 %7, 2 store i64 %add, ptr %i, align 8 @@ -131,7 +131,6 @@ loop.exit: ; preds = %loop.cond ret i64 %8 } -; Function Attrs: define i32 @userland_bitcast.test(float %0) #0 { entry: %expr = alloca float, align 4 @@ -151,14 +150,14 @@ loop.cond: ; preds = %loop.body, %entry br i1 %lt, label %loop.body, label %loop.exit loop.body: ; preds = %loop.cond - %2 = load ptr, ptr %to, align 8 + %2 = load ptr, ptr %b, align 8 %3 = load i64, ptr %i, align 8 %ptradd = getelementptr inbounds i8, ptr %2, i64 %3 - %4 = load ptr, ptr %b, align 8 + %4 = load ptr, ptr %to, align 8 %5 = load i64, ptr %i, align 8 %ptradd1 = getelementptr inbounds i8, ptr %4, i64 %5 - %6 = load i8, ptr %ptradd1, align 1 - store i8 %6, ptr %ptradd, align 1 + %6 = load i8, ptr %ptradd, align 1 + store i8 %6, ptr %ptradd1, align 1 %7 = load i64, ptr %i, align 8 %add = add i64 %7, 1 store i64 %add, ptr %i, align 8 @@ -169,7 +168,6 @@ loop.exit: ; preds = %loop.cond ret i32 %8 } -; Function Attrs: define void @userland_bitcast.main() #0 { entry: %f = alloca float, align 4 @@ -212,14 +210,14 @@ loop.cond: ; preds = %loop.body, %entry br i1 %lt, label %loop.body, label %loop.exit loop.body: ; preds = %loop.cond - %2 = load ptr, ptr %to, align 8 + %2 = load ptr, ptr %b, align 8 %3 = load i64, ptr %i1, align 8 %ptroffset = getelementptr inbounds [4 x i8], ptr %2, i64 %3 - %4 = load ptr, ptr %b, align 8 + %4 = load ptr, ptr %to, align 8 %5 = load i64, ptr %i1, align 8 %ptroffset2 = getelementptr inbounds [4 x i8], ptr %4, i64 %5 - %6 = load i32, ptr %ptroffset2, align 4 - store i32 %6, ptr %ptroffset, align 4 + %6 = load i32, ptr %ptroffset, align 4 + store i32 %6, ptr %ptroffset2, align 4 %7 = load i64, ptr %i1, align 8 %add = add i64 %7, 4 store i64 %add, ptr %i1, align 8 @@ -241,14 +239,14 @@ loop.cond8: ; preds = %loop.body10, %loop. br i1 %lt9, label %loop.body10, label %loop.exit14 loop.body10: ; preds = %loop.cond8 - %11 = load ptr, ptr %to6, align 8 + %11 = load ptr, ptr %b5, align 8 %12 = load i64, ptr %i7, align 8 %ptroffset11 = getelementptr inbounds [4 x i8], ptr %11, i64 %12 - %13 = load ptr, ptr %b5, align 8 + %13 = load ptr, ptr %to6, align 8 %14 = load i64, ptr %i7, align 8 %ptroffset12 = getelementptr inbounds [4 x i8], ptr %13, i64 %14 - %15 = load i32, ptr %ptroffset12, align 4 - store i32 %15, ptr %ptroffset11, align 4 + %15 = load i32, ptr %ptroffset11, align 4 + store i32 %15, ptr %ptroffset12, align 4 %16 = load i64, ptr %i7, align 8 %add13 = add i64 %16, 4 store i64 %add13, ptr %i7, align 8 @@ -277,14 +275,14 @@ loop.cond21: ; preds = %loop.body23, %loop. br i1 %lt22, label %loop.body23, label %loop.exit27 loop.body23: ; preds = %loop.cond21 - %23 = load ptr, ptr %to19, align 8 + %23 = load ptr, ptr %b18, align 8 %24 = load i64, ptr %i20, align 8 %ptroffset24 = getelementptr inbounds [8 x i8], ptr %23, i64 %24 - %25 = load ptr, ptr %b18, align 8 + %25 = load ptr, ptr %to19, align 8 %26 = load i64, ptr %i20, align 8 %ptroffset25 = getelementptr inbounds [8 x i8], ptr %25, i64 %26 - %27 = load i64, ptr %ptroffset25, align 8 - store i64 %27, ptr %ptroffset24, align 8 + %27 = load i64, ptr %ptroffset24, align 8 + store i64 %27, ptr %ptroffset25, align 8 %28 = load i64, ptr %i20, align 8 %add26 = add i64 %28, 8 store i64 %add26, ptr %i20, align 8 @@ -306,14 +304,14 @@ loop.cond33: ; preds = %loop.body35, %loop. br i1 %lt34, label %loop.body35, label %loop.exit39 loop.body35: ; preds = %loop.cond33 - %32 = load ptr, ptr %to31, align 8 + %32 = load ptr, ptr %b30, align 8 %33 = load i64, ptr %i32, align 8 %ptroffset36 = getelementptr inbounds [8 x i8], ptr %32, i64 %33 - %34 = load ptr, ptr %b30, align 8 + %34 = load ptr, ptr %to31, align 8 %35 = load i64, ptr %i32, align 8 %ptroffset37 = getelementptr inbounds [8 x i8], ptr %34, i64 %35 - %36 = load i64, ptr %ptroffset37, align 8 - store i64 %36, ptr %ptroffset36, align 8 + %36 = load i64, ptr %ptroffset36, align 8 + store i64 %36, ptr %ptroffset37, align 8 %37 = load i64, ptr %i32, align 8 %add38 = add i64 %37, 8 store i64 %add38, ptr %i32, align 8 diff --git a/test/test_suite/vector/vector_init_regression.c3t b/test/test_suite/vector/vector_init_regression.c3t index 73ad3b1e0..ed616477d 100644 --- a/test/test_suite/vector/vector_init_regression.c3t +++ b/test/test_suite/vector/vector_init_regression.c3t @@ -152,7 +152,6 @@ entry: %30 = insertelement <4 x float> %23, float %29, i64 2 %31 = insertelement <4 x float> %30, float 0.000000e+00, i64 3 store <4 x float> %31, ptr %a, align 16 - %ptradd = getelementptr inbounds i8, ptr %a, i64 16 %32 = load float, ptr %y, align 4 %33 = load float, ptr %x, align 4 %fmul11 = fmul reassoc arcp contract float %32, %33 @@ -189,45 +188,46 @@ entry: %51 = call reassoc arcp contract float @llvm.fmuladd.f32(float %fmul20, float %fpfptrunc23, float %50) %52 = insertelement <4 x float> %44, float %51, i64 2 %53 = insertelement <4 x float> %52, float 0.000000e+00, i64 3 + %ptradd = getelementptr inbounds i8, ptr %a, i64 16 store <4 x float> %53, ptr %ptradd, align 16 - %ptradd25 = getelementptr inbounds i8, ptr %a, i64 32 %54 = load float, ptr %z, align 4 %55 = load float, ptr %x, align 4 - %fmul26 = fmul reassoc arcp contract float %54, %55 + %fmul25 = fmul reassoc arcp contract float %54, %55 %56 = load float, ptr %cosr, align 4 - %fpfpext27 = fpext - %fsub28 = fsub reassoc arcp contract double 1.000000e+00, %fpfpext27 - %fpfptrunc29 = fptrunc + %fpfpext26 = fpext + %fsub27 = fsub reassoc arcp contract double 1.000000e+00, %fpfpext26 + %fpfptrunc28 = fptrunc %57 = load float, ptr %y, align 4 %58 = load float, ptr %sinr, align 4 - %fmul30 = fmul reassoc arcp contract float %57, %58 - %59 = fneg reassoc arcp contract float %fmul30 - %60 = call reassoc arcp contract float @llvm.fmuladd.f32(float %fmul26, float %fpfptrunc29, float %59) + %fmul29 = fmul reassoc arcp contract float %57, %58 + %59 = fneg reassoc arcp contract float %fmul29 + %60 = call reassoc arcp contract float @llvm.fmuladd.f32(float %fmul25, float %fpfptrunc28, float %59) %61 = insertelement <4 x float> undef, float %60, i64 0 %62 = load float, ptr %z, align 4 %63 = load float, ptr %y, align 4 - %fmul31 = fmul reassoc arcp contract float %62, %63 + %fmul30 = fmul reassoc arcp contract float %62, %63 %64 = load float, ptr %cosr, align 4 - %fpfpext32 = fpext - %fsub33 = fsub reassoc arcp contract double 1.000000e+00, %fpfpext32 - %fpfptrunc34 = fptrunc + %fpfpext31 = fpext + %fsub32 = fsub reassoc arcp contract double 1.000000e+00, %fpfpext31 + %fpfptrunc33 = fptrunc %65 = load float, ptr %x, align 4 %66 = load float, ptr %sinr, align 4 - %fmul35 = fmul reassoc arcp contract float %65, %66 - %67 = call reassoc arcp contract float @llvm.fmuladd.f32(float %fmul31, float %fpfptrunc34, float %fmul35) + %fmul34 = fmul reassoc arcp contract float %65, %66 + %67 = call reassoc arcp contract float @llvm.fmuladd.f32(float %fmul30, float %fpfptrunc33, float %fmul34) %68 = insertelement <4 x float> %61, float %67, i64 1 %69 = load float, ptr %cosr, align 4 %70 = load float, ptr %z, align 4 %71 = load float, ptr %z, align 4 - %fmul36 = fmul reassoc arcp contract float %70, %71 + %fmul35 = fmul reassoc arcp contract float %70, %71 %72 = load float, ptr %cosr, align 4 - %fpfpext37 = fpext - %fsub38 = fsub reassoc arcp contract double 1.000000e+00, %fpfpext37 - %fpfptrunc39 = fptrunc - %73 = call reassoc arcp contract float @llvm.fmuladd.f32(float %fmul36, float %fpfptrunc39, float %69) + %fpfpext36 = fpext + %fsub37 = fsub reassoc arcp contract double 1.000000e+00, %fpfpext36 + %fpfptrunc38 = fptrunc + %73 = call reassoc arcp contract float @llvm.fmuladd.f32(float %fmul35, float %fpfptrunc38, float %69) %74 = insertelement <4 x float> %68, float %73, i64 2 %75 = insertelement <4 x float> %74, float 0.000000e+00, i64 3 - store <4 x float> %75, ptr %ptradd25, align 16 + %ptradd39 = getelementptr inbounds i8, ptr %a, i64 32 + store <4 x float> %75, ptr %ptradd39, align 16 %ptradd40 = getelementptr inbounds i8, ptr %a, i64 48 store <4 x float> , ptr %ptradd40, align 16 %76 = load float, ptr %cosr, align 4