mirror of
https://github.com/c3lang/c3c.git
synced 2026-02-27 12:01:16 +00:00
367 lines
14 KiB
C
367 lines
14 KiB
C
// #target: macos-x64
|
|
module foo;
|
|
extern fn void printf(char*, ...);
|
|
|
|
fn void test(any x)
|
|
{
|
|
switch (x.type)
|
|
{
|
|
case int:
|
|
printf("Was int\n");
|
|
case double:
|
|
printf("Was double\n");
|
|
case any:
|
|
printf("Was variant\n");
|
|
case int*:
|
|
printf("Was int*\n");
|
|
default:
|
|
printf("Unknown type\n");
|
|
}
|
|
}
|
|
|
|
fn void test_all(any... y)
|
|
{
|
|
foreach (element : y)
|
|
{
|
|
test(element);
|
|
}
|
|
}
|
|
|
|
fn void main()
|
|
{
|
|
any x = &&1;
|
|
int z;
|
|
any y = &z;
|
|
typeid g = y.type;
|
|
typeid h = x.type;
|
|
if (y.type == int.typeid)
|
|
{
|
|
printf("y int match\n");
|
|
}
|
|
if (x.type == int.typeid)
|
|
{
|
|
printf("x int match\n");
|
|
}
|
|
y = &&1.0;
|
|
x = &x;
|
|
if (y.type == int.typeid)
|
|
{
|
|
printf("y int match\n");
|
|
}
|
|
if (x.type == int.typeid)
|
|
{
|
|
printf("x int match\n");
|
|
}
|
|
test(x);
|
|
test(&&1.0);
|
|
test(&&1);
|
|
test(&&true);
|
|
printf("----\n");
|
|
int* df = null;
|
|
test_all(x, x, &&1.0, &x, &df);
|
|
}
|
|
|
|
/* #expect: foo.ll
|
|
|
|
%any = type { ptr, i64 }
|
|
%"any[]" = type { ptr, i64 }
|
|
|
|
@"$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.any" = linkonce global %.introspect { i8 7, i64 0, ptr null, i64 16, i64 0, i64 0, [0 x i64] zeroinitializer }, align 8
|
|
@"$ct.p$int" = linkonce global %.introspect { i8 19, i64 0, ptr null, i64 8, i64 ptrtoint (ptr @"$ct.int" to i64), 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:
|
|
%x = alloca %any, align 8
|
|
%switch = alloca i64, align 8
|
|
store i64 %0, ptr %x, align 8
|
|
%ptroffset = getelementptr inbounds ptr, ptr %x, i64 1
|
|
store ptr %1, ptr %ptroffset, align 8
|
|
%2 = getelementptr inbounds %any, ptr %x, 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
|
|
call void (ptr, ...) @printf(ptr @.str)
|
|
br label %switch.exit
|
|
|
|
next_if: ; preds = %result_block
|
|
br label %check_subtype1
|
|
|
|
check_subtype1: ; preds = %parent_type_block3, %next_if
|
|
%10 = phi i64 [ %4, %next_if ], [ %typeid.parent4, %parent_type_block3 ]
|
|
%eq2 = icmp eq i64 ptrtoint (ptr @"$ct.double" to i64), %10
|
|
br i1 %eq2, label %result_block5, label %parent_type_block3
|
|
|
|
parent_type_block3: ; preds = %check_subtype1
|
|
%11 = inttoptr i64 %10 to ptr
|
|
%12 = getelementptr inbounds %.introspect, ptr %11, i32 0, i32 1
|
|
%typeid.parent4 = load i64, ptr %12, align 8
|
|
%13 = icmp eq i64 %typeid.parent4, 0
|
|
br i1 %13, label %result_block5, label %check_subtype1
|
|
|
|
result_block5: ; preds = %parent_type_block3, %check_subtype1
|
|
%14 = phi i1 [ false, %parent_type_block3 ], [ true, %check_subtype1 ]
|
|
br i1 %14, label %switch.case6, label %next_if7
|
|
|
|
switch.case6: ; preds = %result_block5
|
|
call void (ptr, ...) @printf(ptr @.str.1)
|
|
br label %switch.exit
|
|
|
|
next_if7: ; preds = %result_block5
|
|
br label %check_subtype8
|
|
|
|
check_subtype8: ; preds = %parent_type_block10, %next_if7
|
|
%15 = phi i64 [ %4, %next_if7 ], [ %typeid.parent11, %parent_type_block10 ]
|
|
%eq9 = icmp eq i64 ptrtoint (ptr @"$ct.any" to i64), %15
|
|
br i1 %eq9, label %result_block12, label %parent_type_block10
|
|
|
|
parent_type_block10: ; preds = %check_subtype8
|
|
%16 = inttoptr i64 %15 to ptr
|
|
%17 = getelementptr inbounds %.introspect, ptr %16, i32 0, i32 1
|
|
%typeid.parent11 = load i64, ptr %17, align 8
|
|
%18 = icmp eq i64 %typeid.parent11, 0
|
|
br i1 %18, label %result_block12, label %check_subtype8
|
|
|
|
result_block12: ; preds = %parent_type_block10, %check_subtype8
|
|
%19 = phi i1 [ false, %parent_type_block10 ], [ true, %check_subtype8 ]
|
|
br i1 %19, label %switch.case13, label %next_if14
|
|
|
|
switch.case13: ; preds = %result_block12
|
|
call void (ptr, ...) @printf(ptr @.str.2)
|
|
br label %switch.exit
|
|
|
|
next_if14: ; preds = %result_block12
|
|
br label %check_subtype15
|
|
|
|
check_subtype15: ; preds = %parent_type_block17, %next_if14
|
|
%20 = phi i64 [ %4, %next_if14 ], [ %typeid.parent18, %parent_type_block17 ]
|
|
%eq16 = icmp eq i64 ptrtoint (ptr @"$ct.p$int" to i64), %20
|
|
br i1 %eq16, label %result_block19, label %parent_type_block17
|
|
|
|
parent_type_block17: ; preds = %check_subtype15
|
|
%21 = inttoptr i64 %20 to ptr
|
|
%22 = getelementptr inbounds %.introspect, ptr %21, i32 0, i32 1
|
|
%typeid.parent18 = load i64, ptr %22, align 8
|
|
%23 = icmp eq i64 %typeid.parent18, 0
|
|
br i1 %23, label %result_block19, label %check_subtype15
|
|
|
|
result_block19: ; preds = %parent_type_block17, %check_subtype15
|
|
%24 = phi i1 [ false, %parent_type_block17 ], [ true, %check_subtype15 ]
|
|
br i1 %24, label %switch.case20, label %next_if21
|
|
|
|
switch.case20: ; preds = %result_block19
|
|
call void (ptr, ...) @printf(ptr @.str.3)
|
|
br label %switch.exit
|
|
|
|
next_if21: ; preds = %result_block19
|
|
br label %switch.default
|
|
|
|
switch.default: ; preds = %next_if21
|
|
call void (ptr, ...) @printf(ptr @.str.4)
|
|
br label %switch.exit
|
|
|
|
switch.exit: ; preds = %switch.default, %switch.case20, %switch.case13, %switch.case6, %switch.case
|
|
ret void
|
|
}
|
|
|
|
; Function Attrs: nounwind
|
|
define void @foo.test_all(ptr %0, i64 %1) #0 {
|
|
entry:
|
|
%y = alloca %"any[]", align 8
|
|
%.anon = alloca i64, align 8
|
|
%.anon1 = alloca i64, align 8
|
|
%element = alloca %any, align 8
|
|
store ptr %0, ptr %y, align 8
|
|
%ptroffset = getelementptr inbounds i64, ptr %y, i64 1
|
|
store i64 %1, ptr %ptroffset, align 8
|
|
%2 = getelementptr inbounds %"any[]", ptr %y, i32 0, i32 1
|
|
%3 = load i64, ptr %2, align 8
|
|
store i64 %3, ptr %.anon, align 8
|
|
store i64 0, ptr %.anon1, align 8
|
|
br label %loop.cond
|
|
|
|
loop.cond: ; preds = %loop.body, %entry
|
|
%4 = load i64, ptr %.anon1, align 8
|
|
%5 = load i64, ptr %.anon, align 8
|
|
%lt = icmp ult i64 %4, %5
|
|
br i1 %lt, label %loop.body, label %loop.exit
|
|
|
|
loop.body: ; preds = %loop.cond
|
|
%6 = getelementptr inbounds %"any[]", ptr %y, i32 0, i32 0
|
|
%7 = load ptr, ptr %6, align 8
|
|
%8 = load i64, ptr %.anon1, align 8
|
|
%ptroffset2 = getelementptr inbounds %any, ptr %7, i64 %8
|
|
call void @llvm.memcpy.p0.p0.i32(ptr align 8 %element, ptr align 8 %ptroffset2, i32 16, i1 false)
|
|
%9 = getelementptr inbounds { i64, ptr }, ptr %element, i32 0, i32 0
|
|
%lo = load i64, ptr %9, align 8
|
|
%10 = getelementptr inbounds { i64, ptr }, ptr %element, i32 0, i32 1
|
|
%hi = load ptr, ptr %10, align 8
|
|
call void @foo.test(i64 %lo, ptr %hi)
|
|
%11 = load i64, ptr %.anon1, align 8
|
|
%add = add i64 %11, 1
|
|
store i64 %add, ptr %.anon1, align 8
|
|
br label %loop.cond
|
|
|
|
loop.exit: ; preds = %loop.cond
|
|
ret void
|
|
}
|
|
|
|
; Function Attrs: nounwind
|
|
define void @foo.main() #0 {
|
|
entry:
|
|
%x = alloca %any, align 8
|
|
%taddr = alloca i32, align 4
|
|
%z = alloca i32, align 4
|
|
%y = alloca %any, align 8
|
|
%g = alloca i64, align 8
|
|
%h = alloca i64, align 8
|
|
%taddr4 = alloca double, align 8
|
|
%taddr11 = alloca double, align 8
|
|
%taddr12 = alloca %any, align 8
|
|
%taddr15 = alloca i32, align 4
|
|
%taddr16 = alloca %any, align 8
|
|
%taddr19 = alloca i8, align 1
|
|
%taddr20 = alloca %any, align 8
|
|
%df = alloca ptr, align 8
|
|
%varargslots = alloca [5 x %any], align 16
|
|
%taddr23 = alloca double, align 8
|
|
store i32 1, ptr %taddr, align 4
|
|
%0 = insertvalue %any undef, ptr %taddr, 0
|
|
%1 = insertvalue %any %0, i64 ptrtoint (ptr @"$ct.int" to i64), 1
|
|
store %any %1, ptr %x, align 8
|
|
store i32 0, ptr %z, align 4
|
|
%2 = insertvalue %any undef, ptr %z, 0
|
|
%3 = insertvalue %any %2, i64 ptrtoint (ptr @"$ct.int" to i64), 1
|
|
store %any %3, ptr %y, align 8
|
|
%4 = getelementptr inbounds %any, ptr %y, i32 0, i32 1
|
|
%5 = load i64, ptr %4, align 8
|
|
store i64 %5, ptr %g, align 8
|
|
%6 = getelementptr inbounds %any, ptr %x, i32 0, i32 1
|
|
%7 = load i64, ptr %6, align 8
|
|
store i64 %7, ptr %h, align 8
|
|
%8 = getelementptr inbounds %any, ptr %y, i32 0, i32 1
|
|
%9 = load i64, ptr %8, align 8
|
|
%eq = icmp eq i64 %9, ptrtoint (ptr @"$ct.int" to i64)
|
|
br i1 %eq, label %if.then, label %if.exit
|
|
|
|
if.then: ; preds = %entry
|
|
call void (ptr, ...) @printf(ptr @.str.5)
|
|
br label %if.exit
|
|
|
|
if.exit: ; preds = %if.then, %entry
|
|
%10 = getelementptr inbounds %any, ptr %x, i32 0, i32 1
|
|
%11 = load i64, ptr %10, align 8
|
|
%eq1 = icmp eq i64 %11, ptrtoint (ptr @"$ct.int" to i64)
|
|
br i1 %eq1, label %if.then2, label %if.exit3
|
|
|
|
if.then2: ; preds = %if.exit
|
|
call void (ptr, ...) @printf(ptr @.str.6)
|
|
br label %if.exit3
|
|
|
|
if.exit3: ; preds = %if.then2, %if.exit
|
|
store double 1.000000e+00, ptr %taddr4, align 8
|
|
%12 = insertvalue %any undef, ptr %taddr4, 0
|
|
%13 = insertvalue %any %12, i64 ptrtoint (ptr @"$ct.double" to i64), 1
|
|
store %any %13, ptr %y, align 8
|
|
%14 = insertvalue %any undef, ptr %x, 0
|
|
%15 = insertvalue %any %14, i64 ptrtoint (ptr @"$ct.any" to i64), 1
|
|
store %any %15, ptr %x, align 8
|
|
%16 = getelementptr inbounds %any, ptr %y, i32 0, i32 1
|
|
%17 = load i64, ptr %16, align 8
|
|
%eq5 = icmp eq i64 %17, ptrtoint (ptr @"$ct.int" to i64)
|
|
br i1 %eq5, label %if.then6, label %if.exit7
|
|
|
|
if.then6: ; preds = %if.exit3
|
|
call void (ptr, ...) @printf(ptr @.str.7)
|
|
br label %if.exit7
|
|
|
|
if.exit7: ; preds = %if.then6, %if.exit3
|
|
%18 = getelementptr inbounds %any, ptr %x, i32 0, i32 1
|
|
%19 = load i64, ptr %18, align 8
|
|
%eq8 = icmp eq i64 %19, ptrtoint (ptr @"$ct.int" to i64)
|
|
br i1 %eq8, label %if.then9, label %if.exit10
|
|
|
|
if.then9: ; preds = %if.exit7
|
|
call void (ptr, ...) @printf(ptr @.str.8)
|
|
br label %if.exit10
|
|
|
|
if.exit10: ; preds = %if.then9, %if.exit7
|
|
%20 = getelementptr inbounds { i64, ptr }, ptr %x, i32 0, i32 0
|
|
%lo = load i64, ptr %20, align 8
|
|
%21 = getelementptr inbounds { i64, ptr }, ptr %x, i32 0, i32 1
|
|
%hi = load ptr, ptr %21, align 8
|
|
call void @foo.test(i64 %lo, ptr %hi)
|
|
store double 1.000000e+00, ptr %taddr11, align 8
|
|
%22 = insertvalue %any undef, ptr %taddr11, 0
|
|
%23 = insertvalue %any %22, i64 ptrtoint (ptr @"$ct.double" to i64), 1
|
|
store %any %23, ptr %taddr12, align 8
|
|
%24 = getelementptr inbounds { i64, ptr }, ptr %taddr12, i32 0, i32 0
|
|
%lo13 = load i64, ptr %24, align 8
|
|
%25 = getelementptr inbounds { i64, ptr }, ptr %taddr12, i32 0, i32 1
|
|
%hi14 = load ptr, ptr %25, align 8
|
|
call void @foo.test(i64 %lo13, ptr %hi14)
|
|
store i32 1, ptr %taddr15, align 4
|
|
%26 = insertvalue %any undef, ptr %taddr15, 0
|
|
%27 = insertvalue %any %26, i64 ptrtoint (ptr @"$ct.int" to i64), 1
|
|
store %any %27, ptr %taddr16, align 8
|
|
%28 = getelementptr inbounds { i64, ptr }, ptr %taddr16, i32 0, i32 0
|
|
%lo17 = load i64, ptr %28, align 8
|
|
%29 = getelementptr inbounds { i64, ptr }, ptr %taddr16, i32 0, i32 1
|
|
%hi18 = load ptr, ptr %29, align 8
|
|
call void @foo.test(i64 %lo17, ptr %hi18)
|
|
store i8 1, ptr %taddr19, align 1
|
|
%30 = insertvalue %any undef, ptr %taddr19, 0
|
|
%31 = insertvalue %any %30, i64 ptrtoint (ptr @"$ct.bool" to i64), 1
|
|
store %any %31, ptr %taddr20, align 8
|
|
%32 = getelementptr inbounds { i64, ptr }, ptr %taddr20, i32 0, i32 0
|
|
%lo21 = load i64, ptr %32, align 8
|
|
%33 = getelementptr inbounds { i64, ptr }, ptr %taddr20, i32 0, i32 1
|
|
%hi22 = load ptr, ptr %33, align 8
|
|
call void @foo.test(i64 %lo21, ptr %hi22)
|
|
call void (ptr, ...) @printf(ptr @.str.9)
|
|
store ptr null, ptr %df, align 8
|
|
%34 = getelementptr inbounds [5 x %any], ptr %varargslots, i64 0, i64 0
|
|
call void @llvm.memcpy.p0.p0.i32(ptr align 16 %34, ptr align 8 %x, i32 16, i1 false)
|
|
%35 = getelementptr inbounds [5 x %any], ptr %varargslots, i64 0, i64 1
|
|
call void @llvm.memcpy.p0.p0.i32(ptr align 16 %35, ptr align 8 %x, i32 16, i1 false)
|
|
store double 1.000000e+00, ptr %taddr23, align 8
|
|
%36 = insertvalue %any undef, ptr %taddr23, 0
|
|
%37 = insertvalue %any %36, i64 ptrtoint (ptr @"$ct.double" to i64), 1
|
|
%38 = getelementptr inbounds [5 x %any], ptr %varargslots, i64 0, i64 2
|
|
store %any %37, ptr %38, align 16
|
|
%39 = insertvalue %any undef, ptr %x, 0
|
|
%40 = insertvalue %any %39, i64 ptrtoint (ptr @"$ct.any" to i64), 1
|
|
%41 = getelementptr inbounds [5 x %any], ptr %varargslots, i64 0, i64 3
|
|
store %any %40, ptr %41, align 16
|
|
%42 = insertvalue %any undef, ptr %df, 0
|
|
%43 = insertvalue %any %42, i64 ptrtoint (ptr @"$ct.p$int" to i64), 1
|
|
%44 = getelementptr inbounds [5 x %any], ptr %varargslots, i64 0, i64 4
|
|
store %any %43, ptr %44, align 16
|
|
call void @foo.test_all(ptr %varargslots, i64 5)
|
|
ret void
|
|
}
|