Compare commits

..

2 Commits

Author SHA1 Message Date
Jake Bailey 2761414777 compiler: make composite map hashes order dependent
Use the same multiply-and-XOR combination as the runtime interface hash for generated struct and array key hashes. This avoids systematic collisions when components are permuted.
2026-08-31 18:54:45 +02:00
Jake Bailey 7d4b42db83 compiler: test generated composite map hashes 2026-08-31 18:54:45 +02:00
5 changed files with 173 additions and 163 deletions
-159
View File
@@ -1,162 +1,3 @@
0.42.0
---
* **general**
- all: add LLVM 22 support, and support LLVM 19 and LLVM 20 on Fedora 43
- all: build and test using Go 1.27, and raise the max supported Go version to 1.27
- all: modernize and clean up code with Go 1.24+ in mind (#5489, #5498)
- all: use unsafe.SliceData where appropriate
- all: update golang.org/x/tools and go-llvm
- cli: add basic probe-rs support
- cli: clarify the runtime.alloc linker error with -gc=none
- main: allow the -o flag to point to a directory
- main: make the -monitor flag on flash respect the port
- main: update to espflasher 0.8.0 with fixes for esp32c3 and esp32s3
- cgo: add CGO_CFLAGS support (#5453)
- version: update to 0.42.0 for the new dev cycle
- docs: add agents.md guideline for use of ASD-STE100 (#5566)
* **compiler**
- compiler, runtime: make runtime, map, and channel panics recoverable
- compiler, runtime: support recover on riscv64
- compiler, runtime, reflect: generate type-specific hash/equal (#5359)
- support Go 1.27 generic methods via the x/tools upgrade
- canonicalize generic instance and method signature identities
- disambiguate function-local named types and generic instance link names (#5336)
- exclude generic methods from runtime method sets
- support file-level //go:linkname directives and the //go:linknamestd pragma
- add the //go:noheap pragma
- pass large aggregates by pointer
- use LLVM intrinsics for math trig operations
- optimize zero-sized allocations
- consistently pass layout and alignment to createAlloc
- handle nested unsigned shift being untyped after type resolution (#5497)
- store the defer list head in the defer frame and centralize deferred call records
- centralize SSA loads, stores, result handling, and LLVM function type construction
- transform, compiler: support the captures(none) attribute of LLVM 21
* **core**
- reflect: add Type.ConvertibleTo and complex, rune, and integer string conversions
- reflect: implement MakeChan
- reflect: add missing iterator methods
- reflect, reflectlite: make IsRO and MakeRO package methods
- sync: add Map.CompareAndSwap and Map.CompareAndDelete
- sync: fix deadlock in the Map.Range callback
- os, syscall: add Statfs and Fstatfs stubs and Getpagesize for non-hosted targets
- os: add File.Chown on the unix path
- runtime, syscall, internal/poll, os: wasip1 poll_oneoff scheduler integration and net.FileListener (#5386)
- runtime, testing: support Goexit, SkipNow, and FailNow
- syscall: remove sliceHeader, use unsafe.SliceData more
- builder, cgo, syscall: replace fixed-size array casts with unsafe.Slice
- builder, loader: fix -ldflags -X not overriding variables with default values
- builder: build SSA before compiling packages
- builder: increase the stack size margin for automatic stack allocation
- builder: do not count non-writable SHT_NOBITS sections as RAM or bss
- builder: link stack probes on Windows amd64 and arm64, and add chkstk2.S for windows/386
- builder: add strlen to the wasm builtins
- builder: retry cached archive renames on Windows (#5462)
- loader: avoid a race condition when loading the package list, and skip object resolution
- interp: bail out of loops that iterate too many times (#5395)
- interp: fix partial store aliasing and avoid repeated object clones
- interp: defer out-of-bounds loads to runtime instead of crashing
- interp: mark pointers in aggregate call operands as external
- interp: fix switch-instruction handling for the new case-value API of LLVM 22
- transform: follow returned pointer and aggregate alloc aliases
- transform: add -print-allocs-cover and restore the -print-allocs reason output
- device: add device/uefi and device/amd64
- wasm: patch wasm_exec.js and wasm_exec_node.js from Go 1.18+ (#5483)
* **net**
- update the net module with a roundtrip fix for js/wasm
* **runtime**
- make divide-by-zero and nil dereference panics recoverable
- add a Windows vectored exception handler for recoverable panics
- make Goexit exit host threads, and encode a pending Goexit in the panic state
- make out-of-memory and fatal failures unrecoverable
- improve the hardfault handler and stack reporting on Cortex-M
- prevent timer starvation in the cores scheduler
- do not access the timer queue outside of the lock
- fix ticker not stopping when Stop races with its callback (#5487)
- wake channel waiters after releasing locks (#5513)
- implement SetFinalizer and run syscall/js finalizers without a manual GC (#5545)
- implement MemStats.NumGC
- add runtime.fastrandn (#5502)
- make arrays and struct field hashes order dependent
- add critical-section fallbacks for atomic And and Or
- gc: pause all cores before scanning the stack and globals
- gc: correct the old size calculation in block realloc
- gc: correct the leaking allocator bounds and overflow checks
- gc: move objHeader to the end of the block header
- fix the leaking GC build with the cores scheduler
- rp2040: fix -gc=leaking and -gc=none
- rp2: handle the RP2350 shared FIFO IRQ for GC (#5482)
- esp32c6: select the 80MHz PLL as the TIMG0 timer clock source
- split baremetal memory setup and the Windows PE globals scan for UEFI (#5360, #5361)
* **machine**
- usb: support bidirectional endpoints by dynamic registration on RP2, SAMD21/51, and nRF52840 (#5447)
- usb: generate endpoint descriptors dynamically
- usb: implement endpoint stall for nRF52840
- usb: fix a truncated string descriptor when the host requests a short maxLen (#5449)
- usb: add USBDevice.Attach and USBDevice.Detach (#5563)
- usb/cdc: fix the RP2 USB CDC TX race with the cores scheduler (#5391)
- add UART line inversion support (#5522)
- optimize RTT initialization
- device/arm: add ARM v7-M MPU support
- esp32: add interrupt support with vector table, timer alarm, and GPIO SetInterrupt
- esp32: add interrupt-based UART RX and fix the init order
- esp32: implement flash XIP (execute-in-place) support
- esp32: add ADC driver (#5595)
- esp32: fix pullup and pulldown on RTC GPIO pins
- esp32: remove dead code and fix GC root scanning
- esp32: configure UARTs to the specified pins and yield while waiting for the buffer
- esp32, esp32s3: fix the boot crash caused by the LLVM 22 lld l32r relocation bug
- esp32s3: fix register-window corruption under interrupt load
- esp32s3: add temperature reading
- esp32c6: add a minimal implementation with I2C and ADC support
- stm32: fix UART transmission, baud rate, and interrupt handling
- stm32: add an OTG FS USB driver for F4 and F7
- stm32: add STM32H7 and NUCLEO-H753ZI support
- stm32: add support for the STM32U031 chip
- stm32: make the HSE crystal frequency selectable
- stm32u5: configure the system clock to 160 MHz
- nrf: avoid a too high priority interrupt on SoftDevice
- rp2: allow SPI transmit-only without SDI (#5437)
- rp2: clear the USB buffer status before the endpoint handlers
- rp2350: fix the ROM CS control for the RP2350 ROM code
- add GP aliases for waveshare-rp2040-zero
- gba: add support for mGBA debugging
- gba: add bios interrupt flags and sound register constants (#5445)
* **targets**
- add minimal uefi target support with the LinkerFlavor option (#5452, #5465)
- uefi: add support for UEFI time and events, fix STOP newline conversion (#5549)
- uefi: add support for the tasks scheduler and make it the default (#5553)
- add Puya PY32F MCU support (#5106)
- add esp32s3-box-3 (#5388)
- add M5Stack Stamp-S3A (#5524)
- add Pimoroni Blinky 2350 and Badger 2350 (#5434)
- add the 'Plus' board variant of SeeedStudio XIAO nrf52840 (#5479)
- esp32: adjust memory usage, add DRAM1 sections, and export the symbols needed for wifi
- esp32c3: add the BT ROM functions to the linker
- esp32: add the espradio tag for convenience
- builder: fix esp32 XIP so large programs flash correctly, including QEMU image offsets
- wasm_exec.js: add runtime.getRandomData to the gojs imports, coerce memory offsets to unsigned, and reset _pendingEvent
* **libs**
- update macos-minimal-sdk to v0.1.0
* **build/test**
- ci: run the full smoke test once, and split the GNUmakefile (#5616)
- ci: publish a draft release from the artifacts that CI already built
- ci: stop the LLVM caches from being evicted
- ci: modify builds to use LLVM 22
- ci: add a check for compatibility with older Go and LLVM versions
- ci: add a job to make sure go.sum stays in sync with go.mod
- ci: re-add fmt-check, and remove the CircleCI configuration
- ci: adjust runner sizes for Linux, Windows, and macOS
- build: statically link the MinGW runtime in the LLVM tools on Windows
- Makefile: use ${LLVM_PROJECTDIR} during the copy phase
- GNUmakefile: disable DWARF compression for CGo objects, and update the stdlib test lists
- test: run ESP32 programs in QEMU
- test: support simavr 1.8+
- test: normalize LLVM IR when updating goldens
- test: convert TestBinarySize to a golden file test
- testdata: add regression tests for generic instances, generic aliases, and large aggregates
- test: skip flaky and Go 1.27 affected tests for now
0.41.1 0.41.1
--- ---
* **machine** * **machine**
+5 -3
View File
@@ -417,6 +417,7 @@ func (b *builder) generateKeyHash(keyType types.Type, llvmKeyType llvm.Type, key
return b.createRuntimeCall("hashmapInterfacePtrHash", []llvm.Value{keyPtr, size, seed}, "hash") return b.createRuntimeCall("hashmapInterfacePtrHash", []llvm.Value{keyPtr, size, seed}, "hash")
case *types.Struct: case *types.Struct:
hash := llvm.ConstInt(b.ctx.Int32Type(), 0, false) hash := llvm.ConstInt(b.ctx.Int32Type(), 0, false)
multiplier := llvm.ConstInt(b.ctx.Int32Type(), 31, false)
zero := llvm.ConstInt(b.ctx.Int32Type(), 0, false) zero := llvm.ConstInt(b.ctx.Int32Type(), 0, false)
for i := 0; i < keyType.NumFields(); i++ { for i := 0; i < keyType.NumFields(); i++ {
if keyType.Field(i).Name() == "_" { if keyType.Field(i).Name() == "_" {
@@ -430,7 +431,7 @@ func (b *builder) generateKeyHash(keyType types.Type, llvmKeyType llvm.Type, key
idx := llvm.ConstInt(b.ctx.Int32Type(), uint64(i), false) idx := llvm.ConstInt(b.ctx.Int32Type(), uint64(i), false)
fieldPtr := b.CreateInBoundsGEP(llvmKeyType, keyPtr, []llvm.Value{zero, idx}, "") fieldPtr := b.CreateInBoundsGEP(llvmKeyType, keyPtr, []llvm.Value{zero, idx}, "")
fieldHash := b.generateKeyHash(fieldType, llvmFieldType, fieldPtr, seed) fieldHash := b.generateKeyHash(fieldType, llvmFieldType, fieldPtr, seed)
hash = b.CreateXor(hash, fieldHash, "") hash = b.CreateXor(b.CreateMul(hash, multiplier, ""), fieldHash, "")
} }
return hash return hash
case *types.Array: case *types.Array:
@@ -445,6 +446,7 @@ func (b *builder) generateKeyHash(keyType types.Type, llvmKeyType llvm.Type, key
if arrayLen == 0 { if arrayLen == 0 {
return llvm.ConstInt(b.ctx.Int32Type(), 0, false) return llvm.ConstInt(b.ctx.Int32Type(), 0, false)
} }
multiplier := llvm.ConstInt(b.ctx.Int32Type(), 31, false)
if arrayLen <= hashArrayUnrollLimit { if arrayLen <= hashArrayUnrollLimit {
hash := llvm.ConstInt(b.ctx.Int32Type(), 0, false) hash := llvm.ConstInt(b.ctx.Int32Type(), 0, false)
zero := llvm.ConstInt(b.ctx.Int32Type(), 0, false) zero := llvm.ConstInt(b.ctx.Int32Type(), 0, false)
@@ -452,7 +454,7 @@ func (b *builder) generateKeyHash(keyType types.Type, llvmKeyType llvm.Type, key
idx := llvm.ConstInt(b.uintptrType, uint64(i), false) idx := llvm.ConstInt(b.uintptrType, uint64(i), false)
elemPtr := b.CreateInBoundsGEP(llvmKeyType, keyPtr, []llvm.Value{zero, idx}, "") elemPtr := b.CreateInBoundsGEP(llvmKeyType, keyPtr, []llvm.Value{zero, idx}, "")
elemHash := b.generateKeyHash(elemType, llvmElemType, elemPtr, seed) elemHash := b.generateKeyHash(elemType, llvmElemType, elemPtr, seed)
hash = b.CreateXor(hash, elemHash, "") hash = b.CreateXor(b.CreateMul(hash, multiplier, ""), elemHash, "")
} }
return hash return hash
} }
@@ -471,7 +473,7 @@ func (b *builder) generateKeyHash(keyType types.Type, llvmKeyType llvm.Type, key
elemPtr := b.CreateInBoundsGEP(llvmKeyType, keyPtr, []llvm.Value{zero, phiI}, "") elemPtr := b.CreateInBoundsGEP(llvmKeyType, keyPtr, []llvm.Value{zero, phiI}, "")
elemHash := b.generateKeyHash(elemType, llvmElemType, elemPtr, seed) elemHash := b.generateKeyHash(elemType, llvmElemType, elemPtr, seed)
newHash := b.CreateXor(phiHash, elemHash, "") newHash := b.CreateXor(b.CreateMul(phiHash, multiplier, ""), elemHash, "")
nextI := b.CreateAdd(phiI, llvm.ConstInt(b.uintptrType, 1, false), "") nextI := b.CreateAdd(phiI, llvm.ConstInt(b.uintptrType, 1, false), "")
cond := b.CreateICmp(llvm.IntULT, nextI, llvm.ConstInt(b.uintptrType, uint64(arrayLen), false), "") cond := b.CreateICmp(llvm.IntULT, nextI, llvm.ConstInt(b.uintptrType, uint64(arrayLen), false), "")
b.CreateCondBr(cond, loopBody, loopDone) b.CreateCondBr(cond, loopBody, loopDone)
+20
View File
@@ -12,6 +12,11 @@ type nestedPadding struct {
i int i int
} }
type stringStruct struct {
a string
b string
}
//go:noinline //go:noinline
func testZeroGet(m map[hasPadding]int, s hasPadding) int { func testZeroGet(m map[hasPadding]int, s hasPadding) int {
return m[s] return m[s]
@@ -32,6 +37,21 @@ func testZeroArraySet(m map[[2]hasPadding]int, s [2]hasPadding) {
m[s] = 5 m[s] = 5
} }
//go:noinline
func makeStringStructMap() map[stringStruct]int {
return make(map[stringStruct]int)
}
//go:noinline
func makeShortStringArrayMap() map[[2]string]int {
return make(map[[2]string]int)
}
//go:noinline
func makeLongStringArrayMap() map[[5]string]int {
return make(map[[5]string]int)
}
func main() { func main() {
} }
+147
View File
@@ -4,6 +4,7 @@ target datalayout = "e-m:e-p:32:32-p10:8:8-p20:8:8-i64:64-i128:128-n32:64-S128-n
target triple = "wasm32-unknown-wasi" target triple = "wasm32-unknown-wasi"
%main.hasPadding = type { i1, i32, i1 } %main.hasPadding = type { i1, i32, i1 }
%runtime._string = type { ptr, i32 }
declare void @runtime.trackPointer(ptr nocapture readonly, ptr, ptr) #0 declare void @runtime.trackPointer(ptr nocapture readonly, ptr, ptr) #0
@@ -97,6 +98,152 @@ entry:
ret void ret void
} }
; Function Attrs: noinline nounwind
define hidden ptr @main.makeStringStructMap(ptr %context) unnamed_addr #2 {
entry:
%stackalloc = alloca i8, align 1
%0 = call ptr @runtime.hashmapMakeGeneric(i32 16, i32 4, i32 8, ptr null, ptr nonnull @"hashmapKeyHash.struct{string; string}", ptr null, ptr nonnull @"hashmapKeyEqual.struct{string; string}", ptr undef) #4
call void @runtime.trackPointer(ptr %0, ptr nonnull %stackalloc, ptr undef) #4
ret ptr %0
}
; Function Attrs: nounwind
define linkonce_odr i32 @"hashmapKeyHash.struct{string; string}"(ptr %0, i32 %1, i32 %2, ptr %3) unnamed_addr #1 {
entry:
%hash = call i32 @runtime.hashmapStringPtrHash(ptr %0, i32 8, i32 %2, ptr undef) #4
%4 = getelementptr inbounds nuw i8, ptr %0, i32 8
%hash1 = call i32 @runtime.hashmapStringPtrHash(ptr nonnull %4, i32 8, i32 %2, ptr undef) #4
%5 = mul i32 %hash, 31
%6 = xor i32 %5, %hash1
ret i32 %6
}
declare i32 @runtime.hashmapStringPtrHash(ptr, i32, i32, ptr) #0
; Function Attrs: nounwind
define linkonce_odr i1 @"hashmapKeyEqual.struct{string; string}"(ptr %0, ptr %1, i32 %2, ptr %3) unnamed_addr #1 {
entry:
%x.str.unpack = load ptr, ptr %0, align 4
%x.str.elt4 = getelementptr inbounds nuw i8, ptr %0, i32 4
%x.str.unpack5 = load i32, ptr %x.str.elt4, align 4
%y.str.unpack = load ptr, ptr %1, align 4
%y.str.elt7 = getelementptr inbounds nuw i8, ptr %1, i32 4
%y.str.unpack8 = load i32, ptr %y.str.elt7, align 4
%eq = call i1 @runtime.stringEqual(ptr %x.str.unpack, i32 %x.str.unpack5, ptr %y.str.unpack, i32 %y.str.unpack8, ptr undef) #4
%4 = getelementptr inbounds nuw i8, ptr %0, i32 8
%5 = getelementptr inbounds nuw i8, ptr %1, i32 8
%x.str1.unpack = load ptr, ptr %4, align 4
%x.str1.elt10 = getelementptr inbounds nuw i8, ptr %0, i32 12
%x.str1.unpack11 = load i32, ptr %x.str1.elt10, align 4
%y.str2.unpack = load ptr, ptr %5, align 4
%y.str2.elt13 = getelementptr inbounds nuw i8, ptr %1, i32 12
%y.str2.unpack14 = load i32, ptr %y.str2.elt13, align 4
%eq3 = call i1 @runtime.stringEqual(ptr %x.str1.unpack, i32 %x.str1.unpack11, ptr %y.str2.unpack, i32 %y.str2.unpack14, ptr undef) #4
%6 = and i1 %eq, %eq3
ret i1 %6
}
declare i1 @runtime.stringEqual(ptr readonly, i32, ptr readonly, i32, ptr) #0
declare ptr @runtime.hashmapMakeGeneric(i32, i32, i32, ptr, ptr, ptr, ptr, ptr) #0
; Function Attrs: noinline nounwind
define hidden ptr @main.makeShortStringArrayMap(ptr %context) unnamed_addr #2 {
entry:
%stackalloc = alloca i8, align 1
%0 = call ptr @runtime.hashmapMakeGeneric(i32 16, i32 4, i32 8, ptr null, ptr nonnull @"hashmapKeyHash.[2]string", ptr null, ptr nonnull @"hashmapKeyEqual.[2]string", ptr undef) #4
call void @runtime.trackPointer(ptr %0, ptr nonnull %stackalloc, ptr undef) #4
ret ptr %0
}
; Function Attrs: nounwind
define linkonce_odr i32 @"hashmapKeyHash.[2]string"(ptr %0, i32 %1, i32 %2, ptr %3) unnamed_addr #1 {
entry:
%hash = call i32 @runtime.hashmapStringPtrHash(ptr %0, i32 8, i32 %2, ptr undef) #4
%4 = getelementptr inbounds nuw i8, ptr %0, i32 8
%hash1 = call i32 @runtime.hashmapStringPtrHash(ptr nonnull %4, i32 8, i32 %2, ptr undef) #4
%5 = mul i32 %hash, 31
%6 = xor i32 %5, %hash1
ret i32 %6
}
; Function Attrs: nounwind
define linkonce_odr i1 @"hashmapKeyEqual.[2]string"(ptr %0, ptr %1, i32 %2, ptr %3) unnamed_addr #1 {
entry:
%x.str.unpack = load ptr, ptr %0, align 4
%x.str.elt4 = getelementptr inbounds nuw i8, ptr %0, i32 4
%x.str.unpack5 = load i32, ptr %x.str.elt4, align 4
%y.str.unpack = load ptr, ptr %1, align 4
%y.str.elt7 = getelementptr inbounds nuw i8, ptr %1, i32 4
%y.str.unpack8 = load i32, ptr %y.str.elt7, align 4
%eq = call i1 @runtime.stringEqual(ptr %x.str.unpack, i32 %x.str.unpack5, ptr %y.str.unpack, i32 %y.str.unpack8, ptr undef) #4
%4 = getelementptr inbounds nuw i8, ptr %0, i32 8
%5 = getelementptr inbounds nuw i8, ptr %1, i32 8
%x.str1.unpack = load ptr, ptr %4, align 4
%x.str1.elt10 = getelementptr inbounds nuw i8, ptr %0, i32 12
%x.str1.unpack11 = load i32, ptr %x.str1.elt10, align 4
%y.str2.unpack = load ptr, ptr %5, align 4
%y.str2.elt13 = getelementptr inbounds nuw i8, ptr %1, i32 12
%y.str2.unpack14 = load i32, ptr %y.str2.elt13, align 4
%eq3 = call i1 @runtime.stringEqual(ptr %x.str1.unpack, i32 %x.str1.unpack11, ptr %y.str2.unpack, i32 %y.str2.unpack14, ptr undef) #4
%6 = and i1 %eq, %eq3
ret i1 %6
}
; Function Attrs: noinline nounwind
define hidden ptr @main.makeLongStringArrayMap(ptr %context) unnamed_addr #2 {
entry:
%stackalloc = alloca i8, align 1
%0 = call ptr @runtime.hashmapMakeGeneric(i32 40, i32 4, i32 8, ptr null, ptr nonnull @"hashmapKeyHash.[5]string", ptr null, ptr nonnull @"hashmapKeyEqual.[5]string", ptr undef) #4
call void @runtime.trackPointer(ptr %0, ptr nonnull %stackalloc, ptr undef) #4
ret ptr %0
}
; Function Attrs: nounwind
define linkonce_odr i32 @"hashmapKeyHash.[5]string"(ptr %0, i32 %1, i32 %2, ptr %3) unnamed_addr #1 {
entry:
br label %hash.array.body
hash.array.body: ; preds = %hash.array.body, %entry
%i = phi i32 [ 0, %entry ], [ %7, %hash.array.body ]
%hash.acc = phi i32 [ 0, %entry ], [ %6, %hash.array.body ]
%4 = getelementptr inbounds nuw %runtime._string, ptr %0, i32 %i
%hash = call i32 @runtime.hashmapStringPtrHash(ptr %4, i32 8, i32 %2, ptr undef) #4
%5 = mul i32 %hash.acc, 31
%6 = xor i32 %5, %hash
%7 = add nuw nsw i32 %i, 1
%8 = icmp samesign ult i32 %i, 4
br i1 %8, label %hash.array.body, label %hash.array.done
hash.array.done: ; preds = %hash.array.body
ret i32 %6
}
; Function Attrs: nounwind
define linkonce_odr i1 @"hashmapKeyEqual.[5]string"(ptr %0, ptr %1, i32 %2, ptr %3) unnamed_addr #1 {
entry:
br label %eq.array.body
eq.array.body: ; preds = %eq.array.body, %entry
%i = phi i32 [ 0, %entry ], [ %6, %eq.array.body ]
%4 = getelementptr inbounds %runtime._string, ptr %0, i32 %i
%5 = getelementptr inbounds %runtime._string, ptr %1, i32 %i
%x.str.unpack = load ptr, ptr %4, align 4
%x.str.elt1 = getelementptr inbounds nuw i8, ptr %4, i32 4
%x.str.unpack2 = load i32, ptr %x.str.elt1, align 4
%y.str.unpack = load ptr, ptr %5, align 4
%y.str.elt4 = getelementptr inbounds nuw i8, ptr %5, i32 4
%y.str.unpack5 = load i32, ptr %y.str.elt4, align 4
%eq = call i1 @runtime.stringEqual(ptr %x.str.unpack, i32 %x.str.unpack2, ptr %y.str.unpack, i32 %y.str.unpack5, ptr undef) #4
%6 = add i32 %i, 1
%7 = icmp ult i32 %6, 5
%.not7 = and i1 %7, %eq
br i1 %.not7, label %eq.array.body, label %eq.array.done
eq.array.done: ; preds = %eq.array.body
ret i1 %eq
}
; Function Attrs: nounwind ; Function Attrs: nounwind
define hidden void @main.main(ptr %context) unnamed_addr #1 { define hidden void @main.main(ptr %context) unnamed_addr #1 {
entry: entry:
+1 -1
View File
@@ -10,7 +10,7 @@ import (
// Version of TinyGo. // Version of TinyGo.
// Update this value before release of new version of software. // Update this value before release of new version of software.
const version = "0.42.0" const version = "0.42.0-dev"
// Return TinyGo version, either in the form 0.30.0 or as a development version // Return TinyGo version, either in the form 0.30.0 or as a development version
// (like 0.30.0-dev-abcd012). // (like 0.30.0-dev-abcd012).