Fix of ternary / elvis where legs are bool or optional.

This commit is contained in:
Christoffer Lerno
2022-10-18 11:21:46 +02:00
committed by Christoffer Lerno
parent b1ed066e55
commit 76ee384a4c
16 changed files with 1088 additions and 94 deletions

19
lib/std/io/dir.c3 Normal file
View File

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

View File

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

View File

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

View File

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

49
lib/std/os/macos/objc.c3 Normal file
View File

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

View File

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

View File

@@ -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)

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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