nac3core: impl call attributes #217

Merged
sb10q merged 1 commits from call-attributes into master 2022-03-09 22:25:29 +08:00
Contributor

Implemented sret for returning large structs, and byval for struct args in extern
function calls.

Closes #151

Tests: I'm not sure what is the best way to write the test for nac3artiq, but here is the test case I've tested with:

from min_artiq import *
from numpy import int32, int64

@extern
def return_tuple(a: tuple[int32, int32]) -> tuple[int32, int32, int32]:
    ...

@nac3
class Demo:
    core: KernelInvariant[Core]
    def __init__(self):
        self.core = Core()

    @kernel
    def run(self):
        return_tuple((1, 2))

if __name__ == "__main__":
    Demo().run()

LLVM IR:

; ModuleID = 'main'
source_filename = "main"

%min_artiq.Core = type { double }
%min_artiq.TTLOut = type { %min_artiq.Core*, i32, i32 }
%__main__.Demo = type { %min_artiq.Core*, %min_artiq.TTLOut*, %min_artiq.TTLOut* }

@"140115763407984" = global %min_artiq.Core { double 1.000000e-09 }
@"140115763408176" = global %min_artiq.TTLOut { %min_artiq.Core* @"140115763407984", i32 18, i32 4608 }
@"140115763407840" = global %min_artiq.TTLOut { %min_artiq.Core* @"140115763407984", i32 19, i32 4864 }
@"140115763408512" = local_unnamed_addr global %__main__.Demo { %min_artiq.Core* @"140115763407984", %min_artiq.TTLOut* @"140115763408176", %min_artiq.TTLOut* @"140115763407840" }

declare i32 @__nac3_personality(...)

declare void @return_tuple({ i32, i32, i32 }* sret({ i32, i32, i32 }) %0, { i32, i32 }* byval({ i32, i32 }) %1) local_unnamed_addr

define void @__modinit__() local_unnamed_addr personality i32 (...)* @__nac3_personality {
init:
  %call.i = alloca { i32, i32, i32 }, align 8
  %call2.i = alloca { i32, i32 }, align 8
  %0 = bitcast { i32, i32, i32 }* %call.i to i8*
  call void @llvm.lifetime.start.p0i8(i64 12, i8* nonnull %0)
  %1 = bitcast { i32, i32 }* %call2.i to i8*
  call void @llvm.lifetime.start.p0i8(i64 8, i8* nonnull %1)
  %tup_val.fca.0.gep.i = getelementptr inbounds { i32, i32 }, { i32, i32 }* %call2.i, i64 0, i32 0
  store i32 1, i32* %tup_val.fca.0.gep.i, align 8
  %tup_val.fca.1.gep.i = getelementptr inbounds { i32, i32 }, { i32, i32 }* %call2.i, i64 0, i32 1
  store i32 2, i32* %tup_val.fca.1.gep.i, align 4
  call void @return_tuple({ i32, i32, i32 }* nonnull sret({ i32, i32, i32 }) %call.i, { i32, i32 }* nonnull byval({ i32, i32 }) %call2.i)
  call void @llvm.lifetime.end.p0i8(i64 12, i8* nonnull %0)
  call void @llvm.lifetime.end.p0i8(i64 8, i8* nonnull %1)
  ret void
}

; Function Attrs: argmemonly nofree nosync nounwind willreturn
declare void @llvm.lifetime.start.p0i8(i64 immarg %0, i8* nocapture %1) #0

; Function Attrs: argmemonly nofree nosync nounwind willreturn
declare void @llvm.lifetime.end.p0i8(i64 immarg %0, i8* nocapture %1) #0

attributes #0 = { argmemonly nofree nosync nounwind willreturn }
Implemented sret for returning large structs, and byval for struct args in extern function calls. Closes #151 Tests: I'm not sure what is the best way to write the test for nac3artiq, but here is the test case I've tested with: ```python from min_artiq import * from numpy import int32, int64 @extern def return_tuple(a: tuple[int32, int32]) -> tuple[int32, int32, int32]: ... @nac3 class Demo: core: KernelInvariant[Core] def __init__(self): self.core = Core() @kernel def run(self): return_tuple((1, 2)) if __name__ == "__main__": Demo().run() ``` LLVM IR: ``` ; ModuleID = 'main' source_filename = "main" %min_artiq.Core = type { double } %min_artiq.TTLOut = type { %min_artiq.Core*, i32, i32 } %__main__.Demo = type { %min_artiq.Core*, %min_artiq.TTLOut*, %min_artiq.TTLOut* } @"140115763407984" = global %min_artiq.Core { double 1.000000e-09 } @"140115763408176" = global %min_artiq.TTLOut { %min_artiq.Core* @"140115763407984", i32 18, i32 4608 } @"140115763407840" = global %min_artiq.TTLOut { %min_artiq.Core* @"140115763407984", i32 19, i32 4864 } @"140115763408512" = local_unnamed_addr global %__main__.Demo { %min_artiq.Core* @"140115763407984", %min_artiq.TTLOut* @"140115763408176", %min_artiq.TTLOut* @"140115763407840" } declare i32 @__nac3_personality(...) declare void @return_tuple({ i32, i32, i32 }* sret({ i32, i32, i32 }) %0, { i32, i32 }* byval({ i32, i32 }) %1) local_unnamed_addr define void @__modinit__() local_unnamed_addr personality i32 (...)* @__nac3_personality { init: %call.i = alloca { i32, i32, i32 }, align 8 %call2.i = alloca { i32, i32 }, align 8 %0 = bitcast { i32, i32, i32 }* %call.i to i8* call void @llvm.lifetime.start.p0i8(i64 12, i8* nonnull %0) %1 = bitcast { i32, i32 }* %call2.i to i8* call void @llvm.lifetime.start.p0i8(i64 8, i8* nonnull %1) %tup_val.fca.0.gep.i = getelementptr inbounds { i32, i32 }, { i32, i32 }* %call2.i, i64 0, i32 0 store i32 1, i32* %tup_val.fca.0.gep.i, align 8 %tup_val.fca.1.gep.i = getelementptr inbounds { i32, i32 }, { i32, i32 }* %call2.i, i64 0, i32 1 store i32 2, i32* %tup_val.fca.1.gep.i, align 4 call void @return_tuple({ i32, i32, i32 }* nonnull sret({ i32, i32, i32 }) %call.i, { i32, i32 }* nonnull byval({ i32, i32 }) %call2.i) call void @llvm.lifetime.end.p0i8(i64 12, i8* nonnull %0) call void @llvm.lifetime.end.p0i8(i64 8, i8* nonnull %1) ret void } ; Function Attrs: argmemonly nofree nosync nounwind willreturn declare void @llvm.lifetime.start.p0i8(i64 immarg %0, i8* nocapture %1) #0 ; Function Attrs: argmemonly nofree nosync nounwind willreturn declare void @llvm.lifetime.end.p0i8(i64 immarg %0, i8* nocapture %1) #0 attributes #0 = { argmemonly nofree nosync nounwind willreturn } ```
pca006132 added 1 commit 2022-03-09 22:13:51 +08:00
2f85bb3837 nac3core: impl call attributes
sret for returning large structs, and byval for struct args in extern
function calls.
Owner

byval for struct args in extern

This will need updating the artiq firmware, artiq-zynq, and the legacy compiler, correct?

> byval for struct args in extern This will need updating the artiq firmware, artiq-zynq, and the legacy compiler, correct?
Author
Contributor

byval for struct args in extern

This will need updating the artiq firmware, artiq-zynq, and the legacy compiler, correct?

No. The one that needs this update is #187

> > byval for struct args in extern > > This will need updating the artiq firmware, artiq-zynq, and the legacy compiler, correct? No. The one that needs this update is #187
sb10q merged commit 2f85bb3837 into master 2022-03-09 22:25:29 +08:00
sb10q deleted branch call-attributes 2022-03-09 22:25:29 +08:00
Sign in to join this conversation.
No reviewers
No Milestone
No Assignees
2 Participants
Notifications
Due Date
The due date is invalid or out of range. Please use the format 'yyyy-mm-dd'.

No due date set.

Dependencies

No dependencies set.

Reference: M-Labs/nac3#217
No description provided.