Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion builder/sizes_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ func TestBinarySize(t *testing.T) {
// microcontrollers
{"hifive1b", "examples/echo", 3668, 280, 0, 2244},
{"microbit", "examples/serial", 2694, 342, 8, 2248},
{"wioterminal", "examples/pininterrupt", 6837, 1491, 120, 6888},
{"wioterminal", "examples/pininterrupt", 6835, 1493, 120, 6888},

// TODO: also check wasm. Right now this is difficult, because
// wasm binaries are run through wasm-opt and therefore the
Expand Down
12 changes: 12 additions & 0 deletions compiler/calls.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ type paramInfo struct {
llvmType llvm.Type
name string // name, possibly with suffixes for e.g. struct fields
elemSize uint64 // size of pointer element type, or 0 if this isn't a pointer
max uint64 // maximum value (for len/cap)
flags paramFlags // extra flags for this parameter
}

Expand Down Expand Up @@ -171,6 +172,8 @@ func (c *compilerContext) flattenAggregateType(t llvm.Type, name string, goType
}
suffix := strconv.Itoa(i)
isString := false
hasLengths := false
var maxLen uint64
if goType != nil {
// Try to come up with a good suffix for this struct field,
// depending on which Go type it's based on.
Expand All @@ -179,6 +182,9 @@ func (c *compilerContext) flattenAggregateType(t llvm.Type, name string, goType
suffix = []string{"typecode", "value"}[i]
case *types.Slice:
suffix = []string{"data", "len", "cap"}[i]
maxLen = c.maxLen
maxLen /= max(c.targetData.TypeAllocSize(c.getLLVMType(goType.Elem())), 1)
hasLengths = true
case *types.Struct:
suffix = goType.Field(i).Name()
case *types.Basic:
Expand All @@ -188,6 +194,8 @@ func (c *compilerContext) flattenAggregateType(t llvm.Type, name string, goType
case types.String:
suffix = []string{"data", "len"}[i]
isString = true
hasLengths = true
maxLen = c.maxLen
}
case *types.Signature:
suffix = []string{"context", "funcptr"}[i]
Expand All @@ -197,6 +205,10 @@ func (c *compilerContext) flattenAggregateType(t llvm.Type, name string, goType
if isString {
subInfos[0].flags |= paramIsReadonly
}
if hasLengths && i > 0 {
// Add the max to a len/cap
subInfos[0].max = maxLen
}
paramInfos = append(paramInfos, subInfos...)
}
return paramInfos
Expand Down
2 changes: 2 additions & 0 deletions compiler/compiler.go
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,7 @@ type compilerContext struct {
funcPtrType llvm.Type // pointer in function address space (1 for AVR, 0 elsewhere)
funcPtrAddrSpace int
uintptrType llvm.Type
maxLen uint64
program *ssa.Program
diagnostics []error
functionInfos map[*ssa.Function]functionInfo
Expand Down Expand Up @@ -128,6 +129,7 @@ func newCompilerContext(moduleName string, machine llvm.TargetMachine, config *C
panic("unknown pointer size")
}
c.dataPtrType = llvm.PointerType(c.ctx.Int8Type(), 0)
c.maxLen = (uint64(1) << (c.uintptrType.IntTypeWidth() - 1)) - 1

dummyFuncType := llvm.FunctionType(c.ctx.VoidType(), nil, false)
dummyFunc := llvm.AddFunction(c.mod, "tinygo.dummy", dummyFuncType)
Expand Down
7 changes: 7 additions & 0 deletions compiler/symbol.go
Original file line number Diff line number Diff line change
Expand Up @@ -128,11 +128,18 @@ func (c *compilerContext) getFunction(fn *ssa.Function) (llvm.Type, llvm.Value)
c.addStandardDeclaredAttributes(llvmFn)

dereferenceableOrNullKind := llvm.AttributeKindID("dereferenceable_or_null")
rangeKind := llvm.AttributeKindID("range")
for i, paramInfo := range paramInfos {
if paramInfo.elemSize != 0 {
dereferenceableOrNull := c.ctx.CreateEnumAttribute(dereferenceableOrNullKind, paramInfo.elemSize)
llvmFn.AddAttributeAtIndex(i+1, dereferenceableOrNull)
}
if paramInfo.max != 0 {
rangeAttr := c.ctx.CreateSmallRangeAttribute(rangeKind, uint(paramInfo.llvmType.IntTypeWidth()), 0, paramInfo.max+1)
if !rangeAttr.IsNil() {
llvmFn.AddAttributeAtIndex(i+1, rangeAttr)
}
}
if info.noescape && paramInfo.flags&paramIsGoParam != 0 && paramInfo.llvmType.TypeKind() == llvm.PointerTypeKind {
// Parameters to functions with a //go:noescape parameter should get
// the nocapture attribute. However, the context parameter should
Expand Down
2 changes: 1 addition & 1 deletion compiler/testdata/channel.ll
Original file line number Diff line number Diff line change
Expand Up @@ -105,7 +105,7 @@ select.body: ; preds = %select.next
br label %select.done
}

declare { i32, i1 } @runtime.chanSelect(ptr, ptr, i32, i32, ptr, i32, i32, ptr) #1
declare { i32, i1 } @runtime.chanSelect(ptr, ptr, i32 range(i32 0, 268435456), i32 range(i32 0, 268435456), ptr, i32 range(i32 0, 134217728), i32 range(i32 0, 134217728), ptr) #1

attributes #0 = { allockind("alloc,zeroed") allocsize(0) "alloc-family"="runtime.alloc" "target-features"="+bulk-memory,+bulk-memory-opt,+call-indirect-overlong,+mutable-globals,+nontrapping-fptoint,+sign-ext,-multivalue,-reference-types" }
attributes #1 = { "target-features"="+bulk-memory,+bulk-memory-opt,+call-indirect-overlong,+mutable-globals,+nontrapping-fptoint,+sign-ext,-multivalue,-reference-types" }
Expand Down
4 changes: 2 additions & 2 deletions compiler/testdata/go1.20.ll
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ entry:
}

; Function Attrs: nounwind
define hidden ptr @main.unsafeSliceData(ptr %s.data, i32 %s.len, i32 %s.cap, ptr %context) unnamed_addr #2 {
define hidden ptr @main.unsafeSliceData(ptr %s.data, i32 range(i32 0, 536870912) %s.len, i32 range(i32 0, 536870912) %s.cap, ptr %context) unnamed_addr #2 {
entry:
%stackalloc = alloca i8, align 1
call void @runtime.trackPointer(ptr %s.data, ptr nonnull %stackalloc, ptr undef) #3
Expand Down Expand Up @@ -50,7 +50,7 @@ unsafe.String.throw: ; preds = %entry
declare void @runtime.unsafeSlicePanic(ptr) #1

; Function Attrs: nounwind
define hidden ptr @main.unsafeStringData(ptr readonly %s.data, i32 %s.len, ptr %context) unnamed_addr #2 {
define hidden ptr @main.unsafeStringData(ptr readonly %s.data, i32 range(i32 0, -2147483648) %s.len, ptr %context) unnamed_addr #2 {
entry:
%stackalloc = alloca i8, align 1
call void @runtime.trackPointer(ptr %s.data, ptr nonnull %stackalloc, ptr undef) #3
Expand Down
12 changes: 6 additions & 6 deletions compiler/testdata/go1.21.ll
Original file line number Diff line number Diff line change
Expand Up @@ -90,7 +90,7 @@ entry:
declare double @llvm.minimum.f64(double, double) #3

; Function Attrs: nounwind
define hidden %runtime._string @main.minString(ptr readonly %a.data, i32 %a.len, ptr readonly %b.data, i32 %b.len, ptr %context) unnamed_addr #2 {
define hidden %runtime._string @main.minString(ptr readonly %a.data, i32 range(i32 0, -2147483648) %a.len, ptr readonly %b.data, i32 range(i32 0, -2147483648) %b.len, ptr %context) unnamed_addr #2 {
entry:
%0 = insertvalue %runtime._string zeroinitializer, ptr %a.data, 0
%1 = insertvalue %runtime._string %0, i32 %a.len, 1
Expand All @@ -104,7 +104,7 @@ entry:
ret %runtime._string %5
}

declare i1 @runtime.stringLess(ptr readonly, i32, ptr readonly, i32, ptr) #1
declare i1 @runtime.stringLess(ptr readonly, i32 range(i32 0, -2147483648), ptr readonly, i32 range(i32 0, -2147483648), ptr) #1

; Function Attrs: nounwind
define hidden i32 @main.maxInt(i32 %a, i32 %b, ptr %context) unnamed_addr #2 {
Expand Down Expand Up @@ -137,7 +137,7 @@ entry:
declare float @llvm.maximum.f32(float, float) #3

; Function Attrs: nounwind
define hidden %runtime._string @main.maxString(ptr readonly %a.data, i32 %a.len, ptr readonly %b.data, i32 %b.len, ptr %context) unnamed_addr #2 {
define hidden %runtime._string @main.maxString(ptr readonly %a.data, i32 range(i32 0, -2147483648) %a.len, ptr readonly %b.data, i32 range(i32 0, -2147483648) %b.len, ptr %context) unnamed_addr #2 {
entry:
%0 = insertvalue %runtime._string zeroinitializer, ptr %a.data, 0
%1 = insertvalue %runtime._string %0, i32 %a.len, 1
Expand All @@ -152,9 +152,9 @@ entry:
}

; Function Attrs: nounwind
define hidden void @main.clearSlice(ptr %s.data, i32 %s.len, i32 %s.cap, ptr %context) unnamed_addr #2 {
define hidden void @main.clearSlice(ptr %s.data, i32 range(i32 0, 536870912) %s.len, i32 range(i32 0, 536870912) %s.cap, ptr %context) unnamed_addr #2 {
entry:
%0 = shl i32 %s.len, 2
%0 = shl nuw nsw i32 %s.len, 2
call void @llvm.memset.p0.i32(ptr align 4 %s.data, i8 0, i32 %0, i1 false)
ret void
}
Expand All @@ -163,7 +163,7 @@ entry:
declare void @llvm.memset.p0.i32(ptr nocapture writeonly, i8, i32, i1 immarg) #4

; Function Attrs: nounwind
define hidden void @main.clearZeroSizedSlice(ptr %s.data, i32 %s.len, i32 %s.cap, ptr %context) unnamed_addr #2 {
define hidden void @main.clearZeroSizedSlice(ptr %s.data, i32 range(i32 0, -2147483648) %s.len, i32 range(i32 0, -2147483648) %s.cap, ptr %context) unnamed_addr #2 {
entry:
ret void
}
Expand Down
2 changes: 1 addition & 1 deletion compiler/testdata/goroutine-cortex-m-qemu-tasks.ll
Original file line number Diff line number Diff line change
Expand Up @@ -132,7 +132,7 @@ entry:
}

; Function Attrs: nounwind
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 {
define hidden void @main.copyBuiltinGoroutine(ptr %dst.data, i32 range(i32 0, -2147483648) %dst.len, i32 range(i32 0, -2147483648) %dst.cap, ptr %src.data, i32 range(i32 0, -2147483648) %src.len, i32 range(i32 0, -2147483648) %src.cap, ptr %context) unnamed_addr #1 {
entry:
%copy.n = call i32 @llvm.umin.i32(i32 %dst.len, i32 %src.len)
call void @llvm.memmove.p0.p0.i32(ptr align 1 %dst.data, ptr align 1 %src.data, i32 %copy.n, i1 false)
Expand Down
2 changes: 1 addition & 1 deletion compiler/testdata/goroutine-wasm-asyncify.ll
Original file line number Diff line number Diff line change
Expand Up @@ -141,7 +141,7 @@ entry:
}

; Function Attrs: nounwind
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 #2 {
define hidden void @main.copyBuiltinGoroutine(ptr %dst.data, i32 range(i32 0, -2147483648) %dst.len, i32 range(i32 0, -2147483648) %dst.cap, ptr %src.data, i32 range(i32 0, -2147483648) %src.len, i32 range(i32 0, -2147483648) %src.cap, ptr %context) unnamed_addr #2 {
entry:
%copy.n = call i32 @llvm.umin.i32(i32 %dst.len, i32 %src.len)
call void @llvm.memmove.p0.p0.i32(ptr align 1 %dst.data, ptr align 1 %src.data, i32 %copy.n, i1 false)
Expand Down
4 changes: 2 additions & 2 deletions compiler/testdata/pragma.ll
Original file line number Diff line number Diff line change
Expand Up @@ -85,10 +85,10 @@ entry:

declare void @main.undefinedFunctionNotInSection(ptr) #1

declare void @main.doesNotEscapeParam(ptr nocapture dereferenceable_or_null(4), ptr nocapture, i32, i32, ptr nocapture dereferenceable_or_null(36), ptr nocapture, ptr) #1
declare void @main.doesNotEscapeParam(ptr nocapture dereferenceable_or_null(4), ptr nocapture, i32 range(i32 0, 536870912), i32 range(i32 0, 536870912), ptr nocapture dereferenceable_or_null(36), ptr nocapture, ptr) #1

; Function Attrs: nounwind
define hidden void @main.stillEscapes(ptr dereferenceable_or_null(4) %a, ptr %b.data, i32 %b.len, i32 %b.cap, ptr dereferenceable_or_null(36) %c, ptr %d, ptr %context) unnamed_addr #2 {
define hidden void @main.stillEscapes(ptr dereferenceable_or_null(4) %a, ptr %b.data, i32 range(i32 0, 536870912) %b.len, i32 range(i32 0, 536870912) %b.cap, ptr dereferenceable_or_null(36) %c, ptr %d, ptr %context) unnamed_addr #2 {
entry:
ret void
}
Expand Down
18 changes: 9 additions & 9 deletions compiler/testdata/slice.ll
Original file line number Diff line number Diff line change
Expand Up @@ -15,19 +15,19 @@ entry:
}

; Function Attrs: nounwind
define hidden i32 @main.sliceLen(ptr %ints.data, i32 %ints.len, i32 %ints.cap, ptr %context) unnamed_addr #2 {
define hidden i32 @main.sliceLen(ptr %ints.data, i32 range(i32 0, 536870912) %ints.len, i32 range(i32 0, 536870912) %ints.cap, ptr %context) unnamed_addr #2 {
entry:
ret i32 %ints.len
}

; Function Attrs: nounwind
define hidden i32 @main.sliceCap(ptr %ints.data, i32 %ints.len, i32 %ints.cap, ptr %context) unnamed_addr #2 {
define hidden i32 @main.sliceCap(ptr %ints.data, i32 range(i32 0, 536870912) %ints.len, i32 range(i32 0, 536870912) %ints.cap, ptr %context) unnamed_addr #2 {
entry:
ret i32 %ints.cap
}

; Function Attrs: nounwind
define hidden i32 @main.sliceElement(ptr %ints.data, i32 %ints.len, i32 %ints.cap, i32 %index, ptr %context) unnamed_addr #2 {
define hidden i32 @main.sliceElement(ptr %ints.data, i32 range(i32 0, 536870912) %ints.len, i32 range(i32 0, 536870912) %ints.cap, i32 %index, ptr %context) unnamed_addr #2 {
entry:
%.not = icmp ult i32 %index, %ints.len
br i1 %.not, label %lookup.next, label %lookup.throw
Expand All @@ -45,7 +45,7 @@ lookup.throw: ; preds = %entry
declare void @runtime.lookupPanic(ptr) #1

; Function Attrs: nounwind
define hidden { ptr, i32, i32 } @main.sliceAppendValues(ptr %ints.data, i32 %ints.len, i32 %ints.cap, ptr %context) unnamed_addr #2 {
define hidden { ptr, i32, i32 } @main.sliceAppendValues(ptr %ints.data, i32 range(i32 0, 536870912) %ints.len, i32 range(i32 0, 536870912) %ints.cap, ptr %context) unnamed_addr #2 {
entry:
%stackalloc = alloca i8, align 1
%varargs = call align 4 dereferenceable(12) ptr @runtime.alloc(i32 12, ptr nonnull inttoptr (i32 3 to ptr), ptr undef) #5
Expand All @@ -69,7 +69,7 @@ entry:
declare { ptr, i32, i32 } @runtime.sliceAppend(ptr, ptr nocapture readonly, i32, i32, i32, i32, ptr, ptr) #1

; Function Attrs: nounwind
define hidden { ptr, i32, i32 } @main.sliceAppendSlice(ptr %ints.data, i32 %ints.len, i32 %ints.cap, ptr %added.data, i32 %added.len, i32 %added.cap, ptr %context) unnamed_addr #2 {
define hidden { ptr, i32, i32 } @main.sliceAppendSlice(ptr %ints.data, i32 range(i32 0, 536870912) %ints.len, i32 range(i32 0, 536870912) %ints.cap, ptr %added.data, i32 range(i32 0, 536870912) %added.len, i32 range(i32 0, 536870912) %added.cap, ptr %context) unnamed_addr #2 {
entry:
%stackalloc = alloca i8, align 1
%append.new = call { ptr, i32, i32 } @runtime.sliceAppend(ptr %ints.data, ptr %added.data, i32 %ints.len, i32 %ints.cap, i32 %added.len, i32 4, ptr nonnull inttoptr (i32 3 to ptr), ptr undef) #5
Expand All @@ -84,10 +84,10 @@ entry:
}

; Function Attrs: nounwind
define hidden i32 @main.sliceCopy(ptr %dst.data, i32 %dst.len, i32 %dst.cap, ptr %src.data, i32 %src.len, i32 %src.cap, ptr %context) unnamed_addr #2 {
define hidden i32 @main.sliceCopy(ptr %dst.data, i32 range(i32 0, 536870912) %dst.len, i32 range(i32 0, 536870912) %dst.cap, ptr %src.data, i32 range(i32 0, 536870912) %src.len, i32 range(i32 0, 536870912) %src.cap, ptr %context) unnamed_addr #2 {
entry:
%copy.n = call i32 @llvm.umin.i32(i32 %dst.len, i32 %src.len)
%copy.size = shl nuw i32 %copy.n, 2
%copy.size = shl nuw nsw i32 %copy.n, 2
call void @llvm.memmove.p0.p0.i32(ptr align 4 %dst.data, ptr align 4 %src.data, i32 %copy.size, i1 false)
ret i32 %copy.n
}
Expand Down Expand Up @@ -203,9 +203,9 @@ entry:
}

; Function Attrs: nounwind
define hidden ptr @main.SliceToArray(ptr %s.data, i32 %s.len, i32 %s.cap, ptr %context) unnamed_addr #2 {
define hidden ptr @main.SliceToArray(ptr %s.data, i32 range(i32 0, 536870912) %s.len, i32 range(i32 0, 536870912) %s.cap, ptr %context) unnamed_addr #2 {
entry:
%0 = icmp ult i32 %s.len, 4
%0 = icmp samesign ult i32 %s.len, 4
br i1 %0, label %slicetoarray.throw, label %slicetoarray.next

slicetoarray.next: ; preds = %entry
Expand Down
18 changes: 9 additions & 9 deletions compiler/testdata/string.ll
Original file line number Diff line number Diff line change
Expand Up @@ -31,13 +31,13 @@ entry:
}

; Function Attrs: nounwind
define hidden i32 @main.stringLen(ptr readonly %s.data, i32 %s.len, ptr %context) unnamed_addr #2 {
define hidden i32 @main.stringLen(ptr readonly %s.data, i32 range(i32 0, -2147483648) %s.len, ptr %context) unnamed_addr #2 {
entry:
ret i32 %s.len
}

; Function Attrs: nounwind
define hidden i8 @main.stringIndex(ptr readonly %s.data, i32 %s.len, i32 %index, ptr %context) unnamed_addr #2 {
define hidden i8 @main.stringIndex(ptr readonly %s.data, i32 range(i32 0, -2147483648) %s.len, i32 %index, ptr %context) unnamed_addr #2 {
entry:
%.not = icmp ult i32 %index, %s.len
br i1 %.not, label %lookup.next, label %lookup.throw
Expand All @@ -55,36 +55,36 @@ lookup.throw: ; preds = %entry
declare void @runtime.lookupPanic(ptr) #1

; Function Attrs: nounwind
define hidden i1 @main.stringCompareEqual(ptr readonly %s1.data, i32 %s1.len, ptr readonly %s2.data, i32 %s2.len, ptr %context) unnamed_addr #2 {
define hidden i1 @main.stringCompareEqual(ptr readonly %s1.data, i32 range(i32 0, -2147483648) %s1.len, ptr readonly %s2.data, i32 range(i32 0, -2147483648) %s2.len, ptr %context) unnamed_addr #2 {
entry:
%0 = call i1 @runtime.stringEqual(ptr %s1.data, i32 %s1.len, ptr %s2.data, i32 %s2.len, ptr undef) #3
ret i1 %0
}

declare i1 @runtime.stringEqual(ptr readonly, i32, ptr readonly, i32, ptr) #1
declare i1 @runtime.stringEqual(ptr readonly, i32 range(i32 0, -2147483648), ptr readonly, i32 range(i32 0, -2147483648), ptr) #1

; Function Attrs: nounwind
define hidden i1 @main.stringCompareUnequal(ptr readonly %s1.data, i32 %s1.len, ptr readonly %s2.data, i32 %s2.len, ptr %context) unnamed_addr #2 {
define hidden i1 @main.stringCompareUnequal(ptr readonly %s1.data, i32 range(i32 0, -2147483648) %s1.len, ptr readonly %s2.data, i32 range(i32 0, -2147483648) %s2.len, ptr %context) unnamed_addr #2 {
entry:
%0 = call i1 @runtime.stringEqual(ptr %s1.data, i32 %s1.len, ptr %s2.data, i32 %s2.len, ptr undef) #3
%1 = xor i1 %0, true
ret i1 %1
}

; Function Attrs: nounwind
define hidden i1 @main.stringCompareLarger(ptr readonly %s1.data, i32 %s1.len, ptr readonly %s2.data, i32 %s2.len, ptr %context) unnamed_addr #2 {
define hidden i1 @main.stringCompareLarger(ptr readonly %s1.data, i32 range(i32 0, -2147483648) %s1.len, ptr readonly %s2.data, i32 range(i32 0, -2147483648) %s2.len, ptr %context) unnamed_addr #2 {
entry:
%0 = call i1 @runtime.stringLess(ptr %s2.data, i32 %s2.len, ptr %s1.data, i32 %s1.len, ptr undef) #3
ret i1 %0
}

declare i1 @runtime.stringLess(ptr readonly, i32, ptr readonly, i32, ptr) #1
declare i1 @runtime.stringLess(ptr readonly, i32 range(i32 0, -2147483648), ptr readonly, i32 range(i32 0, -2147483648), ptr) #1

; Function Attrs: nounwind
define hidden i8 @main.stringLookup(ptr readonly %s.data, i32 %s.len, i8 %x, ptr %context) unnamed_addr #2 {
define hidden i8 @main.stringLookup(ptr readonly %s.data, i32 range(i32 0, -2147483648) %s.len, i8 %x, ptr %context) unnamed_addr #2 {
entry:
%0 = zext i8 %x to i32
%.not = icmp ugt i32 %s.len, %0
%.not = icmp samesign ugt i32 %s.len, %0
br i1 %.not, label %lookup.next, label %lookup.throw

lookup.next: ; preds = %entry
Expand Down
2 changes: 1 addition & 1 deletion go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ require (
golang.org/x/sys v0.30.0
golang.org/x/tools v0.30.0
gopkg.in/yaml.v2 v2.4.0
tinygo.org/x/go-llvm v0.0.0-20250422114502-b8f170971e74
tinygo.org/x/go-llvm v0.0.0-20260107134614-6418b7937619
)

require (
Expand Down
4 changes: 4 additions & 0 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -60,3 +60,7 @@ gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
tinygo.org/x/go-llvm v0.0.0-20250422114502-b8f170971e74 h1:ovavgTdIBWCH8YWlcfq9gkpoyT1+IxMKSn+Df27QwE8=
tinygo.org/x/go-llvm v0.0.0-20250422114502-b8f170971e74/go.mod h1:GFbusT2VTA4I+l4j80b17KFK+6whv69Wtny5U+T8RR0=
tinygo.org/x/go-llvm v0.0.0-20260107115532-8bd5473cfa70 h1:ERUdTqps/hemakjNJN7fB9K3jCLsPP1h7YAdifdHuIc=
tinygo.org/x/go-llvm v0.0.0-20260107115532-8bd5473cfa70/go.mod h1:GFbusT2VTA4I+l4j80b17KFK+6whv69Wtny5U+T8RR0=
tinygo.org/x/go-llvm v0.0.0-20260107134614-6418b7937619 h1:JKG6n6Yr0SB1JDzN0yiwJBKQoz+ZNMjahDej3XpV+pw=
tinygo.org/x/go-llvm v0.0.0-20260107134614-6418b7937619/go.mod h1:GFbusT2VTA4I+l4j80b17KFK+6whv69Wtny5U+T8RR0=
Loading