mirror of
https://github.com/c3lang/c3c.git
synced 2026-02-27 20:11:17 +00:00
144 lines
2.7 KiB
C
144 lines
2.7 KiB
C
// #target: macos-x64
|
|
module test;
|
|
import std::io;
|
|
|
|
def FooFn = fn void(Foo* f, int x);
|
|
|
|
struct Foo
|
|
{
|
|
FooFn x;
|
|
}
|
|
|
|
struct FooTest
|
|
{
|
|
inline Foo a;
|
|
}
|
|
|
|
struct FooTest2
|
|
{
|
|
inline Foo a;
|
|
int z;
|
|
}
|
|
|
|
fn void Foo.test(Foo* f, int x)
|
|
{
|
|
f.x(f, x);
|
|
}
|
|
|
|
fn void FooTest.init(FooTest* this)
|
|
{
|
|
static FooFn foo = foo_fn(FooTest);
|
|
this.x = foo;
|
|
}
|
|
|
|
fn void FooTest.high(FooTest* t, int x)
|
|
{
|
|
io::printfn("High: %d", x);
|
|
}
|
|
|
|
fn void FooTest.low(FooTest* t, int x)
|
|
{
|
|
io::printfn("Low: %d", x);
|
|
}
|
|
|
|
fn void FooTest2.init(FooTest2* this, int z)
|
|
{
|
|
static FooFn foo = foo_fn(FooTest2);
|
|
this.x = foo;
|
|
this.z = z;
|
|
}
|
|
|
|
fn void FooTest2.high(FooTest2* t, int x)
|
|
{
|
|
io::printfn("High2: %d", x * t.z);
|
|
}
|
|
|
|
fn void FooTest2.low(FooTest2* t, int x)
|
|
{
|
|
io::printfn("Low2: %d", x * t.z);
|
|
}
|
|
|
|
macro FooFn foo_fn($FooType)
|
|
{
|
|
return fn void(Foo* f, int x) {
|
|
$FooType* z = ($FooType*)f;
|
|
if (x > 0) return z.high(x);
|
|
return z.low(x);
|
|
};
|
|
}
|
|
|
|
fn int main()
|
|
{
|
|
FooTest a;
|
|
a.init();
|
|
a.test(10);
|
|
a.test(0);
|
|
a.test(-1);
|
|
FooTest2 b;
|
|
b.init(100);
|
|
b.test(10);
|
|
b.test(0);
|
|
b.test(-1);
|
|
return 0;
|
|
}
|
|
|
|
/* #expect: test.ll
|
|
|
|
@init.foo = internal unnamed_addr global ptr @"test.$global$lambda1", align 8
|
|
@init.foo.2 = internal unnamed_addr global ptr @"test.$global$lambda2", align 8
|
|
|
|
|
|
define void @test.Foo.test(ptr %0, i32 %1) #0 {
|
|
entry:
|
|
%2 = getelementptr inbounds %Foo, ptr %0, i32 0, i32 0
|
|
%3 = load ptr, ptr %2, align 8
|
|
call void %3(ptr %0, i32 %1)
|
|
ret void
|
|
}
|
|
|
|
|
|
define void @test.FooTest.init(ptr %0) #0 {
|
|
entry:
|
|
%1 = getelementptr inbounds %FooTest, ptr %0, i32 0, i32 0
|
|
%2 = getelementptr inbounds %Foo, ptr %1, i32 0, i32 0
|
|
%3 = load ptr, ptr @init.foo, align 8
|
|
store ptr %3, ptr %2, align 8
|
|
ret void
|
|
}
|
|
|
|
define internal void @"test.$global$lambda1"(ptr %0, i32 %1) #0 {
|
|
entry:
|
|
%z = alloca ptr, align 8
|
|
store ptr %0, ptr %z, align 8
|
|
%gt = icmp sgt i32 %1, 0
|
|
br i1 %gt, label %if.then, label %if.exit
|
|
|
|
if.then: ; preds = %entry
|
|
%2 = load ptr, ptr %z, align 8
|
|
call void @test.FooTest.high(ptr %2, i32 %1)
|
|
ret void
|
|
|
|
if.exit: ; preds = %entry
|
|
%3 = load ptr, ptr %z, align 8
|
|
call void @test.FooTest.low(ptr %3, i32 %1)
|
|
ret void
|
|
}
|
|
|
|
|
|
define internal void @"test.$global$lambda2"(ptr %0, i32 %1) #0 {
|
|
entry:
|
|
%z = alloca ptr, align 8
|
|
store ptr %0, ptr %z, align 8
|
|
%gt = icmp sgt i32 %1, 0
|
|
br i1 %gt, label %if.then, label %if.exit
|
|
|
|
if.then: ; preds = %entry
|
|
%2 = load ptr, ptr %z, align 8
|
|
call void @test.FooTest2.high(ptr %2, i32 %1)
|
|
ret void
|
|
|
|
if.exit: ; preds = %entry
|
|
%3 = load ptr, ptr %z, align 8
|
|
call void @test.FooTest2.low(ptr %3, i32 %1)
|
|
ret void
|
|
}
|