compiler, runtime: add layout parameter to runtime.alloc

This layout parameter is currently always nil and ignored, but will
eventually contain a pointer to a memory layout.

This commit also adds module verification to the transform tests, as I
found out that it didn't (and therefore didn't initially catch all
bugs).
Этот коммит содержится в:
Ayke van Laethem 2021-07-09 14:01:37 +02:00 коммит произвёл Ron Evans
родитель c454568688
коммит f24a93c51d
38 изменённых файлов: 99 добавлений и 89 удалений

Просмотреть файл

@ -1524,7 +1524,8 @@ func (b *builder) createExpr(expr ssa.Value) (llvm.Value, error) {
return llvm.Value{}, b.makeError(expr.Pos(), fmt.Sprintf("value is too big (%v bytes)", size)) return llvm.Value{}, b.makeError(expr.Pos(), fmt.Sprintf("value is too big (%v bytes)", size))
} }
sizeValue := llvm.ConstInt(b.uintptrType, size, false) sizeValue := llvm.ConstInt(b.uintptrType, size, false)
buf := b.createRuntimeCall("alloc", []llvm.Value{sizeValue}, expr.Comment) nilPtr := llvm.ConstNull(b.i8ptrType)
buf := b.createRuntimeCall("alloc", []llvm.Value{sizeValue, nilPtr}, expr.Comment)
buf = b.CreateBitCast(buf, llvm.PointerType(typ, 0), "") buf = b.CreateBitCast(buf, llvm.PointerType(typ, 0), "")
return buf, nil return buf, nil
} else { } else {
@ -1736,7 +1737,8 @@ func (b *builder) createExpr(expr ssa.Value) (llvm.Value, error) {
return llvm.Value{}, err return llvm.Value{}, err
} }
sliceSize := b.CreateBinOp(llvm.Mul, elemSizeValue, sliceCapCast, "makeslice.cap") sliceSize := b.CreateBinOp(llvm.Mul, elemSizeValue, sliceCapCast, "makeslice.cap")
slicePtr := b.createRuntimeCall("alloc", []llvm.Value{sliceSize}, "makeslice.buf") nilPtr := llvm.ConstNull(b.i8ptrType)
slicePtr := b.createRuntimeCall("alloc", []llvm.Value{sliceSize, nilPtr}, "makeslice.buf")
slicePtr = b.CreateBitCast(slicePtr, llvm.PointerType(llvmElemType, 0), "makeslice.array") slicePtr = b.CreateBitCast(slicePtr, llvm.PointerType(llvmElemType, 0), "makeslice.array")
// Extend or truncate if necessary. This is safe as we've already done // Extend or truncate if necessary. This is safe as we've already done

Просмотреть файл

@ -217,7 +217,8 @@ func (b *builder) createDefer(instr *ssa.Defer) {
// This may be hit a variable number of times, so use a heap allocation. // This may be hit a variable number of times, so use a heap allocation.
size := b.targetData.TypeAllocSize(deferFrameType) size := b.targetData.TypeAllocSize(deferFrameType)
sizeValue := llvm.ConstInt(b.uintptrType, size, false) sizeValue := llvm.ConstInt(b.uintptrType, size, false)
allocCall := b.createRuntimeCall("alloc", []llvm.Value{sizeValue}, "defer.alloc.call") nilPtr := llvm.ConstNull(b.i8ptrType)
allocCall := b.createRuntimeCall("alloc", []llvm.Value{sizeValue, nilPtr}, "defer.alloc.call")
alloca = b.CreateBitCast(allocCall, llvm.PointerType(deferFrameType, 0), "defer.alloc") alloca = b.CreateBitCast(allocCall, llvm.PointerType(deferFrameType, 0), "defer.alloc")
} }
if b.NeedsStackObjects { if b.NeedsStackObjects {

Просмотреть файл

@ -97,6 +97,7 @@ func EmitPointerPack(builder llvm.Builder, mod llvm.Module, needsStackObjects bo
alloc := mod.NamedFunction("runtime.alloc") alloc := mod.NamedFunction("runtime.alloc")
packedHeapAlloc := builder.CreateCall(alloc, []llvm.Value{ packedHeapAlloc := builder.CreateCall(alloc, []llvm.Value{
sizeValue, sizeValue,
llvm.ConstNull(i8ptrType),
llvm.Undef(i8ptrType), // unused context parameter llvm.Undef(i8ptrType), // unused context parameter
llvm.ConstPointerNull(i8ptrType), // coroutine handle llvm.ConstPointerNull(i8ptrType), // coroutine handle
}, "") }, "")

2
compiler/testdata/basic.ll предоставленный
Просмотреть файл

@ -6,7 +6,7 @@ target triple = "wasm32-unknown-wasi"
%main.kv = type { float } %main.kv = type { float }
%main.kv.0 = type { i8 } %main.kv.0 = type { i8 }
declare noalias nonnull i8* @runtime.alloc(i32, i8*, i8*) declare noalias nonnull i8* @runtime.alloc(i32, i8*, i8*, i8*)
; Function Attrs: nounwind ; Function Attrs: nounwind
define hidden void @main.init(i8* %context, i8* %parentHandle) unnamed_addr #0 { define hidden void @main.init(i8* %context, i8* %parentHandle) unnamed_addr #0 {

2
compiler/testdata/channel.ll предоставленный
Просмотреть файл

@ -9,7 +9,7 @@ target triple = "wasm32-unknown-wasi"
%"internal/task.state" = type { i8* } %"internal/task.state" = type { i8* }
%runtime.chanSelectState = type { %runtime.channel*, i8* } %runtime.chanSelectState = type { %runtime.channel*, i8* }
declare noalias nonnull i8* @runtime.alloc(i32, i8*, i8*) declare noalias nonnull i8* @runtime.alloc(i32, i8*, i8*, i8*)
; Function Attrs: nounwind ; Function Attrs: nounwind
define hidden void @main.init(i8* %context, i8* %parentHandle) unnamed_addr #0 { define hidden void @main.init(i8* %context, i8* %parentHandle) unnamed_addr #0 {

2
compiler/testdata/float.ll предоставленный
Просмотреть файл

@ -3,7 +3,7 @@ source_filename = "float.go"
target datalayout = "e-m:e-p:32:32-i64:64-n32:64-S128" target datalayout = "e-m:e-p:32:32-i64:64-n32:64-S128"
target triple = "wasm32-unknown-wasi" target triple = "wasm32-unknown-wasi"
declare noalias nonnull i8* @runtime.alloc(i32, i8*, i8*) declare noalias nonnull i8* @runtime.alloc(i32, i8*, i8*, i8*)
; Function Attrs: nounwind ; Function Attrs: nounwind
define hidden void @main.init(i8* %context, i8* %parentHandle) unnamed_addr #0 { define hidden void @main.init(i8* %context, i8* %parentHandle) unnamed_addr #0 {

2
compiler/testdata/func.ll предоставленный
Просмотреть файл

@ -8,7 +8,7 @@ target triple = "wasm32-unknown-wasi"
@"reflect/types.funcid:func:{basic:int}{}" = external constant i8 @"reflect/types.funcid:func:{basic:int}{}" = external constant i8
@"main.someFunc$withSignature" = linkonce_odr constant %runtime.funcValueWithSignature { i32 ptrtoint (void (i32, i8*, i8*)* @main.someFunc to i32), i8* @"reflect/types.funcid:func:{basic:int}{}" } @"main.someFunc$withSignature" = linkonce_odr constant %runtime.funcValueWithSignature { i32 ptrtoint (void (i32, i8*, i8*)* @main.someFunc to i32), i8* @"reflect/types.funcid:func:{basic:int}{}" }
declare noalias nonnull i8* @runtime.alloc(i32, i8*, i8*) declare noalias nonnull i8* @runtime.alloc(i32, i8*, i8*, i8*)
; Function Attrs: nounwind ; Function Attrs: nounwind
define hidden void @main.init(i8* %context, i8* %parentHandle) unnamed_addr #0 { define hidden void @main.init(i8* %context, i8* %parentHandle) unnamed_addr #0 {

4
compiler/testdata/go1.17.ll предоставленный
Просмотреть файл

@ -3,7 +3,7 @@ source_filename = "go1.17.go"
target datalayout = "e-m:e-p:32:32-i64:64-n32:64-S128" target datalayout = "e-m:e-p:32:32-i64:64-n32:64-S128"
target triple = "wasm32-unknown-wasi" target triple = "wasm32-unknown-wasi"
declare noalias nonnull i8* @runtime.alloc(i32, i8*, i8*) declare noalias nonnull i8* @runtime.alloc(i32, i8*, i8*, i8*)
; Function Attrs: nounwind ; Function Attrs: nounwind
define hidden void @main.init(i8* %context, i8* %parentHandle) unnamed_addr #0 { define hidden void @main.init(i8* %context, i8* %parentHandle) unnamed_addr #0 {
@ -46,7 +46,7 @@ declare void @runtime.sliceToArrayPointerPanic(i8*, i8*)
; Function Attrs: nounwind ; Function Attrs: nounwind
define hidden [4 x i32]* @main.SliceToArrayConst(i8* %context, i8* %parentHandle) unnamed_addr #0 { define hidden [4 x i32]* @main.SliceToArrayConst(i8* %context, i8* %parentHandle) unnamed_addr #0 {
entry: entry:
%makeslice = call i8* @runtime.alloc(i32 24, i8* undef, i8* null) #0 %makeslice = call i8* @runtime.alloc(i32 24, i8* null, i8* undef, i8* null) #0
br i1 false, label %slicetoarray.throw, label %slicetoarray.next br i1 false, label %slicetoarray.throw, label %slicetoarray.next
slicetoarray.throw: ; preds = %entry slicetoarray.throw: ; preds = %entry

10
compiler/testdata/goroutine-cortex-m-qemu.ll предоставленный
Просмотреть файл

@ -11,7 +11,7 @@ target triple = "armv7m-unknown-unknown-eabi"
@"main.startInterfaceMethod$string" = internal unnamed_addr constant [4 x i8] c"test", align 1 @"main.startInterfaceMethod$string" = internal unnamed_addr constant [4 x i8] c"test", align 1
declare noalias nonnull i8* @runtime.alloc(i32, i8*, i8*) declare noalias nonnull i8* @runtime.alloc(i32, i8*, i8*, i8*)
; Function Attrs: nounwind ; Function Attrs: nounwind
define hidden void @main.init(i8* %context, i8* %parentHandle) unnamed_addr #0 { define hidden void @main.init(i8* %context, i8* %parentHandle) unnamed_addr #0 {
@ -66,10 +66,10 @@ entry:
; Function Attrs: nounwind ; Function Attrs: nounwind
define hidden void @main.closureFunctionGoroutine(i8* %context, i8* %parentHandle) unnamed_addr #0 { define hidden void @main.closureFunctionGoroutine(i8* %context, i8* %parentHandle) unnamed_addr #0 {
entry: entry:
%n = call i8* @runtime.alloc(i32 4, i8* undef, i8* null) #0 %n = call i8* @runtime.alloc(i32 4, i8* null, i8* undef, i8* null) #0
%0 = bitcast i8* %n to i32* %0 = bitcast i8* %n to i32*
store i32 3, i32* %0, align 4 store i32 3, i32* %0, align 4
%1 = call i8* @runtime.alloc(i32 8, i8* undef, i8* null) #0 %1 = call i8* @runtime.alloc(i32 8, i8* null, i8* undef, i8* null) #0
%2 = bitcast i8* %1 to i32* %2 = bitcast i8* %1 to i32*
store i32 5, i32* %2, align 4 store i32 5, i32* %2, align 4
%3 = getelementptr inbounds i8, i8* %1, i32 4 %3 = getelementptr inbounds i8, i8* %1, i32 4
@ -107,7 +107,7 @@ declare void @runtime.printint32(i32, i8*, i8*)
; Function Attrs: nounwind ; Function Attrs: nounwind
define hidden void @main.funcGoroutine(i8* %fn.context, void ()* %fn.funcptr, i8* %context, i8* %parentHandle) unnamed_addr #0 { define hidden void @main.funcGoroutine(i8* %fn.context, void ()* %fn.funcptr, i8* %context, i8* %parentHandle) unnamed_addr #0 {
entry: entry:
%0 = call i8* @runtime.alloc(i32 12, i8* undef, i8* null) #0 %0 = call i8* @runtime.alloc(i32 12, i8* null, i8* undef, i8* null) #0
%1 = bitcast i8* %0 to i32* %1 = bitcast i8* %0 to i32*
store i32 5, i32* %1, align 4 store i32 5, i32* %1, align 4
%2 = getelementptr inbounds i8, i8* %0, i32 4 %2 = getelementptr inbounds i8, i8* %0, i32 4
@ -163,7 +163,7 @@ declare void @runtime.chanClose(%runtime.channel* dereferenceable_or_null(32), i
; Function Attrs: nounwind ; Function Attrs: nounwind
define hidden void @main.startInterfaceMethod(i32 %itf.typecode, i8* %itf.value, i8* %context, i8* %parentHandle) unnamed_addr #0 { define hidden void @main.startInterfaceMethod(i32 %itf.typecode, i8* %itf.value, i8* %context, i8* %parentHandle) unnamed_addr #0 {
entry: entry:
%0 = call i8* @runtime.alloc(i32 16, i8* undef, i8* null) #0 %0 = call i8* @runtime.alloc(i32 16, i8* null, i8* undef, i8* null) #0
%1 = bitcast i8* %0 to i8** %1 = bitcast i8* %0 to i8**
store i8* %itf.value, i8** %1, align 4 store i8* %itf.value, i8** %1, align 4
%2 = getelementptr inbounds i8, i8* %0, i32 4 %2 = getelementptr inbounds i8, i8* %0, i32 4

10
compiler/testdata/goroutine-wasm.ll предоставленный
Просмотреть файл

@ -16,7 +16,7 @@ target triple = "wasm32-unknown-wasi"
@"main.closureFunctionGoroutine$1$withSignature" = linkonce_odr constant %runtime.funcValueWithSignature { i32 ptrtoint (void (i32, i8*, i8*)* @"main.closureFunctionGoroutine$1" to i32), i8* @"reflect/types.funcid:func:{basic:int}{}" } @"main.closureFunctionGoroutine$1$withSignature" = linkonce_odr constant %runtime.funcValueWithSignature { i32 ptrtoint (void (i32, i8*, i8*)* @"main.closureFunctionGoroutine$1" to i32), i8* @"reflect/types.funcid:func:{basic:int}{}" }
@"main.startInterfaceMethod$string" = internal unnamed_addr constant [4 x i8] c"test", align 1 @"main.startInterfaceMethod$string" = internal unnamed_addr constant [4 x i8] c"test", align 1
declare noalias nonnull i8* @runtime.alloc(i32, i8*, i8*) declare noalias nonnull i8* @runtime.alloc(i32, i8*, i8*, i8*)
; Function Attrs: nounwind ; Function Attrs: nounwind
define hidden void @main.init(i8* %context, i8* %parentHandle) unnamed_addr #0 { define hidden void @main.init(i8* %context, i8* %parentHandle) unnamed_addr #0 {
@ -51,10 +51,10 @@ entry:
; Function Attrs: nounwind ; Function Attrs: nounwind
define hidden void @main.closureFunctionGoroutine(i8* %context, i8* %parentHandle) unnamed_addr #0 { define hidden void @main.closureFunctionGoroutine(i8* %context, i8* %parentHandle) unnamed_addr #0 {
entry: entry:
%n = call i8* @runtime.alloc(i32 4, i8* undef, i8* null) #0 %n = call i8* @runtime.alloc(i32 4, i8* null, i8* undef, i8* null) #0
%0 = bitcast i8* %n to i32* %0 = bitcast i8* %n to i32*
store i32 3, i32* %0, align 4 store i32 3, i32* %0, align 4
%1 = call i8* @runtime.alloc(i32 8, i8* undef, i8* null) #0 %1 = call i8* @runtime.alloc(i32 8, i8* null, i8* undef, i8* null) #0
%2 = bitcast i8* %1 to i32* %2 = bitcast i8* %1 to i32*
store i32 5, i32* %2, align 4 store i32 5, i32* %2, align 4
%3 = getelementptr inbounds i8, i8* %1, i32 4 %3 = getelementptr inbounds i8, i8* %1, i32 4
@ -80,7 +80,7 @@ declare void @runtime.printint32(i32, i8*, i8*)
define hidden void @main.funcGoroutine(i8* %fn.context, i32 %fn.funcptr, i8* %context, i8* %parentHandle) unnamed_addr #0 { define hidden void @main.funcGoroutine(i8* %fn.context, i32 %fn.funcptr, i8* %context, i8* %parentHandle) unnamed_addr #0 {
entry: entry:
%0 = call i32 @runtime.getFuncPtr(i8* %fn.context, i32 %fn.funcptr, i8* nonnull @"reflect/types.funcid:func:{basic:int}{}", i8* undef, i8* null) #0 %0 = call i32 @runtime.getFuncPtr(i8* %fn.context, i32 %fn.funcptr, i8* nonnull @"reflect/types.funcid:func:{basic:int}{}", i8* undef, i8* null) #0
%1 = call i8* @runtime.alloc(i32 8, i8* undef, i8* null) #0 %1 = call i8* @runtime.alloc(i32 8, i8* null, i8* undef, i8* null) #0
%2 = bitcast i8* %1 to i32* %2 = bitcast i8* %1 to i32*
store i32 5, i32* %2, align 4 store i32 5, i32* %2, align 4
%3 = getelementptr inbounds i8, i8* %1, i32 4 %3 = getelementptr inbounds i8, i8* %1, i32 4
@ -119,7 +119,7 @@ declare void @runtime.chanClose(%runtime.channel* dereferenceable_or_null(32), i
; Function Attrs: nounwind ; Function Attrs: nounwind
define hidden void @main.startInterfaceMethod(i32 %itf.typecode, i8* %itf.value, i8* %context, i8* %parentHandle) unnamed_addr #0 { define hidden void @main.startInterfaceMethod(i32 %itf.typecode, i8* %itf.value, i8* %context, i8* %parentHandle) unnamed_addr #0 {
entry: entry:
%0 = call i8* @runtime.alloc(i32 16, i8* undef, i8* null) #0 %0 = call i8* @runtime.alloc(i32 16, i8* null, i8* undef, i8* null) #0
%1 = bitcast i8* %0 to i8** %1 = bitcast i8* %0 to i8**
store i8* %itf.value, i8** %1, align 4 store i8* %itf.value, i8** %1, align 4
%2 = getelementptr inbounds i8, i8* %0, i32 4 %2 = getelementptr inbounds i8, i8* %0, i32 4

2
compiler/testdata/interface.ll предоставленный
Просмотреть файл

@ -22,7 +22,7 @@ target triple = "wasm32-unknown-wasi"
@"reflect/types.interface:interface{String() string}$interface" = linkonce_odr constant [1 x i8*] [i8* @"reflect/methods.String() string"] @"reflect/types.interface:interface{String() string}$interface" = linkonce_odr constant [1 x i8*] [i8* @"reflect/methods.String() string"]
@"reflect/types.typeid:basic:int" = external constant i8 @"reflect/types.typeid:basic:int" = external constant i8
declare noalias nonnull i8* @runtime.alloc(i32, i8*, i8*) declare noalias nonnull i8* @runtime.alloc(i32, i8*, i8*, i8*)
; Function Attrs: nounwind ; Function Attrs: nounwind
define hidden void @main.init(i8* %context, i8* %parentHandle) unnamed_addr #0 { define hidden void @main.init(i8* %context, i8* %parentHandle) unnamed_addr #0 {

2
compiler/testdata/intrinsics-cortex-m-qemu.ll предоставленный
Просмотреть файл

@ -3,7 +3,7 @@ source_filename = "intrinsics.go"
target datalayout = "e-m:e-p:32:32-Fi8-i64:64-v128:64:128-a:0:32-n32-S64" target datalayout = "e-m:e-p:32:32-Fi8-i64:64-v128:64:128-a:0:32-n32-S64"
target triple = "armv7m-unknown-unknown-eabi" target triple = "armv7m-unknown-unknown-eabi"
declare noalias nonnull i8* @runtime.alloc(i32, i8*, i8*) declare noalias nonnull i8* @runtime.alloc(i32, i8*, i8*, i8*)
; Function Attrs: nounwind ; Function Attrs: nounwind
define hidden void @main.init(i8* %context, i8* %parentHandle) unnamed_addr #0 { define hidden void @main.init(i8* %context, i8* %parentHandle) unnamed_addr #0 {

2
compiler/testdata/intrinsics-wasm.ll предоставленный
Просмотреть файл

@ -3,7 +3,7 @@ source_filename = "intrinsics.go"
target datalayout = "e-m:e-p:32:32-i64:64-n32:64-S128" target datalayout = "e-m:e-p:32:32-i64:64-n32:64-S128"
target triple = "wasm32-unknown-wasi" target triple = "wasm32-unknown-wasi"
declare noalias nonnull i8* @runtime.alloc(i32, i8*, i8*) declare noalias nonnull i8* @runtime.alloc(i32, i8*, i8*, i8*)
; Function Attrs: nounwind ; Function Attrs: nounwind
define hidden void @main.init(i8* %context, i8* %parentHandle) unnamed_addr #0 { define hidden void @main.init(i8* %context, i8* %parentHandle) unnamed_addr #0 {

2
compiler/testdata/pointer.ll предоставленный
Просмотреть файл

@ -3,7 +3,7 @@ source_filename = "pointer.go"
target datalayout = "e-m:e-p:32:32-i64:64-n32:64-S128" target datalayout = "e-m:e-p:32:32-i64:64-n32:64-S128"
target triple = "wasm32-unknown-wasi" target triple = "wasm32-unknown-wasi"
declare noalias nonnull i8* @runtime.alloc(i32, i8*, i8*) declare noalias nonnull i8* @runtime.alloc(i32, i8*, i8*, i8*)
; Function Attrs: nounwind ; Function Attrs: nounwind
define hidden void @main.init(i8* %context, i8* %parentHandle) unnamed_addr #0 { define hidden void @main.init(i8* %context, i8* %parentHandle) unnamed_addr #0 {

2
compiler/testdata/pragma.ll предоставленный
Просмотреть файл

@ -10,7 +10,7 @@ target triple = "wasm32-unknown-wasi"
@undefinedGlobalNotInSection = external global i32, align 4 @undefinedGlobalNotInSection = external global i32, align 4
@main.multipleGlobalPragmas = hidden global i32 0, section ".global_section", align 1024 @main.multipleGlobalPragmas = hidden global i32 0, section ".global_section", align 1024
declare noalias nonnull i8* @runtime.alloc(i32, i8*, i8*) declare noalias nonnull i8* @runtime.alloc(i32, i8*, i8*, i8*)
; Function Attrs: nounwind ; Function Attrs: nounwind
define hidden void @main.init(i8* %context, i8* %parentHandle) unnamed_addr #0 { define hidden void @main.init(i8* %context, i8* %parentHandle) unnamed_addr #0 {

12
compiler/testdata/slice.ll предоставленный
Просмотреть файл

@ -3,7 +3,7 @@ source_filename = "slice.go"
target datalayout = "e-m:e-p:32:32-i64:64-n32:64-S128" target datalayout = "e-m:e-p:32:32-i64:64-n32:64-S128"
target triple = "wasm32-unknown-wasi" target triple = "wasm32-unknown-wasi"
declare noalias nonnull i8* @runtime.alloc(i32, i8*, i8*) declare noalias nonnull i8* @runtime.alloc(i32, i8*, i8*, i8*)
; Function Attrs: nounwind ; Function Attrs: nounwind
define hidden void @main.init(i8* %context, i8* %parentHandle) unnamed_addr #0 { define hidden void @main.init(i8* %context, i8* %parentHandle) unnamed_addr #0 {
@ -44,7 +44,7 @@ declare void @runtime.lookupPanic(i8*, i8*)
; Function Attrs: nounwind ; Function Attrs: nounwind
define hidden { i32*, i32, i32 } @main.sliceAppendValues(i32* %ints.data, i32 %ints.len, i32 %ints.cap, i8* %context, i8* %parentHandle) unnamed_addr #0 { define hidden { i32*, i32, i32 } @main.sliceAppendValues(i32* %ints.data, i32 %ints.len, i32 %ints.cap, i8* %context, i8* %parentHandle) unnamed_addr #0 {
entry: entry:
%varargs = call i8* @runtime.alloc(i32 12, i8* undef, i8* null) #0 %varargs = call i8* @runtime.alloc(i32 12, i8* null, i8* undef, i8* null) #0
%0 = bitcast i8* %varargs to i32* %0 = bitcast i8* %varargs to i32*
store i32 1, i32* %0, align 4 store i32 1, i32* %0, align 4
%1 = getelementptr inbounds i8, i8* %varargs, i32 4 %1 = getelementptr inbounds i8, i8* %varargs, i32 4
@ -105,7 +105,7 @@ slice.throw: ; preds = %entry
unreachable unreachable
slice.next: ; preds = %entry slice.next: ; preds = %entry
%makeslice.buf = call i8* @runtime.alloc(i32 %len, i8* undef, i8* null) #0 %makeslice.buf = call i8* @runtime.alloc(i32 %len, i8* null, i8* undef, i8* null) #0
%0 = insertvalue { i8*, i32, i32 } undef, i8* %makeslice.buf, 0 %0 = insertvalue { i8*, i32, i32 } undef, i8* %makeslice.buf, 0
%1 = insertvalue { i8*, i32, i32 } %0, i32 %len, 1 %1 = insertvalue { i8*, i32, i32 } %0, i32 %len, 1
%2 = insertvalue { i8*, i32, i32 } %1, i32 %len, 2 %2 = insertvalue { i8*, i32, i32 } %1, i32 %len, 2
@ -126,7 +126,7 @@ slice.throw: ; preds = %entry
slice.next: ; preds = %entry slice.next: ; preds = %entry
%makeslice.cap = shl i32 %len, 1 %makeslice.cap = shl i32 %len, 1
%makeslice.buf = call i8* @runtime.alloc(i32 %makeslice.cap, i8* undef, i8* null) #0 %makeslice.buf = call i8* @runtime.alloc(i32 %makeslice.cap, i8* null, i8* undef, i8* null) #0
%makeslice.array = bitcast i8* %makeslice.buf to i16* %makeslice.array = bitcast i8* %makeslice.buf to i16*
%0 = insertvalue { i16*, i32, i32 } undef, i16* %makeslice.array, 0 %0 = insertvalue { i16*, i32, i32 } undef, i16* %makeslice.array, 0
%1 = insertvalue { i16*, i32, i32 } %0, i32 %len, 1 %1 = insertvalue { i16*, i32, i32 } %0, i32 %len, 1
@ -146,7 +146,7 @@ slice.throw: ; preds = %entry
slice.next: ; preds = %entry slice.next: ; preds = %entry
%makeslice.cap = mul i32 %len, 3 %makeslice.cap = mul i32 %len, 3
%makeslice.buf = call i8* @runtime.alloc(i32 %makeslice.cap, i8* undef, i8* null) #0 %makeslice.buf = call i8* @runtime.alloc(i32 %makeslice.cap, i8* null, i8* undef, i8* null) #0
%makeslice.array = bitcast i8* %makeslice.buf to [3 x i8]* %makeslice.array = bitcast i8* %makeslice.buf to [3 x i8]*
%0 = insertvalue { [3 x i8]*, i32, i32 } undef, [3 x i8]* %makeslice.array, 0 %0 = insertvalue { [3 x i8]*, i32, i32 } undef, [3 x i8]* %makeslice.array, 0
%1 = insertvalue { [3 x i8]*, i32, i32 } %0, i32 %len, 1 %1 = insertvalue { [3 x i8]*, i32, i32 } %0, i32 %len, 1
@ -166,7 +166,7 @@ slice.throw: ; preds = %entry
slice.next: ; preds = %entry slice.next: ; preds = %entry
%makeslice.cap = shl i32 %len, 2 %makeslice.cap = shl i32 %len, 2
%makeslice.buf = call i8* @runtime.alloc(i32 %makeslice.cap, i8* undef, i8* null) #0 %makeslice.buf = call i8* @runtime.alloc(i32 %makeslice.cap, i8* null, i8* undef, i8* null) #0
%makeslice.array = bitcast i8* %makeslice.buf to i32* %makeslice.array = bitcast i8* %makeslice.buf to i32*
%0 = insertvalue { i32*, i32, i32 } undef, i32* %makeslice.array, 0 %0 = insertvalue { i32*, i32, i32 } undef, i32* %makeslice.array, 0
%1 = insertvalue { i32*, i32, i32 } %0, i32 %len, 1 %1 = insertvalue { i32*, i32, i32 } %0, i32 %len, 1

2
compiler/testdata/string.ll предоставленный
Просмотреть файл

@ -7,7 +7,7 @@ target triple = "wasm32-unknown-wasi"
@"main.someString$string" = internal unnamed_addr constant [3 x i8] c"foo", align 1 @"main.someString$string" = internal unnamed_addr constant [3 x i8] c"foo", align 1
declare noalias nonnull i8* @runtime.alloc(i32, i8*, i8*) declare noalias nonnull i8* @runtime.alloc(i32, i8*, i8*, i8*)
; Function Attrs: nounwind ; Function Attrs: nounwind
define hidden void @main.init(i8* %context, i8* %parentHandle) unnamed_addr #0 { define hidden void @main.init(i8* %context, i8* %parentHandle) unnamed_addr #0 {

6
interp/testdata/slice-copy.ll предоставленный
Просмотреть файл

@ -10,7 +10,7 @@ target triple = "x86_64--linux"
declare i64 @runtime.sliceCopy(i8* %dst, i8* %src, i64 %dstLen, i64 %srcLen, i64 %elemSize) unnamed_addr declare i64 @runtime.sliceCopy(i8* %dst, i8* %src, i64 %dstLen, i64 %srcLen, i64 %elemSize) unnamed_addr
declare i8* @runtime.alloc(i64) unnamed_addr declare i8* @runtime.alloc(i64, i8*) unnamed_addr
declare void @runtime.printuint8(i8) declare void @runtime.printuint8(i8)
@ -52,7 +52,7 @@ entry:
; uint8SliceDst = make([]uint8, len(uint8SliceSrc)) ; uint8SliceDst = make([]uint8, len(uint8SliceSrc))
%uint8SliceSrc = load { i8*, i64, i64 }, { i8*, i64, i64 }* @main.uint8SliceSrc %uint8SliceSrc = load { i8*, i64, i64 }, { i8*, i64, i64 }* @main.uint8SliceSrc
%uint8SliceSrc.len = extractvalue { i8*, i64, i64 } %uint8SliceSrc, 1 %uint8SliceSrc.len = extractvalue { i8*, i64, i64 } %uint8SliceSrc, 1
%uint8SliceDst.buf = call i8* @runtime.alloc(i64 %uint8SliceSrc.len) %uint8SliceDst.buf = call i8* @runtime.alloc(i64 %uint8SliceSrc.len, i8* null)
%0 = insertvalue { i8*, i64, i64 } undef, i8* %uint8SliceDst.buf, 0 %0 = insertvalue { i8*, i64, i64 } undef, i8* %uint8SliceDst.buf, 0
%1 = insertvalue { i8*, i64, i64 } %0, i64 %uint8SliceSrc.len, 1 %1 = insertvalue { i8*, i64, i64 } %0, i64 %uint8SliceSrc.len, 1
%2 = insertvalue { i8*, i64, i64 } %1, i64 %uint8SliceSrc.len, 2 %2 = insertvalue { i8*, i64, i64 } %1, i64 %uint8SliceSrc.len, 2
@ -68,7 +68,7 @@ entry:
%int16SliceSrc = load { i16*, i64, i64 }, { i16*, i64, i64 }* @main.int16SliceSrc %int16SliceSrc = load { i16*, i64, i64 }, { i16*, i64, i64 }* @main.int16SliceSrc
%int16SliceSrc.len = extractvalue { i16*, i64, i64 } %int16SliceSrc, 1 %int16SliceSrc.len = extractvalue { i16*, i64, i64 } %int16SliceSrc, 1
%int16SliceSrc.len.bytes = mul i64 %int16SliceSrc.len, 2 %int16SliceSrc.len.bytes = mul i64 %int16SliceSrc.len, 2
%int16SliceDst.buf.raw = call i8* @runtime.alloc(i64 %int16SliceSrc.len.bytes) %int16SliceDst.buf.raw = call i8* @runtime.alloc(i64 %int16SliceSrc.len.bytes, i8* null)
%int16SliceDst.buf = bitcast i8* %int16SliceDst.buf.raw to i16* %int16SliceDst.buf = bitcast i8* %int16SliceDst.buf.raw to i16*
%3 = insertvalue { i16*, i64, i64 } undef, i16* %int16SliceDst.buf, 0 %3 = insertvalue { i16*, i64, i64 } undef, i16* %int16SliceDst.buf, 0
%4 = insertvalue { i16*, i64, i64 } %3, i64 %int16SliceSrc.len, 1 %4 = insertvalue { i16*, i64, i64 } %3, i64 %int16SliceSrc.len, 1

Просмотреть файл

@ -729,7 +729,7 @@ func Zero(typ Type) Value {
func New(typ Type) Value { func New(typ Type) Value {
return Value{ return Value{
typecode: PtrTo(typ).(rawType), typecode: PtrTo(typ).(rawType),
value: alloc(typ.Size()), value: alloc(typ.Size(), nil),
flags: valueFlagExported, flags: valueFlagExported,
} }
} }
@ -778,7 +778,7 @@ func (e *ValueError) Error() string {
func memcpy(dst, src unsafe.Pointer, size uintptr) func memcpy(dst, src unsafe.Pointer, size uintptr)
//go:linkname alloc runtime.alloc //go:linkname alloc runtime.alloc
func alloc(size uintptr) unsafe.Pointer func alloc(size uintptr, layout unsafe.Pointer) unsafe.Pointer
//go:linkname sliceAppend runtime.sliceAppend //go:linkname sliceAppend runtime.sliceAppend
func sliceAppend(srcBuf, elemsBuf unsafe.Pointer, srcLen, srcCap, elemsLen uintptr, elemSize uintptr) (unsafe.Pointer, uintptr, uintptr) func sliceAppend(srcBuf, elemsBuf unsafe.Pointer, srcLen, srcCap, elemsLen uintptr, elemSize uintptr) (unsafe.Pointer, uintptr, uintptr)

Просмотреть файл

@ -66,7 +66,7 @@ func growHeap() bool {
//export malloc //export malloc
func libc_malloc(size uintptr) unsafe.Pointer { func libc_malloc(size uintptr) unsafe.Pointer {
return alloc(size) return alloc(size, nil)
} }
//export free //export free
@ -79,7 +79,7 @@ func libc_calloc(nmemb, size uintptr) unsafe.Pointer {
// Note: we could be even more correct here and check that nmemb * size // Note: we could be even more correct here and check that nmemb * size
// doesn't overflow. However the current implementation should normally work // doesn't overflow. However the current implementation should normally work
// fine. // fine.
return alloc(nmemb * size) return alloc(nmemb*size, nil)
} }
//export realloc //export realloc

Просмотреть файл

@ -38,7 +38,7 @@ func growHeap() bool {
//export malloc //export malloc
func libc_malloc(size uintptr) unsafe.Pointer { func libc_malloc(size uintptr) unsafe.Pointer {
return alloc(size) return alloc(size, nil)
} }
//export free //export free

Просмотреть файл

@ -133,7 +133,7 @@ func chanMake(elementSize uintptr, bufSize uintptr) *channel {
return &channel{ return &channel{
elementSize: elementSize, elementSize: elementSize,
bufSize: bufSize, bufSize: bufSize,
buf: alloc(elementSize * bufSize), buf: alloc(elementSize*bufSize, nil),
} }
} }

Просмотреть файл

@ -263,7 +263,7 @@ func calculateHeapAddresses() {
// alloc tries to find some free space on the heap, possibly doing a garbage // alloc tries to find some free space on the heap, possibly doing a garbage
// collection cycle if needed. If no space is free, it panics. // collection cycle if needed. If no space is free, it panics.
//go:noinline //go:noinline
func alloc(size uintptr) unsafe.Pointer { func alloc(size uintptr, layout unsafe.Pointer) unsafe.Pointer {
if size == 0 { if size == 0 {
return unsafe.Pointer(&zeroSizedAlloc) return unsafe.Pointer(&zeroSizedAlloc)
} }

Просмотреть файл

@ -527,7 +527,7 @@ var zeroSizedAlloc uint8
// alloc tries to find some free space on the heap, possibly doing a garbage // alloc tries to find some free space on the heap, possibly doing a garbage
// collection cycle if needed. If no space is free, it panics. // collection cycle if needed. If no space is free, it panics.
//go:noinline //go:noinline
func alloc(size uintptr) unsafe.Pointer { func alloc(size uintptr, layout unsafe.Pointer) unsafe.Pointer {
if size == 0 { if size == 0 {
return unsafe.Pointer(&zeroSizedAlloc) return unsafe.Pointer(&zeroSizedAlloc)
} }

Просмотреть файл

@ -13,7 +13,7 @@ import (
// Ever-incrementing pointer: no memory is freed. // Ever-incrementing pointer: no memory is freed.
var heapptr = heapStart var heapptr = heapStart
func alloc(size uintptr) unsafe.Pointer { func alloc(size uintptr, layout unsafe.Pointer) unsafe.Pointer {
// TODO: this can be optimized by not casting between pointers and ints so // TODO: this can be optimized by not casting between pointers and ints so
// much. And by using platform-native data types (e.g. *uint8 for 8-bit // much. And by using platform-native data types (e.g. *uint8 for 8-bit
// systems). // systems).

Просмотреть файл

@ -10,7 +10,7 @@ import (
"unsafe" "unsafe"
) )
func alloc(size uintptr) unsafe.Pointer func alloc(size uintptr, layout unsafe.Pointer) unsafe.Pointer
func free(ptr unsafe.Pointer) { func free(ptr unsafe.Pointer) {
// Nothing to free when nothing gets allocated. // Nothing to free when nothing gets allocated.

Просмотреть файл

@ -69,7 +69,7 @@ func hashmapMake(keySize, valueSize uint8, sizeHint uintptr) *hashmap {
bucketBits++ bucketBits++
} }
bucketBufSize := unsafe.Sizeof(hashmapBucket{}) + uintptr(keySize)*8 + uintptr(valueSize)*8 bucketBufSize := unsafe.Sizeof(hashmapBucket{}) + uintptr(keySize)*8 + uintptr(valueSize)*8
buckets := alloc(bucketBufSize * (1 << bucketBits)) buckets := alloc(bucketBufSize*(1<<bucketBits), nil)
return &hashmap{ return &hashmap{
buckets: buckets, buckets: buckets,
keySize: keySize, keySize: keySize,
@ -157,7 +157,7 @@ func hashmapSet(m *hashmap, key unsafe.Pointer, value unsafe.Pointer, hash uint3
// value into the bucket, and returns a pointer to this bucket. // value into the bucket, and returns a pointer to this bucket.
func hashmapInsertIntoNewBucket(m *hashmap, key, value unsafe.Pointer, tophash uint8) *hashmapBucket { func hashmapInsertIntoNewBucket(m *hashmap, key, value unsafe.Pointer, tophash uint8) *hashmapBucket {
bucketBufSize := unsafe.Sizeof(hashmapBucket{}) + uintptr(m.keySize)*8 + uintptr(m.valueSize)*8 bucketBufSize := unsafe.Sizeof(hashmapBucket{}) + uintptr(m.keySize)*8 + uintptr(m.valueSize)*8
bucketBuf := alloc(bucketBufSize) bucketBuf := alloc(bucketBufSize, nil)
// Insert into the first slot, which is empty as it has just been allocated. // Insert into the first slot, which is empty as it has just been allocated.
slotKeyOffset := unsafe.Sizeof(hashmapBucket{}) slotKeyOffset := unsafe.Sizeof(hashmapBucket{})
slotKey := unsafe.Pointer(uintptr(bucketBuf) + slotKeyOffset) slotKey := unsafe.Pointer(uintptr(bucketBuf) + slotKeyOffset)

Просмотреть файл

@ -27,7 +27,7 @@ func sliceAppend(srcBuf, elemsBuf unsafe.Pointer, srcLen, srcCap, elemsLen uintp
// programs). // programs).
srcCap *= 2 srcCap *= 2
} }
buf := alloc(srcCap * elemSize) buf := alloc(srcCap*elemSize, nil)
// Copy the old slice to the new slice. // Copy the old slice to the new slice.
if srcLen != 0 { if srcLen != 0 {

Просмотреть файл

@ -57,7 +57,7 @@ func stringConcat(x, y _string) _string {
return x return x
} else { } else {
length := x.length + y.length length := x.length + y.length
buf := alloc(length) buf := alloc(length, nil)
memcpy(buf, unsafe.Pointer(x.ptr), x.length) memcpy(buf, unsafe.Pointer(x.ptr), x.length)
memcpy(unsafe.Pointer(uintptr(buf)+x.length), unsafe.Pointer(y.ptr), y.length) memcpy(unsafe.Pointer(uintptr(buf)+x.length), unsafe.Pointer(y.ptr), y.length)
return _string{ptr: (*byte)(buf), length: length} return _string{ptr: (*byte)(buf), length: length}
@ -70,7 +70,7 @@ func stringFromBytes(x struct {
len uintptr len uintptr
cap uintptr cap uintptr
}) _string { }) _string {
buf := alloc(x.len) buf := alloc(x.len, nil)
memcpy(buf, unsafe.Pointer(x.ptr), x.len) memcpy(buf, unsafe.Pointer(x.ptr), x.len)
return _string{ptr: (*byte)(buf), length: x.len} return _string{ptr: (*byte)(buf), length: x.len}
} }
@ -81,7 +81,7 @@ func stringToBytes(x _string) (slice struct {
len uintptr len uintptr
cap uintptr cap uintptr
}) { }) {
buf := alloc(x.length) buf := alloc(x.length, nil)
memcpy(buf, unsafe.Pointer(x.ptr), x.length) memcpy(buf, unsafe.Pointer(x.ptr), x.length)
slice.ptr = (*byte)(buf) slice.ptr = (*byte)(buf)
slice.len = x.length slice.len = x.length
@ -98,7 +98,7 @@ func stringFromRunes(runeSlice []rune) (s _string) {
} }
// Allocate memory for the string. // Allocate memory for the string.
s.ptr = (*byte)(alloc(s.length)) s.ptr = (*byte)(alloc(s.length, nil))
// Encode runes to UTF-8 and store the resulting bytes in the string. // Encode runes to UTF-8 and store the resulting bytes in the string.
index := uintptr(0) index := uintptr(0)

Просмотреть файл

@ -70,7 +70,7 @@ func OptimizeAllocs(mod llvm.Module, printAllocs *regexp.Regexp, logger func(tok
} }
// In general the pattern is: // In general the pattern is:
// %0 = call i8* @runtime.alloc(i32 %size) // %0 = call i8* @runtime.alloc(i32 %size, i8* null)
// %1 = bitcast i8* %0 to type* // %1 = bitcast i8* %0 to type*
// (use %1 only) // (use %1 only)
// But the bitcast might sometimes be dropped when allocating an *i8. // But the bitcast might sometimes be dropped when allocating an *i8.

Просмотреть файл

@ -627,7 +627,7 @@ func (async *asyncFunc) hasValueStoreReturn() bool {
func (c *coroutineLoweringPass) heapAlloc(t llvm.Type, name string) llvm.Value { func (c *coroutineLoweringPass) heapAlloc(t llvm.Type, name string) llvm.Value {
sizeT := c.alloc.FirstParam().Type() sizeT := c.alloc.FirstParam().Type()
size := llvm.ConstInt(sizeT, c.target.TypeAllocSize(t), false) size := llvm.ConstInt(sizeT, c.target.TypeAllocSize(t), false)
return c.builder.CreateCall(c.alloc, []llvm.Value{size, llvm.Undef(c.i8ptr), llvm.Undef(c.i8ptr)}, name) return c.builder.CreateCall(c.alloc, []llvm.Value{size, llvm.ConstNull(c.i8ptr), llvm.Undef(c.i8ptr), llvm.Undef(c.i8ptr)}, name)
} }
// lowerFuncFast lowers an async function that has no suspend points. // lowerFuncFast lowers an async function that has no suspend points.
@ -798,7 +798,7 @@ func (c *coroutineLoweringPass) lowerFuncCoro(fn *asyncFunc) {
// %coro.size = call i32 @llvm.coro.size.i32() // %coro.size = call i32 @llvm.coro.size.i32()
coroSize := c.builder.CreateCall(c.coroSize, []llvm.Value{}, "coro.size") coroSize := c.builder.CreateCall(c.coroSize, []llvm.Value{}, "coro.size")
// %coro.alloc = call i8* runtime.alloc(i32 %coro.size) // %coro.alloc = call i8* runtime.alloc(i32 %coro.size)
coroAlloc := c.builder.CreateCall(c.alloc, []llvm.Value{coroSize, llvm.Undef(c.i8ptr), llvm.Undef(c.i8ptr)}, "coro.alloc") coroAlloc := c.builder.CreateCall(c.alloc, []llvm.Value{coroSize, llvm.ConstNull(c.i8ptr), llvm.Undef(c.i8ptr), llvm.Undef(c.i8ptr)}, "coro.alloc")
// %coro.state = call noalias i8* @llvm.coro.begin(token %coro.id, i8* %coro.alloc) // %coro.state = call noalias i8* @llvm.coro.begin(token %coro.id, i8* %coro.alloc)
coroState := c.builder.CreateCall(c.coroBegin, []llvm.Value{coroId, coroAlloc}, "coro.state") coroState := c.builder.CreateCall(c.coroBegin, []llvm.Value{coroId, coroAlloc}, "coro.state")
c.track(coroState) c.track(coroState)

18
transform/testdata/allocs.ll предоставленный
Просмотреть файл

@ -3,11 +3,11 @@ target triple = "armv7m-none-eabi"
@runtime.zeroSizedAlloc = internal global i8 0, align 1 @runtime.zeroSizedAlloc = internal global i8 0, align 1
declare nonnull i8* @runtime.alloc(i32) declare nonnull i8* @runtime.alloc(i32, i8*)
; Test allocating a single int (i32) that should be allocated on the stack. ; Test allocating a single int (i32) that should be allocated on the stack.
define void @testInt() { define void @testInt() {
%1 = call i8* @runtime.alloc(i32 4) %1 = call i8* @runtime.alloc(i32 4, i8* null)
%2 = bitcast i8* %1 to i32* %2 = bitcast i8* %1 to i32*
store i32 5, i32* %2 store i32 5, i32* %2
ret void ret void
@ -16,7 +16,7 @@ define void @testInt() {
; Test allocating an array of 3 i16 values that should be allocated on the ; Test allocating an array of 3 i16 values that should be allocated on the
; stack. ; stack.
define i16 @testArray() { define i16 @testArray() {
%1 = call i8* @runtime.alloc(i32 6) %1 = call i8* @runtime.alloc(i32 6, i8* null)
%2 = bitcast i8* %1 to i16* %2 = bitcast i8* %1 to i16*
%3 = getelementptr i16, i16* %2, i32 1 %3 = getelementptr i16, i16* %2, i32 1
store i16 5, i16* %3 store i16 5, i16* %3
@ -28,14 +28,14 @@ define i16 @testArray() {
; Call a function that will let the pointer escape, so the heap-to-stack ; Call a function that will let the pointer escape, so the heap-to-stack
; transform shouldn't be applied. ; transform shouldn't be applied.
define void @testEscapingCall() { define void @testEscapingCall() {
%1 = call i8* @runtime.alloc(i32 4) %1 = call i8* @runtime.alloc(i32 4, i8* null)
%2 = bitcast i8* %1 to i32* %2 = bitcast i8* %1 to i32*
%3 = call i32* @escapeIntPtr(i32* %2) %3 = call i32* @escapeIntPtr(i32* %2)
ret void ret void
} }
define void @testEscapingCall2() { define void @testEscapingCall2() {
%1 = call i8* @runtime.alloc(i32 4) %1 = call i8* @runtime.alloc(i32 4, i8* null)
%2 = bitcast i8* %1 to i32* %2 = bitcast i8* %1 to i32*
%3 = call i32* @escapeIntPtrSometimes(i32* %2, i32* %2) %3 = call i32* @escapeIntPtrSometimes(i32* %2, i32* %2)
ret void ret void
@ -43,7 +43,7 @@ define void @testEscapingCall2() {
; Call a function that doesn't let the pointer escape. ; Call a function that doesn't let the pointer escape.
define void @testNonEscapingCall() { define void @testNonEscapingCall() {
%1 = call i8* @runtime.alloc(i32 4) %1 = call i8* @runtime.alloc(i32 4, i8* null)
%2 = bitcast i8* %1 to i32* %2 = bitcast i8* %1 to i32*
%3 = call i32* @noescapeIntPtr(i32* %2) %3 = call i32* @noescapeIntPtr(i32* %2)
ret void ret void
@ -51,7 +51,7 @@ define void @testNonEscapingCall() {
; Return the allocated value, which lets it escape. ; Return the allocated value, which lets it escape.
define i32* @testEscapingReturn() { define i32* @testEscapingReturn() {
%1 = call i8* @runtime.alloc(i32 4) %1 = call i8* @runtime.alloc(i32 4, i8* null)
%2 = bitcast i8* %1 to i32* %2 = bitcast i8* %1 to i32*
ret i32* %2 ret i32* %2
} }
@ -61,7 +61,7 @@ define void @testNonEscapingLoop() {
entry: entry:
br label %loop br label %loop
loop: loop:
%0 = call i8* @runtime.alloc(i32 4) %0 = call i8* @runtime.alloc(i32 4, i8* null)
%1 = bitcast i8* %0 to i32* %1 = bitcast i8* %0 to i32*
%2 = call i32* @noescapeIntPtr(i32* %1) %2 = call i32* @noescapeIntPtr(i32* %1)
%3 = icmp eq i32* null, %2 %3 = icmp eq i32* null, %2
@ -72,7 +72,7 @@ end:
; Test a zero-sized allocation. ; Test a zero-sized allocation.
define void @testZeroSizedAlloc() { define void @testZeroSizedAlloc() {
%1 = call i8* @runtime.alloc(i32 0) %1 = call i8* @runtime.alloc(i32 0, i8* null)
%2 = bitcast i8* %1 to i32* %2 = bitcast i8* %1 to i32*
%3 = call i32* @noescapeIntPtr(i32* %2) %3 = call i32* @noescapeIntPtr(i32* %2)
ret void ret void

8
transform/testdata/allocs.out.ll предоставленный
Просмотреть файл

@ -3,7 +3,7 @@ target triple = "armv7m-none-eabi"
@runtime.zeroSizedAlloc = internal global i8 0, align 1 @runtime.zeroSizedAlloc = internal global i8 0, align 1
declare nonnull i8* @runtime.alloc(i32) declare nonnull i8* @runtime.alloc(i32, i8*)
define void @testInt() { define void @testInt() {
%stackalloc.alloca = alloca [1 x i32], align 4 %stackalloc.alloca = alloca [1 x i32], align 4
@ -25,14 +25,14 @@ define i16 @testArray() {
} }
define void @testEscapingCall() { define void @testEscapingCall() {
%1 = call i8* @runtime.alloc(i32 4) %1 = call i8* @runtime.alloc(i32 4, i8* null)
%2 = bitcast i8* %1 to i32* %2 = bitcast i8* %1 to i32*
%3 = call i32* @escapeIntPtr(i32* %2) %3 = call i32* @escapeIntPtr(i32* %2)
ret void ret void
} }
define void @testEscapingCall2() { define void @testEscapingCall2() {
%1 = call i8* @runtime.alloc(i32 4) %1 = call i8* @runtime.alloc(i32 4, i8* null)
%2 = bitcast i8* %1 to i32* %2 = bitcast i8* %1 to i32*
%3 = call i32* @escapeIntPtrSometimes(i32* %2, i32* %2) %3 = call i32* @escapeIntPtrSometimes(i32* %2, i32* %2)
ret void ret void
@ -47,7 +47,7 @@ define void @testNonEscapingCall() {
} }
define i32* @testEscapingReturn() { define i32* @testEscapingReturn() {
%1 = call i8* @runtime.alloc(i32 4) %1 = call i8* @runtime.alloc(i32 4, i8* null)
%2 = bitcast i8* %1 to i32* %2 = bitcast i8* %1 to i32*
ret i32* %2 ret i32* %2
} }

2
transform/testdata/coroutines.ll предоставленный
Просмотреть файл

@ -9,7 +9,7 @@ declare void @"internal/task.Pause"(i8*, i8*)
declare void @runtime.scheduler(i8*, i8*) declare void @runtime.scheduler(i8*, i8*)
declare i8* @runtime.alloc(i32, i8*, i8*) declare i8* @runtime.alloc(i32, i8*, i8*, i8*)
declare void @runtime.free(i8*, i8*, i8*) declare void @runtime.free(i8*, i8*, i8*)
declare %"internal/task.Task"* @"internal/task.Current"(i8*, i8*) declare %"internal/task.Task"* @"internal/task.Current"(i8*, i8*)

14
transform/testdata/coroutines.out.ll предоставленный
Просмотреть файл

@ -10,7 +10,7 @@ declare void @"internal/task.Pause"(i8*, i8*)
declare void @runtime.scheduler(i8*, i8*) declare void @runtime.scheduler(i8*, i8*)
declare i8* @runtime.alloc(i32, i8*, i8*) declare i8* @runtime.alloc(i32, i8*, i8*, i8*)
declare void @runtime.free(i8*, i8*, i8*) declare void @runtime.free(i8*, i8*, i8*)
@ -66,7 +66,7 @@ entry:
define void @ditchTail(i32 %0, i64 %1, i8* %2, i8* %parentHandle) { define void @ditchTail(i32 %0, i64 %1, i8* %2, i8* %parentHandle) {
entry: entry:
%task.current = bitcast i8* %parentHandle to %"internal/task.Task"* %task.current = bitcast i8* %parentHandle to %"internal/task.Task"*
%ret.ditch = call i8* @runtime.alloc(i32 4, i8* undef, i8* undef) %ret.ditch = call i8* @runtime.alloc(i32 4, i8* null, i8* undef, i8* undef)
call void @"(*internal/task.Task).setReturnPtr"(%"internal/task.Task"* %task.current, i8* %ret.ditch, i8* undef, i8* undef) call void @"(*internal/task.Task).setReturnPtr"(%"internal/task.Task"* %task.current, i8* %ret.ditch, i8* undef, i8* undef)
%3 = call i32 @delayedValue(i32 %0, i64 %1, i8* undef, i8* %parentHandle) %3 = call i32 @delayedValue(i32 %0, i64 %1, i8* undef, i8* %parentHandle)
ret void ret void
@ -85,7 +85,7 @@ entry:
%ret.ptr = call i8* @"(*internal/task.Task).getReturnPtr"(%"internal/task.Task"* %task.current, i8* undef, i8* undef) %ret.ptr = call i8* @"(*internal/task.Task).getReturnPtr"(%"internal/task.Task"* %task.current, i8* undef, i8* undef)
%ret.ptr.bitcast = bitcast i8* %ret.ptr to i32* %ret.ptr.bitcast = bitcast i8* %ret.ptr to i32*
store i32 %0, i32* %ret.ptr.bitcast, align 4 store i32 %0, i32* %ret.ptr.bitcast, align 4
%ret.alternate = call i8* @runtime.alloc(i32 4, i8* undef, i8* undef) %ret.alternate = call i8* @runtime.alloc(i32 4, i8* null, i8* undef, i8* undef)
call void @"(*internal/task.Task).setReturnPtr"(%"internal/task.Task"* %task.current, i8* %ret.alternate, i8* undef, i8* undef) call void @"(*internal/task.Task).setReturnPtr"(%"internal/task.Task"* %task.current, i8* %ret.alternate, i8* undef, i8* undef)
%4 = call i32 @delayedValue(i32 %1, i64 %2, i8* undef, i8* %parentHandle) %4 = call i32 @delayedValue(i32 %1, i64 %2, i8* undef, i8* %parentHandle)
ret i32 undef ret i32 undef
@ -96,7 +96,7 @@ entry:
%call.return = alloca i32, align 4 %call.return = alloca i32, align 4
%coro.id = call token @llvm.coro.id(i32 0, i8* null, i8* null, i8* null) %coro.id = call token @llvm.coro.id(i32 0, i8* null, i8* null, i8* null)
%coro.size = call i32 @llvm.coro.size.i32() %coro.size = call i32 @llvm.coro.size.i32()
%coro.alloc = call i8* @runtime.alloc(i32 %coro.size, i8* undef, i8* undef) %coro.alloc = call i8* @runtime.alloc(i32 %coro.size, i8* null, i8* undef, i8* undef)
%coro.state = call i8* @llvm.coro.begin(token %coro.id, i8* %coro.alloc) %coro.state = call i8* @llvm.coro.begin(token %coro.id, i8* %coro.alloc)
%task.current2 = bitcast i8* %parentHandle to %"internal/task.Task"* %task.current2 = bitcast i8* %parentHandle to %"internal/task.Task"*
%task.state.parent = call i8* @"(*internal/task.Task).setState"(%"internal/task.Task"* %task.current2, i8* %coro.state, i8* undef, i8* undef) %task.state.parent = call i8* @"(*internal/task.Task).setState"(%"internal/task.Task"* %task.current2, i8* %coro.state, i8* undef, i8* undef)
@ -143,7 +143,7 @@ entry:
%a = alloca i8, align 1 %a = alloca i8, align 1
%coro.id = call token @llvm.coro.id(i32 0, i8* null, i8* null, i8* null) %coro.id = call token @llvm.coro.id(i32 0, i8* null, i8* null, i8* null)
%coro.size = call i32 @llvm.coro.size.i32() %coro.size = call i32 @llvm.coro.size.i32()
%coro.alloc = call i8* @runtime.alloc(i32 %coro.size, i8* undef, i8* undef) %coro.alloc = call i8* @runtime.alloc(i32 %coro.size, i8* null, i8* undef, i8* undef)
%coro.state = call i8* @llvm.coro.begin(token %coro.id, i8* %coro.alloc) %coro.state = call i8* @llvm.coro.begin(token %coro.id, i8* %coro.alloc)
%task.current = bitcast i8* %parentHandle to %"internal/task.Task"* %task.current = bitcast i8* %parentHandle to %"internal/task.Task"*
%task.state.parent = call i8* @"(*internal/task.Task).setState"(%"internal/task.Task"* %task.current, i8* %coro.state, i8* undef, i8* undef) %task.state.parent = call i8* @"(*internal/task.Task).setState"(%"internal/task.Task"* %task.current, i8* %coro.state, i8* undef, i8* undef)
@ -180,7 +180,7 @@ entry:
%a = alloca i8, align 1 %a = alloca i8, align 1
%coro.id = call token @llvm.coro.id(i32 0, i8* null, i8* null, i8* null) %coro.id = call token @llvm.coro.id(i32 0, i8* null, i8* null, i8* null)
%coro.size = call i32 @llvm.coro.size.i32() %coro.size = call i32 @llvm.coro.size.i32()
%coro.alloc = call i8* @runtime.alloc(i32 %coro.size, i8* undef, i8* undef) %coro.alloc = call i8* @runtime.alloc(i32 %coro.size, i8* null, i8* undef, i8* undef)
%coro.state = call i8* @llvm.coro.begin(token %coro.id, i8* %coro.alloc) %coro.state = call i8* @llvm.coro.begin(token %coro.id, i8* %coro.alloc)
%task.current = bitcast i8* %parentHandle to %"internal/task.Task"* %task.current = bitcast i8* %parentHandle to %"internal/task.Task"*
%task.state.parent = call i8* @"(*internal/task.Task).setState"(%"internal/task.Task"* %task.current, i8* %coro.state, i8* undef, i8* undef) %task.state.parent = call i8* @"(*internal/task.Task).setState"(%"internal/task.Task"* %task.current, i8* %coro.state, i8* undef, i8* undef)
@ -225,7 +225,7 @@ define i8 @usePtr(i8* %0, i8* %1, i8* %parentHandle) {
entry: entry:
%coro.id = call token @llvm.coro.id(i32 0, i8* null, i8* null, i8* null) %coro.id = call token @llvm.coro.id(i32 0, i8* null, i8* null, i8* null)
%coro.size = call i32 @llvm.coro.size.i32() %coro.size = call i32 @llvm.coro.size.i32()
%coro.alloc = call i8* @runtime.alloc(i32 %coro.size, i8* undef, i8* undef) %coro.alloc = call i8* @runtime.alloc(i32 %coro.size, i8* null, i8* undef, i8* undef)
%coro.state = call i8* @llvm.coro.begin(token %coro.id, i8* %coro.alloc) %coro.state = call i8* @llvm.coro.begin(token %coro.id, i8* %coro.alloc)
%task.current = bitcast i8* %parentHandle to %"internal/task.Task"* %task.current = bitcast i8* %parentHandle to %"internal/task.Task"*
%task.state.parent = call i8* @"(*internal/task.Task).setState"(%"internal/task.Task"* %task.current, i8* %coro.state, i8* undef, i8* undef) %task.state.parent = call i8* @"(*internal/task.Task).setState"(%"internal/task.Task"* %task.current, i8* %coro.state, i8* undef, i8* undef)

14
transform/testdata/gc-stackslots.ll предоставленный
Просмотреть файл

@ -8,7 +8,7 @@ target triple = "wasm32-unknown-unknown-wasm"
declare void @runtime.trackPointer(i8* nocapture readonly) declare void @runtime.trackPointer(i8* nocapture readonly)
declare noalias nonnull i8* @runtime.alloc(i32) declare noalias nonnull i8* @runtime.alloc(i32, i8*)
; Generic function that returns a pointer (that must be tracked). ; Generic function that returns a pointer (that must be tracked).
define i8* @getPointer() { define i8* @getPointer() {
@ -18,7 +18,7 @@ define i8* @getPointer() {
define i8* @needsStackSlots() { define i8* @needsStackSlots() {
; Tracked pointer. Although, in this case the value is immediately returned ; Tracked pointer. Although, in this case the value is immediately returned
; so tracking it is not really necessary. ; so tracking it is not really necessary.
%ptr = call i8* @runtime.alloc(i32 4) %ptr = call i8* @runtime.alloc(i32 4, i8* null)
call void @runtime.trackPointer(i8* %ptr) call void @runtime.trackPointer(i8* %ptr)
; Restoring the stack pointer can happen at this position, before the return. ; Restoring the stack pointer can happen at this position, before the return.
; This avoids issues with tail calls. ; This avoids issues with tail calls.
@ -41,7 +41,7 @@ define i8* @needsStackSlots2() {
call void @runtime.trackPointer(i8* %ptr2) call void @runtime.trackPointer(i8* %ptr2)
; Here is finally the point where an allocation happens. ; Here is finally the point where an allocation happens.
%unused = call i8* @runtime.alloc(i32 4) %unused = call i8* @runtime.alloc(i32 4, i8* null)
call void @runtime.trackPointer(i8* %unused) call void @runtime.trackPointer(i8* %unused)
ret i8* %ptr1 ret i8* %ptr1
@ -59,7 +59,7 @@ define i8* @fibNext(i8* %x, i8* %y) {
%x.val = load i8, i8* %x %x.val = load i8, i8* %x
%y.val = load i8, i8* %y %y.val = load i8, i8* %y
%out.val = add i8 %x.val, %y.val %out.val = add i8 %x.val, %y.val
%out.alloc = call i8* @runtime.alloc(i32 1) %out.alloc = call i8* @runtime.alloc(i32 1, i8* null)
call void @runtime.trackPointer(i8* %out.alloc) call void @runtime.trackPointer(i8* %out.alloc)
store i8 %out.val, i8* %out.alloc store i8 %out.val, i8* %out.alloc
ret i8* %out.alloc ret i8* %out.alloc
@ -67,9 +67,9 @@ define i8* @fibNext(i8* %x, i8* %y) {
define i8* @allocLoop() { define i8* @allocLoop() {
entry: entry:
%entry.x = call i8* @runtime.alloc(i32 1) %entry.x = call i8* @runtime.alloc(i32 1, i8* null)
call void @runtime.trackPointer(i8* %entry.x) call void @runtime.trackPointer(i8* %entry.x)
%entry.y = call i8* @runtime.alloc(i32 1) %entry.y = call i8* @runtime.alloc(i32 1, i8* null)
call void @runtime.trackPointer(i8* %entry.y) call void @runtime.trackPointer(i8* %entry.y)
store i8 1, i8* %entry.y store i8 1, i8* %entry.y
br label %loop br label %loop
@ -95,7 +95,7 @@ define void @testGEPBitcast() {
%arr = call [32 x i8]* @arrayAlloc() %arr = call [32 x i8]* @arrayAlloc()
%arr.bitcast = getelementptr [32 x i8], [32 x i8]* %arr, i32 0, i32 0 %arr.bitcast = getelementptr [32 x i8], [32 x i8]* %arr, i32 0, i32 0
call void @runtime.trackPointer(i8* %arr.bitcast) call void @runtime.trackPointer(i8* %arr.bitcast)
%other = call i8* @runtime.alloc(i32 1) %other = call i8* @runtime.alloc(i32 1, i8* null)
call void @runtime.trackPointer(i8* %other) call void @runtime.trackPointer(i8* %other)
ret void ret void
} }

14
transform/testdata/gc-stackslots.out.ll предоставленный
Просмотреть файл

@ -8,7 +8,7 @@ target triple = "wasm32-unknown-unknown-wasm"
declare void @runtime.trackPointer(i8* nocapture readonly) declare void @runtime.trackPointer(i8* nocapture readonly)
declare noalias nonnull i8* @runtime.alloc(i32) declare noalias nonnull i8* @runtime.alloc(i32, i8*)
define i8* @getPointer() { define i8* @getPointer() {
ret i8* @someGlobal ret i8* @someGlobal
@ -22,7 +22,7 @@ define i8* @needsStackSlots() {
store %runtime.stackChainObject* %1, %runtime.stackChainObject** %2, align 4 store %runtime.stackChainObject* %1, %runtime.stackChainObject** %2, align 4
%3 = bitcast { %runtime.stackChainObject*, i32, i8* }* %gc.stackobject to %runtime.stackChainObject* %3 = bitcast { %runtime.stackChainObject*, i32, i8* }* %gc.stackobject to %runtime.stackChainObject*
store %runtime.stackChainObject* %3, %runtime.stackChainObject** @runtime.stackChainStart, align 4 store %runtime.stackChainObject* %3, %runtime.stackChainObject** @runtime.stackChainStart, align 4
%ptr = call i8* @runtime.alloc(i32 4) %ptr = call i8* @runtime.alloc(i32 4, i8* null)
%4 = getelementptr { %runtime.stackChainObject*, i32, i8* }, { %runtime.stackChainObject*, i32, i8* }* %gc.stackobject, i32 0, i32 2 %4 = getelementptr { %runtime.stackChainObject*, i32, i8* }, { %runtime.stackChainObject*, i32, i8* }* %gc.stackobject, i32 0, i32 2
store i8* %ptr, i8** %4, align 4 store i8* %ptr, i8** %4, align 4
store %runtime.stackChainObject* %1, %runtime.stackChainObject** @runtime.stackChainStart, align 4 store %runtime.stackChainObject* %1, %runtime.stackChainObject** @runtime.stackChainStart, align 4
@ -49,7 +49,7 @@ define i8* @needsStackSlots2() {
%ptr2 = getelementptr i8, i8* @someGlobal, i32 0 %ptr2 = getelementptr i8, i8* @someGlobal, i32 0
%7 = getelementptr { %runtime.stackChainObject*, i32, i8*, i8*, i8*, i8*, i8* }, { %runtime.stackChainObject*, i32, i8*, i8*, i8*, i8*, i8* }* %gc.stackobject, i32 0, i32 5 %7 = getelementptr { %runtime.stackChainObject*, i32, i8*, i8*, i8*, i8*, i8* }, { %runtime.stackChainObject*, i32, i8*, i8*, i8*, i8*, i8* }* %gc.stackobject, i32 0, i32 5
store i8* %ptr2, i8** %7, align 4 store i8* %ptr2, i8** %7, align 4
%unused = call i8* @runtime.alloc(i32 4) %unused = call i8* @runtime.alloc(i32 4, i8* null)
%8 = getelementptr { %runtime.stackChainObject*, i32, i8*, i8*, i8*, i8*, i8* }, { %runtime.stackChainObject*, i32, i8*, i8*, i8*, i8*, i8* }* %gc.stackobject, i32 0, i32 6 %8 = getelementptr { %runtime.stackChainObject*, i32, i8*, i8*, i8*, i8*, i8* }, { %runtime.stackChainObject*, i32, i8*, i8*, i8*, i8*, i8* }* %gc.stackobject, i32 0, i32 6
store i8* %unused, i8** %8, align 4 store i8* %unused, i8** %8, align 4
store %runtime.stackChainObject* %1, %runtime.stackChainObject** @runtime.stackChainStart, align 4 store %runtime.stackChainObject* %1, %runtime.stackChainObject** @runtime.stackChainStart, align 4
@ -72,7 +72,7 @@ define i8* @fibNext(i8* %x, i8* %y) {
%x.val = load i8, i8* %x, align 1 %x.val = load i8, i8* %x, align 1
%y.val = load i8, i8* %y, align 1 %y.val = load i8, i8* %y, align 1
%out.val = add i8 %x.val, %y.val %out.val = add i8 %x.val, %y.val
%out.alloc = call i8* @runtime.alloc(i32 1) %out.alloc = call i8* @runtime.alloc(i32 1, i8* null)
%4 = getelementptr { %runtime.stackChainObject*, i32, i8* }, { %runtime.stackChainObject*, i32, i8* }* %gc.stackobject, i32 0, i32 2 %4 = getelementptr { %runtime.stackChainObject*, i32, i8* }, { %runtime.stackChainObject*, i32, i8* }* %gc.stackobject, i32 0, i32 2
store i8* %out.alloc, i8** %4, align 4 store i8* %out.alloc, i8** %4, align 4
store %runtime.stackChainObject* %1, %runtime.stackChainObject** @runtime.stackChainStart, align 4 store %runtime.stackChainObject* %1, %runtime.stackChainObject** @runtime.stackChainStart, align 4
@ -89,10 +89,10 @@ entry:
store %runtime.stackChainObject* %0, %runtime.stackChainObject** %1, align 4 store %runtime.stackChainObject* %0, %runtime.stackChainObject** %1, align 4
%2 = bitcast { %runtime.stackChainObject*, i32, i8*, i8*, i8*, i8*, i8* }* %gc.stackobject to %runtime.stackChainObject* %2 = bitcast { %runtime.stackChainObject*, i32, i8*, i8*, i8*, i8*, i8* }* %gc.stackobject to %runtime.stackChainObject*
store %runtime.stackChainObject* %2, %runtime.stackChainObject** @runtime.stackChainStart, align 4 store %runtime.stackChainObject* %2, %runtime.stackChainObject** @runtime.stackChainStart, align 4
%entry.x = call i8* @runtime.alloc(i32 1) %entry.x = call i8* @runtime.alloc(i32 1, i8* null)
%3 = getelementptr { %runtime.stackChainObject*, i32, i8*, i8*, i8*, i8*, i8* }, { %runtime.stackChainObject*, i32, i8*, i8*, i8*, i8*, i8* }* %gc.stackobject, i32 0, i32 2 %3 = getelementptr { %runtime.stackChainObject*, i32, i8*, i8*, i8*, i8*, i8* }, { %runtime.stackChainObject*, i32, i8*, i8*, i8*, i8*, i8* }* %gc.stackobject, i32 0, i32 2
store i8* %entry.x, i8** %3, align 4 store i8* %entry.x, i8** %3, align 4
%entry.y = call i8* @runtime.alloc(i32 1) %entry.y = call i8* @runtime.alloc(i32 1, i8* null)
%4 = getelementptr { %runtime.stackChainObject*, i32, i8*, i8*, i8*, i8*, i8* }, { %runtime.stackChainObject*, i32, i8*, i8*, i8*, i8*, i8* }* %gc.stackobject, i32 0, i32 3 %4 = getelementptr { %runtime.stackChainObject*, i32, i8*, i8*, i8*, i8*, i8* }, { %runtime.stackChainObject*, i32, i8*, i8*, i8*, i8*, i8* }* %gc.stackobject, i32 0, i32 3
store i8* %entry.y, i8** %4, align 4 store i8* %entry.y, i8** %4, align 4
store i8 1, i8* %entry.y, align 1 store i8 1, i8* %entry.y, align 1
@ -131,7 +131,7 @@ define void @testGEPBitcast() {
%arr.bitcast = getelementptr [32 x i8], [32 x i8]* %arr, i32 0, i32 0 %arr.bitcast = getelementptr [32 x i8], [32 x i8]* %arr, i32 0, i32 0
%4 = getelementptr { %runtime.stackChainObject*, i32, i8*, i8* }, { %runtime.stackChainObject*, i32, i8*, i8* }* %gc.stackobject, i32 0, i32 2 %4 = getelementptr { %runtime.stackChainObject*, i32, i8*, i8* }, { %runtime.stackChainObject*, i32, i8*, i8* }* %gc.stackobject, i32 0, i32 2
store i8* %arr.bitcast, i8** %4, align 4 store i8* %arr.bitcast, i8** %4, align 4
%other = call i8* @runtime.alloc(i32 1) %other = call i8* @runtime.alloc(i32 1, i8* null)
%5 = getelementptr { %runtime.stackChainObject*, i32, i8*, i8* }, { %runtime.stackChainObject*, i32, i8*, i8* }* %gc.stackobject, i32 0, i32 3 %5 = getelementptr { %runtime.stackChainObject*, i32, i8*, i8* }, { %runtime.stackChainObject*, i32, i8*, i8* }* %gc.stackobject, i32 0, i32 3
store i8* %other, i8** %5, align 4 store i8* %other, i8** %5, align 4
store %runtime.stackChainObject* %1, %runtime.stackChainObject** @runtime.stackChainStart, align 4 store %runtime.stackChainObject* %1, %runtime.stackChainObject** @runtime.stackChainStart, align 4

Просмотреть файл

@ -41,6 +41,12 @@ func testTransform(t *testing.T, pathPrefix string, transform func(mod llvm.Modu
// Perform the transform. // Perform the transform.
transform(mod) transform(mod)
// Check for any incorrect IR.
err = llvm.VerifyModule(mod, llvm.PrintMessageAction)
if err != nil {
t.Fatal("IR verification failed")
}
// Get the output from the test and filter some irrelevant lines. // Get the output from the test and filter some irrelevant lines.
actual := mod.String() actual := mod.String()
actual = actual[strings.Index(actual, "\ntarget datalayout = ")+1:] actual = actual[strings.Index(actual, "\ntarget datalayout = ")+1:]