From 6454856fdbea107a51178200f91ba366808fb427 Mon Sep 17 00:00:00 2001 From: Christoffer Lerno Date: Wed, 16 Apr 2025 23:19:28 +0200 Subject: [PATCH] String str = "" is now guaranteed to be null terminated. #2083 --- releasenotes.md | 1 + src/compiler/llvm_codegen_expr.c | 3 +- test/test_suite/bitstruct/bitstruct_be.c3t | 6 +-- .../test_suite/compile_time/concat_append.c3t | 3 +- .../compile_time/ct_forach_with_defer.c3t | 41 ++++++++++++++++++- test/test_suite/compile_time/ct_memberof.c3t | 32 ++++++++++++--- test/test_suite/errors/error_regression_2.c3t | 17 +++----- test/test_suite/from_docs/examples_defer.c3t | 6 +-- .../struct/init_cont_struct_array_locally.c3t | 40 +++++++++++++++++- 9 files changed, 123 insertions(+), 26 deletions(-) diff --git a/releasenotes.md b/releasenotes.md index bf80ee6f3..e1f9b46b1 100644 --- a/releasenotes.md +++ b/releasenotes.md @@ -13,6 +13,7 @@ - Make aliases able to use `@deprecated`. - Refactored stdlib file organization. - Allow `@if` on locals. +- String str = "" is now guaranteed to be null terminated. #2083 ### Fixes - Trying to cast an enum to int and back caused the compiler to crash. diff --git a/src/compiler/llvm_codegen_expr.c b/src/compiler/llvm_codegen_expr.c index 9971017f7..9a688cac8 100644 --- a/src/compiler/llvm_codegen_expr.c +++ b/src/compiler/llvm_codegen_expr.c @@ -4701,7 +4701,8 @@ static void llvm_emit_const_expr(GenContext *c, BEValue *be_value, Expr *expr) ArraySize len = expr->const_expr.bytes.len; if (len == 0 && str_type->type_kind == TYPE_SLICE) { - llvm_value_set(be_value, llvm_get_zero(c, expr->type), expr->type); + LLVMValueRef data[2] = { llvm_emit_zstring_named(c, "", ".emptystr"), llvm_get_zero(c, type_usz) }; + llvm_value_set(be_value, llvm_get_struct_named(c->chars_type, data, 2), expr->type); return; } ArraySize size = expr->const_expr.bytes.len; diff --git a/test/test_suite/bitstruct/bitstruct_be.c3t b/test/test_suite/bitstruct/bitstruct_be.c3t index 5e20ec6eb..4458f51b7 100644 --- a/test/test_suite/bitstruct/bitstruct_be.c3t +++ b/test/test_suite/bitstruct/bitstruct_be.c3t @@ -86,7 +86,7 @@ loop.body: ; preds = %loop.cond loop.exit: ; preds = %loop.cond %17 = call ptr @std.io.stdout() - %18 = call i64 @std.io.File.write(ptr %retparam5, ptr %17, ptr null, i64 0) + %18 = call i64 @std.io.File.write(ptr %retparam5, ptr %17, ptr @.emptystr, i64 0) %not_err = icmp eq i64 %18, 0 %19 = call i1 @llvm.expect.i1(i1 %not_err, i1 true) br i1 %19, label %after_check, label %assign_optional @@ -166,7 +166,7 @@ loop.body21: ; preds = %loop.cond19 loop.exit29: ; preds = %loop.cond19 %34 = call ptr @std.io.stdout() - %35 = call i64 @std.io.File.write(ptr %retparam33, ptr %34, ptr null, i64 0) + %35 = call i64 @std.io.File.write(ptr %retparam33, ptr %34, ptr @.emptystr, i64 0) %not_err34 = icmp eq i64 %35, 0 %36 = call i1 @llvm.expect.i1(i1 %not_err34, i1 true) br i1 %36, label %after_check36, label %assign_optional35 @@ -276,7 +276,7 @@ loop.body67: ; preds = %loop.cond65 loop.exit75: ; preds = %loop.cond65 %73 = call ptr @std.io.stdout() - %74 = call i64 @std.io.File.write(ptr %retparam79, ptr %73, ptr null, i64 0) + %74 = call i64 @std.io.File.write(ptr %retparam79, ptr %73, ptr @.emptystr, i64 0) %not_err80 = icmp eq i64 %74, 0 %75 = call i1 @llvm.expect.i1(i1 %not_err80, i1 true) br i1 %75, label %after_check82, label %assign_optional81 diff --git a/test/test_suite/compile_time/concat_append.c3t b/test/test_suite/compile_time/concat_append.c3t index ccd583762..610213b5e 100644 --- a/test/test_suite/compile_time/concat_append.c3t +++ b/test/test_suite/compile_time/concat_append.c3t @@ -31,6 +31,7 @@ fn int main() @.str.5 = private unnamed_addr constant [10 x i8] c"hello... \00", align 1 @.str.6 = private unnamed_addr constant [8 x i8] c" there!\00", align 1 @.__const.7 = private unnamed_addr constant [2 x %"char[]"] [%"char[]" { ptr @.str.5, i64 9 }, %"char[]" { ptr @.str.6, i64 7 }], align 16 +@.emptystr = internal constant [1 x i8] zeroinitializer, align 1 @.str.8 = private unnamed_addr constant [4 x i8] c"bye\00", align 1 define i32 @main() #0 { @@ -54,7 +55,7 @@ entry: %1 = insertvalue %"int[]" %0, i64 3, 1 store %"int[]" %1, ptr %d, align 8 call void @llvm.memcpy.p0.p0.i32(ptr align 16 %e, ptr align 16 @.__const.7, i32 32, i1 false) - store %"char[]" zeroinitializer, ptr %f, align 8 + store %"char[]" { ptr @.emptystr, i64 0 }, ptr %f, align 8 store %"char[]" { ptr @.str.8, i64 3 }, ptr %g, align 8 store i32 1000299617, ptr %h, align 4 ret i32 0 diff --git a/test/test_suite/compile_time/ct_forach_with_defer.c3t b/test/test_suite/compile_time/ct_forach_with_defer.c3t index 7b63a3211..d40711214 100644 --- a/test/test_suite/compile_time/ct_forach_with_defer.c3t +++ b/test/test_suite/compile_time/ct_forach_with_defer.c3t @@ -75,13 +75,17 @@ entry: %not_err = icmp eq i64 %16, 0 %17 = call i1 @llvm.expect.i1(i1 %not_err, i1 true) br i1 %17, label %after_check, label %assign_optional + assign_optional: ; preds = %entry store i64 %16, ptr %error_var, align 8 br label %guard_block + after_check: ; preds = %entry br label %noerr_block + guard_block: ; preds = %assign_optional br label %voiderr + noerr_block: ; preds = %after_check %18 = load i64, ptr %retparam14, align 8 store i64 %18, ptr %len, align 8 @@ -89,29 +93,38 @@ noerr_block: ; preds = %after_check %not_err16 = icmp eq i64 %19, 0 %20 = call i1 @llvm.expect.i1(i1 %not_err16, i1 true) br i1 %20, label %after_check18, label %assign_optional17 + assign_optional17: ; preds = %noerr_block store i64 %19, ptr %error_var15, align 8 br label %guard_block19 + after_check18: ; preds = %noerr_block br label %noerr_block20 + guard_block19: ; preds = %assign_optional17 br label %voiderr + noerr_block20: ; preds = %after_check18 %21 = call i64 @std.io.File.flush(ptr %15) %not_err22 = icmp eq i64 %21, 0 %22 = call i1 @llvm.expect.i1(i1 %not_err22, i1 true) br i1 %22, label %after_check24, label %assign_optional23 + assign_optional23: ; preds = %noerr_block20 store i64 %21, ptr %error_var21, align 8 br label %guard_block25 + after_check24: ; preds = %noerr_block20 br label %noerr_block26 + guard_block25: ; preds = %assign_optional23 br label %voiderr + noerr_block26: ; preds = %after_check24 %23 = load i64, ptr %len, align 8 %add = add i64 %23, 1 br label %voiderr + voiderr: ; preds = %noerr_block26, %guard_block25, %guard_block19, %guard_block ret void } @@ -169,17 +182,21 @@ entry: store %any %13, ptr %varargslots10, align 16 %14 = call i64 @std.io.printf(ptr %retparam12, ptr @.str.11, i64 2, ptr %varargslots10, i64 1) %15 = call ptr @std.io.stdout() - %16 = call i64 @std.io.File.write(ptr %retparam14, ptr %15, ptr null, i64 0) + %16 = call i64 @std.io.File.write(ptr %retparam14, ptr %15, ptr @.emptystr, i64 0) %not_err = icmp eq i64 %16, 0 %17 = call i1 @llvm.expect.i1(i1 %not_err, i1 true) br i1 %17, label %after_check, label %assign_optional + assign_optional: ; preds = %entry store i64 %16, ptr %error_var, align 8 br label %guard_block + after_check: ; preds = %entry br label %noerr_block + guard_block: ; preds = %assign_optional br label %voiderr + noerr_block: ; preds = %after_check %18 = load i64, ptr %retparam14, align 8 store i64 %18, ptr %len, align 8 @@ -187,42 +204,55 @@ noerr_block: ; preds = %after_check %not_err16 = icmp eq i64 %19, 0 %20 = call i1 @llvm.expect.i1(i1 %not_err16, i1 true) br i1 %20, label %after_check18, label %assign_optional17 + assign_optional17: ; preds = %noerr_block store i64 %19, ptr %error_var15, align 8 br label %guard_block19 + after_check18: ; preds = %noerr_block br label %noerr_block20 + guard_block19: ; preds = %assign_optional17 br label %voiderr + noerr_block20: ; preds = %after_check18 %21 = call i64 @std.io.File.flush(ptr %15) %not_err22 = icmp eq i64 %21, 0 %22 = call i1 @llvm.expect.i1(i1 %not_err22, i1 true) br i1 %22, label %after_check24, label %assign_optional23 + assign_optional23: ; preds = %noerr_block20 store i64 %21, ptr %error_var21, align 8 br label %guard_block25 + after_check24: ; preds = %noerr_block20 br label %noerr_block26 + guard_block25: ; preds = %assign_optional23 br label %voiderr + noerr_block26: ; preds = %after_check24 %23 = load i64, ptr %len, align 8 %add = add i64 %23, 1 br label %voiderr + voiderr: ; preds = %noerr_block26, %guard_block25, %guard_block19, %guard_block %24 = call ptr @std.io.stdout() %25 = call i64 @std.io.File.write(ptr %retparam30, ptr %24, ptr @.str.12, i64 6) %not_err31 = icmp eq i64 %25, 0 %26 = call i1 @llvm.expect.i1(i1 %not_err31, i1 true) br i1 %26, label %after_check33, label %assign_optional32 + assign_optional32: ; preds = %voiderr store i64 %25, ptr %error_var28, align 8 br label %guard_block34 + after_check33: ; preds = %voiderr br label %noerr_block35 + guard_block34: ; preds = %assign_optional32 br label %voiderr49 + noerr_block35: ; preds = %after_check33 %27 = load i64, ptr %retparam30, align 8 store i64 %27, ptr %len27, align 8 @@ -230,29 +260,38 @@ noerr_block35: ; preds = %after_check33 %not_err37 = icmp eq i64 %28, 0 %29 = call i1 @llvm.expect.i1(i1 %not_err37, i1 true) br i1 %29, label %after_check39, label %assign_optional38 + assign_optional38: ; preds = %noerr_block35 store i64 %28, ptr %error_var36, align 8 br label %guard_block40 + after_check39: ; preds = %noerr_block35 br label %noerr_block41 + guard_block40: ; preds = %assign_optional38 br label %voiderr49 + noerr_block41: ; preds = %after_check39 %30 = call i64 @std.io.File.flush(ptr %24) %not_err43 = icmp eq i64 %30, 0 %31 = call i1 @llvm.expect.i1(i1 %not_err43, i1 true) br i1 %31, label %after_check45, label %assign_optional44 + assign_optional44: ; preds = %noerr_block41 store i64 %30, ptr %error_var42, align 8 br label %guard_block46 + after_check45: ; preds = %noerr_block41 br label %noerr_block47 + guard_block46: ; preds = %assign_optional44 br label %voiderr49 + noerr_block47: ; preds = %after_check45 %32 = load i64, ptr %len27, align 8 %add48 = add i64 %32, 1 br label %voiderr49 + voiderr49: ; preds = %noerr_block47, %guard_block46, %guard_block40, %guard_block34 ret void } diff --git a/test/test_suite/compile_time/ct_memberof.c3t b/test/test_suite/compile_time/ct_memberof.c3t index afe68060a..64c39437f 100644 --- a/test/test_suite/compile_time/ct_memberof.c3t +++ b/test/test_suite/compile_time/ct_memberof.c3t @@ -114,7 +114,7 @@ entry: ret void } -; Function Attrs: + define void @test.test(i32 %0) #0 { entry: %len = alloca i64, align 8 @@ -206,13 +206,17 @@ entry: %not_err = icmp eq i64 %2, 0 %3 = call i1 @llvm.expect.i1(i1 %not_err, i1 true) br i1 %3, label %after_check, label %assign_optional + assign_optional: ; preds = %entry store i64 %2, ptr %error_var, align 8 br label %guard_block + after_check: ; preds = %entry br label %noerr_block + guard_block: ; preds = %assign_optional br label %voiderr + noerr_block: ; preds = %after_check %4 = load i64, ptr %retparam, align 8 store i64 %4, ptr %len, align 8 @@ -220,42 +224,55 @@ noerr_block: ; preds = %after_check %not_err3 = icmp eq i64 %5, 0 %6 = call i1 @llvm.expect.i1(i1 %not_err3, i1 true) br i1 %6, label %after_check5, label %assign_optional4 + assign_optional4: ; preds = %noerr_block store i64 %5, ptr %error_var2, align 8 br label %guard_block6 + after_check5: ; preds = %noerr_block br label %noerr_block7 + guard_block6: ; preds = %assign_optional4 br label %voiderr + noerr_block7: ; preds = %after_check5 %7 = call i64 @std.io.File.flush(ptr %1) %not_err9 = icmp eq i64 %7, 0 %8 = call i1 @llvm.expect.i1(i1 %not_err9, i1 true) br i1 %8, label %after_check11, label %assign_optional10 + assign_optional10: ; preds = %noerr_block7 store i64 %7, ptr %error_var8, align 8 br label %guard_block12 + after_check11: ; preds = %noerr_block7 br label %noerr_block13 + guard_block12: ; preds = %assign_optional10 br label %voiderr + noerr_block13: ; preds = %after_check11 %9 = load i64, ptr %len, align 8 %add = add i64 %9, 1 br label %voiderr + voiderr: ; preds = %noerr_block13, %guard_block12, %guard_block6, %guard_block %10 = call ptr @std.io.stdout() %11 = call i64 @std.io.File.write(ptr %retparam17, ptr %10, ptr @.str.10, i64 3) %not_err18 = icmp eq i64 %11, 0 %12 = call i1 @llvm.expect.i1(i1 %not_err18, i1 true) br i1 %12, label %after_check20, label %assign_optional19 + assign_optional19: ; preds = %voiderr store i64 %11, ptr %error_var15, align 8 br label %guard_block21 + after_check20: ; preds = %voiderr br label %noerr_block22 + guard_block21: ; preds = %assign_optional19 br label %voiderr36 + noerr_block22: ; preds = %after_check20 %13 = load i64, ptr %retparam17, align 8 store i64 %13, ptr %len14, align 8 @@ -263,6 +280,7 @@ noerr_block22: ; preds = %after_check20 %not_err24 = icmp eq i64 %14, 0 %15 = call i1 @llvm.expect.i1(i1 %not_err24, i1 true) br i1 %15, label %after_check26, label %assign_optional25 + assign_optional25: ; preds = %noerr_block22 store i64 %14, ptr %error_var23, align 8 br label %guard_block27 @@ -600,7 +618,7 @@ voiderr151: ; preds = %noerr_block149, %gu %ptradd164 = getelementptr inbounds i8, ptr %varargslots161, i64 16 store %any %75, ptr %ptradd164, align 16 %76 = call i64 @std.io.printfn(ptr %retparam165, ptr @.str.21, i64 6, ptr %varargslots161, i64 2) - store %"char[]" zeroinitializer, ptr %taddr169, align 8 + store %"char[]" { ptr @.emptystr, i64 0 }, ptr %taddr169, align 8 %77 = insertvalue %any undef, ptr %taddr169, 0 %78 = insertvalue %any %77, i64 ptrtoint (ptr @"$ct.String" to i64), 1 store %any %78, ptr %varargslots168, align 16 @@ -645,7 +663,7 @@ voiderr151: ; preds = %noerr_block149, %gu %ptradd197 = getelementptr inbounds i8, ptr %varargslots194, i64 16 store %any %98, ptr %ptradd197, align 16 %99 = call i64 @std.io.printfn(ptr %retparam198, ptr @.str.34, i64 6, ptr %varargslots194, i64 2) - store %"char[]" zeroinitializer, ptr %taddr202, align 8 + store %"char[]" { ptr @.emptystr, i64 0 }, ptr %taddr202, align 8 %100 = insertvalue %any undef, ptr %taddr202, 0 %101 = insertvalue %any %100, i64 ptrtoint (ptr @"$ct.String" to i64), 1 store %any %101, ptr %varargslots201, align 16 @@ -693,7 +711,7 @@ voiderr151: ; preds = %noerr_block149, %gu ret void } -; Function Attrs: nounwind uwtable + define void @test.main() #0 { entry: %varargslots = alloca [1 x %any], align 16 @@ -836,19 +854,23 @@ entry: ret void } -; Function Attrs: nounwind uwtable + define i32 @main(i32 %0, ptr %1) #0 { entry: call void @test.main() ret i32 0 } + declare extern_weak ptr @std.io.stdout() #0 + declare extern_weak i64 @std.io.File.write(ptr, ptr, ptr, i64) #0 declare extern_weak i64 @std.io.File.write_byte(ptr, i8 zeroext) #0 + declare extern_weak i64 @std.io.File.flush(ptr) #0 + declare extern_weak i64 @std.io.printfn(ptr, ptr, i64, ptr, i64) #0 diff --git a/test/test_suite/errors/error_regression_2.c3t b/test/test_suite/errors/error_regression_2.c3t index 4e5437951..906c93653 100644 --- a/test/test_suite/errors/error_regression_2.c3t +++ b/test/test_suite/errors/error_regression_2.c3t @@ -173,7 +173,6 @@ cond.phi: ; preds = %cond.rhs, %cond.lhs ret void } -; Function Attrs: define zeroext i8 @test.contains(ptr %0, i64 %1, ptr %2, i64 %3) #0 { entry: %haystack = alloca %"char[]", align 8 @@ -247,7 +246,6 @@ loop.exit: ; preds = %loop.cond ret i8 0 } -; Function Attrs: define i64 @test.readDoc(ptr %0, ptr %1, i64 %2) #0 { entry: %url = alloca %"char[]", align 8 @@ -351,7 +349,7 @@ if.exit16: ; preds = %if.exit6 if.then20: ; preds = %if.exit16 store ptr null, ptr %literal24, align 8 - store %"char[]" zeroinitializer, ptr %value26, align 8 + store %"char[]" { ptr @.emptystr, i64 0 }, ptr %value26, align 8 %16 = call ptr @std.core.mem.malloc(i64 16) #3 store ptr %16, ptr %temp27, align 8 %17 = load ptr, ptr %temp27, align 8 @@ -486,7 +484,6 @@ noerr_block66: ; preds = %if.exit64 ret i64 0 } -; Function Attrs: define { ptr, i8 } @test.buildSummary(ptr %0) #0 { entry: %doc = alloca %Doc, align 8 @@ -516,7 +513,6 @@ cond.phi: ; preds = %cond.rhs, %cond.lhs ret { ptr, i8 } %4 } -; Function Attrs: define { ptr, i8 } @test.readAndBuildSummary(ptr %0, i64 %1) #0 { entry: %url = alloca %"char[]", align 8 @@ -550,7 +546,6 @@ phi_block: ; preds = %else_block, %after_ ret { ptr, i8 } %6 } -; Function Attrs: define i64 @test.isTitleNonEmpty(ptr %0, ptr %1) #0 { entry: %doc = alloca %Doc, align 8 @@ -585,7 +580,7 @@ if.exit3: ; preds = %if.exit ret i64 0 } -; Function Attrs: + define i64 @test.readWhetherTitleNonEmpty(ptr %0, ptr %1, i64 %2) #0 { entry: %url = alloca %"char[]", align 8 @@ -628,7 +623,7 @@ err_retblock: ; preds = %assign_optional4, % ret i64 %9 } -; Function Attrs: + define ptr @test.bool_to_string(i8 zeroext %0) #0 { entry: %1 = trunc i8 %0 to i1 @@ -636,7 +631,7 @@ entry: ret ptr %ternary } -; Function Attrs: + define ptr @test.nameFromError(i64 %0) #0 { entry: %switch = alloca i64, align 8 @@ -672,7 +667,7 @@ switch.default: ; preds = %next_if6 ret ptr @.str.13 } -; Function Attrs: + define void @test.main() #0 { entry: %.anon = alloca i64, align 8 @@ -727,7 +722,7 @@ cond.rhs: ; preds = %loop.body br label %cond.phi cond.phi: ; preds = %cond.rhs, %cond.lhs - %val = phi %"char[]" [ %13, %cond.lhs ], [ zeroinitializer, %cond.rhs ] + %val = phi %"char[]" [ %13, %cond.lhs ], [ { ptr @.emptystr, i64 0 }, %cond.rhs ] store %"char[]" %val, ptr %title_sure, align 8 %ptradd2 = getelementptr inbounds i8, ptr %title_sure, i64 8 %14 = load i64, ptr %ptradd2, align 8 diff --git a/test/test_suite/from_docs/examples_defer.c3t b/test/test_suite/from_docs/examples_defer.c3t index d634771af..8466691fe 100644 --- a/test/test_suite/from_docs/examples_defer.c3t +++ b/test/test_suite/from_docs/examples_defer.c3t @@ -53,7 +53,7 @@ if.then: ; preds = %entry %1 = call ptr @std.io.stdout() %2 = call i64 @std.io.File.write(ptr %retparam, ptr %1, ptr @.str, i64 1) %3 = call ptr @std.io.stdout() - %4 = call i64 @std.io.File.write(ptr %retparam2, ptr %3, ptr null, i64 0) + %4 = call i64 @std.io.File.write(ptr %retparam2, ptr %3, ptr @.emptystr, i64 0) %not_err = icmp eq i64 %4, 0 %5 = call i1 @llvm.expect.i1(i1 %not_err, i1 true) br i1 %5, label %after_check, label %assign_optional @@ -120,7 +120,7 @@ if.then16: ; preds = %if.exit %14 = call ptr @std.io.stdout() %15 = call i64 @std.io.File.write(ptr %retparam20, ptr %14, ptr @.str.2, i64 1) %16 = call ptr @std.io.stdout() - %17 = call i64 @std.io.File.write(ptr %retparam26, ptr %16, ptr null, i64 0) + %17 = call i64 @std.io.File.write(ptr %retparam26, ptr %16, ptr @.emptystr, i64 0) %not_err27 = icmp eq i64 %17, 0 %18 = call i1 @llvm.expect.i1(i1 %not_err27, i1 true) br i1 %18, label %after_check29, label %assign_optional28 @@ -185,7 +185,7 @@ if.exit46: ; preds = %if.exit %29 = call ptr @std.io.stdout() %30 = call i64 @std.io.File.write(ptr %retparam53, ptr %29, ptr @.str.5, i64 1) %31 = call ptr @std.io.stdout() - %32 = call i64 @std.io.File.write(ptr %retparam59, ptr %31, ptr null, i64 0) + %32 = call i64 @std.io.File.write(ptr %retparam59, ptr %31, ptr @.emptystr, i64 0) %not_err60 = icmp eq i64 %32, 0 %33 = call i1 @llvm.expect.i1(i1 %not_err60, i1 true) br i1 %33, label %after_check62, label %assign_optional61 diff --git a/test/test_suite/struct/init_cont_struct_array_locally.c3t b/test/test_suite/struct/init_cont_struct_array_locally.c3t index b56588b26..66282d803 100644 --- a/test/test_suite/struct/init_cont_struct_array_locally.c3t +++ b/test/test_suite/struct/init_cont_struct_array_locally.c3t @@ -59,15 +59,19 @@ entry: %not_err = icmp eq i64 %3, 0 %4 = call i1 @llvm.expect.i1(i1 %not_err, i1 true) br i1 %4, label %after_check, label %assign_optional + assign_optional: ; preds = %entry store i64 %3, ptr %error_var5, align 8 br label %guard_block + after_check: ; preds = %entry br label %noerr_block + guard_block: ; preds = %assign_optional %5 = load i64, ptr %error_var5, align 8 store i64 %5, ptr %error_var, align 8 br label %guard_block28 + noerr_block: ; preds = %after_check %6 = load i64, ptr %retparam, align 8 store i64 %6, ptr %total, align 8 @@ -80,15 +84,19 @@ noerr_block: ; preds = %after_check %not_err9 = icmp eq i64 %10, 0 %11 = call i1 @llvm.expect.i1(i1 %not_err9, i1 true) br i1 %11, label %after_check11, label %assign_optional10 + assign_optional10: ; preds = %noerr_block store i64 %10, ptr %error_var6, align 8 br label %guard_block12 + after_check11: ; preds = %noerr_block br label %noerr_block13 + guard_block12: ; preds = %assign_optional10 %12 = load i64, ptr %error_var6, align 8 store i64 %12, ptr %error_var, align 8 br label %guard_block28 + noerr_block13: ; preds = %after_check11 %13 = load i64, ptr %retparam8, align 8 %add = add i64 %7, %13 @@ -101,15 +109,19 @@ noerr_block13: ; preds = %after_check11 %not_err17 = icmp eq i64 %17, 0 %18 = call i1 @llvm.expect.i1(i1 %not_err17, i1 true) br i1 %18, label %after_check19, label %assign_optional18 + assign_optional18: ; preds = %noerr_block13 store i64 %17, ptr %error_var14, align 8 br label %guard_block20 + after_check19: ; preds = %noerr_block13 br label %noerr_block21 + guard_block20: ; preds = %assign_optional18 %19 = load i64, ptr %error_var14, align 8 store i64 %19, ptr %error_var, align 8 br label %guard_block28 + noerr_block21: ; preds = %after_check19 %20 = load i64, ptr %retparam16, align 8 %add22 = add i64 %14, %20 @@ -119,58 +131,75 @@ noerr_block21: ; preds = %after_check19 %not_err24 = icmp eq i64 %22, 0 %23 = call i1 @llvm.expect.i1(i1 %not_err24, i1 true) br i1 %23, label %after_check26, label %assign_optional25 + assign_optional25: ; preds = %noerr_block21 store i64 %22, ptr %error_var, align 8 br label %guard_block28 + after_check26: ; preds = %noerr_block21 %24 = load i64, ptr %retparam23, align 8 %add27 = add i64 %21, %24 br label %noerr_block29 + guard_block28: ; preds = %assign_optional25, %guard_block20, %guard_block12, %guard_block br label %voiderr + noerr_block29: ; preds = %after_check26 store i64 %add27, ptr %len, align 8 %25 = call i64 @std.io.File.write_byte(ptr %0, i8 zeroext 10) %not_err31 = icmp eq i64 %25, 0 %26 = call i1 @llvm.expect.i1(i1 %not_err31, i1 true) br i1 %26, label %after_check33, label %assign_optional32 + assign_optional32: ; preds = %noerr_block29 store i64 %25, ptr %error_var30, align 8 br label %guard_block34 + after_check33: ; preds = %noerr_block29 br label %noerr_block35 + guard_block34: ; preds = %assign_optional32 br label %voiderr + noerr_block35: ; preds = %after_check33 %27 = call i64 @std.io.File.flush(ptr %0) %not_err37 = icmp eq i64 %27, 0 %28 = call i1 @llvm.expect.i1(i1 %not_err37, i1 true) br i1 %28, label %after_check39, label %assign_optional38 + assign_optional38: ; preds = %noerr_block35 store i64 %27, ptr %error_var36, align 8 br label %guard_block40 + after_check39: ; preds = %noerr_block35 br label %noerr_block41 + guard_block40: ; preds = %assign_optional38 br label %voiderr + noerr_block41: ; preds = %after_check39 %29 = load i64, ptr %len, align 8 %add42 = add i64 %29, 1 br label %voiderr + voiderr: ; preds = %noerr_block41, %guard_block40, %guard_block34, %guard_block28 call void @llvm.memcpy.p0.p0.i32(ptr align 1 %y, ptr align 1 @.__const, i32 2, i1 false) %30 = call ptr @std.io.stdout() - %31 = call i64 @std.io.File.write(ptr %retparam46, ptr %30, ptr null, i64 0) + %31 = call i64 @std.io.File.write(ptr %retparam46, ptr %30, ptr @.emptystr, i64 0) %not_err47 = icmp eq i64 %31, 0 %32 = call i1 @llvm.expect.i1(i1 %not_err47, i1 true) br i1 %32, label %after_check49, label %assign_optional48 + assign_optional48: ; preds = %voiderr store i64 %31, ptr %error_var44, align 8 br label %guard_block50 + after_check49: ; preds = %voiderr br label %noerr_block51 + guard_block50: ; preds = %assign_optional48 br label %voiderr65 + noerr_block51: ; preds = %after_check49 %33 = load i64, ptr %retparam46, align 8 store i64 %33, ptr %len43, align 8 @@ -178,29 +207,38 @@ noerr_block51: ; preds = %after_check49 %not_err53 = icmp eq i64 %34, 0 %35 = call i1 @llvm.expect.i1(i1 %not_err53, i1 true) br i1 %35, label %after_check55, label %assign_optional54 + assign_optional54: ; preds = %noerr_block51 store i64 %34, ptr %error_var52, align 8 br label %guard_block56 + after_check55: ; preds = %noerr_block51 br label %noerr_block57 + guard_block56: ; preds = %assign_optional54 br label %voiderr65 + noerr_block57: ; preds = %after_check55 %36 = call i64 @std.io.File.flush(ptr %30) %not_err59 = icmp eq i64 %36, 0 %37 = call i1 @llvm.expect.i1(i1 %not_err59, i1 true) br i1 %37, label %after_check61, label %assign_optional60 + assign_optional60: ; preds = %noerr_block57 store i64 %36, ptr %error_var58, align 8 br label %guard_block62 + after_check61: ; preds = %noerr_block57 br label %noerr_block63 + guard_block62: ; preds = %assign_optional60 br label %voiderr65 + noerr_block63: ; preds = %after_check61 %38 = load i64, ptr %len43, align 8 %add64 = add i64 %38, 1 br label %voiderr65 + voiderr65: ; preds = %noerr_block63, %guard_block62, %guard_block56, %guard_block50 ret i32 0 }