diff --git a/lib/std/io/dir.c3 b/lib/std/io/dir.c3 new file mode 100644 index 000000000..a939bd8bd --- /dev/null +++ b/lib/std/io/dir.c3 @@ -0,0 +1,19 @@ +module std::io::dir; + +struct PlatformDir +{ + void* data; +} + +define Dir = distinct PlatformDir*; + +$if (env::OS_TYPE == OsType.WIN32): +/* +private extern ulong _win32_GetCurrentDirectoryW(ulong, Char16* buffer) @extname("GetCurrentDirectoryW"); +private extern bool _win32_CreateSymbolicLinkW(Char16* symlink_file, Char16* target_file, ulong flags) @extname("CreateSymbolicLinkW"); +private extern bool _win32_CreateDirectoryW(Char16* path_name, void* security_attributes) @extname("CreateDirectoryW"); +private extern bool _win32_DeleteFileW(Char16* file) @extname("DeleteFileW"); +private extern bool _win32_CopyFileW(Char16* from_file, Char16* to_file, bool no_overwrite) @extname("CopyFileW"); +private extern ulong _win32_GetFullPathNameW(Char16* file_name, ulong buffer_len, Char16* buffer, Char16** file_part) @extname("GetFullPathNameW"); +*/ +$endif; \ No newline at end of file diff --git a/lib/std/io.c3 b/lib/std/io/io.c3 similarity index 100% rename from lib/std/io.c3 rename to lib/std/io/io.c3 diff --git a/lib/std/io_formatter_private.c3 b/lib/std/io/io_formatter_private.c3 similarity index 100% rename from lib/std/io_formatter_private.c3 rename to lib/std/io/io_formatter_private.c3 diff --git a/lib/std/io_printf.c3 b/lib/std/io/io_printf.c3 similarity index 100% rename from lib/std/io_printf.c3 rename to lib/std/io/io_printf.c3 diff --git a/lib/std/os/macos/cf_allocator.c3 b/lib/std/os/macos/cf_allocator.c3 new file mode 100644 index 000000000..4924f6d93 --- /dev/null +++ b/lib/std/os/macos/cf_allocator.c3 @@ -0,0 +1,21 @@ +module std::os::macos::cf; + +$if (env::OS_TYPE == OsType.MACOSX): + +define CFAllocatorRef = distinct void*; +define CFAllocatorContextRef = distinct void*; +define CFOptionFlags = usz; + +macro CFAllocatorRef default_allocator() = _macos_CFAllocatorGetDefault(); +macro void CFAllocatorRef.dealloc(CFAllocatorRef allocator, void* ptr) = _macos_CFAllocatorDeallocate(allocator, ptr); +macro void* CFAllocatorRef.alloc(CFAllocatorRef allocator, usz size) = _macos_CFAllocatorAllocate(allocator, size, 0); +macro usz CFAllocatorRef.get_preferred_size(CFAllocatorRef allocator, usz req_size) = _macos_CFAllocatorGetPreferredSizeForSize(allocator, req_size, 0); +macro void CFAllocatorRef.set_default(CFAllocatorRef allocator) = _macos_CFAllocatorSetDefault(allocator); + +extern fn CFAllocatorRef _macos_CFAllocatorCreate(CFAllocatorRef allocator, CFAllocatorContextRef context) @extname("CFAllocatorCreate"); +extern fn void _macos_CFAllocatorDeallocate(CFAllocatorRef allocator, void* ptr) @extname("CFAllocatorDeallocate"); +extern fn CFAllocatorRef _macos_CFAllocatorGetDefault() @extname("CFAllocatorGetDefault"); +extern fn void _macos_CFAllocatorSetDefault(CFAllocatorRef allocator) @extname("CFAllocatorSetDefault"); +extern fn void* _macos_CFAllocatorAllocate(CFAllocatorRef allocator, CFIndex size, CFOptionFlags hint) @extname("CFAllocatorAllocate"); +extern fn CFIndex _macos_CFAllocatorGetPreferredSizeForSize(CFAllocatorRef allocator, CFIndex size, CFOptionFlags hint) @extname("CFAllocatorGetPreferredSizeForSize"); +$endif; \ No newline at end of file diff --git a/lib/std/os/macos/cf_array.c3 b/lib/std/os/macos/cf_array.c3 new file mode 100644 index 000000000..3eef22ec8 --- /dev/null +++ b/lib/std/os/macos/cf_array.c3 @@ -0,0 +1,14 @@ +module std::os::macos::cf; + +$if (env::OS_TYPE == OsType.MACOSX): + +define CFArrayRef = distinct void*; +define CFArrayCallBacksRef = distinct void*; +define CFMutableArrayRef = distinct void*; +extern fn CFArrayRef _macos_CFArrayCreate(CFAllocatorRef allocator, void** values, CFIndex num_values, CFArrayCallBacksRef callBacks) @extname("CFArrayCreate"); +extern fn CFArrayRef _macos_CFArrayCopy(CFAllocatorRef allocator, CFArrayRef array) @extname("CFArrayCopy"); +extern fn CFIndex _macos_CFArrayGetCount(CFArrayRef array) @extname("CFArrayGetCount"); +extern fn void _macos_CFArrayAppendArray(CFMutableArrayRef theArray, CFArrayRef otherArray, CFRange otherRange) @extname("CFArrayAppendArray"); +extern fn CFMutableArrayRef _macos_CFArrayCreateMutable(CFAllocatorRef allocator, CFIndex capacity, CFArrayCallBacksRef callBacks) @extname("CFArrayCreateMutable"); +extern fn void _macos_CFArrayAppendValue(CFMutableArrayRef theArray, void *value) @extname("CFArrayAppendValue"); +$endif; \ No newline at end of file diff --git a/lib/std/os/macos/core_foundation.c3 b/lib/std/os/macos/core_foundation.c3 new file mode 100644 index 000000000..f562bbb24 --- /dev/null +++ b/lib/std/os/macos/core_foundation.c3 @@ -0,0 +1,16 @@ +module std::os::macos::cf; + +$if (env::OS_TYPE == OsType.MACOSX): + +define CFTypeRef = distinct void*; +define CFIndex = isz; +struct CFRange +{ + CFIndex location; + CFIndex length; +} + +extern fn CFTypeRef _macos_CFRetain(CFTypeRef cf) @extname("CFRetain"); +extern fn void _macos_CFRelease(CFTypeRef cf) @extname("CFRelease"); + +$endif; \ No newline at end of file diff --git a/lib/std/os/macos/objc.c3 b/lib/std/os/macos/objc.c3 new file mode 100644 index 000000000..2ebeedfa1 --- /dev/null +++ b/lib/std/os/macos/objc.c3 @@ -0,0 +1,49 @@ +module std::os::macos::objc; + +$if (env::OS_TYPE == OsType.MACOSX): + +define Class = distinct void*; +define Method = distinct void*; +define Ivar = distinct void*; +define Selector = distinct void*; + +fault ObjcFailure +{ + CLASS_NOT_FOUND +} + +macro char* Class.name(Class cls) = _macos_class_getName(cls); +macro Class Class.superclass(Class cls) = _macos_class_getSuperclass(cls); +macro bool Class.responds_to(Class cls, Selector sel) = _macos_class_respondsToSelector(cls, sel); +macro Method Class.method(Class cls, Selector name) = _macos_class_getClassMethod(cls, name); + +macro bool Selector.equals(Selector a, Selector b) = a == b; +macro bool Class.equals(Class a, Class b) = a == b; + +macro Selector selector_register(char* c) = _macos_sel_registerName(c); +macro Class! class_by_name(char* c) +{ + Class cls = _macos_objc_lookUpClass(c); + if (!cls) return ObjcFailure.CLASS_NOT_FOUND!; + return cls; +} + +macro Class[] class_get_list(Allocator *allocator = mem::temp_allocator()) +{ + int num_classes = _macos_objc_getClassList(null, 0); + if (!num_classes) return {}; + Class[] entries = array::make(Class, num_classes, allocator); + _macos_objc_getClassList(entries.ptr, entries.len); + return entries; +} + +extern fn Class _macos_objc_getClass(char* name) @extname("objc_getClass"); +extern fn int _macos_objc_getClassList(Class* buffer, int buffer_count) @extname("objc_getClassList"); +extern fn char* _macos_class_getName(Class cls) @extname("class_getName"); +extern fn Class _macos_class_getSuperclass(Class cls) @extname("class_getSuperclass"); +extern fn Method _macos_class_getClassMethod(Class cls, Selector name) @extname("class_getClassMethod"); +extern fn bool _macos_class_respondsToSelector(Class cls, Selector name) @extname("class_respondsToSelector"); +extern fn Selector _macos_sel_registerName(char* str) @extname("sel_registerName"); +extern fn Class _macos_objc_lookUpClass(char* name) @extname("objc_lookUpClass"); +$endif; + diff --git a/src/compiler/linker.c b/src/compiler/linker.c index 8294e0b5d..b9397c1e4 100644 --- a/src/compiler/linker.c +++ b/src/compiler/linker.c @@ -274,7 +274,11 @@ static void linker_setup_windows_gnu(const char ***args_ref, LinkerType linker_t static void linker_setup_macos(const char ***args_ref, LinkerType linker_type) { - if (linker_type == LINKER_CC) return; + add_arg("-framework CoreFoundation"); + if (linker_type == LINKER_CC) + { + return; + } add_arg("-arch"); add_arg(arch_to_linker_arch(platform_target.arch)); diff --git a/src/compiler/llvm_codegen_expr.c b/src/compiler/llvm_codegen_expr.c index eef547da3..1dfadae7d 100644 --- a/src/compiler/llvm_codegen_expr.c +++ b/src/compiler/llvm_codegen_expr.c @@ -3817,7 +3817,6 @@ static void llvm_emit_binary_expr(GenContext *c, BEValue *be_value, Expr *expr) void gencontext_emit_elvis_expr(GenContext *c, BEValue *value, Expr *expr) { - LLVMBasicBlockRef current_block = c->current_block; LLVMBasicBlockRef phi_block = llvm_basic_block_new(c, "cond.phi"); LLVMBasicBlockRef rhs_block = llvm_basic_block_new(c, "cond.rhs"); @@ -3825,6 +3824,8 @@ void gencontext_emit_elvis_expr(GenContext *c, BEValue *value, Expr *expr) Expr *cond = exprptr(expr->ternary_expr.cond); llvm_emit_expr(c, value, cond); + if (value->type == type_void) return; + // Get the Rvalue version (in case we have an address) llvm_value_rvalue(c, value); @@ -3840,7 +3841,7 @@ void gencontext_emit_elvis_expr(GenContext *c, BEValue *value, Expr *expr) } Expr *else_expr = exprptr(expr->ternary_expr.else_expr); - if (expr_is_constant_eval(else_expr, CONSTANT_EVAL_NO_SIDE_EFFECTS)) + if (!IS_OPTIONAL(expr) && expr_is_constant_eval(else_expr, CONSTANT_EVAL_NO_SIDE_EFFECTS)) { BEValue right; llvm_emit_expr(c, &right, else_expr); @@ -3857,6 +3858,8 @@ void gencontext_emit_elvis_expr(GenContext *c, BEValue *value, Expr *expr) return; } + LLVMBasicBlockRef lhs_exit = llvm_get_current_block_if_in_use(c); + assert(lhs_exit); llvm_emit_cond_br(c, value, phi_block, rhs_block); llvm_emit_block(c, rhs_block); @@ -3865,7 +3868,15 @@ void gencontext_emit_elvis_expr(GenContext *c, BEValue *value, Expr *expr) // Lower to value. llvm_value_rvalue(c, value); - LLVMBasicBlockRef end_block = c->current_block; + LLVMBasicBlockRef rhs_exit = llvm_get_current_block_if_in_use(c); + + // RHS may be a jump, in that case just emit the "phi" block. + if (!rhs_exit) + { + llvm_emit_block(c, phi_block); + return; + } + llvm_emit_br(c, phi_block); // Generate phi @@ -3876,7 +3887,7 @@ void gencontext_emit_elvis_expr(GenContext *c, BEValue *value, Expr *expr) LLVMValueRef phi = LLVMBuildPhi(c->builder, phi_type, "val"); LLVMValueRef logic_values[2] = { lhs, value->value }; - LLVMBasicBlockRef blocks[2] = { current_block, end_block }; + LLVMBasicBlockRef blocks[2] = { lhs_exit, rhs_exit }; LLVMAddIncoming(phi, logic_values, blocks, 2); // The rest of value should now be set to the right value. @@ -3885,11 +3896,7 @@ void gencontext_emit_elvis_expr(GenContext *c, BEValue *value, Expr *expr) void gencontext_emit_ternary_expr(GenContext *c, BEValue *value, Expr *expr) { - if (!expr->ternary_expr.then_expr) - { - gencontext_emit_elvis_expr(c, value, expr); - return; - } + bool is_elvis = !expr->ternary_expr.then_expr; // Set up basic blocks, following Cone LLVMBasicBlockRef phi_block = llvm_basic_block_new(c, "cond.phi"); @@ -3897,23 +3904,47 @@ void gencontext_emit_ternary_expr(GenContext *c, BEValue *value, Expr *expr) LLVMBasicBlockRef rhs_block = llvm_basic_block_new(c, "cond.rhs"); // Generate condition and conditional branch - - llvm_emit_exprid(c, value, expr->ternary_expr.cond); + Expr *cond = exprptr(expr->ternary_expr.cond); + llvm_emit_expr(c, value, cond); llvm_value_rvalue(c, value); - assert(value->kind == BE_BOOLEAN); - - Expr *else_expr = exprptr(expr->ternary_expr.else_expr); - Expr *then_expr = exprptr(expr->ternary_expr.then_expr); - if (!IS_OPTIONAL(expr) && expr_is_constant_eval(else_expr, CONSTANT_EVAL_NO_SIDE_EFFECTS) && expr_is_constant_eval(then_expr, CONSTANT_EVAL_NO_SIDE_EFFECTS)) + LLVMValueRef lhs_value = is_elvis ? value->value : NULL; + if (value->kind != BE_BOOLEAN) { - BEValue left; - llvm_emit_expr(c, &left, then_expr); - llvm_value_rvalue(c, &left); + assert(is_elvis); + CastKind cast = cast_to_bool_kind(value->type); + llvm_emit_cast(c, cast, cond, value, type_bool, value->type); + } + + Expr *else_expr; + Expr *then_expr; + + if (is_elvis) + { + then_expr = NULL; + else_expr = exprptr(expr->ternary_expr.else_expr); + } + else + { + else_expr = exprptr(expr->ternary_expr.else_expr); + then_expr = exprptr(expr->ternary_expr.then_expr); + + } + + if (!IS_OPTIONAL(expr) && expr_is_constant_eval(else_expr, CONSTANT_EVAL_NO_SIDE_EFFECTS) + && (is_elvis || expr_is_constant_eval(then_expr, CONSTANT_EVAL_NO_SIDE_EFFECTS))) + { + if (!lhs_value) + { + BEValue left; + llvm_emit_expr(c, &left, then_expr); + llvm_value_rvalue(c, &left); + lhs_value = left.value; + } BEValue right; llvm_emit_expr(c, &right, else_expr); llvm_value_rvalue(c, &right); - LLVMValueRef val = LLVMBuildSelect(c->builder, value->value, left.value, right.value, "ternary"); + LLVMValueRef val = LLVMBuildSelect(c->builder, value->value, lhs_value, right.value, "ternary"); if (right.type == type_bool) { llvm_value_set_bool(value, val); @@ -3925,20 +3956,38 @@ void gencontext_emit_ternary_expr(GenContext *c, BEValue *value, Expr *expr) return; } - llvm_emit_cond_br(c, value, lhs_block, rhs_block); - - llvm_emit_block(c, lhs_block); - BEValue lhs; - llvm_emit_expr(c, &lhs, then_expr); - LLVMValueRef lhs_value = llvm_load_value_store(c, &lhs); - - LLVMBasicBlockRef lhs_exit = llvm_get_current_block_if_in_use(c); - if (lhs_exit) llvm_emit_br(c, phi_block); + LLVMBasicBlockRef lhs_exit; + if (is_elvis) + { + lhs_exit = llvm_get_current_block_if_in_use(c); + if (!lhs_exit) return; + llvm_emit_cond_br(c, value, phi_block, rhs_block); + } + else + { + llvm_emit_cond_br(c, value, lhs_block, rhs_block); + llvm_emit_block(c, lhs_block); + BEValue lhs; + llvm_emit_expr(c, &lhs, then_expr); + llvm_value_rvalue(c, &lhs); + lhs_value = lhs.value; + lhs_exit = llvm_get_current_block_if_in_use(c); + if (lhs.type == type_bool && LLVMTypeOf(lhs_value) != c->bool_type) + { + llvm_emit_trunc_bool(c, lhs_value); + } + if (lhs_exit) llvm_emit_br(c, phi_block); + } llvm_emit_block(c, rhs_block); BEValue rhs; llvm_emit_expr(c, &rhs, else_expr); - LLVMValueRef rhs_value = llvm_load_value_store(c, &rhs); + llvm_value_rvalue(c, &rhs); + LLVMValueRef rhs_value = rhs.value; + if (rhs.type == type_bool && LLVMTypeOf(rhs_value) != c->bool_type) + { + llvm_emit_trunc_bool(c, rhs_value); + } LLVMBasicBlockRef rhs_exit = llvm_get_current_block_if_in_use(c); if (rhs_exit) llvm_emit_br(c, phi_block); @@ -3947,20 +3996,39 @@ void gencontext_emit_ternary_expr(GenContext *c, BEValue *value, Expr *expr) llvm_emit_block(c, phi_block); if (!rhs_exit) { - llvm_value_set(value, lhs_value, lhs.type); + if (!lhs_value) lhs_value = LLVMGetUndef(llvm_get_type(c, expr->type)); + if (LLVMTypeOf(lhs_value) == c->bool_type) + { + llvm_value_set_bool(value, lhs_value); + return; + } + llvm_value_set(value, lhs_value, type_flatten(expr->type)); return; } + if (!lhs_exit) { - llvm_value_set(value, rhs_value, rhs.type); + if (!rhs_value) rhs_value = LLVMGetUndef(llvm_get_type(c, expr->type)); + if (LLVMTypeOf(rhs_value) == c->bool_type) + { + llvm_value_set_bool(value, rhs_value); + return; + } + llvm_value_set(value, rhs_value, type_flatten(expr->type)); return; } + Type *expr_type = type_flatten(expr->type); - LLVMValueRef phi = LLVMBuildPhi(c->builder, llvm_get_type(c, expr_type), "val"); + LLVMTypeRef type = expr_type == type_bool ? c->bool_type : llvm_get_type(c, expr_type); + LLVMValueRef phi = LLVMBuildPhi(c->builder, type, "val"); LLVMValueRef logic_values[2] = { lhs_value, rhs_value }; LLVMBasicBlockRef blocks[2] = { lhs_exit, rhs_exit }; LLVMAddIncoming(phi, logic_values, blocks, 2); - + if (expr_type == type_bool) + { + llvm_value_set_bool(value, phi); + return; + } llvm_value_set(value, phi, expr_type); } static LLVMValueRef llvm_emit_real(LLVMTypeRef type, Float f) diff --git a/test/test_suite/expressions/optional_ternary.c3t b/test/test_suite/expressions/optional_ternary.c3t new file mode 100644 index 000000000..e1dc71fb3 --- /dev/null +++ b/test/test_suite/expressions/optional_ternary.c3t @@ -0,0 +1,384 @@ +// #target: macos-x64 + +module test; + +fault Foo +{ + X +} + +fn int! test(int i) +{ + return i ?: Foo.X!; +} + +fn int! test2(int i) +{ + return i ? Foo.X! : Foo.X!; +} + + +fn int! test3(int i) +{ + return i ? 2 : Foo.X!; +} + + +fn int! test4(int i) +{ + int! y = i; + return (y?) ?: Foo.X!; +} +fn int! test5(int i) +{ + int! y = i; + return (y?) ? Foo.X! : Foo.X!; +} + +fn int! test6(int i) +{ + int! y = i; + return (y?) ? 2 : Foo.X!; +} + +fn int! test7(int i) +{ + int! y = i; + return (y?) ? Foo.X! : 2; +} + +fn void main() +{ + test(1)!!; + test7(0)!!; + test6(1)!!; + int! i = test2(3); +} + +/* #expect: test.ll + + +define i64 @test_test(i32* %0, i32 %1) #0 { +entry: + %reterr = alloca i64, align 8 + %intbool = icmp ne i32 %1, 0 + br i1 %intbool, label %cond.phi, label %cond.rhs + +cond.rhs: ; preds = %entry + store i64 ptrtoint (%.fault* @"test_Foo$X" to i64), i64* %reterr, align 8 + br label %err_retblock + +cond.phi: ; preds = %entry + store i32 %1, i32* %0, align 4 + ret i64 0 + +err_retblock: ; preds = %cond.rhs + %2 = load i64, i64* %reterr, align 8 + ret i64 %2 +} + +; Function Attrs: nounwind +define i64 @test_test2(i32* %0, i32 %1) #0 { +entry: + %reterr = alloca i64, align 8 + %intbool = icmp ne i32 %1, 0 + br i1 %intbool, label %cond.lhs, label %cond.rhs + +cond.lhs: ; preds = %entry + store i64 ptrtoint (%.fault* @"test_Foo$X" to i64), i64* %reterr, align 8 + br label %err_retblock + +cond.rhs: ; preds = %entry + store i64 ptrtoint (%.fault* @"test_Foo$X" to i64), i64* %reterr, align 8 + br label %err_retblock + +cond.phi: ; No predecessors! + store i32 undef, i32* %0, align 4 + ret i64 0 + +err_retblock: ; preds = %cond.rhs, %cond.lhs + %2 = load i64, i64* %reterr, align 8 + ret i64 %2 +} + +; Function Attrs: nounwind +define i64 @test_test3(i32* %0, i32 %1) #0 { +entry: + %reterr = alloca i64, align 8 + %intbool = icmp ne i32 %1, 0 + br i1 %intbool, label %cond.lhs, label %cond.rhs + +cond.lhs: ; preds = %entry + br label %cond.phi + +cond.rhs: ; preds = %entry + store i64 ptrtoint (%.fault* @"test_Foo$X" to i64), i64* %reterr, align 8 + br label %err_retblock + +cond.phi: ; preds = %cond.lhs + store i32 2, i32* %0, align 4 + ret i64 0 + +err_retblock: ; preds = %cond.rhs + %2 = load i64, i64* %reterr, align 8 + ret i64 %2 +} + +; Function Attrs: nounwind +define i64 @test_test4(i32* %0, i32 %1) #0 { +entry: + %y = alloca i32, align 4 + %y.f = alloca i64, align 8 + %reterr = alloca i64, align 8 + %error_var = alloca i64, align 8 + store i32 %1, i32* %y, align 4 + store i64 0, i64* %y.f, align 8 + %optval = load i64, i64* %y.f, align 8 + %not_err = icmp eq i64 %optval, 0 + br i1 %not_err, label %after_check, label %assign_optional + +assign_optional: ; preds = %entry + store i64 %optval, i64* %error_var, align 8 + br label %guard_block + +after_check: ; preds = %entry + br label %noerr_block + +guard_block: ; preds = %assign_optional + %2 = load i64, i64* %error_var, align 8 + ret i64 %2 + +noerr_block: ; preds = %after_check + %3 = load i32, i32* %y, align 4 + %intbool = icmp ne i32 %3, 0 + br i1 %intbool, label %cond.phi, label %cond.rhs + +cond.rhs: ; preds = %noerr_block + store i64 ptrtoint (%.fault* @"test_Foo$X" to i64), i64* %reterr, align 8 + br label %err_retblock + +cond.phi: ; preds = %noerr_block + store i32 %3, i32* %0, align 4 + ret i64 0 + +err_retblock: ; preds = %cond.rhs + %4 = load i64, i64* %reterr, align 8 + ret i64 %4 +} + +; Function Attrs: nounwind +define i64 @test_test5(i32* %0, i32 %1) #0 { +entry: + %y = alloca i32, align 4 + %y.f = alloca i64, align 8 + %reterr = alloca i64, align 8 + %error_var = alloca i64, align 8 + store i32 %1, i32* %y, align 4 + store i64 0, i64* %y.f, align 8 + %optval = load i64, i64* %y.f, align 8 + %not_err = icmp eq i64 %optval, 0 + br i1 %not_err, label %after_check, label %assign_optional + +assign_optional: ; preds = %entry + store i64 %optval, i64* %error_var, align 8 + br label %guard_block + +after_check: ; preds = %entry + br label %noerr_block + +guard_block: ; preds = %assign_optional + %2 = load i64, i64* %error_var, align 8 + ret i64 %2 + +noerr_block: ; preds = %after_check + %3 = load i32, i32* %y, align 4 + %intbool = icmp ne i32 %3, 0 + br i1 %intbool, label %cond.lhs, label %cond.rhs + +cond.lhs: ; preds = %noerr_block + store i64 ptrtoint (%.fault* @"test_Foo$X" to i64), i64* %reterr, align 8 + br label %err_retblock + +cond.rhs: ; preds = %noerr_block + store i64 ptrtoint (%.fault* @"test_Foo$X" to i64), i64* %reterr, align 8 + br label %err_retblock + +cond.phi: ; No predecessors! + store i32 undef, i32* %0, align 4 + ret i64 0 + +err_retblock: ; preds = %cond.rhs, %cond.lhs + %4 = load i64, i64* %reterr, align 8 + ret i64 %4 +} + +; Function Attrs: nounwind +define i64 @test_test6(i32* %0, i32 %1) #0 { +entry: + %y = alloca i32, align 4 + %y.f = alloca i64, align 8 + %reterr = alloca i64, align 8 + %error_var = alloca i64, align 8 + store i32 %1, i32* %y, align 4 + store i64 0, i64* %y.f, align 8 + %optval = load i64, i64* %y.f, align 8 + %not_err = icmp eq i64 %optval, 0 + br i1 %not_err, label %after_check, label %assign_optional + +assign_optional: ; preds = %entry + store i64 %optval, i64* %error_var, align 8 + br label %guard_block + +after_check: ; preds = %entry + br label %noerr_block + +guard_block: ; preds = %assign_optional + %2 = load i64, i64* %error_var, align 8 + ret i64 %2 + +noerr_block: ; preds = %after_check + %3 = load i32, i32* %y, align 4 + %intbool = icmp ne i32 %3, 0 + br i1 %intbool, label %cond.lhs, label %cond.rhs + +cond.lhs: ; preds = %noerr_block + br label %cond.phi + +cond.rhs: ; preds = %noerr_block + store i64 ptrtoint (%.fault* @"test_Foo$X" to i64), i64* %reterr, align 8 + br label %err_retblock + +cond.phi: ; preds = %cond.lhs + store i32 2, i32* %0, align 4 + ret i64 0 + +err_retblock: ; preds = %cond.rhs + %4 = load i64, i64* %reterr, align 8 + ret i64 %4 +} + +; Function Attrs: nounwind +define i64 @test_test7(i32* %0, i32 %1) #0 { +entry: + %y = alloca i32, align 4 + %y.f = alloca i64, align 8 + %reterr = alloca i64, align 8 + %error_var = alloca i64, align 8 + store i32 %1, i32* %y, align 4 + store i64 0, i64* %y.f, align 8 + %optval = load i64, i64* %y.f, align 8 + %not_err = icmp eq i64 %optval, 0 + br i1 %not_err, label %after_check, label %assign_optional + +assign_optional: ; preds = %entry + store i64 %optval, i64* %error_var, align 8 + br label %guard_block + +after_check: ; preds = %entry + br label %noerr_block + +guard_block: ; preds = %assign_optional + %2 = load i64, i64* %error_var, align 8 + ret i64 %2 + +noerr_block: ; preds = %after_check + %3 = load i32, i32* %y, align 4 + %intbool = icmp ne i32 %3, 0 + br i1 %intbool, label %cond.lhs, label %cond.rhs + +cond.lhs: ; preds = %noerr_block + store i64 ptrtoint (%.fault* @"test_Foo$X" to i64), i64* %reterr, align 8 + br label %err_retblock + +cond.rhs: ; preds = %noerr_block + br label %cond.phi + +cond.phi: ; preds = %cond.rhs + store i32 2, i32* %0, align 4 + ret i64 0 + +err_retblock: ; preds = %cond.lhs + %4 = load i64, i64* %reterr, align 8 + ret i64 %4 +} + +; Function Attrs: nounwind +define void @test_main() #0 { +entry: + %error_var = alloca i64, align 8 + %retparam = alloca i32, align 4 + %error_var1 = alloca i64, align 8 + %retparam2 = alloca i32, align 4 + %error_var8 = alloca i64, align 8 + %retparam9 = alloca i32, align 4 + %i = alloca i32, align 4 + %i.f = alloca i64, align 8 + %retparam15 = alloca i32, align 4 + %0 = call i64 @test_test(i32* %retparam, i32 1) + %not_err = icmp eq i64 %0, 0 + br i1 %not_err, label %after_check, label %assign_optional + +assign_optional: ; preds = %entry + store i64 %0, i64* %error_var, align 8 + br label %panic_block + +after_check: ; preds = %entry + %1 = load i32, i32* %retparam, align 4 + br label %noerr_block + +panic_block: ; preds = %assign_optional + call void @std_core_builtin_panic(i8* getelementptr inbounds ([28 x i8], [28 x i8]* @.zstr, i64 0, i64 0), i8* getelementptr inbounds ([20 x i8], [20 x i8]* @.zstr.1, i64 0, i64 0), i8* getelementptr inbounds ([5 x i8], [5 x i8]* @.zstr.2, i64 0, i64 0), i32 51) + unreachable + +noerr_block: ; preds = %after_check + %2 = call i64 @test_test7(i32* %retparam2, i32 0) + %not_err3 = icmp eq i64 %2, 0 + br i1 %not_err3, label %after_check5, label %assign_optional4 + +assign_optional4: ; preds = %noerr_block + store i64 %2, i64* %error_var1, align 8 + br label %panic_block6 + +after_check5: ; preds = %noerr_block + %3 = load i32, i32* %retparam2, align 4 + br label %noerr_block7 + +panic_block6: ; preds = %assign_optional4 + call void @std_core_builtin_panic(i8* getelementptr inbounds ([28 x i8], [28 x i8]* @.zstr.3, i64 0, i64 0), i8* getelementptr inbounds ([20 x i8], [20 x i8]* @.zstr.4, i64 0, i64 0), i8* getelementptr inbounds ([5 x i8], [5 x i8]* @.zstr.5, i64 0, i64 0), i32 52) + unreachable + +noerr_block7: ; preds = %after_check5 + %4 = call i64 @test_test6(i32* %retparam9, i32 1) + %not_err10 = icmp eq i64 %4, 0 + br i1 %not_err10, label %after_check12, label %assign_optional11 + +assign_optional11: ; preds = %noerr_block7 + store i64 %4, i64* %error_var8, align 8 + br label %panic_block13 + +after_check12: ; preds = %noerr_block7 + %5 = load i32, i32* %retparam9, align 4 + br label %noerr_block14 + +panic_block13: ; preds = %assign_optional11 + call void @std_core_builtin_panic(i8* getelementptr inbounds ([28 x i8], [28 x i8]* @.zstr.6, i64 0, i64 0), i8* getelementptr inbounds ([20 x i8], [20 x i8]* @.zstr.7, i64 0, i64 0), i8* getelementptr inbounds ([5 x i8], [5 x i8]* @.zstr.8, i64 0, i64 0), i32 53) + unreachable + +noerr_block14: ; preds = %after_check12 + %6 = call i64 @test_test2(i32* %retparam15, i32 3) + %not_err16 = icmp eq i64 %6, 0 + br i1 %not_err16, label %after_check18, label %assign_optional17 + +assign_optional17: ; preds = %noerr_block14 + store i64 %6, i64* %i.f, align 8 + br label %after_assign + +after_check18: ; preds = %noerr_block14 + %7 = load i32, i32* %retparam15, align 4 + store i32 %7, i32* %i, align 4 + store i64 0, i64* %i.f, align 8 + br label %after_assign + +after_assign: ; preds = %after_check18, %assign_optional17 + ret void +} diff --git a/test/test_suite/expressions/ternary_bool.c3t b/test/test_suite/expressions/ternary_bool.c3t index b50047abe..f723b3a09 100644 --- a/test/test_suite/expressions/ternary_bool.c3t +++ b/test/test_suite/expressions/ternary_bool.c3t @@ -13,7 +13,7 @@ fn void main() if (b ?: b) printf("Woa!\n"); } -// #expect: ternary_bool.ll +/* #expect: ternary_bool.ll define void @ternary_bool_main() #0 { entry: @@ -29,58 +29,60 @@ entry: cond.lhs: ; preds = %entry %3 = load i8*, i8** %c, align 8 %4 = load i8, i8* %3, align 8 + %5 = trunc i8 %4 to i1 br label %cond.phi cond.rhs: ; preds = %entry - %5 = load i8*, i8** %c, align 8 - %6 = load i8, i8* %5, align 8 + %6 = load i8*, i8** %c, align 8 + %7 = load i8, i8* %6, align 8 + %8 = trunc i8 %7 to i1 br label %cond.phi cond.phi: ; preds = %cond.rhs, %cond.lhs - %val = phi i8 [ %4, %cond.lhs ], [ %6, %cond.rhs ] - %7 = trunc i8 %val to i1 - br i1 %7, label %if.then, label %if.exit + %val = phi i1 [ %5, %cond.lhs ], [ %8, %cond.rhs ] + br i1 %val, label %if.then, label %if.exit if.then: ; preds = %cond.phi call void (i8*, ...) @printf(i8* getelementptr inbounds ([6 x i8], [6 x i8]* @.str, i32 0, i32 0)) br label %if.exit if.exit: ; preds = %if.then, %cond.phi - %8 = load i8, i8* %b, align 1 - %9 = trunc i8 %8 to i1 - br i1 %9, label %cond.lhs1, label %cond.rhs2 + %9 = load i8, i8* %b, align 1 + %10 = trunc i8 %9 to i1 + br i1 %10, label %cond.lhs1, label %cond.rhs2 cond.lhs1: ; preds = %if.exit - %10 = load i8, i8* %b, align 1 + %11 = load i8, i8* %b, align 1 + %12 = trunc i8 %11 to i1 br label %cond.phi3 cond.rhs2: ; preds = %if.exit - %11 = load i8, i8* %b, align 1 + %13 = load i8, i8* %b, align 1 + %14 = trunc i8 %13 to i1 br label %cond.phi3 cond.phi3: ; preds = %cond.rhs2, %cond.lhs1 - %val4 = phi i8 [ %10, %cond.lhs1 ], [ %11, %cond.rhs2 ] - %12 = trunc i8 %val4 to i1 - br i1 %12, label %if.then5, label %if.exit6 + %val4 = phi i1 [ %12, %cond.lhs1 ], [ %14, %cond.rhs2 ] + br i1 %val4, label %if.then5, label %if.exit6 if.then5: ; preds = %cond.phi3 call void (i8*, ...) @printf(i8* getelementptr inbounds ([6 x i8], [6 x i8]* @.str.1, i32 0, i32 0)) br label %if.exit6 if.exit6: ; preds = %if.then5, %cond.phi3 - %13 = load i8*, i8** %c, align 8 - %14 = load i8, i8* %13, align 8 - %15 = trunc i8 %14 to i1 - br i1 %15, label %cond.phi8, label %cond.rhs7 + %15 = load i8*, i8** %c, align 8 + %16 = load i8, i8* %15, align 8 + %17 = trunc i8 %16 to i1 + br i1 %17, label %cond.phi8, label %cond.rhs7 cond.rhs7: ; preds = %if.exit6 - %16 = load i8*, i8** %c, align 8 - %17 = load i8, i8* %16, align 8 - %18 = trunc i8 %17 to i1 + %18 = load i8*, i8** %c, align 8 + %19 = load i8, i8* %18, align 8 + %20 = trunc i8 %19 to i1 br label %cond.phi8 cond.phi8: ; preds = %cond.rhs7, %if.exit6 - %val9 = phi i1 [ %15, %if.exit6 ], [ %18, %cond.rhs7 ] + %val9 = phi i1 [ %17, %if.exit6 ], [ %20, %cond.rhs7 ] br i1 %val9, label %if.then10, label %if.exit11 if.then10: ; preds = %cond.phi8 @@ -88,17 +90,17 @@ if.then10: ; preds = %cond.phi8 br label %if.exit11 if.exit11: ; preds = %if.then10, %cond.phi8 - %19 = load i8, i8* %b, align 1 - %20 = trunc i8 %19 to i1 - br i1 %20, label %cond.phi13, label %cond.rhs12 - -cond.rhs12: ; preds = %if.exit11 %21 = load i8, i8* %b, align 1 %22 = trunc i8 %21 to i1 + br i1 %22, label %cond.phi13, label %cond.rhs12 + +cond.rhs12: ; preds = %if.exit11 + %23 = load i8, i8* %b, align 1 + %24 = trunc i8 %23 to i1 br label %cond.phi13 cond.phi13: ; preds = %cond.rhs12, %if.exit11 - %val14 = phi i1 [ %20, %if.exit11 ], [ %22, %cond.rhs12 ] + %val14 = phi i1 [ %22, %if.exit11 ], [ %24, %cond.rhs12 ] br i1 %val14, label %if.then15, label %if.exit16 if.then15: ; preds = %cond.phi13 diff --git a/test/test_suite/statements/comparison_widening.c3t b/test/test_suite/statements/comparison_widening.c3t index b2006abc5..2ceef4f9a 100644 --- a/test/test_suite/statements/comparison_widening.c3t +++ b/test/test_suite/statements/comparison_widening.c3t @@ -28,7 +28,7 @@ entry: store i8 %ternary, i8* %c, align 1 %2 = load i32, i32* %b, align 4 %intbool = icmp ne i32 %2, 0 - %elvis = select i1 %intbool, i32 %2, i32 1 - store i32 %elvis, i32* %d, align 4 + %ternary1 = select i1 %intbool, i32 %2, i32 1 + store i32 %ternary1, i32* %d, align 4 ret void } \ No newline at end of file diff --git a/test/test_suite2/expressions/optional_ternary.c3t b/test/test_suite2/expressions/optional_ternary.c3t new file mode 100644 index 000000000..231a3edb0 --- /dev/null +++ b/test/test_suite2/expressions/optional_ternary.c3t @@ -0,0 +1,415 @@ +// #target: macos-x64 + +module test; + +fault Foo +{ + X +} + +fn int! test(int i) +{ + return i ?: Foo.X!; +} + +fn int! test2(int i) +{ + return i ? Foo.X! : Foo.X!; +} + + +fn int! test3(int i) +{ + return i ? 2 : Foo.X!; +} + + +fn int! test4(int i) +{ + int! y = i; + return (y?) ?: Foo.X!; +} +fn int! test5(int i) +{ + int! y = i; + return (y?) ? Foo.X! : Foo.X!; +} + +fn int! test6(int i) +{ + int! y = i; + return (y?) ? 2 : Foo.X!; +} + +fn int! test7(int i) +{ + int! y = i; + return (y?) ? Foo.X! : 2; +} + +fn void main() +{ + test(1)!!; + test7(0)!!; + test6(1)!!; + int! i = test2(3); +} + +/* expect: test.ll +source_filename = "test" +target datalayout = "e-m:o-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128" +target triple = "x86_64-apple-darwin" + +%.fault = type { i64, %"char[]" } +%"char[]" = type { i8*, i64 } +%.introspect = type { i8, i64, i64, i64, [0 x i64] } + +@"test_Foo$X" = linkonce constant %.fault { i64 ptrtoint (%.introspect* @"ct$test_Foo" to i64), %"char[]" { i8* getelementptr inbounds ([2 x i8], [2 x i8]* @.fault, i64 0, i64 0), i64 1 } }, align 8 +@.fault = internal constant [2 x i8] c"X\00", align 1 +@"ct$test_Foo" = linkonce constant %.introspect { i8 9, i64 8, i64 0, i64 1, [0 x i64] zeroinitializer }, align 8 +@.zstr = internal constant [28 x i8] c"Runtime error force unwrap!\00", align 1 +@.zstr.1 = internal constant [20 x i8] c"optional_ternary.c3\00", align 1 +@.zstr.2 = internal constant [5 x i8] c"main\00", align 1 +@.zstr.3 = internal constant [28 x i8] c"Runtime error force unwrap!\00", align 1 +@.zstr.4 = internal constant [20 x i8] c"optional_ternary.c3\00", align 1 +@.zstr.5 = internal constant [5 x i8] c"main\00", align 1 +@.zstr.6 = internal constant [28 x i8] c"Runtime error force unwrap!\00", align 1 +@.zstr.7 = internal constant [20 x i8] c"optional_ternary.c3\00", align 1 +@.zstr.8 = internal constant [5 x i8] c"main\00", align 1 + +; Function Attrs: nounwind +define i64 @test_test(i32* %0, i32 %1) #0 { +entry: + %reterr = alloca i64, align 8 + %intbool = icmp ne i32 %1, 0 + br i1 %intbool, label %cond.phi, label %cond.rhs + +cond.rhs: ; preds = %entry + store i64 ptrtoint (%.fault* @"test_Foo$X" to i64), i64* %reterr, align 8 + br label %err_retblock + +cond.phi: ; preds = %entry + store i32 %1, i32* %0, align 4 + ret i64 0 + +err_retblock: ; preds = %cond.rhs + %2 = load i64, i64* %reterr, align 8 + ret i64 %2 +} + +; Function Attrs: nounwind +define i64 @test_test2(i32* %0, i32 %1) #0 { +entry: + %reterr = alloca i64, align 8 + %intbool = icmp ne i32 %1, 0 + br i1 %intbool, label %cond.lhs, label %cond.rhs + +cond.lhs: ; preds = %entry + store i64 ptrtoint (%.fault* @"test_Foo$X" to i64), i64* %reterr, align 8 + br label %err_retblock + +cond.rhs: ; preds = %entry + store i64 ptrtoint (%.fault* @"test_Foo$X" to i64), i64* %reterr, align 8 + br label %err_retblock + +cond.phi: ; No predecessors! + store i32 undef, i32* %0, align 4 + ret i64 0 + +err_retblock: ; preds = %cond.rhs, %cond.lhs + %2 = load i64, i64* %reterr, align 8 + ret i64 %2 +} + +; Function Attrs: nounwind +define i64 @test_test3(i32* %0, i32 %1) #0 { +entry: + %reterr = alloca i64, align 8 + %intbool = icmp ne i32 %1, 0 + br i1 %intbool, label %cond.lhs, label %cond.rhs + +cond.lhs: ; preds = %entry + br label %cond.phi + +cond.rhs: ; preds = %entry + store i64 ptrtoint (%.fault* @"test_Foo$X" to i64), i64* %reterr, align 8 + br label %err_retblock + +cond.phi: ; preds = %cond.lhs + store i32 2, i32* %0, align 4 + ret i64 0 + +err_retblock: ; preds = %cond.rhs + %2 = load i64, i64* %reterr, align 8 + ret i64 %2 +} + +; Function Attrs: nounwind +define i64 @test_test4(i32* %0, i32 %1) #0 { +entry: + %y = alloca i32, align 4 + %y.f = alloca i64, align 8 + %reterr = alloca i64, align 8 + %error_var = alloca i64, align 8 + store i32 %1, i32* %y, align 4 + store i64 0, i64* %y.f, align 8 + %optval = load i64, i64* %y.f, align 8 + %not_err = icmp eq i64 %optval, 0 + br i1 %not_err, label %after_check, label %assign_optional + +assign_optional: ; preds = %entry + store i64 %optval, i64* %error_var, align 8 + br label %guard_block + +after_check: ; preds = %entry + br label %noerr_block + +guard_block: ; preds = %assign_optional + %2 = load i64, i64* %error_var, align 8 + ret i64 %2 + +noerr_block: ; preds = %after_check + %3 = load i32, i32* %y, align 4 + %intbool = icmp ne i32 %3, 0 + br i1 %intbool, label %cond.phi, label %cond.rhs + +cond.rhs: ; preds = %noerr_block + store i64 ptrtoint (%.fault* @"test_Foo$X" to i64), i64* %reterr, align 8 + br label %err_retblock + +cond.phi: ; preds = %noerr_block + store i32 %3, i32* %0, align 4 + ret i64 0 + +err_retblock: ; preds = %cond.rhs + %4 = load i64, i64* %reterr, align 8 + ret i64 %4 +} + +; Function Attrs: nounwind +define i64 @test_test5(i32* %0, i32 %1) #0 { +entry: + %y = alloca i32, align 4 + %y.f = alloca i64, align 8 + %reterr = alloca i64, align 8 + %error_var = alloca i64, align 8 + store i32 %1, i32* %y, align 4 + store i64 0, i64* %y.f, align 8 + %optval = load i64, i64* %y.f, align 8 + %not_err = icmp eq i64 %optval, 0 + br i1 %not_err, label %after_check, label %assign_optional + +assign_optional: ; preds = %entry + store i64 %optval, i64* %error_var, align 8 + br label %guard_block + +after_check: ; preds = %entry + br label %noerr_block + +guard_block: ; preds = %assign_optional + %2 = load i64, i64* %error_var, align 8 + ret i64 %2 + +noerr_block: ; preds = %after_check + %3 = load i32, i32* %y, align 4 + %intbool = icmp ne i32 %3, 0 + br i1 %intbool, label %cond.lhs, label %cond.rhs + +cond.lhs: ; preds = %noerr_block + store i64 ptrtoint (%.fault* @"test_Foo$X" to i64), i64* %reterr, align 8 + br label %err_retblock + +cond.rhs: ; preds = %noerr_block + store i64 ptrtoint (%.fault* @"test_Foo$X" to i64), i64* %reterr, align 8 + br label %err_retblock + +cond.phi: ; No predecessors! + store i32 undef, i32* %0, align 4 + ret i64 0 + +err_retblock: ; preds = %cond.rhs, %cond.lhs + %4 = load i64, i64* %reterr, align 8 + ret i64 %4 +} + +; Function Attrs: nounwind +define i64 @test_test6(i32* %0, i32 %1) #0 { +entry: + %y = alloca i32, align 4 + %y.f = alloca i64, align 8 + %reterr = alloca i64, align 8 + %error_var = alloca i64, align 8 + store i32 %1, i32* %y, align 4 + store i64 0, i64* %y.f, align 8 + %optval = load i64, i64* %y.f, align 8 + %not_err = icmp eq i64 %optval, 0 + br i1 %not_err, label %after_check, label %assign_optional + +assign_optional: ; preds = %entry + store i64 %optval, i64* %error_var, align 8 + br label %guard_block + +after_check: ; preds = %entry + br label %noerr_block + +guard_block: ; preds = %assign_optional + %2 = load i64, i64* %error_var, align 8 + ret i64 %2 + +noerr_block: ; preds = %after_check + %3 = load i32, i32* %y, align 4 + %intbool = icmp ne i32 %3, 0 + br i1 %intbool, label %cond.lhs, label %cond.rhs + +cond.lhs: ; preds = %noerr_block + br label %cond.phi + +cond.rhs: ; preds = %noerr_block + store i64 ptrtoint (%.fault* @"test_Foo$X" to i64), i64* %reterr, align 8 + br label %err_retblock + +cond.phi: ; preds = %cond.lhs + store i32 2, i32* %0, align 4 + ret i64 0 + +err_retblock: ; preds = %cond.rhs + %4 = load i64, i64* %reterr, align 8 + ret i64 %4 +} + +; Function Attrs: nounwind +define i64 @test_test7(i32* %0, i32 %1) #0 { +entry: + %y = alloca i32, align 4 + %y.f = alloca i64, align 8 + %reterr = alloca i64, align 8 + %error_var = alloca i64, align 8 + store i32 %1, i32* %y, align 4 + store i64 0, i64* %y.f, align 8 + %optval = load i64, i64* %y.f, align 8 + %not_err = icmp eq i64 %optval, 0 + br i1 %not_err, label %after_check, label %assign_optional + +assign_optional: ; preds = %entry + store i64 %optval, i64* %error_var, align 8 + br label %guard_block + +after_check: ; preds = %entry + br label %noerr_block + +guard_block: ; preds = %assign_optional + %2 = load i64, i64* %error_var, align 8 + ret i64 %2 + +noerr_block: ; preds = %after_check + %3 = load i32, i32* %y, align 4 + %intbool = icmp ne i32 %3, 0 + br i1 %intbool, label %cond.lhs, label %cond.rhs + +cond.lhs: ; preds = %noerr_block + store i64 ptrtoint (%.fault* @"test_Foo$X" to i64), i64* %reterr, align 8 + br label %err_retblock + +cond.rhs: ; preds = %noerr_block + br label %cond.phi + +cond.phi: ; preds = %cond.rhs + store i32 2, i32* %0, align 4 + ret i64 0 + +err_retblock: ; preds = %cond.lhs + %4 = load i64, i64* %reterr, align 8 + ret i64 %4 +} + +; Function Attrs: nounwind +define void @test_main() #0 { +entry: + %error_var = alloca i64, align 8 + %retparam = alloca i32, align 4 + %error_var1 = alloca i64, align 8 + %retparam2 = alloca i32, align 4 + %error_var8 = alloca i64, align 8 + %retparam9 = alloca i32, align 4 + %i = alloca i32, align 4 + %i.f = alloca i64, align 8 + %retparam15 = alloca i32, align 4 + %0 = call i64 @test_test(i32* %retparam, i32 1) + %not_err = icmp eq i64 %0, 0 + br i1 %not_err, label %after_check, label %assign_optional + +assign_optional: ; preds = %entry + store i64 %0, i64* %error_var, align 8 + br label %panic_block + +after_check: ; preds = %entry + %1 = load i32, i32* %retparam, align 4 + br label %noerr_block + +panic_block: ; preds = %assign_optional + call void @std_core_builtin_panic(i8* getelementptr inbounds ([28 x i8], [28 x i8]* @.zstr, i64 0, i64 0), i8* getelementptr inbounds ([20 x i8], [20 x i8]* @.zstr.1, i64 0, i64 0), i8* getelementptr inbounds ([5 x i8], [5 x i8]* @.zstr.2, i64 0, i64 0), i32 51) + unreachable + +noerr_block: ; preds = %after_check + %2 = call i64 @test_test7(i32* %retparam2, i32 0) + %not_err3 = icmp eq i64 %2, 0 + br i1 %not_err3, label %after_check5, label %assign_optional4 + +assign_optional4: ; preds = %noerr_block + store i64 %2, i64* %error_var1, align 8 + br label %panic_block6 + +after_check5: ; preds = %noerr_block + %3 = load i32, i32* %retparam2, align 4 + br label %noerr_block7 + +panic_block6: ; preds = %assign_optional4 + call void @std_core_builtin_panic(i8* getelementptr inbounds ([28 x i8], [28 x i8]* @.zstr.3, i64 0, i64 0), i8* getelementptr inbounds ([20 x i8], [20 x i8]* @.zstr.4, i64 0, i64 0), i8* getelementptr inbounds ([5 x i8], [5 x i8]* @.zstr.5, i64 0, i64 0), i32 52) + unreachable + +noerr_block7: ; preds = %after_check5 + %4 = call i64 @test_test6(i32* %retparam9, i32 1) + %not_err10 = icmp eq i64 %4, 0 + br i1 %not_err10, label %after_check12, label %assign_optional11 + +assign_optional11: ; preds = %noerr_block7 + store i64 %4, i64* %error_var8, align 8 + br label %panic_block13 + +after_check12: ; preds = %noerr_block7 + %5 = load i32, i32* %retparam9, align 4 + br label %noerr_block14 + +panic_block13: ; preds = %assign_optional11 + call void @std_core_builtin_panic(i8* getelementptr inbounds ([28 x i8], [28 x i8]* @.zstr.6, i64 0, i64 0), i8* getelementptr inbounds ([20 x i8], [20 x i8]* @.zstr.7, i64 0, i64 0), i8* getelementptr inbounds ([5 x i8], [5 x i8]* @.zstr.8, i64 0, i64 0), i32 53) + unreachable + +noerr_block14: ; preds = %after_check12 + %6 = call i64 @test_test2(i32* %retparam15, i32 3) + %not_err16 = icmp eq i64 %6, 0 + br i1 %not_err16, label %after_check18, label %assign_optional17 + +assign_optional17: ; preds = %noerr_block14 + store i64 %6, i64* %i.f, align 8 + br label %after_assign + +after_check18: ; preds = %noerr_block14 + %7 = load i32, i32* %retparam15, align 4 + store i32 %7, i32* %i, align 4 + store i64 0, i64* %i.f, align 8 + br label %after_assign + +after_assign: ; preds = %after_check18, %assign_optional17 + ret void +} + +; Function Attrs: nounwind +define i32 @main(i32 %0, i8** %1) #0 { +entry: + call void @test_main() + ret i32 0 +} + +declare void @std_core_builtin_panic(i8*, i8*, i8*, i32) + +attributes #0 = { nounwind } \ No newline at end of file diff --git a/test/test_suite2/expressions/ternary_bool.c3t b/test/test_suite2/expressions/ternary_bool.c3t index 2097a2bad..ac559f05f 100644 --- a/test/test_suite2/expressions/ternary_bool.c3t +++ b/test/test_suite2/expressions/ternary_bool.c3t @@ -29,58 +29,60 @@ entry: cond.lhs: ; preds = %entry %3 = load ptr, ptr %c, align 8 %4 = load i8, ptr %3, align 8 + %5 = trunc i8 %4 to i1 br label %cond.phi cond.rhs: ; preds = %entry - %5 = load ptr, ptr %c, align 8 - %6 = load i8, ptr %5, align 8 + %6 = load ptr, ptr %c, align 8 + %7 = load i8, ptr %6, align 8 + %8 = trunc i8 %7 to i1 br label %cond.phi cond.phi: ; preds = %cond.rhs, %cond.lhs - %val = phi i8 [ %4, %cond.lhs ], [ %6, %cond.rhs ] - %7 = trunc i8 %val to i1 - br i1 %7, label %if.then, label %if.exit + %val = phi i1 [ %5, %cond.lhs ], [ %8, %cond.rhs ] + br i1 %val, label %if.then, label %if.exit if.then: ; preds = %cond.phi call void (ptr, ...) @printf(ptr @.str) br label %if.exit if.exit: ; preds = %if.then, %cond.phi - %8 = load i8, ptr %b, align 1 - %9 = trunc i8 %8 to i1 - br i1 %9, label %cond.lhs1, label %cond.rhs2 + %9 = load i8, ptr %b, align 1 + %10 = trunc i8 %9 to i1 + br i1 %10, label %cond.lhs1, label %cond.rhs2 cond.lhs1: ; preds = %if.exit - %10 = load i8, ptr %b, align 1 + %11 = load i8, ptr %b, align 1 + %12 = trunc i8 %11 to i1 br label %cond.phi3 cond.rhs2: ; preds = %if.exit - %11 = load i8, ptr %b, align 1 + %13 = load i8, ptr %b, align 1 + %14 = trunc i8 %13 to i1 br label %cond.phi3 cond.phi3: ; preds = %cond.rhs2, %cond.lhs1 - %val4 = phi i8 [ %10, %cond.lhs1 ], [ %11, %cond.rhs2 ] - %12 = trunc i8 %val4 to i1 - br i1 %12, label %if.then5, label %if.exit6 + %val4 = phi i1 [ %12, %cond.lhs1 ], [ %14, %cond.rhs2 ] + br i1 %val4, label %if.then5, label %if.exit6 if.then5: ; preds = %cond.phi3 call void (ptr, ...) @printf(ptr @.str.1) br label %if.exit6 if.exit6: ; preds = %if.then5, %cond.phi3 - %13 = load ptr, ptr %c, align 8 - %14 = load i8, ptr %13, align 8 - %15 = trunc i8 %14 to i1 - br i1 %15, label %cond.phi8, label %cond.rhs7 + %15 = load ptr, ptr %c, align 8 + %16 = load i8, ptr %15, align 8 + %17 = trunc i8 %16 to i1 + br i1 %17, label %cond.phi8, label %cond.rhs7 cond.rhs7: ; preds = %if.exit6 - %16 = load ptr, ptr %c, align 8 - %17 = load i8, ptr %16, align 8 - %18 = trunc i8 %17 to i1 + %18 = load ptr, ptr %c, align 8 + %19 = load i8, ptr %18, align 8 + %20 = trunc i8 %19 to i1 br label %cond.phi8 cond.phi8: ; preds = %cond.rhs7, %if.exit6 - %val9 = phi i1 [ %15, %if.exit6 ], [ %18, %cond.rhs7 ] + %val9 = phi i1 [ %17, %if.exit6 ], [ %20, %cond.rhs7 ] br i1 %val9, label %if.then10, label %if.exit11 if.then10: ; preds = %cond.phi8 @@ -88,17 +90,17 @@ if.then10: ; preds = %cond.phi8 br label %if.exit11 if.exit11: ; preds = %if.then10, %cond.phi8 - %19 = load i8, ptr %b, align 1 - %20 = trunc i8 %19 to i1 - br i1 %20, label %cond.phi13, label %cond.rhs12 - -cond.rhs12: ; preds = %if.exit11 %21 = load i8, ptr %b, align 1 %22 = trunc i8 %21 to i1 + br i1 %22, label %cond.phi13, label %cond.rhs12 + +cond.rhs12: ; preds = %if.exit11 + %23 = load i8, ptr %b, align 1 + %24 = trunc i8 %23 to i1 br label %cond.phi13 cond.phi13: ; preds = %cond.rhs12, %if.exit11 - %val14 = phi i1 [ %20, %if.exit11 ], [ %22, %cond.rhs12 ] + %val14 = phi i1 [ %22, %if.exit11 ], [ %24, %cond.rhs12 ] br i1 %val14, label %if.then15, label %if.exit16 if.then15: ; preds = %cond.phi13 diff --git a/test/test_suite2/statements/comparison_widening.c3t b/test/test_suite2/statements/comparison_widening.c3t index 9134aa87e..5e873dbb8 100644 --- a/test/test_suite2/statements/comparison_widening.c3t +++ b/test/test_suite2/statements/comparison_widening.c3t @@ -28,7 +28,7 @@ entry: store i8 %ternary, ptr %c, align 1 %2 = load i32, ptr %b, align 4 %intbool = icmp ne i32 %2, 0 - %elvis = select i1 %intbool, i32 %2, i32 1 - store i32 %elvis, ptr %d, align 4 + %ternary1 = select i1 %intbool, i32 %2, i32 1 + store i32 %ternary1, ptr %d, align 4 ret void } \ No newline at end of file