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).
Этот коммит содержится в:
родитель
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))
|
||||
}
|
||||
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), "")
|
||||
return buf, nil
|
||||
} else {
|
||||
|
@ -1736,7 +1737,8 @@ func (b *builder) createExpr(expr ssa.Value) (llvm.Value, error) {
|
|||
return llvm.Value{}, err
|
||||
}
|
||||
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")
|
||||
|
||||
// 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.
|
||||
size := b.targetData.TypeAllocSize(deferFrameType)
|
||||
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")
|
||||
}
|
||||
if b.NeedsStackObjects {
|
||||
|
|
|
@ -97,6 +97,7 @@ func EmitPointerPack(builder llvm.Builder, mod llvm.Module, needsStackObjects bo
|
|||
alloc := mod.NamedFunction("runtime.alloc")
|
||||
packedHeapAlloc := builder.CreateCall(alloc, []llvm.Value{
|
||||
sizeValue,
|
||||
llvm.ConstNull(i8ptrType),
|
||||
llvm.Undef(i8ptrType), // unused context parameter
|
||||
llvm.ConstPointerNull(i8ptrType), // coroutine handle
|
||||
}, "")
|
||||
|
|
2
compiler/testdata/basic.ll
предоставленный
2
compiler/testdata/basic.ll
предоставленный
|
@ -6,7 +6,7 @@ target triple = "wasm32-unknown-wasi"
|
|||
%main.kv = type { float }
|
||||
%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
|
||||
define hidden void @main.init(i8* %context, i8* %parentHandle) unnamed_addr #0 {
|
||||
|
|
2
compiler/testdata/channel.ll
предоставленный
2
compiler/testdata/channel.ll
предоставленный
|
@ -9,7 +9,7 @@ target triple = "wasm32-unknown-wasi"
|
|||
%"internal/task.state" = type { 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
|
||||
define hidden void @main.init(i8* %context, i8* %parentHandle) unnamed_addr #0 {
|
||||
|
|
2
compiler/testdata/float.ll
предоставленный
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 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
|
||||
define hidden void @main.init(i8* %context, i8* %parentHandle) unnamed_addr #0 {
|
||||
|
|
2
compiler/testdata/func.ll
предоставленный
2
compiler/testdata/func.ll
предоставленный
|
@ -8,7 +8,7 @@ target triple = "wasm32-unknown-wasi"
|
|||
@"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}{}" }
|
||||
|
||||
declare noalias nonnull i8* @runtime.alloc(i32, i8*, i8*)
|
||||
declare noalias nonnull i8* @runtime.alloc(i32, i8*, i8*, i8*)
|
||||
|
||||
; Function Attrs: nounwind
|
||||
define hidden void @main.init(i8* %context, i8* %parentHandle) unnamed_addr #0 {
|
||||
|
|
4
compiler/testdata/go1.17.ll
предоставленный
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 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
|
||||
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
|
||||
define hidden [4 x i32]* @main.SliceToArrayConst(i8* %context, i8* %parentHandle) unnamed_addr #0 {
|
||||
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
|
||||
|
||||
slicetoarray.throw: ; preds = %entry
|
||||
|
|
10
compiler/testdata/goroutine-cortex-m-qemu.ll
предоставленный
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
|
||||
|
||||
declare noalias nonnull i8* @runtime.alloc(i32, i8*, i8*)
|
||||
declare noalias nonnull i8* @runtime.alloc(i32, i8*, i8*, i8*)
|
||||
|
||||
; Function Attrs: nounwind
|
||||
define hidden void @main.init(i8* %context, i8* %parentHandle) unnamed_addr #0 {
|
||||
|
@ -66,10 +66,10 @@ entry:
|
|||
; Function Attrs: nounwind
|
||||
define hidden void @main.closureFunctionGoroutine(i8* %context, i8* %parentHandle) unnamed_addr #0 {
|
||||
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*
|
||||
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*
|
||||
store i32 5, i32* %2, align 4
|
||||
%3 = getelementptr inbounds i8, i8* %1, i32 4
|
||||
|
@ -107,7 +107,7 @@ declare void @runtime.printint32(i32, i8*, i8*)
|
|||
; Function Attrs: nounwind
|
||||
define hidden void @main.funcGoroutine(i8* %fn.context, void ()* %fn.funcptr, i8* %context, i8* %parentHandle) unnamed_addr #0 {
|
||||
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*
|
||||
store i32 5, i32* %1, align 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
|
||||
define hidden void @main.startInterfaceMethod(i32 %itf.typecode, i8* %itf.value, i8* %context, i8* %parentHandle) unnamed_addr #0 {
|
||||
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**
|
||||
store i8* %itf.value, i8** %1, align 4
|
||||
%2 = getelementptr inbounds i8, i8* %0, i32 4
|
||||
|
|
10
compiler/testdata/goroutine-wasm.ll
предоставленный
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.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
|
||||
define hidden void @main.init(i8* %context, i8* %parentHandle) unnamed_addr #0 {
|
||||
|
@ -51,10 +51,10 @@ entry:
|
|||
; Function Attrs: nounwind
|
||||
define hidden void @main.closureFunctionGoroutine(i8* %context, i8* %parentHandle) unnamed_addr #0 {
|
||||
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*
|
||||
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*
|
||||
store i32 5, i32* %2, align 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 {
|
||||
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
|
||||
%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*
|
||||
store i32 5, i32* %2, align 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
|
||||
define hidden void @main.startInterfaceMethod(i32 %itf.typecode, i8* %itf.value, i8* %context, i8* %parentHandle) unnamed_addr #0 {
|
||||
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**
|
||||
store i8* %itf.value, i8** %1, align 4
|
||||
%2 = getelementptr inbounds i8, i8* %0, i32 4
|
||||
|
|
2
compiler/testdata/interface.ll
предоставленный
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.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
|
||||
define hidden void @main.init(i8* %context, i8* %parentHandle) unnamed_addr #0 {
|
||||
|
|
2
compiler/testdata/intrinsics-cortex-m-qemu.ll
предоставленный
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 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
|
||||
define hidden void @main.init(i8* %context, i8* %parentHandle) unnamed_addr #0 {
|
||||
|
|
2
compiler/testdata/intrinsics-wasm.ll
предоставленный
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 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
|
||||
define hidden void @main.init(i8* %context, i8* %parentHandle) unnamed_addr #0 {
|
||||
|
|
2
compiler/testdata/pointer.ll
предоставленный
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 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
|
||||
define hidden void @main.init(i8* %context, i8* %parentHandle) unnamed_addr #0 {
|
||||
|
|
2
compiler/testdata/pragma.ll
предоставленный
2
compiler/testdata/pragma.ll
предоставленный
|
@ -10,7 +10,7 @@ target triple = "wasm32-unknown-wasi"
|
|||
@undefinedGlobalNotInSection = external global i32, align 4
|
||||
@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
|
||||
define hidden void @main.init(i8* %context, i8* %parentHandle) unnamed_addr #0 {
|
||||
|
|
12
compiler/testdata/slice.ll
предоставленный
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 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
|
||||
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
|
||||
define hidden { i32*, i32, i32 } @main.sliceAppendValues(i32* %ints.data, i32 %ints.len, i32 %ints.cap, i8* %context, i8* %parentHandle) unnamed_addr #0 {
|
||||
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*
|
||||
store i32 1, i32* %0, align 4
|
||||
%1 = getelementptr inbounds i8, i8* %varargs, i32 4
|
||||
|
@ -105,7 +105,7 @@ slice.throw: ; preds = %entry
|
|||
unreachable
|
||||
|
||||
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
|
||||
%1 = insertvalue { i8*, i32, i32 } %0, i32 %len, 1
|
||||
%2 = insertvalue { i8*, i32, i32 } %1, i32 %len, 2
|
||||
|
@ -126,7 +126,7 @@ slice.throw: ; preds = %entry
|
|||
|
||||
slice.next: ; preds = %entry
|
||||
%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*
|
||||
%0 = insertvalue { i16*, i32, i32 } undef, i16* %makeslice.array, 0
|
||||
%1 = insertvalue { i16*, i32, i32 } %0, i32 %len, 1
|
||||
|
@ -146,7 +146,7 @@ slice.throw: ; preds = %entry
|
|||
|
||||
slice.next: ; preds = %entry
|
||||
%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]*
|
||||
%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
|
||||
|
@ -166,7 +166,7 @@ slice.throw: ; preds = %entry
|
|||
|
||||
slice.next: ; preds = %entry
|
||||
%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*
|
||||
%0 = insertvalue { i32*, i32, i32 } undef, i32* %makeslice.array, 0
|
||||
%1 = insertvalue { i32*, i32, i32 } %0, i32 %len, 1
|
||||
|
|
2
compiler/testdata/string.ll
предоставленный
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
|
||||
|
||||
declare noalias nonnull i8* @runtime.alloc(i32, i8*, i8*)
|
||||
declare noalias nonnull i8* @runtime.alloc(i32, i8*, i8*, i8*)
|
||||
|
||||
; Function Attrs: nounwind
|
||||
define hidden void @main.init(i8* %context, i8* %parentHandle) unnamed_addr #0 {
|
||||
|
|
6
interp/testdata/slice-copy.ll
предоставленный
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 i8* @runtime.alloc(i64) unnamed_addr
|
||||
declare i8* @runtime.alloc(i64, i8*) unnamed_addr
|
||||
|
||||
declare void @runtime.printuint8(i8)
|
||||
|
||||
|
@ -52,7 +52,7 @@ entry:
|
|||
; uint8SliceDst = make([]uint8, len(uint8SliceSrc))
|
||||
%uint8SliceSrc = load { i8*, i64, i64 }, { i8*, i64, i64 }* @main.uint8SliceSrc
|
||||
%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
|
||||
%1 = insertvalue { i8*, i64, i64 } %0, i64 %uint8SliceSrc.len, 1
|
||||
%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.len = extractvalue { i16*, i64, i64 } %int16SliceSrc, 1
|
||||
%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*
|
||||
%3 = insertvalue { i16*, i64, i64 } undef, i16* %int16SliceDst.buf, 0
|
||||
%4 = insertvalue { i16*, i64, i64 } %3, i64 %int16SliceSrc.len, 1
|
||||
|
|
|
@ -729,7 +729,7 @@ func Zero(typ Type) Value {
|
|||
func New(typ Type) Value {
|
||||
return Value{
|
||||
typecode: PtrTo(typ).(rawType),
|
||||
value: alloc(typ.Size()),
|
||||
value: alloc(typ.Size(), nil),
|
||||
flags: valueFlagExported,
|
||||
}
|
||||
}
|
||||
|
@ -778,7 +778,7 @@ func (e *ValueError) Error() string {
|
|||
func memcpy(dst, src unsafe.Pointer, size uintptr)
|
||||
|
||||
//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
|
||||
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
|
||||
func libc_malloc(size uintptr) unsafe.Pointer {
|
||||
return alloc(size)
|
||||
return alloc(size, nil)
|
||||
}
|
||||
|
||||
//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
|
||||
// doesn't overflow. However the current implementation should normally work
|
||||
// fine.
|
||||
return alloc(nmemb * size)
|
||||
return alloc(nmemb*size, nil)
|
||||
}
|
||||
|
||||
//export realloc
|
||||
|
|
|
@ -38,7 +38,7 @@ func growHeap() bool {
|
|||
|
||||
//export malloc
|
||||
func libc_malloc(size uintptr) unsafe.Pointer {
|
||||
return alloc(size)
|
||||
return alloc(size, nil)
|
||||
}
|
||||
|
||||
//export free
|
||||
|
|
|
@ -133,7 +133,7 @@ func chanMake(elementSize uintptr, bufSize uintptr) *channel {
|
|||
return &channel{
|
||||
elementSize: elementSize,
|
||||
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
|
||||
// collection cycle if needed. If no space is free, it panics.
|
||||
//go:noinline
|
||||
func alloc(size uintptr) unsafe.Pointer {
|
||||
func alloc(size uintptr, layout unsafe.Pointer) unsafe.Pointer {
|
||||
if size == 0 {
|
||||
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
|
||||
// collection cycle if needed. If no space is free, it panics.
|
||||
//go:noinline
|
||||
func alloc(size uintptr) unsafe.Pointer {
|
||||
func alloc(size uintptr, layout unsafe.Pointer) unsafe.Pointer {
|
||||
if size == 0 {
|
||||
return unsafe.Pointer(&zeroSizedAlloc)
|
||||
}
|
||||
|
|
|
@ -13,7 +13,7 @@ import (
|
|||
// Ever-incrementing pointer: no memory is freed.
|
||||
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
|
||||
// much. And by using platform-native data types (e.g. *uint8 for 8-bit
|
||||
// systems).
|
||||
|
|
|
@ -10,7 +10,7 @@ import (
|
|||
"unsafe"
|
||||
)
|
||||
|
||||
func alloc(size uintptr) unsafe.Pointer
|
||||
func alloc(size uintptr, layout unsafe.Pointer) unsafe.Pointer
|
||||
|
||||
func free(ptr unsafe.Pointer) {
|
||||
// Nothing to free when nothing gets allocated.
|
||||
|
|
|
@ -69,7 +69,7 @@ func hashmapMake(keySize, valueSize uint8, sizeHint uintptr) *hashmap {
|
|||
bucketBits++
|
||||
}
|
||||
bucketBufSize := unsafe.Sizeof(hashmapBucket{}) + uintptr(keySize)*8 + uintptr(valueSize)*8
|
||||
buckets := alloc(bucketBufSize * (1 << bucketBits))
|
||||
buckets := alloc(bucketBufSize*(1<<bucketBits), nil)
|
||||
return &hashmap{
|
||||
buckets: buckets,
|
||||
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.
|
||||
func hashmapInsertIntoNewBucket(m *hashmap, key, value unsafe.Pointer, tophash uint8) *hashmapBucket {
|
||||
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.
|
||||
slotKeyOffset := unsafe.Sizeof(hashmapBucket{})
|
||||
slotKey := unsafe.Pointer(uintptr(bucketBuf) + slotKeyOffset)
|
||||
|
|
|
@ -27,7 +27,7 @@ func sliceAppend(srcBuf, elemsBuf unsafe.Pointer, srcLen, srcCap, elemsLen uintp
|
|||
// programs).
|
||||
srcCap *= 2
|
||||
}
|
||||
buf := alloc(srcCap * elemSize)
|
||||
buf := alloc(srcCap*elemSize, nil)
|
||||
|
||||
// Copy the old slice to the new slice.
|
||||
if srcLen != 0 {
|
||||
|
|
|
@ -57,7 +57,7 @@ func stringConcat(x, y _string) _string {
|
|||
return x
|
||||
} else {
|
||||
length := x.length + y.length
|
||||
buf := alloc(length)
|
||||
buf := alloc(length, nil)
|
||||
memcpy(buf, unsafe.Pointer(x.ptr), x.length)
|
||||
memcpy(unsafe.Pointer(uintptr(buf)+x.length), unsafe.Pointer(y.ptr), y.length)
|
||||
return _string{ptr: (*byte)(buf), length: length}
|
||||
|
@ -70,7 +70,7 @@ func stringFromBytes(x struct {
|
|||
len uintptr
|
||||
cap uintptr
|
||||
}) _string {
|
||||
buf := alloc(x.len)
|
||||
buf := alloc(x.len, nil)
|
||||
memcpy(buf, unsafe.Pointer(x.ptr), x.len)
|
||||
return _string{ptr: (*byte)(buf), length: x.len}
|
||||
}
|
||||
|
@ -81,7 +81,7 @@ func stringToBytes(x _string) (slice struct {
|
|||
len uintptr
|
||||
cap uintptr
|
||||
}) {
|
||||
buf := alloc(x.length)
|
||||
buf := alloc(x.length, nil)
|
||||
memcpy(buf, unsafe.Pointer(x.ptr), x.length)
|
||||
slice.ptr = (*byte)(buf)
|
||||
slice.len = x.length
|
||||
|
@ -98,7 +98,7 @@ func stringFromRunes(runeSlice []rune) (s _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.
|
||||
index := uintptr(0)
|
||||
|
|
|
@ -70,7 +70,7 @@ func OptimizeAllocs(mod llvm.Module, printAllocs *regexp.Regexp, logger func(tok
|
|||
}
|
||||
|
||||
// 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*
|
||||
// (use %1 only)
|
||||
// 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 {
|
||||
sizeT := c.alloc.FirstParam().Type()
|
||||
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.
|
||||
|
@ -798,7 +798,7 @@ func (c *coroutineLoweringPass) lowerFuncCoro(fn *asyncFunc) {
|
|||
// %coro.size = call i32 @llvm.coro.size.i32()
|
||||
coroSize := c.builder.CreateCall(c.coroSize, []llvm.Value{}, "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)
|
||||
coroState := c.builder.CreateCall(c.coroBegin, []llvm.Value{coroId, coroAlloc}, "coro.state")
|
||||
c.track(coroState)
|
||||
|
|
18
transform/testdata/allocs.ll
предоставленный
18
transform/testdata/allocs.ll
предоставленный
|
@ -3,11 +3,11 @@ target triple = "armv7m-none-eabi"
|
|||
|
||||
@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.
|
||||
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*
|
||||
store i32 5, i32* %2
|
||||
ret void
|
||||
|
@ -16,7 +16,7 @@ define void @testInt() {
|
|||
; Test allocating an array of 3 i16 values that should be allocated on the
|
||||
; stack.
|
||||
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*
|
||||
%3 = getelementptr i16, i16* %2, i32 1
|
||||
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
|
||||
; transform shouldn't be applied.
|
||||
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*
|
||||
%3 = call i32* @escapeIntPtr(i32* %2)
|
||||
ret void
|
||||
}
|
||||
|
||||
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*
|
||||
%3 = call i32* @escapeIntPtrSometimes(i32* %2, i32* %2)
|
||||
ret void
|
||||
|
@ -43,7 +43,7 @@ define void @testEscapingCall2() {
|
|||
|
||||
; Call a function that doesn't let the pointer escape.
|
||||
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*
|
||||
%3 = call i32* @noescapeIntPtr(i32* %2)
|
||||
ret void
|
||||
|
@ -51,7 +51,7 @@ define void @testNonEscapingCall() {
|
|||
|
||||
; Return the allocated value, which lets it escape.
|
||||
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*
|
||||
ret i32* %2
|
||||
}
|
||||
|
@ -61,7 +61,7 @@ define void @testNonEscapingLoop() {
|
|||
entry:
|
||||
br label %loop
|
||||
loop:
|
||||
%0 = call i8* @runtime.alloc(i32 4)
|
||||
%0 = call i8* @runtime.alloc(i32 4, i8* null)
|
||||
%1 = bitcast i8* %0 to i32*
|
||||
%2 = call i32* @noescapeIntPtr(i32* %1)
|
||||
%3 = icmp eq i32* null, %2
|
||||
|
@ -72,7 +72,7 @@ end:
|
|||
|
||||
; Test a zero-sized allocation.
|
||||
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*
|
||||
%3 = call i32* @noescapeIntPtr(i32* %2)
|
||||
ret void
|
||||
|
|
8
transform/testdata/allocs.out.ll
предоставленный
8
transform/testdata/allocs.out.ll
предоставленный
|
@ -3,7 +3,7 @@ target triple = "armv7m-none-eabi"
|
|||
|
||||
@runtime.zeroSizedAlloc = internal global i8 0, align 1
|
||||
|
||||
declare nonnull i8* @runtime.alloc(i32)
|
||||
declare nonnull i8* @runtime.alloc(i32, i8*)
|
||||
|
||||
define void @testInt() {
|
||||
%stackalloc.alloca = alloca [1 x i32], align 4
|
||||
|
@ -25,14 +25,14 @@ define i16 @testArray() {
|
|||
}
|
||||
|
||||
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*
|
||||
%3 = call i32* @escapeIntPtr(i32* %2)
|
||||
ret void
|
||||
}
|
||||
|
||||
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*
|
||||
%3 = call i32* @escapeIntPtrSometimes(i32* %2, i32* %2)
|
||||
ret void
|
||||
|
@ -47,7 +47,7 @@ define void @testNonEscapingCall() {
|
|||
}
|
||||
|
||||
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*
|
||||
ret i32* %2
|
||||
}
|
||||
|
|
2
transform/testdata/coroutines.ll
предоставленный
2
transform/testdata/coroutines.ll
предоставленный
|
@ -9,7 +9,7 @@ declare void @"internal/task.Pause"(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 %"internal/task.Task"* @"internal/task.Current"(i8*, i8*)
|
||||
|
|
14
transform/testdata/coroutines.out.ll
предоставленный
14
transform/testdata/coroutines.out.ll
предоставленный
|
@ -10,7 +10,7 @@ declare void @"internal/task.Pause"(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*)
|
||||
|
||||
|
@ -66,7 +66,7 @@ entry:
|
|||
define void @ditchTail(i32 %0, i64 %1, i8* %2, i8* %parentHandle) {
|
||||
entry:
|
||||
%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)
|
||||
%3 = call i32 @delayedValue(i32 %0, i64 %1, i8* undef, i8* %parentHandle)
|
||||
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.bitcast = bitcast i8* %ret.ptr to i32*
|
||||
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)
|
||||
%4 = call i32 @delayedValue(i32 %1, i64 %2, i8* undef, i8* %parentHandle)
|
||||
ret i32 undef
|
||||
|
@ -96,7 +96,7 @@ entry:
|
|||
%call.return = alloca i32, align 4
|
||||
%coro.id = call token @llvm.coro.id(i32 0, i8* null, i8* null, i8* null)
|
||||
%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)
|
||||
%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)
|
||||
|
@ -143,7 +143,7 @@ entry:
|
|||
%a = alloca i8, align 1
|
||||
%coro.id = call token @llvm.coro.id(i32 0, i8* null, i8* null, i8* null)
|
||||
%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)
|
||||
%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)
|
||||
|
@ -180,7 +180,7 @@ entry:
|
|||
%a = alloca i8, align 1
|
||||
%coro.id = call token @llvm.coro.id(i32 0, i8* null, i8* null, i8* null)
|
||||
%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)
|
||||
%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)
|
||||
|
@ -225,7 +225,7 @@ define i8 @usePtr(i8* %0, i8* %1, i8* %parentHandle) {
|
|||
entry:
|
||||
%coro.id = call token @llvm.coro.id(i32 0, i8* null, i8* null, i8* null)
|
||||
%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)
|
||||
%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)
|
||||
|
|
14
transform/testdata/gc-stackslots.ll
предоставленный
14
transform/testdata/gc-stackslots.ll
предоставленный
|
@ -8,7 +8,7 @@ target triple = "wasm32-unknown-unknown-wasm"
|
|||
|
||||
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).
|
||||
define i8* @getPointer() {
|
||||
|
@ -18,7 +18,7 @@ define i8* @getPointer() {
|
|||
define i8* @needsStackSlots() {
|
||||
; Tracked pointer. Although, in this case the value is immediately returned
|
||||
; 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)
|
||||
; Restoring the stack pointer can happen at this position, before the return.
|
||||
; This avoids issues with tail calls.
|
||||
|
@ -41,7 +41,7 @@ define i8* @needsStackSlots2() {
|
|||
call void @runtime.trackPointer(i8* %ptr2)
|
||||
|
||||
; 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)
|
||||
|
||||
ret i8* %ptr1
|
||||
|
@ -59,7 +59,7 @@ define i8* @fibNext(i8* %x, i8* %y) {
|
|||
%x.val = load i8, i8* %x
|
||||
%y.val = load i8, i8* %y
|
||||
%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)
|
||||
store i8 %out.val, i8* %out.alloc
|
||||
ret i8* %out.alloc
|
||||
|
@ -67,9 +67,9 @@ define i8* @fibNext(i8* %x, i8* %y) {
|
|||
|
||||
define i8* @allocLoop() {
|
||||
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)
|
||||
%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)
|
||||
store i8 1, i8* %entry.y
|
||||
br label %loop
|
||||
|
@ -95,7 +95,7 @@ define void @testGEPBitcast() {
|
|||
%arr = call [32 x i8]* @arrayAlloc()
|
||||
%arr.bitcast = getelementptr [32 x i8], [32 x i8]* %arr, i32 0, i32 0
|
||||
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)
|
||||
ret void
|
||||
}
|
||||
|
|
14
transform/testdata/gc-stackslots.out.ll
предоставленный
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 noalias nonnull i8* @runtime.alloc(i32)
|
||||
declare noalias nonnull i8* @runtime.alloc(i32, i8*)
|
||||
|
||||
define i8* @getPointer() {
|
||||
ret i8* @someGlobal
|
||||
|
@ -22,7 +22,7 @@ define i8* @needsStackSlots() {
|
|||
store %runtime.stackChainObject* %1, %runtime.stackChainObject** %2, align 4
|
||||
%3 = bitcast { %runtime.stackChainObject*, i32, i8* }* %gc.stackobject to %runtime.stackChainObject*
|
||||
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
|
||||
store i8* %ptr, i8** %4, 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
|
||||
%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
|
||||
%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
|
||||
store i8* %unused, i8** %8, 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
|
||||
%y.val = load i8, i8* %y, align 1
|
||||
%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
|
||||
store i8* %out.alloc, i8** %4, 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
|
||||
%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
|
||||
%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
|
||||
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
|
||||
store i8* %entry.y, i8** %4, align 4
|
||||
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
|
||||
%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
|
||||
%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
|
||||
store i8* %other, i8** %5, 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.
|
||||
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.
|
||||
actual := mod.String()
|
||||
actual = actual[strings.Index(actual, "\ntarget datalayout = ")+1:]
|
||||
|
|
Загрузка…
Создание таблицы
Сослаться в новой задаче