Skip to content

Commit ba5988c

Browse files
committed
compiler: implement copy directly
The compiler now implements the copy builtin directly instead of calling sliceCopy. The length is calculated with the llvm.umax.* intrinsics, and the move is performed by llvm.memmove.*. Both of these operations are easily understood by LLVM's optimization passes. The type's alignment is also provided to llvm.memmove.*, which is useful when rewriting the move. Interp no longer needs to reimplement sliceCopy. Some edge case handling was implemented by sliceCopy but not llvm.memmove.*/llvm.memcpy.*. I copied this over, so copies of external slices should work now. Volatile moves/copies are now run at runtime by interp. There is a 4-byte size increase due to some confusing length logic in sendUSBPacket. I will look at sendUSBPacket in a future PR.
1 parent 8ef36ed commit ba5988c

File tree

17 files changed

+353
-358
lines changed

17 files changed

+353
-358
lines changed

builder/sizes_test.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,7 @@ func TestBinarySize(t *testing.T) {
4444
// microcontrollers
4545
{"hifive1b", "examples/echo", 3668, 280, 0, 2244},
4646
{"microbit", "examples/serial", 2694, 342, 8, 2248},
47-
{"wioterminal", "examples/pininterrupt", 6833, 1491, 120, 6888},
47+
{"wioterminal", "examples/pininterrupt", 6837, 1491, 120, 6888},
4848

4949
// TODO: also check wasm. Right now this is difficult, because
5050
// wasm binaries are run through wasm-opt and therefore the

compiler/compiler.go

Lines changed: 31 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1682,13 +1682,41 @@ func (b *builder) createBuiltin(argTypes []types.Type, argValues []llvm.Value, c
16821682
case "copy":
16831683
dst := argValues[0]
16841684
src := argValues[1]
1685+
// Fetch the lengths.
16851686
dstLen := b.CreateExtractValue(dst, 1, "copy.dstLen")
16861687
srcLen := b.CreateExtractValue(src, 1, "copy.srcLen")
1687-
dstBuf := b.CreateExtractValue(dst, 0, "copy.dstArray")
1688-
srcBuf := b.CreateExtractValue(src, 0, "copy.srcArray")
1688+
// Find the minimum of the lengths.
1689+
minFuncName := "llvm.umin.i" + strconv.Itoa(b.uintptrType.IntTypeWidth())
1690+
minFunc := b.mod.NamedFunction(minFuncName)
1691+
if minFunc.IsNil() {
1692+
fnType := llvm.FunctionType(b.uintptrType, []llvm.Type{b.uintptrType, b.uintptrType}, false)
1693+
minFunc = llvm.AddFunction(b.mod, minFuncName, fnType)
1694+
}
1695+
minLen := b.CreateCall(minFunc.GlobalValueType(), minFunc, []llvm.Value{dstLen, srcLen}, "copy.n")
1696+
// Multiply the length by the element size.
16891697
elemType := b.getLLVMType(argTypes[0].Underlying().(*types.Slice).Elem())
16901698
elemSize := llvm.ConstInt(b.uintptrType, b.targetData.TypeAllocSize(elemType), false)
1691-
return b.createRuntimeCall("sliceCopy", []llvm.Value{dstBuf, srcBuf, dstLen, srcLen, elemSize}, "copy.n"), nil
1699+
// NOTE: This is also NSW when uintptr is int, but we can only choose one through the C API?
1700+
size := b.CreateNUWMul(minLen, elemSize, "copy.size")
1701+
// Fetch the pointers.
1702+
dstBuf := b.CreateExtractValue(dst, 0, "copy.dstPtr")
1703+
srcBuf := b.CreateExtractValue(src, 0, "copy.srcPtr")
1704+
// Create a memcpy.
1705+
call := b.createMemCopy("memmove", dstBuf, srcBuf, size)
1706+
align := b.targetData.ABITypeAlignment(elemType)
1707+
if align > 1 {
1708+
// Apply the type's alignment to the arguments.
1709+
// LLVM sometimes turns constant-length moves into loads and stores.
1710+
// It may use this alignment for the created loads and stores.
1711+
alignAttr := b.ctx.CreateEnumAttribute(llvm.AttributeKindID("align"), uint64(align))
1712+
call.AddCallSiteAttribute(1, alignAttr)
1713+
call.AddCallSiteAttribute(2, alignAttr)
1714+
}
1715+
// Extend and return the copied length.
1716+
if b.targetData.TypeAllocSize(minLen.Type()) < b.targetData.TypeAllocSize(b.intType) {
1717+
minLen = b.CreateZExt(minLen, b.intType, "copy.n.zext")
1718+
}
1719+
return minLen, nil
16921720
case "delete":
16931721
m := argValues[0]
16941722
key := argValues[1]

compiler/intrinsics.go

Lines changed: 13 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -50,19 +50,24 @@ func (b *builder) defineIntrinsicFunction() {
5050
// and will otherwise be lowered to regular libc memcpy/memmove calls.
5151
func (b *builder) createMemoryCopyImpl() {
5252
b.createFunctionStart(true)
53-
fnName := "llvm." + b.fn.Name() + ".p0.p0.i" + strconv.Itoa(b.uintptrType.IntTypeWidth())
53+
params := b.fn.Params[0:3]
54+
b.createMemCopy(
55+
b.fn.Name(),
56+
b.getValue(params[0], getPos(b.fn)),
57+
b.getValue(params[1], getPos(b.fn)),
58+
b.getValue(params[2], getPos(b.fn)),
59+
)
60+
b.CreateRetVoid()
61+
}
62+
63+
func (b *builder) createMemCopy(kind string, dst, src, len llvm.Value) llvm.Value {
64+
fnName := "llvm." + kind + ".p0.p0.i" + strconv.Itoa(b.uintptrType.IntTypeWidth())
5465
llvmFn := b.mod.NamedFunction(fnName)
5566
if llvmFn.IsNil() {
5667
fnType := llvm.FunctionType(b.ctx.VoidType(), []llvm.Type{b.dataPtrType, b.dataPtrType, b.uintptrType, b.ctx.Int1Type()}, false)
5768
llvmFn = llvm.AddFunction(b.mod, fnName, fnType)
5869
}
59-
var params []llvm.Value
60-
for _, param := range b.fn.Params {
61-
params = append(params, b.getValue(param, getPos(b.fn)))
62-
}
63-
params = append(params, llvm.ConstInt(b.ctx.Int1Type(), 0, false))
64-
b.CreateCall(llvmFn.GlobalValueType(), llvmFn, params, "")
65-
b.CreateRetVoid()
70+
return b.CreateCall(llvmFn.GlobalValueType(), llvmFn, []llvm.Value{dst, src, len, llvm.ConstInt(b.ctx.Int1Type(), 0, false)}, "")
6671
}
6772

6873
// createMemoryZeroImpl creates calls to llvm.memset.* to zero a block of

compiler/symbol.go

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -184,12 +184,6 @@ func (c *compilerContext) getFunction(fn *ssa.Function) (llvm.Type, llvm.Value)
184184
// be modified.
185185
llvmFn.AddAttributeAtIndex(2, c.ctx.CreateEnumAttribute(llvm.AttributeKindID("nocapture"), 0))
186186
llvmFn.AddAttributeAtIndex(2, c.ctx.CreateEnumAttribute(llvm.AttributeKindID("readonly"), 0))
187-
case "runtime.sliceCopy":
188-
// Copying a slice won't capture any of the parameters.
189-
llvmFn.AddAttributeAtIndex(1, c.ctx.CreateEnumAttribute(llvm.AttributeKindID("writeonly"), 0))
190-
llvmFn.AddAttributeAtIndex(1, c.ctx.CreateEnumAttribute(llvm.AttributeKindID("nocapture"), 0))
191-
llvmFn.AddAttributeAtIndex(2, c.ctx.CreateEnumAttribute(llvm.AttributeKindID("readonly"), 0))
192-
llvmFn.AddAttributeAtIndex(2, c.ctx.CreateEnumAttribute(llvm.AttributeKindID("nocapture"), 0))
193187
case "runtime.stringFromBytes":
194188
llvmFn.AddAttributeAtIndex(1, c.ctx.CreateEnumAttribute(llvm.AttributeKindID("nocapture"), 0))
195189
llvmFn.AddAttributeAtIndex(1, c.ctx.CreateEnumAttribute(llvm.AttributeKindID("readonly"), 0))

compiler/testdata/goroutine-cortex-m-qemu-tasks.ll

Lines changed: 35 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -17,8 +17,8 @@ entry:
1717
; Function Attrs: nounwind
1818
define hidden void @main.regularFunctionGoroutine(ptr %context) unnamed_addr #1 {
1919
entry:
20-
%stacksize = call i32 @"internal/task.getGoroutineStackSize"(i32 ptrtoint (ptr @"main.regularFunction$gowrapper" to i32), ptr undef) #9
21-
call void @"internal/task.start"(i32 ptrtoint (ptr @"main.regularFunction$gowrapper" to i32), ptr nonnull inttoptr (i32 5 to ptr), i32 %stacksize, ptr undef) #9
20+
%stacksize = call i32 @"internal/task.getGoroutineStackSize"(i32 ptrtoint (ptr @"main.regularFunction$gowrapper" to i32), ptr undef) #11
21+
call void @"internal/task.start"(i32 ptrtoint (ptr @"main.regularFunction$gowrapper" to i32), ptr nonnull inttoptr (i32 5 to ptr), i32 %stacksize, ptr undef) #11
2222
ret void
2323
}
2424

@@ -28,7 +28,7 @@ declare void @main.regularFunction(i32, ptr) #2
2828
define linkonce_odr void @"main.regularFunction$gowrapper"(ptr %0) unnamed_addr #3 {
2929
entry:
3030
%unpack.int = ptrtoint ptr %0 to i32
31-
call void @main.regularFunction(i32 %unpack.int, ptr undef) #9
31+
call void @main.regularFunction(i32 %unpack.int, ptr undef) #11
3232
ret void
3333
}
3434

@@ -39,8 +39,8 @@ declare void @"internal/task.start"(i32, ptr, i32, ptr) #2
3939
; Function Attrs: nounwind
4040
define hidden void @main.inlineFunctionGoroutine(ptr %context) unnamed_addr #1 {
4141
entry:
42-
%stacksize = call i32 @"internal/task.getGoroutineStackSize"(i32 ptrtoint (ptr @"main.inlineFunctionGoroutine$1$gowrapper" to i32), ptr undef) #9
43-
call void @"internal/task.start"(i32 ptrtoint (ptr @"main.inlineFunctionGoroutine$1$gowrapper" to i32), ptr nonnull inttoptr (i32 5 to ptr), i32 %stacksize, ptr undef) #9
42+
%stacksize = call i32 @"internal/task.getGoroutineStackSize"(i32 ptrtoint (ptr @"main.inlineFunctionGoroutine$1$gowrapper" to i32), ptr undef) #11
43+
call void @"internal/task.start"(i32 ptrtoint (ptr @"main.inlineFunctionGoroutine$1$gowrapper" to i32), ptr nonnull inttoptr (i32 5 to ptr), i32 %stacksize, ptr undef) #11
4444
ret void
4545
}
4646

@@ -61,18 +61,18 @@ entry:
6161
; Function Attrs: nounwind
6262
define hidden void @main.closureFunctionGoroutine(ptr %context) unnamed_addr #1 {
6363
entry:
64-
%n = call align 4 dereferenceable(4) ptr @runtime.alloc(i32 4, ptr nonnull inttoptr (i32 3 to ptr), ptr undef) #9
64+
%n = call align 4 dereferenceable(4) ptr @runtime.alloc(i32 4, ptr nonnull inttoptr (i32 3 to ptr), ptr undef) #11
6565
store i32 3, ptr %n, align 4
66-
%0 = call align 4 dereferenceable(8) ptr @runtime.alloc(i32 8, ptr null, ptr undef) #9
66+
%0 = call align 4 dereferenceable(8) ptr @runtime.alloc(i32 8, ptr null, ptr undef) #11
6767
store i32 5, ptr %0, align 4
6868
%1 = getelementptr inbounds nuw i8, ptr %0, i32 4
6969
store ptr %n, ptr %1, align 4
70-
%stacksize = call i32 @"internal/task.getGoroutineStackSize"(i32 ptrtoint (ptr @"main.closureFunctionGoroutine$1$gowrapper" to i32), ptr undef) #9
71-
call void @"internal/task.start"(i32 ptrtoint (ptr @"main.closureFunctionGoroutine$1$gowrapper" to i32), ptr nonnull %0, i32 %stacksize, ptr undef) #9
70+
%stacksize = call i32 @"internal/task.getGoroutineStackSize"(i32 ptrtoint (ptr @"main.closureFunctionGoroutine$1$gowrapper" to i32), ptr undef) #11
71+
call void @"internal/task.start"(i32 ptrtoint (ptr @"main.closureFunctionGoroutine$1$gowrapper" to i32), ptr nonnull %0, i32 %stacksize, ptr undef) #11
7272
%2 = load i32, ptr %n, align 4
73-
call void @runtime.printlock(ptr undef) #9
74-
call void @runtime.printint32(i32 %2, ptr undef) #9
75-
call void @runtime.printunlock(ptr undef) #9
73+
call void @runtime.printlock(ptr undef) #11
74+
call void @runtime.printint32(i32 %2, ptr undef) #11
75+
call void @runtime.printunlock(ptr undef) #11
7676
ret void
7777
}
7878

@@ -102,14 +102,14 @@ declare void @runtime.printunlock(ptr) #2
102102
; Function Attrs: nounwind
103103
define hidden void @main.funcGoroutine(ptr %fn.context, ptr %fn.funcptr, ptr %context) unnamed_addr #1 {
104104
entry:
105-
%0 = call align 4 dereferenceable(12) ptr @runtime.alloc(i32 12, ptr null, ptr undef) #9
105+
%0 = call align 4 dereferenceable(12) ptr @runtime.alloc(i32 12, ptr null, ptr undef) #11
106106
store i32 5, ptr %0, align 4
107107
%1 = getelementptr inbounds nuw i8, ptr %0, i32 4
108108
store ptr %fn.context, ptr %1, align 4
109109
%2 = getelementptr inbounds nuw i8, ptr %0, i32 8
110110
store ptr %fn.funcptr, ptr %2, align 4
111-
%stacksize = call i32 @"internal/task.getGoroutineStackSize"(i32 ptrtoint (ptr @main.funcGoroutine.gowrapper to i32), ptr undef) #9
112-
call void @"internal/task.start"(i32 ptrtoint (ptr @main.funcGoroutine.gowrapper to i32), ptr nonnull %0, i32 %stacksize, ptr undef) #9
111+
%stacksize = call i32 @"internal/task.getGoroutineStackSize"(i32 ptrtoint (ptr @main.funcGoroutine.gowrapper to i32), ptr undef) #11
112+
call void @"internal/task.start"(i32 ptrtoint (ptr @main.funcGoroutine.gowrapper to i32), ptr nonnull %0, i32 %stacksize, ptr undef) #11
113113
ret void
114114
}
115115

@@ -121,7 +121,7 @@ entry:
121121
%3 = load ptr, ptr %2, align 4
122122
%4 = getelementptr inbounds nuw i8, ptr %0, i32 8
123123
%5 = load ptr, ptr %4, align 4
124-
call void %5(i32 %1, ptr %3) #9
124+
call void %5(i32 %1, ptr %3) #11
125125
ret void
126126
}
127127

@@ -134,16 +134,21 @@ entry:
134134
; Function Attrs: nounwind
135135
define hidden void @main.copyBuiltinGoroutine(ptr %dst.data, i32 %dst.len, i32 %dst.cap, ptr %src.data, i32 %src.len, i32 %src.cap, ptr %context) unnamed_addr #1 {
136136
entry:
137-
%copy.n = call i32 @runtime.sliceCopy(ptr %dst.data, ptr %src.data, i32 %dst.len, i32 %src.len, i32 1, ptr undef) #9
137+
%copy.n = call i32 @llvm.umin.i32(i32 %dst.len, i32 %src.len)
138+
call void @llvm.memmove.p0.p0.i32(ptr align 1 %dst.data, ptr align 1 %src.data, i32 %copy.n, i1 false)
138139
ret void
139140
}
140141

141-
declare i32 @runtime.sliceCopy(ptr nocapture writeonly, ptr nocapture readonly, i32, i32, i32, ptr) #2
142+
; Function Attrs: nocallback nofree nosync nounwind speculatable willreturn memory(none)
143+
declare i32 @llvm.umin.i32(i32, i32) #7
144+
145+
; Function Attrs: nocallback nofree nounwind willreturn memory(argmem: readwrite)
146+
declare void @llvm.memmove.p0.p0.i32(ptr nocapture writeonly, ptr nocapture readonly, i32, i1 immarg) #8
142147

143148
; Function Attrs: nounwind
144149
define hidden void @main.closeBuiltinGoroutine(ptr dereferenceable_or_null(36) %ch, ptr %context) unnamed_addr #1 {
145150
entry:
146-
call void @runtime.chanClose(ptr %ch, ptr undef) #9
151+
call void @runtime.chanClose(ptr %ch, ptr undef) #11
147152
ret void
148153
}
149154

@@ -152,23 +157,23 @@ declare void @runtime.chanClose(ptr dereferenceable_or_null(36), ptr) #2
152157
; Function Attrs: nounwind
153158
define hidden void @main.startInterfaceMethod(ptr %itf.typecode, ptr %itf.value, ptr %context) unnamed_addr #1 {
154159
entry:
155-
%0 = call align 4 dereferenceable(16) ptr @runtime.alloc(i32 16, ptr null, ptr undef) #9
160+
%0 = call align 4 dereferenceable(16) ptr @runtime.alloc(i32 16, ptr null, ptr undef) #11
156161
store ptr %itf.value, ptr %0, align 4
157162
%1 = getelementptr inbounds nuw i8, ptr %0, i32 4
158163
store ptr @"main$string", ptr %1, align 4
159164
%2 = getelementptr inbounds nuw i8, ptr %0, i32 8
160165
store i32 4, ptr %2, align 4
161166
%3 = getelementptr inbounds nuw i8, ptr %0, i32 12
162167
store ptr %itf.typecode, ptr %3, align 4
163-
%stacksize = call i32 @"internal/task.getGoroutineStackSize"(i32 ptrtoint (ptr @"interface:{Print:func:{basic:string}{}}.Print$invoke$gowrapper" to i32), ptr undef) #9
164-
call void @"internal/task.start"(i32 ptrtoint (ptr @"interface:{Print:func:{basic:string}{}}.Print$invoke$gowrapper" to i32), ptr nonnull %0, i32 %stacksize, ptr undef) #9
168+
%stacksize = call i32 @"internal/task.getGoroutineStackSize"(i32 ptrtoint (ptr @"interface:{Print:func:{basic:string}{}}.Print$invoke$gowrapper" to i32), ptr undef) #11
169+
call void @"internal/task.start"(i32 ptrtoint (ptr @"interface:{Print:func:{basic:string}{}}.Print$invoke$gowrapper" to i32), ptr nonnull %0, i32 %stacksize, ptr undef) #11
165170
ret void
166171
}
167172

168-
declare void @"interface:{Print:func:{basic:string}{}}.Print$invoke"(ptr, ptr, i32, ptr, ptr) #7
173+
declare void @"interface:{Print:func:{basic:string}{}}.Print$invoke"(ptr, ptr, i32, ptr, ptr) #9
169174

170175
; Function Attrs: nounwind
171-
define linkonce_odr void @"interface:{Print:func:{basic:string}{}}.Print$invoke$gowrapper"(ptr %0) unnamed_addr #8 {
176+
define linkonce_odr void @"interface:{Print:func:{basic:string}{}}.Print$invoke$gowrapper"(ptr %0) unnamed_addr #10 {
172177
entry:
173178
%1 = load ptr, ptr %0, align 4
174179
%2 = getelementptr inbounds nuw i8, ptr %0, i32 4
@@ -177,7 +182,7 @@ entry:
177182
%5 = load i32, ptr %4, align 4
178183
%6 = getelementptr inbounds nuw i8, ptr %0, i32 12
179184
%7 = load ptr, ptr %6, align 4
180-
call void @"interface:{Print:func:{basic:string}{}}.Print$invoke"(ptr %1, ptr %3, i32 %5, ptr %7, ptr undef) #9
185+
call void @"interface:{Print:func:{basic:string}{}}.Print$invoke"(ptr %1, ptr %3, i32 %5, ptr %7, ptr undef) #11
181186
ret void
182187
}
183188

@@ -188,6 +193,8 @@ attributes #3 = { nounwind "target-features"="+armv7-m,+hwdiv,+soft-float,+thumb
188193
attributes #4 = { nounwind "target-features"="+armv7-m,+hwdiv,+soft-float,+thumb-mode,-aes,-bf16,-cdecp0,-cdecp1,-cdecp2,-cdecp3,-cdecp4,-cdecp5,-cdecp6,-cdecp7,-crc,-crypto,-d32,-dotprod,-dsp,-fp-armv8,-fp-armv8d16,-fp-armv8d16sp,-fp-armv8sp,-fp16,-fp16fml,-fp64,-fpregs,-fullfp16,-hwdiv-arm,-i8mm,-lob,-mve,-mve.fp,-neon,-pacbti,-ras,-sb,-sha2,-vfp2,-vfp2sp,-vfp3,-vfp3d16,-vfp3d16sp,-vfp3sp,-vfp4,-vfp4d16,-vfp4d16sp,-vfp4sp" "tinygo-gowrapper"="main.inlineFunctionGoroutine$1" }
189194
attributes #5 = { nounwind "target-features"="+armv7-m,+hwdiv,+soft-float,+thumb-mode,-aes,-bf16,-cdecp0,-cdecp1,-cdecp2,-cdecp3,-cdecp4,-cdecp5,-cdecp6,-cdecp7,-crc,-crypto,-d32,-dotprod,-dsp,-fp-armv8,-fp-armv8d16,-fp-armv8d16sp,-fp-armv8sp,-fp16,-fp16fml,-fp64,-fpregs,-fullfp16,-hwdiv-arm,-i8mm,-lob,-mve,-mve.fp,-neon,-pacbti,-ras,-sb,-sha2,-vfp2,-vfp2sp,-vfp3,-vfp3d16,-vfp3d16sp,-vfp3sp,-vfp4,-vfp4d16,-vfp4d16sp,-vfp4sp" "tinygo-gowrapper"="main.closureFunctionGoroutine$1" }
190195
attributes #6 = { nounwind "target-features"="+armv7-m,+hwdiv,+soft-float,+thumb-mode,-aes,-bf16,-cdecp0,-cdecp1,-cdecp2,-cdecp3,-cdecp4,-cdecp5,-cdecp6,-cdecp7,-crc,-crypto,-d32,-dotprod,-dsp,-fp-armv8,-fp-armv8d16,-fp-armv8d16sp,-fp-armv8sp,-fp16,-fp16fml,-fp64,-fpregs,-fullfp16,-hwdiv-arm,-i8mm,-lob,-mve,-mve.fp,-neon,-pacbti,-ras,-sb,-sha2,-vfp2,-vfp2sp,-vfp3,-vfp3d16,-vfp3d16sp,-vfp3sp,-vfp4,-vfp4d16,-vfp4d16sp,-vfp4sp" "tinygo-gowrapper" }
191-
attributes #7 = { "target-features"="+armv7-m,+hwdiv,+soft-float,+thumb-mode,-aes,-bf16,-cdecp0,-cdecp1,-cdecp2,-cdecp3,-cdecp4,-cdecp5,-cdecp6,-cdecp7,-crc,-crypto,-d32,-dotprod,-dsp,-fp-armv8,-fp-armv8d16,-fp-armv8d16sp,-fp-armv8sp,-fp16,-fp16fml,-fp64,-fpregs,-fullfp16,-hwdiv-arm,-i8mm,-lob,-mve,-mve.fp,-neon,-pacbti,-ras,-sb,-sha2,-vfp2,-vfp2sp,-vfp3,-vfp3d16,-vfp3d16sp,-vfp3sp,-vfp4,-vfp4d16,-vfp4d16sp,-vfp4sp" "tinygo-invoke"="reflect/methods.Print(string)" "tinygo-methods"="reflect/methods.Print(string)" }
192-
attributes #8 = { nounwind "target-features"="+armv7-m,+hwdiv,+soft-float,+thumb-mode,-aes,-bf16,-cdecp0,-cdecp1,-cdecp2,-cdecp3,-cdecp4,-cdecp5,-cdecp6,-cdecp7,-crc,-crypto,-d32,-dotprod,-dsp,-fp-armv8,-fp-armv8d16,-fp-armv8d16sp,-fp-armv8sp,-fp16,-fp16fml,-fp64,-fpregs,-fullfp16,-hwdiv-arm,-i8mm,-lob,-mve,-mve.fp,-neon,-pacbti,-ras,-sb,-sha2,-vfp2,-vfp2sp,-vfp3,-vfp3d16,-vfp3d16sp,-vfp3sp,-vfp4,-vfp4d16,-vfp4d16sp,-vfp4sp" "tinygo-gowrapper"="interface:{Print:func:{basic:string}{}}.Print$invoke" }
193-
attributes #9 = { nounwind }
196+
attributes #7 = { nocallback nofree nosync nounwind speculatable willreturn memory(none) }
197+
attributes #8 = { nocallback nofree nounwind willreturn memory(argmem: readwrite) }
198+
attributes #9 = { "target-features"="+armv7-m,+hwdiv,+soft-float,+thumb-mode,-aes,-bf16,-cdecp0,-cdecp1,-cdecp2,-cdecp3,-cdecp4,-cdecp5,-cdecp6,-cdecp7,-crc,-crypto,-d32,-dotprod,-dsp,-fp-armv8,-fp-armv8d16,-fp-armv8d16sp,-fp-armv8sp,-fp16,-fp16fml,-fp64,-fpregs,-fullfp16,-hwdiv-arm,-i8mm,-lob,-mve,-mve.fp,-neon,-pacbti,-ras,-sb,-sha2,-vfp2,-vfp2sp,-vfp3,-vfp3d16,-vfp3d16sp,-vfp3sp,-vfp4,-vfp4d16,-vfp4d16sp,-vfp4sp" "tinygo-invoke"="reflect/methods.Print(string)" "tinygo-methods"="reflect/methods.Print(string)" }
199+
attributes #10 = { nounwind "target-features"="+armv7-m,+hwdiv,+soft-float,+thumb-mode,-aes,-bf16,-cdecp0,-cdecp1,-cdecp2,-cdecp3,-cdecp4,-cdecp5,-cdecp6,-cdecp7,-crc,-crypto,-d32,-dotprod,-dsp,-fp-armv8,-fp-armv8d16,-fp-armv8d16sp,-fp-armv8sp,-fp16,-fp16fml,-fp64,-fpregs,-fullfp16,-hwdiv-arm,-i8mm,-lob,-mve,-mve.fp,-neon,-pacbti,-ras,-sb,-sha2,-vfp2,-vfp2sp,-vfp3,-vfp3d16,-vfp3d16sp,-vfp3sp,-vfp4,-vfp4d16,-vfp4d16sp,-vfp4sp" "tinygo-gowrapper"="interface:{Print:func:{basic:string}{}}.Print$invoke" }
200+
attributes #11 = { nounwind }

0 commit comments

Comments
 (0)