Compare commits

..

3 Commits

Author SHA1 Message Date
deadprogram ae9eb7e64e esp32c6: bind ROM data symbols to their ROM addresses
The ROM symbol tables were emitted entirely as PROVIDE(), which is right
for ROM functions but wrong for ROM data. Symbols like g_osi_funcs_p,
pTxRx, our_tx_eb and lmacConfMib_ptr are variables in RAM that mask ROM
code reads and writes at a fixed address; they are shared storage, not a
fallback implementation.

With PROVIDE(), a weak definition in the program wins and the program and
the mask ROM then use two different locations for the same variable.
g_osi_funcs_p hit exactly this: espradio declares it weak, so it resolved
to .bss while ROM code kept reading 0x4087ff6c, which nothing ever wrote.

Assign the 121 ROM data symbols unconditionally, as esp32c3.ld already
does for the same variables. Addresses verified identical to ESP-IDF's
esp32c6 ROM linker scripts.

Signed-off-by: Ron Evans <ron@hybridgroup.com>
2026-08-30 11:05:14 +02:00
deadprogram 6b53c58f92 esp32c6: fix .rodata flash mapping being off by a few bytes
The flash MMU maps 64kB pages, so a flash-mapped section is only read
correctly when its virtual address and its offset within the firmware
image agree modulo 64kB. targets/esp32c6.ld reproduces the image offset
in .rodata_dummy by accumulating the preceding segment sizes and headers,
which works only if the linker inserts no alignment padding between the
dummy and .rodata -- padding moves the virtual address without moving the
image offset.

lld gives .rodata 8-byte alignment, but the accumulated offset is only
4-byte aligned, so whenever the preceding segments happened to leave the
running offset at a 4-mod-8 boundary the whole of .rodata was mapped 4
bytes off. Every read of constant data then returned neighbouring bytes.

This is silent and looks like arbitrary memory corruption rather than a
mapping bug. It was found while bringing up WiFi: the blob rejected its
init config because the first field of a const struct read back as a code
pointer, and whether a given build was affected depended on unrelated code
size changes.

Pad .data, .iram and .text to a multiple of 8 so the running image offset
stays 8-aligned and matches, and add ASSERTs for both flash-mapped
sections so this cannot regress silently.

Signed-off-by: Ron Evans <ron@hybridgroup.com>
2026-08-30 10:36:44 +02:00
deadprogram a7626e87e9 esp32c6: prepare target for espradio WiFi support
The ESP32-C6 target was never built with a radio blob in mind. Three gaps
in targets/esp32c6.ld prevented espradio from linking or running:

- The Espressif WiFi/PHY libraries resolve ~245 internal symbols against
  the mask ROM. Only seven ROM symbols were defined. Add the ESP-IDF
  generated ROM interface tables (1201 symbols), all as PROVIDE() so any
  real definition in the program wins over the ROM copy.
- The .iram output section did not collect the blob IRAM sections
  (.wifi0iram, .wifirxiram, .wifislpiram, .wifislprxiram, .wifiextrairam,
  .wifiorslpiram, .coexiram, .iram1). Without them that code lands in
  flash and crashes when called from an interrupt.
- _heap_end ran to the end of SRAM at 0x40880000, over the mask ROM stack
  and ROM data. phy_param_rom sits at 0x4087fce8, inside that range, so a
  growing Go heap would corrupt the PHY. Cap the heap at 0x4087C610.

Also add the espradio build tag to esp32c6.json, matching esp32c3.json
and esp32s3.json.

Signed-off-by: Ron Evans <ron@hybridgroup.com>
2026-08-29 19:30:41 +02:00
12 changed files with 1315 additions and 425 deletions
-35
View File
@@ -1,35 +0,0 @@
#!/bin/sh
# Print the CHANGELOG.md entry for one version, to use as release notes.
# The file uses a setext heading: the bare version, then a line of dashes.
set -e
version="$1"
if [ -z "$version" ]; then
echo "usage: $0 <version>" >&2
exit 1
fi
notes=$(awk -v version="$version" '
found {
if ($0 ~ /^---+$/ && previous != "") { previous = ""; exit }
if (previous != "") print previous
previous = $0
next
}
$0 ~ /^---+$/ && previous == version {
found = 1
previous = ""
next
}
{ previous = $0 }
END { if (found && previous != "") print previous }
' CHANGELOG.md)
if [ -z "$notes" ]; then
echo "no CHANGELOG.md entry for version $version" >&2
exit 1
fi
echo "$notes"
-158
View File
@@ -1,158 +0,0 @@
# Publish a GitHub release from the artifacts that CI already built.
#
# The Linux, macOS and Windows workflows build every file that a release needs
# when the release branch is pushed. This workflow collects the artifacts of
# those runs for the tagged commit, so what ships is what was tested.
#
# The release is a draft, so the notes can be reviewed before publication.
name: Release
on:
push:
tags:
- 'v*'
workflow_dispatch:
inputs:
tag:
description: 'Tag to release, for example v0.42.0'
required: true
concurrency:
group: release-${{ inputs.tag || github.ref_name }}
cancel-in-progress: false
permissions:
contents: write
actions: read
jobs:
release:
runs-on: ubuntu-latest
env:
GH_TOKEN: ${{ github.token }}
GH_REPO: ${{ github.repository }}
TAG: ${{ inputs.tag || github.ref_name }}
steps:
- name: Checkout
uses: actions/checkout@v6
with:
ref: ${{ inputs.tag || github.ref_name }}
fetch-depth: 0
- name: Read the version
id: version
# The release file names come from goenv/version.go, not from the tag,
# so the two must agree.
run: |
version=$(./.github/workflows/tinygo-extract-version.sh | cut -d= -f2-)
case "$version" in
*-dev)
echo "::error::goenv/version.go has development version $version"
exit 1
;;
esac
if [ "v$version" != "$TAG" ]; then
echo "::error::tag $TAG does not match version $version in goenv/version.go"
exit 1
fi
echo "version=$version" >> "$GITHUB_OUTPUT"
- name: Wait for the CI runs of this commit
id: runs
# A pull request run has the merge commit as its head, so look at push
# runs only.
run: |
sha=$(git rev-parse HEAD)
for workflow in linux.yml build-macos.yml windows.yml; do
id=
for _ in $(seq 20); do
id=$(gh run list --workflow "$workflow" --commit "$sha" --event push --limit 1 --json databaseId --jq '.[0].databaseId')
if [ -n "$id" ]; then
break
fi
echo "waiting for $workflow to start on $sha"
sleep 30
done
if [ -z "$id" ]; then
echo "::error::no $workflow run for commit $sha"
exit 1
fi
echo "$workflow: run $id"
gh run watch "$id" --exit-status > /dev/null || true
conclusion=$(gh run view "$id" --json conclusion --jq .conclusion)
if [ "$conclusion" != "success" ]; then
echo "::error::$workflow run $id concluded with $conclusion"
exit 1
fi
case "$workflow" in
linux.yml) echo "linux=$id" >> "$GITHUB_OUTPUT" ;;
build-macos.yml) echo "macos=$id" >> "$GITHUB_OUTPUT" ;;
windows.yml) echo "windows=$id" >> "$GITHUB_OUTPUT" ;;
esac
done
# The build jobs upload with `archive: false`, so the artifact is the
# release file itself. skip-decompress keeps it that way. The Windows
# release is a .zip, which a download would otherwise unpack.
- name: Download the Linux artifacts
uses: actions/download-artifact@v8
with:
run-id: ${{ steps.runs.outputs.linux }}
github-token: ${{ github.token }}
path: artifacts
skip-decompress: true
- name: Download the macOS artifacts
uses: actions/download-artifact@v8
with:
run-id: ${{ steps.runs.outputs.macos }}
github-token: ${{ github.token }}
path: artifacts
skip-decompress: true
- name: Download the Windows artifacts
uses: actions/download-artifact@v8
with:
run-id: ${{ steps.runs.outputs.windows }}
github-token: ${{ github.token }}
path: artifacts
skip-decompress: true
- name: Collect the release files
# A build that stopped uploading must not give a half complete release,
# so list the files that are expected. The search is by file name, not
# by artifact name, because the artifact names are not uniform.
env:
VERSION: ${{ steps.version.outputs.version }}
run: |
version=$VERSION
mkdir -p dist
missing=0
for file in \
"tinygo$version.linux-amd64.tar.gz" "tinygo_${version}_amd64.deb" \
"tinygo$version.linux-arm.tar.gz" "tinygo_${version}_armhf.deb" \
"tinygo$version.linux-arm64.tar.gz" "tinygo_${version}_arm64.deb" \
"tinygo$version.darwin-amd64.tar.gz" \
"tinygo$version.darwin-arm64.tar.gz" \
"tinygo$version.windows-amd64.zip"; do
found=$(find artifacts -type f -name "$file" | head -1)
if [ -z "$found" ]; then
echo "::error::missing release file $file"
missing=1
else
mv "$found" "dist/$file"
fi
done
ls -l dist
exit $missing
- name: Extract the release notes
env:
VERSION: ${{ steps.version.outputs.version }}
run: ./.github/workflows/extract-changelog.sh "$VERSION" > notes.md
- name: Create the draft release
env:
VERSION: ${{ steps.version.outputs.version }}
run: |
version=$VERSION
set --
case "$version" in
*-*) set -- --prerelease ;;
esac
gh release create "$TAG" --draft --verify-tag "$@" \
--title "$version" \
--notes-file notes.md \
dist/*
-32
View File
@@ -123,35 +123,3 @@ the following command (for example in ~/lib):
TinyGo will get extracted to a `tinygo` directory. You can then call it with:
./tinygo/bin/tinygo
## Publish a release
The `Release` workflow (`.github/workflows/release.yml`) publishes releases. It
does not build anything. The Linux, macOS and Windows workflows already build
every file that a release needs when the `release` branch is pushed, so the
release workflow collects the artifacts of those runs for the tagged commit.
What ships is what was tested.
1. On the `dev` branch, set `const version` in `goenv/version.go` to the new
version (without a `v` prefix), and add the entry to `CHANGELOG.md`.
2. Merge `dev` into the `release` branch.
3. Tag that commit and push the tag:
git tag v0.42.0
git push origin v0.42.0
The tag must be `v` plus the version in `goenv/version.go`, because the
release file names come from that constant.
4. The workflow waits for the Linux, macOS and Windows runs of the tagged
commit, collects their nine files, and creates a **draft** release. The
release notes come from the `CHANGELOG.md` entry for that version.
5. Review the draft release and publish it.
6. On the `dev` branch, set `goenv/version.go` to the next `-dev` version.
To release again after a failure, delete the draft release and start the
workflow from the Actions tab with the tag as its input.
GitHub keeps a SHA-256 digest of every published file. The digest is not shown
on the release page, but it can be printed with:
gh release view v0.42.0 --json assets --jq '.assets[] | "\(.digest) \(.name)"'
+2 -2
View File
@@ -43,11 +43,11 @@ var libWasmBuiltins = Library{
sourceDir: func() string { return filepath.Join(goenv.Get("TINYGOROOT"), "lib/wasi-libc") },
librarySources: func(target string, _ bool) ([]string, error) {
return []string{
// Memory builtins needed for LLVM intrinsics and library calls.
// memory builtins needed for llvm.memcpy.*, llvm.memmove.*, and
// llvm.memset.* LLVM intrinsics.
"libc-top-half/musl/src/string/memcpy.c",
"libc-top-half/musl/src/string/memmove.c",
"libc-top-half/musl/src/string/memset.c",
"libc-top-half/musl/src/string/strlen.c",
// exp, exp2, and log are needed for LLVM math builtin functions
// like llvm.exp.*.
+2 -3
View File
@@ -23,9 +23,8 @@ import (
// builder.Library struct but that's hard to do since we want to know the
// library path in advance in several places).
var libVersions = map[string]int{
"musl": 3,
"bdwgc": 2,
"wasmbuiltins": 1,
"musl": 3,
"bdwgc": 2,
}
// Config keeps all configuration affecting the build in a single struct.
+3 -5
View File
@@ -417,7 +417,6 @@ func (b *builder) generateKeyHash(keyType types.Type, llvmKeyType llvm.Type, key
return b.createRuntimeCall("hashmapInterfacePtrHash", []llvm.Value{keyPtr, size, seed}, "hash")
case *types.Struct:
hash := llvm.ConstInt(b.ctx.Int32Type(), 0, false)
multiplier := llvm.ConstInt(b.ctx.Int32Type(), 31, false)
zero := llvm.ConstInt(b.ctx.Int32Type(), 0, false)
for i := 0; i < keyType.NumFields(); i++ {
if keyType.Field(i).Name() == "_" {
@@ -431,7 +430,7 @@ func (b *builder) generateKeyHash(keyType types.Type, llvmKeyType llvm.Type, key
idx := llvm.ConstInt(b.ctx.Int32Type(), uint64(i), false)
fieldPtr := b.CreateInBoundsGEP(llvmKeyType, keyPtr, []llvm.Value{zero, idx}, "")
fieldHash := b.generateKeyHash(fieldType, llvmFieldType, fieldPtr, seed)
hash = b.CreateXor(b.CreateMul(hash, multiplier, ""), fieldHash, "")
hash = b.CreateXor(hash, fieldHash, "")
}
return hash
case *types.Array:
@@ -446,7 +445,6 @@ func (b *builder) generateKeyHash(keyType types.Type, llvmKeyType llvm.Type, key
if arrayLen == 0 {
return llvm.ConstInt(b.ctx.Int32Type(), 0, false)
}
multiplier := llvm.ConstInt(b.ctx.Int32Type(), 31, false)
if arrayLen <= hashArrayUnrollLimit {
hash := llvm.ConstInt(b.ctx.Int32Type(), 0, false)
zero := llvm.ConstInt(b.ctx.Int32Type(), 0, false)
@@ -454,7 +452,7 @@ func (b *builder) generateKeyHash(keyType types.Type, llvmKeyType llvm.Type, key
idx := llvm.ConstInt(b.uintptrType, uint64(i), false)
elemPtr := b.CreateInBoundsGEP(llvmKeyType, keyPtr, []llvm.Value{zero, idx}, "")
elemHash := b.generateKeyHash(elemType, llvmElemType, elemPtr, seed)
hash = b.CreateXor(b.CreateMul(hash, multiplier, ""), elemHash, "")
hash = b.CreateXor(hash, elemHash, "")
}
return hash
}
@@ -473,7 +471,7 @@ func (b *builder) generateKeyHash(keyType types.Type, llvmKeyType llvm.Type, key
elemPtr := b.CreateInBoundsGEP(llvmKeyType, keyPtr, []llvm.Value{zero, phiI}, "")
elemHash := b.generateKeyHash(elemType, llvmElemType, elemPtr, seed)
newHash := b.CreateXor(b.CreateMul(phiHash, multiplier, ""), elemHash, "")
newHash := b.CreateXor(phiHash, elemHash, "")
nextI := b.CreateAdd(phiI, llvm.ConstInt(b.uintptrType, 1, false), "")
cond := b.CreateICmp(llvm.IntULT, nextI, llvm.ConstInt(b.uintptrType, uint64(arrayLen), false), "")
b.CreateCondBr(cond, loopBody, loopDone)
-20
View File
@@ -12,11 +12,6 @@ type nestedPadding struct {
i int
}
type stringStruct struct {
a string
b string
}
//go:noinline
func testZeroGet(m map[hasPadding]int, s hasPadding) int {
return m[s]
@@ -37,21 +32,6 @@ func testZeroArraySet(m map[[2]hasPadding]int, s [2]hasPadding) {
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() {
}
-147
View File
@@ -4,7 +4,6 @@ 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"
%main.hasPadding = type { i1, i32, i1 }
%runtime._string = type { ptr, i32 }
declare void @runtime.trackPointer(ptr nocapture readonly, ptr, ptr) #0
@@ -98,152 +97,6 @@ entry:
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
define hidden void @main.main(ptr %context) unnamed_addr #1 {
entry:
+3 -4
View File
@@ -573,10 +573,9 @@ smoketest-riscv: | build/smoke
smoketest-wasm: SMOKE_OUT = build/smoke/wasm
smoketest-wasm: | build/smoke
ifneq ($(WASM), 0)
$(TINYGO) build -size short -o $(SMOKE_OUT).wasm -target=wasm examples/wasm/export
$(TINYGO) build -size short -o $(SMOKE_OUT).wasm -target=wasm examples/wasm/main
$(TINYGO) build -size short -o $(SMOKE_OUT).wasm -target=wasm-unknown examples/hello-wasm-unknown
$(TINYGO) build -size short -o $(SMOKE_OUT).wasm -target=wasm-unknown -opt=2 ./testdata/wasm-unknown-opt
$(TINYGO) build -size short -o $(SMOKE_OUT).wasm -target=wasm examples/wasm/export
$(TINYGO) build -size short -o $(SMOKE_OUT).wasm -target=wasm examples/wasm/main
$(TINYGO) build -size short -o $(SMOKE_OUT).wasm -target=wasm-unknown examples/hello-wasm-unknown
endif
smoketest-flags: SMOKE_OUT = build/smoke/flags
+2 -1
View File
@@ -6,7 +6,8 @@
"features": "+32bit,+a,+c,+m,+zaamo,+zalrsc,+zmmul,-relax",
"build-tags": [
"esp32c6",
"esp"
"esp",
"espradio"
],
"serial": "usb",
"rtlib": "compiler-rt",
+1303 -3
View File
File diff suppressed because it is too large Load Diff
-15
View File
@@ -1,15 +0,0 @@
package main
import "reflect"
type value struct {
Field int
}
//go:wasmexport typeNameLength
func typeNameLength() uint32 {
return uint32(len(reflect.TypeOf(value{}).String()))
}
func main() {
}