mirror of
https://github.com/c3lang/c3c.git
synced 2026-02-27 12:01:16 +00:00
424 lines
16 KiB
C
424 lines
16 KiB
C
// #target: macos-x64
|
|
module foo;
|
|
|
|
extern fn void printf(char*, ...);
|
|
|
|
fn void test(any z)
|
|
{
|
|
switch (z)
|
|
{
|
|
case int:
|
|
printf("int: %d\n", *z);
|
|
case double:
|
|
printf("double %f\n", *z);
|
|
default:
|
|
printf("Unknown type.\n");
|
|
}
|
|
}
|
|
fn void test2(any y)
|
|
{
|
|
switch (z = y)
|
|
{
|
|
case int:
|
|
y = &&12;
|
|
printf("int: %d\n", *z);
|
|
case double:
|
|
printf("double %f\n", *z);
|
|
default:
|
|
printf("Unknown type.\n");
|
|
}
|
|
}
|
|
|
|
fn void test3(any y)
|
|
{
|
|
switch (z = *y)
|
|
{
|
|
case int:
|
|
printf("int: %d\n", z);
|
|
case double:
|
|
printf("double %f\n", z);
|
|
default:
|
|
printf("Unknown type.\n");
|
|
}
|
|
}
|
|
|
|
fn int main()
|
|
{
|
|
test(&&123.0);
|
|
test(&&1);
|
|
test(&&true);
|
|
test2(&&123.5);
|
|
test2(&&1);
|
|
test2(&&true);
|
|
test3(&&124.0);
|
|
test3(&&2);
|
|
test3(&&true);
|
|
return 0;
|
|
}
|
|
|
|
/* #expect: foo.ll
|
|
|
|
@"$ct.int" = linkonce global %.introspect { i8 2, i64 0, ptr null, i64 4, i64 0, i64 0, [0 x i64] zeroinitializer }, align 8
|
|
@"$ct.double" = linkonce global %.introspect { i8 4, i64 0, ptr null, i64 8, i64 0, i64 0, [0 x i64] zeroinitializer }, align 8
|
|
@"$ct.bool" = linkonce global %.introspect { i8 1, i64 0, ptr null, i64 1, i64 0, i64 0, [0 x i64] zeroinitializer }, align 8
|
|
|
|
define void @foo.test(i64 %0, ptr %1) #0 {
|
|
entry:
|
|
%z = alloca %any, align 8
|
|
%switch = alloca i64, align 8
|
|
%z1 = alloca ptr, align 8
|
|
%z8 = alloca ptr, align 8
|
|
store i64 %0, ptr %z, align 8
|
|
%ptroffset = getelementptr inbounds ptr, ptr %z, i64 1
|
|
store ptr %1, ptr %ptroffset, align 8
|
|
%2 = getelementptr inbounds %any, ptr %z, i32 0, i32 1
|
|
%3 = load i64, ptr %2, align 8
|
|
store i64 %3, ptr %switch, align 8
|
|
br label %switch.entry
|
|
|
|
switch.entry: ; preds = %entry
|
|
%4 = load i64, ptr %switch, align 8
|
|
br label %check_subtype
|
|
|
|
check_subtype: ; preds = %parent_type_block, %switch.entry
|
|
%5 = phi i64 [ %4, %switch.entry ], [ %typeid.parent, %parent_type_block ]
|
|
%eq = icmp eq i64 ptrtoint (ptr @"$ct.int" to i64), %5
|
|
br i1 %eq, label %result_block, label %parent_type_block
|
|
|
|
parent_type_block: ; preds = %check_subtype
|
|
%6 = inttoptr i64 %5 to ptr
|
|
%7 = getelementptr inbounds %.introspect, ptr %6, i32 0, i32 1
|
|
%typeid.parent = load i64, ptr %7, align 8
|
|
%8 = icmp eq i64 %typeid.parent, 0
|
|
br i1 %8, label %result_block, label %check_subtype
|
|
|
|
result_block: ; preds = %parent_type_block, %check_subtype
|
|
%9 = phi i1 [ false, %parent_type_block ], [ true, %check_subtype ]
|
|
br i1 %9, label %switch.case, label %next_if
|
|
|
|
switch.case: ; preds = %result_block
|
|
%10 = getelementptr inbounds %any, ptr %z, i32 0, i32 0
|
|
%11 = load ptr, ptr %10, align 8
|
|
store ptr %11, ptr %z1, align 8
|
|
%12 = load ptr, ptr %z1, align 8
|
|
%13 = load i32, ptr %12, align 4
|
|
call void (ptr, ...) @printf(ptr @.str, i32 %13)
|
|
br label %switch.exit
|
|
|
|
next_if: ; preds = %result_block
|
|
br label %check_subtype2
|
|
|
|
check_subtype2: ; preds = %parent_type_block4, %next_if
|
|
%14 = phi i64 [ %4, %next_if ], [ %typeid.parent5, %parent_type_block4 ]
|
|
%eq3 = icmp eq i64 ptrtoint (ptr @"$ct.double" to i64), %14
|
|
br i1 %eq3, label %result_block6, label %parent_type_block4
|
|
|
|
parent_type_block4: ; preds = %check_subtype2
|
|
%15 = inttoptr i64 %14 to ptr
|
|
%16 = getelementptr inbounds %.introspect, ptr %15, i32 0, i32 1
|
|
%typeid.parent5 = load i64, ptr %16, align 8
|
|
%17 = icmp eq i64 %typeid.parent5, 0
|
|
br i1 %17, label %result_block6, label %check_subtype2
|
|
|
|
result_block6: ; preds = %parent_type_block4, %check_subtype2
|
|
%18 = phi i1 [ false, %parent_type_block4 ], [ true, %check_subtype2 ]
|
|
br i1 %18, label %switch.case7, label %next_if9
|
|
|
|
switch.case7: ; preds = %result_block6
|
|
%19 = getelementptr inbounds %any, ptr %z, i32 0, i32 0
|
|
%20 = load ptr, ptr %19, align 8
|
|
store ptr %20, ptr %z8, align 8
|
|
%21 = load ptr, ptr %z8, align 8
|
|
%22 = load double, ptr %21, align 8
|
|
call void (ptr, ...) @printf(ptr @.str.1, double %22)
|
|
br label %switch.exit
|
|
|
|
next_if9: ; preds = %result_block6
|
|
br label %switch.default
|
|
|
|
switch.default: ; preds = %next_if9
|
|
call void (ptr, ...) @printf(ptr @.str.2)
|
|
br label %switch.exit
|
|
|
|
switch.exit: ; preds = %switch.default, %switch.case7, %switch.case
|
|
ret void
|
|
}
|
|
|
|
; Function Attrs: nounwind
|
|
define void @foo.test2(i64 %0, ptr %1) #0 {
|
|
entry:
|
|
%y = alloca %any, align 8
|
|
%.anon = alloca %any, align 8
|
|
%switch = alloca i64, align 8
|
|
%z = alloca ptr, align 8
|
|
%taddr = alloca i32, align 4
|
|
%z7 = alloca ptr, align 8
|
|
store i64 %0, ptr %y, align 8
|
|
%ptroffset = getelementptr inbounds ptr, ptr %y, i64 1
|
|
store ptr %1, ptr %ptroffset, align 8
|
|
call void @llvm.memcpy.p0.p0.i32(ptr align 8 %.anon, ptr align 8 %y, i32 16, i1 false)
|
|
%2 = getelementptr inbounds %any, ptr %y, i32 0, i32 1
|
|
%3 = load i64, ptr %2, align 8
|
|
store i64 %3, ptr %switch, align 8
|
|
br label %switch.entry
|
|
|
|
switch.entry: ; preds = %entry
|
|
%4 = load i64, ptr %switch, align 8
|
|
br label %check_subtype
|
|
|
|
check_subtype: ; preds = %parent_type_block, %switch.entry
|
|
%5 = phi i64 [ %4, %switch.entry ], [ %typeid.parent, %parent_type_block ]
|
|
%eq = icmp eq i64 ptrtoint (ptr @"$ct.int" to i64), %5
|
|
br i1 %eq, label %result_block, label %parent_type_block
|
|
|
|
parent_type_block: ; preds = %check_subtype
|
|
%6 = inttoptr i64 %5 to ptr
|
|
%7 = getelementptr inbounds %.introspect, ptr %6, i32 0, i32 1
|
|
%typeid.parent = load i64, ptr %7, align 8
|
|
%8 = icmp eq i64 %typeid.parent, 0
|
|
br i1 %8, label %result_block, label %check_subtype
|
|
|
|
result_block: ; preds = %parent_type_block, %check_subtype
|
|
%9 = phi i1 [ false, %parent_type_block ], [ true, %check_subtype ]
|
|
br i1 %9, label %switch.case, label %next_if
|
|
|
|
switch.case: ; preds = %result_block
|
|
%10 = getelementptr inbounds %any, ptr %.anon, i32 0, i32 0
|
|
%11 = load ptr, ptr %10, align 8
|
|
store ptr %11, ptr %z, align 8
|
|
store i32 12, ptr %taddr, align 4
|
|
%12 = insertvalue %any undef, ptr %taddr, 0
|
|
%13 = insertvalue %any %12, i64 ptrtoint (ptr @"$ct.int" to i64), 1
|
|
store %any %13, ptr %y, align 8
|
|
%14 = load ptr, ptr %z, align 8
|
|
%15 = load i32, ptr %14, align 4
|
|
call void (ptr, ...) @printf(ptr @.str.3, i32 %15)
|
|
br label %switch.exit
|
|
|
|
next_if: ; preds = %result_block
|
|
br label %check_subtype1
|
|
|
|
check_subtype1: ; preds = %parent_type_block3, %next_if
|
|
%16 = phi i64 [ %4, %next_if ], [ %typeid.parent4, %parent_type_block3 ]
|
|
%eq2 = icmp eq i64 ptrtoint (ptr @"$ct.double" to i64), %16
|
|
br i1 %eq2, label %result_block5, label %parent_type_block3
|
|
|
|
parent_type_block3: ; preds = %check_subtype1
|
|
%17 = inttoptr i64 %16 to ptr
|
|
%18 = getelementptr inbounds %.introspect, ptr %17, i32 0, i32 1
|
|
%typeid.parent4 = load i64, ptr %18, align 8
|
|
%19 = icmp eq i64 %typeid.parent4, 0
|
|
br i1 %19, label %result_block5, label %check_subtype1
|
|
|
|
result_block5: ; preds = %parent_type_block3, %check_subtype1
|
|
%20 = phi i1 [ false, %parent_type_block3 ], [ true, %check_subtype1 ]
|
|
br i1 %20, label %switch.case6, label %next_if8
|
|
|
|
switch.case6: ; preds = %result_block5
|
|
%21 = getelementptr inbounds %any, ptr %.anon, i32 0, i32 0
|
|
%22 = load ptr, ptr %21, align 8
|
|
store ptr %22, ptr %z7, align 8
|
|
%23 = load ptr, ptr %z7, align 8
|
|
%24 = load double, ptr %23, align 8
|
|
call void (ptr, ...) @printf(ptr @.str.4, double %24)
|
|
br label %switch.exit
|
|
|
|
next_if8: ; preds = %result_block5
|
|
br label %switch.default
|
|
|
|
switch.default: ; preds = %next_if8
|
|
call void (ptr, ...) @printf(ptr @.str.5)
|
|
br label %switch.exit
|
|
|
|
switch.exit: ; preds = %switch.default, %switch.case6, %switch.case
|
|
ret void
|
|
}
|
|
|
|
define void @foo.test3(i64 %0, ptr %1) #0 {
|
|
entry:
|
|
%y = alloca %any, align 8
|
|
%.anon = alloca %any, align 8
|
|
%switch = alloca i64, align 8
|
|
%z = alloca i32, align 4
|
|
%z7 = alloca double, align 8
|
|
store i64 %0, ptr %y, align 8
|
|
%ptroffset = getelementptr inbounds ptr, ptr %y, i64 1
|
|
store ptr %1, ptr %ptroffset, align 8
|
|
call void @llvm.memcpy.p0.p0.i32(ptr align 8 %.anon, ptr align 8 %y, i32 16, i1 false)
|
|
%2 = getelementptr inbounds %any, ptr %y, i32 0, i32 1
|
|
%3 = load i64, ptr %2, align 8
|
|
store i64 %3, ptr %switch, align 8
|
|
br label %switch.entry
|
|
|
|
switch.entry: ; preds = %entry
|
|
%4 = load i64, ptr %switch, align 8
|
|
br label %check_subtype
|
|
|
|
check_subtype: ; preds = %parent_type_block, %switch.entry
|
|
%5 = phi i64 [ %4, %switch.entry ], [ %typeid.parent, %parent_type_block ]
|
|
%eq = icmp eq i64 ptrtoint (ptr @"$ct.int" to i64), %5
|
|
br i1 %eq, label %result_block, label %parent_type_block
|
|
|
|
parent_type_block: ; preds = %check_subtype
|
|
%6 = inttoptr i64 %5 to ptr
|
|
%7 = getelementptr inbounds %.introspect, ptr %6, i32 0, i32 1
|
|
%typeid.parent = load i64, ptr %7, align 8
|
|
%8 = icmp eq i64 %typeid.parent, 0
|
|
br i1 %8, label %result_block, label %check_subtype
|
|
|
|
result_block: ; preds = %parent_type_block, %check_subtype
|
|
%9 = phi i1 [ false, %parent_type_block ], [ true, %check_subtype ]
|
|
br i1 %9, label %switch.case, label %next_if
|
|
|
|
switch.case: ; preds = %result_block
|
|
%10 = getelementptr inbounds %any, ptr %.anon, i32 0, i32 0
|
|
%11 = load ptr, ptr %10, align 8
|
|
%12 = load i32, ptr %11, align 4
|
|
store i32 %12, ptr %z, align 4
|
|
%13 = load i32, ptr %z, align 4
|
|
call void (ptr, ...) @printf(ptr @.str.6, i32 %13)
|
|
br label %switch.exit
|
|
|
|
next_if: ; preds = %result_block
|
|
br label %check_subtype1
|
|
|
|
check_subtype1: ; preds = %parent_type_block3, %next_if
|
|
%14 = phi i64 [ %4, %next_if ], [ %typeid.parent4, %parent_type_block3 ]
|
|
%eq2 = icmp eq i64 ptrtoint (ptr @"$ct.double" to i64), %14
|
|
br i1 %eq2, label %result_block5, label %parent_type_block3
|
|
|
|
parent_type_block3: ; preds = %check_subtype1
|
|
%15 = inttoptr i64 %14 to ptr
|
|
%16 = getelementptr inbounds %.introspect, ptr %15, i32 0, i32 1
|
|
%typeid.parent4 = load i64, ptr %16, align 8
|
|
%17 = icmp eq i64 %typeid.parent4, 0
|
|
br i1 %17, label %result_block5, label %check_subtype1
|
|
|
|
result_block5: ; preds = %parent_type_block3, %check_subtype1
|
|
%18 = phi i1 [ false, %parent_type_block3 ], [ true, %check_subtype1 ]
|
|
br i1 %18, label %switch.case6, label %next_if8
|
|
|
|
switch.case6: ; preds = %result_block5
|
|
%19 = getelementptr inbounds %any, ptr %.anon, i32 0, i32 0
|
|
%20 = load ptr, ptr %19, align 8
|
|
%21 = load double, ptr %20, align 8
|
|
store double %21, ptr %z7, align 8
|
|
%22 = load double, ptr %z7, align 8
|
|
call void (ptr, ...) @printf(ptr @.str.7, double %22)
|
|
br label %switch.exit
|
|
|
|
next_if8: ; preds = %result_block5
|
|
br label %switch.default
|
|
|
|
switch.default: ; preds = %next_if8
|
|
call void (ptr, ...) @printf(ptr @.str.8)
|
|
br label %switch.exit
|
|
|
|
switch.exit: ; preds = %switch.default, %switch.case6, %switch.case
|
|
ret void
|
|
}
|
|
|
|
define i32 @main() #0 {
|
|
entry:
|
|
%taddr = alloca double, align 8
|
|
%taddr1 = alloca %any, align 8
|
|
%taddr2 = alloca i32, align 4
|
|
%taddr3 = alloca %any, align 8
|
|
%taddr6 = alloca i8, align 1
|
|
%taddr7 = alloca %any, align 8
|
|
%taddr10 = alloca double, align 8
|
|
%taddr11 = alloca %any, align 8
|
|
%taddr14 = alloca i32, align 4
|
|
%taddr15 = alloca %any, align 8
|
|
%taddr18 = alloca i8, align 1
|
|
%taddr19 = alloca %any, align 8
|
|
%taddr22 = alloca double, align 8
|
|
%taddr23 = alloca %any, align 8
|
|
%taddr26 = alloca i32, align 4
|
|
%taddr27 = alloca %any, align 8
|
|
%taddr30 = alloca i8, align 1
|
|
%taddr31 = alloca %any, align 8
|
|
store double 1.230000e+02, ptr %taddr, align 8
|
|
%0 = insertvalue %any undef, ptr %taddr, 0
|
|
%1 = insertvalue %any %0, i64 ptrtoint (ptr @"$ct.double" to i64), 1
|
|
store %any %1, ptr %taddr1, align 8
|
|
%2 = getelementptr inbounds { i64, ptr }, ptr %taddr1, i32 0, i32 0
|
|
%lo = load i64, ptr %2, align 8
|
|
%3 = getelementptr inbounds { i64, ptr }, ptr %taddr1, i32 0, i32 1
|
|
%hi = load ptr, ptr %3, align 8
|
|
call void @foo.test(i64 %lo, ptr %hi)
|
|
store i32 1, ptr %taddr2, align 4
|
|
%4 = insertvalue %any undef, ptr %taddr2, 0
|
|
%5 = insertvalue %any %4, i64 ptrtoint (ptr @"$ct.int" to i64), 1
|
|
store %any %5, ptr %taddr3, align 8
|
|
%6 = getelementptr inbounds { i64, ptr }, ptr %taddr3, i32 0, i32 0
|
|
%lo4 = load i64, ptr %6, align 8
|
|
%7 = getelementptr inbounds { i64, ptr }, ptr %taddr3, i32 0, i32 1
|
|
%hi5 = load ptr, ptr %7, align 8
|
|
call void @foo.test(i64 %lo4, ptr %hi5)
|
|
store i8 1, ptr %taddr6, align 1
|
|
%8 = insertvalue %any undef, ptr %taddr6, 0
|
|
%9 = insertvalue %any %8, i64 ptrtoint (ptr @"$ct.bool" to i64), 1
|
|
store %any %9, ptr %taddr7, align 8
|
|
%10 = getelementptr inbounds { i64, ptr }, ptr %taddr7, i32 0, i32 0
|
|
%lo8 = load i64, ptr %10, align 8
|
|
%11 = getelementptr inbounds { i64, ptr }, ptr %taddr7, i32 0, i32 1
|
|
%hi9 = load ptr, ptr %11, align 8
|
|
call void @foo.test(i64 %lo8, ptr %hi9)
|
|
store double 1.235000e+02, ptr %taddr10, align 8
|
|
%12 = insertvalue %any undef, ptr %taddr10, 0
|
|
%13 = insertvalue %any %12, i64 ptrtoint (ptr @"$ct.double" to i64), 1
|
|
store %any %13, ptr %taddr11, align 8
|
|
%14 = getelementptr inbounds { i64, ptr }, ptr %taddr11, i32 0, i32 0
|
|
%lo12 = load i64, ptr %14, align 8
|
|
%15 = getelementptr inbounds { i64, ptr }, ptr %taddr11, i32 0, i32 1
|
|
%hi13 = load ptr, ptr %15, align 8
|
|
call void @foo.test2(i64 %lo12, ptr %hi13)
|
|
store i32 1, ptr %taddr14, align 4
|
|
%16 = insertvalue %any undef, ptr %taddr14, 0
|
|
%17 = insertvalue %any %16, i64 ptrtoint (ptr @"$ct.int" to i64), 1
|
|
store %any %17, ptr %taddr15, align 8
|
|
%18 = getelementptr inbounds { i64, ptr }, ptr %taddr15, i32 0, i32 0
|
|
%lo16 = load i64, ptr %18, align 8
|
|
%19 = getelementptr inbounds { i64, ptr }, ptr %taddr15, i32 0, i32 1
|
|
%hi17 = load ptr, ptr %19, align 8
|
|
call void @foo.test2(i64 %lo16, ptr %hi17)
|
|
store i8 1, ptr %taddr18, align 1
|
|
%20 = insertvalue %any undef, ptr %taddr18, 0
|
|
%21 = insertvalue %any %20, i64 ptrtoint (ptr @"$ct.bool" to i64), 1
|
|
store %any %21, ptr %taddr19, align 8
|
|
%22 = getelementptr inbounds { i64, ptr }, ptr %taddr19, i32 0, i32 0
|
|
%lo20 = load i64, ptr %22, align 8
|
|
%23 = getelementptr inbounds { i64, ptr }, ptr %taddr19, i32 0, i32 1
|
|
%hi21 = load ptr, ptr %23, align 8
|
|
call void @foo.test2(i64 %lo20, ptr %hi21)
|
|
store double 1.240000e+02, ptr %taddr22, align 8
|
|
%24 = insertvalue %any undef, ptr %taddr22, 0
|
|
%25 = insertvalue %any %24, i64 ptrtoint (ptr @"$ct.double" to i64), 1
|
|
store %any %25, ptr %taddr23, align 8
|
|
%26 = getelementptr inbounds { i64, ptr }, ptr %taddr23, i32 0, i32 0
|
|
%lo24 = load i64, ptr %26, align 8
|
|
%27 = getelementptr inbounds { i64, ptr }, ptr %taddr23, i32 0, i32 1
|
|
%hi25 = load ptr, ptr %27, align 8
|
|
call void @foo.test3(i64 %lo24, ptr %hi25)
|
|
store i32 2, ptr %taddr26, align 4
|
|
%28 = insertvalue %any undef, ptr %taddr26, 0
|
|
%29 = insertvalue %any %28, i64 ptrtoint (ptr @"$ct.int" to i64), 1
|
|
store %any %29, ptr %taddr27, align 8
|
|
%30 = getelementptr inbounds { i64, ptr }, ptr %taddr27, i32 0, i32 0
|
|
%lo28 = load i64, ptr %30, align 8
|
|
%31 = getelementptr inbounds { i64, ptr }, ptr %taddr27, i32 0, i32 1
|
|
%hi29 = load ptr, ptr %31, align 8
|
|
call void @foo.test3(i64 %lo28, ptr %hi29)
|
|
store i8 1, ptr %taddr30, align 1
|
|
%32 = insertvalue %any undef, ptr %taddr30, 0
|
|
%33 = insertvalue %any %32, i64 ptrtoint (ptr @"$ct.bool" to i64), 1
|
|
store %any %33, ptr %taddr31, align 8
|
|
%34 = getelementptr inbounds { i64, ptr }, ptr %taddr31, i32 0, i32 0
|
|
%lo32 = load i64, ptr %34, align 8
|
|
%35 = getelementptr inbounds { i64, ptr }, ptr %taddr31, i32 0, i32 1
|
|
%hi33 = load ptr, ptr %35, align 8
|
|
call void @foo.test3(i64 %lo32, ptr %hi33)
|
|
ret i32 0
|
|
}
|