Macros generating lambdas now actually is a thing.

This commit is contained in:
Christoffer Lerno
2023-06-22 23:42:40 +02:00
parent d90fa5e292
commit 0eee9daf1d
11 changed files with 365 additions and 49 deletions

View File

@@ -0,0 +1,147 @@
// #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
; Function Attrs: nounwind
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
}
; Function Attrs: nounwind
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
}
; Function Attrs: nounwind
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
}
; Function Attrs: nounwind
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
}

View File

@@ -0,0 +1,82 @@
// #target: macos-x64
module test;
import std::io;
def Call = fn void();
fn int main()
{
var $x = 0;
$for (var $i = 0; $i < 10; $i++)
{
var $Type = int;
$if $i % 2 == 0:
$Type = double;
$endif
$if $i % 3 == 0:
$x++;
$endif;
Call x = fn () => (void)io::printfn("%d %s", $x, $Type.nameof);
x();
}
$endfor
return 0;
}
/* #expect: test.ll
@.str.1 = private unnamed_addr constant [7 x i8] c"double\00", align 1
@.str.3 = private unnamed_addr constant [4 x i8] c"int\00", align 1
@.str.5 = private unnamed_addr constant [4 x i8] c"int\00", align 1
@.str.7 = private unnamed_addr constant [7 x i8] c"double\00", align 1
@.str.9 = private unnamed_addr constant [7 x i8] c"double\00", align 1
@.str.11 = private unnamed_addr constant [4 x i8] c"int\00", align 1
@.str.13 = private unnamed_addr constant [4 x i8] c"int\00", align 1
; Function Attrs: nounwind
define i32 @main() #0 {
store ptr @"main$lambda1", ptr %x, align 8
%0 = load ptr, ptr %x, align 8
call void %0()
store ptr @"main$lambda2", ptr %x1, align 8
%1 = load ptr, ptr %x1, align 8
call void %1()
store ptr @"main$lambda1", ptr %x2, align 8
%2 = load ptr, ptr %x2, align 8
call void %2()
store ptr @"main$lambda3", ptr %x3, align 8
%3 = load ptr, ptr %x3, align 8
call void %3()
store ptr @"main$lambda4", ptr %x4, align 8
%4 = load ptr, ptr %x4, align 8
call void %4()
store ptr @"main$lambda3", ptr %x5, align 8
%5 = load ptr, ptr %x5, align 8
call void %5()
store ptr @"main$lambda5", ptr %x6, align 8
%6 = load ptr, ptr %x6, align 8
call void %6()
store ptr @"main$lambda6", ptr %x7, align 8
%7 = load ptr, ptr %x7, align 8
call void %7()
store ptr @"main$lambda5", ptr %x8, align 8
%8 = load ptr, ptr %x8, align 8
call void %8()
store ptr @"main$lambda7", ptr %x9, align 8
%9 = load ptr, ptr %x9, align 8
call void %9()
define internal void @"main$lambda1"() #0 {
store %"char[]" { ptr @.str.1, i64 6 }, ptr %taddr1, align 8
define internal void @"main$lambda2"() #0 {
store %"char[]" { ptr @.str.3, i64 3 }, ptr %taddr1, align 8
define internal void @"main$lambda3"() #0 {
store %"char[]" { ptr @.str.5, i64 3 }, ptr %taddr1, align 8
define internal void @"main$lambda4"() #0 {
store %"char[]" { ptr @.str.7, i64 6 }, ptr %taddr1, align 8
define internal void @"main$lambda5"() #0 {
store %"char[]" { ptr @.str.9, i64 6 }, ptr %taddr1, align 8
define internal void @"main$lambda6"() #0 {
store %"char[]" { ptr @.str.11, i64 3 }, ptr %taddr1, align 8
define internal void @"main$lambda7"() #0 {
store %"char[]" { ptr @.str.13, i64 3 }, ptr %taddr1, align 8

View File

@@ -29,17 +29,17 @@ fn void main()
/* #expect: test.ll
store ptr @"test.test$lambda1", ptr %z, align 8
%1 = call i32 %0(i32 3)
store ptr @"test.test$lambda2", ptr %z3, align 8
%7 = call double %6(double 3.300000e+00)
store ptr @"test.test$lambda2", ptr %z7, align 8
%13 = call double %12(double 3.300000e+00)
%18 = call i32 @"test.test2$lambda3"(i32 3)
%23 = call i32 @"test.test2$lambda3"(i32 3)
%28 = call double @"test.test2$lambda4"(double 3.300000e+00)
store ptr @"test.test$lambda1", ptr %z, align 8
%1 = call i32 %0(i32 3)
store ptr @"test.test$lambda2", ptr %z3, align 8
%7 = call double %6(double 3.300000e+00)
store ptr @"test.test$lambda2", ptr %z7, align 8
%13 = call double %12(double 3.300000e+00)
%18 = call i32 @"test.test2$lambda3"(i32 3)
%23 = call i32 @"test.test2$lambda3"(i32 3)
%28 = call double @"test.test2$lambda4"(double 3.300000e+00)
define internal double @"test.test2$lambda4"(double %0) #0 {
define internal i32 @"test.test2$lambda3"(i32 %0) #0 {
define internal double @"test.test$lambda2"(double %0) #0 {
define internal i32 @"test.test$lambda1"(i32 %0) #0 {
define internal i32 @"test.test$lambda1"(i32 %0) #0 {
define internal double @"test.test$lambda2"(double %0) #0 {
define internal i32 @"test.test2$lambda3"(i32 %0) #0 {
define internal double @"test.test2$lambda4"(double %0) #0 {

View File

@@ -54,28 +54,26 @@ declare i32 @"bar.get_callback$lambda1"()
// #expect: foo.ll
define i32 @"foo.get_callback$lambda1"() #0 {
%0 = call i32 @"bar.get_callback2$lambda2"()
define i32 @"foo.get_callback2$lambda2"() #0 {
%1 = load i32, ptr @foo.xz, align 4
define i32 @"foo.get_callback$lambda1"() #0 {
%0 = call i32 @"bar.get_callback2$lambda2"()
declare i32 @"bar.get_callback2$lambda2"()
// #expect: bar.ll
define i32 @"bar.get_callback$lambda1"() #0 {
entry:
%0 = call i32 @"foo.get_callback$lambda1"()
ret i32 %0
}
define i32 @"bar.get_callback2$lambda2"() #0 {
entry:
%0 = call i32 @"foo.get_callback2$lambda2"()
ret i32 %0
}
define i32 @"bar.get_callback$lambda1"() #0 {
entry:
%0 = call i32 @"foo.get_callback$lambda1"()
ret i32 %0
declare i32 @"foo.get_callback$lambda1"()
declare i32 @"foo.get_callback2$lambda2"()
declare i32 @"foo.get_callback2$lambda2"() #0
declare i32 @"foo.get_callback$lambda1"() #0

View File

@@ -25,5 +25,9 @@ entry:
%0 = call i32 @simple_lambda.xy(ptr @"simple_lambda.main$lambda1")
%5 = call i32 @simple_lambda.xy(ptr @"simple_lambda.main$lambda2")
define internal i32 @"simple_lambda.main$lambda1"() #0 {
define internal i32 @"simple_lambda.main$lambda2"() #0 {
define internal i32 @"simple_lambda.main$lambda1"() #0 {
entry:
ret i32 3
}