mirror of
https://github.com/tinygo-org/tinygo.git
synced 2026-08-15 16:33:40 +00:00
Compare commits
2 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| c33682cf00 | |||
| 570a3deac2 |
@@ -40,7 +40,7 @@ jobs:
|
|||||||
- name: Install Go
|
- name: Install Go
|
||||||
uses: actions/setup-go@v6
|
uses: actions/setup-go@v6
|
||||||
with:
|
with:
|
||||||
go-version: '1.27.0-rc.3'
|
go-version: '1.27.0-rc.2'
|
||||||
cache: true
|
cache: true
|
||||||
- name: Restore LLVM source cache
|
- name: Restore LLVM source cache
|
||||||
uses: actions/cache/restore@v5
|
uses: actions/cache/restore@v5
|
||||||
@@ -131,7 +131,7 @@ jobs:
|
|||||||
- name: Install Go
|
- name: Install Go
|
||||||
uses: actions/setup-go@v6
|
uses: actions/setup-go@v6
|
||||||
with:
|
with:
|
||||||
go-version: '1.27.0-rc.3'
|
go-version: '1.27.0-rc.2'
|
||||||
cache: true
|
cache: true
|
||||||
- name: Build TinyGo (LLVM ${{ matrix.version }})
|
- name: Build TinyGo (LLVM ${{ matrix.version }})
|
||||||
run: go install -tags=llvm${{ matrix.version }}
|
run: go install -tags=llvm${{ matrix.version }}
|
||||||
|
|||||||
@@ -23,7 +23,7 @@ jobs:
|
|||||||
- name: Install Go
|
- name: Install Go
|
||||||
uses: actions/setup-go@v6
|
uses: actions/setup-go@v6
|
||||||
with:
|
with:
|
||||||
go-version: '1.27.0-rc.3'
|
go-version: '1.27.0-rc.2'
|
||||||
cache: true
|
cache: true
|
||||||
- name: Run go mod tidy
|
- name: Run go mod tidy
|
||||||
run: go mod tidy
|
run: go mod tidy
|
||||||
@@ -36,7 +36,7 @@ jobs:
|
|||||||
# statically linked binary.
|
# statically linked binary.
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
container:
|
container:
|
||||||
image: golang:1.27rc3-alpine
|
image: golang:1.27rc2-alpine
|
||||||
outputs:
|
outputs:
|
||||||
version: ${{ steps.version.outputs.version }}
|
version: ${{ steps.version.outputs.version }}
|
||||||
steps:
|
steps:
|
||||||
@@ -160,7 +160,7 @@ jobs:
|
|||||||
- name: Install Go
|
- name: Install Go
|
||||||
uses: actions/setup-go@v6
|
uses: actions/setup-go@v6
|
||||||
with:
|
with:
|
||||||
go-version: '1.27.0-rc.3'
|
go-version: '1.27.0-rc.2'
|
||||||
cache: true
|
cache: true
|
||||||
- name: Install wasmtime
|
- name: Install wasmtime
|
||||||
uses: bytecodealliance/actions/wasmtime/setup@v1
|
uses: bytecodealliance/actions/wasmtime/setup@v1
|
||||||
@@ -204,7 +204,7 @@ jobs:
|
|||||||
- name: Install Go
|
- name: Install Go
|
||||||
uses: actions/setup-go@v6
|
uses: actions/setup-go@v6
|
||||||
with:
|
with:
|
||||||
go-version: '1.27.0-rc.3'
|
go-version: '1.27.0-rc.2'
|
||||||
cache: true
|
cache: true
|
||||||
- name: Install Node.js
|
- name: Install Node.js
|
||||||
uses: actions/setup-node@v6
|
uses: actions/setup-node@v6
|
||||||
@@ -323,7 +323,7 @@ jobs:
|
|||||||
- name: Install Go
|
- name: Install Go
|
||||||
uses: actions/setup-go@v6
|
uses: actions/setup-go@v6
|
||||||
with:
|
with:
|
||||||
go-version: '1.27.0-rc.3'
|
go-version: '1.27.0-rc.2'
|
||||||
cache: true
|
cache: true
|
||||||
- name: Restore LLVM source cache
|
- name: Restore LLVM source cache
|
||||||
uses: actions/cache/restore@v5
|
uses: actions/cache/restore@v5
|
||||||
|
|||||||
@@ -34,7 +34,7 @@ jobs:
|
|||||||
- name: Install Go
|
- name: Install Go
|
||||||
uses: actions/setup-go@v6
|
uses: actions/setup-go@v6
|
||||||
with:
|
with:
|
||||||
go-version: '1.27.0-rc.3'
|
go-version: '1.27.0-rc.2'
|
||||||
cache: true
|
cache: true
|
||||||
- name: Restore cached LLVM source
|
- name: Restore cached LLVM source
|
||||||
uses: actions/cache/restore@v5
|
uses: actions/cache/restore@v5
|
||||||
@@ -129,7 +129,7 @@ jobs:
|
|||||||
- name: Install Go
|
- name: Install Go
|
||||||
uses: actions/setup-go@v6
|
uses: actions/setup-go@v6
|
||||||
with:
|
with:
|
||||||
go-version: '1.27.0-rc.3'
|
go-version: '1.27.0-rc.2'
|
||||||
cache: true
|
cache: true
|
||||||
- name: Download TinyGo build
|
- name: Download TinyGo build
|
||||||
uses: actions/download-artifact@v8
|
uses: actions/download-artifact@v8
|
||||||
@@ -150,7 +150,7 @@ jobs:
|
|||||||
- name: Install Go
|
- name: Install Go
|
||||||
uses: actions/setup-go@v6
|
uses: actions/setup-go@v6
|
||||||
with:
|
with:
|
||||||
go-version: '1.27.0-rc.3'
|
go-version: '1.27.0-rc.2'
|
||||||
cache: true
|
cache: true
|
||||||
- name: Download TinyGo build
|
- name: Download TinyGo build
|
||||||
uses: actions/download-artifact@v8
|
uses: actions/download-artifact@v8
|
||||||
@@ -176,7 +176,7 @@ jobs:
|
|||||||
- name: Install Go
|
- name: Install Go
|
||||||
uses: actions/setup-go@v6
|
uses: actions/setup-go@v6
|
||||||
with:
|
with:
|
||||||
go-version: '1.27.0-rc.3'
|
go-version: '1.27.0-rc.2'
|
||||||
cache: true
|
cache: true
|
||||||
- name: Download TinyGo build
|
- name: Download TinyGo build
|
||||||
uses: actions/download-artifact@v8
|
uses: actions/download-artifact@v8
|
||||||
|
|||||||
+2
-2
@@ -1,5 +1,5 @@
|
|||||||
# tinygo-llvm stage obtains the llvm source for TinyGo
|
# tinygo-llvm stage obtains the llvm source for TinyGo
|
||||||
FROM golang:1.27rc3 AS tinygo-llvm
|
FROM golang:1.27rc2 AS tinygo-llvm
|
||||||
|
|
||||||
RUN apt-get update && \
|
RUN apt-get update && \
|
||||||
apt-get install -y apt-utils make cmake clang-17 ninja-build && \
|
apt-get install -y apt-utils make cmake clang-17 ninja-build && \
|
||||||
@@ -33,7 +33,7 @@ RUN cd /tinygo/ && \
|
|||||||
|
|
||||||
# tinygo-compiler copies the compiler build over to a base Go container (without
|
# tinygo-compiler copies the compiler build over to a base Go container (without
|
||||||
# all the build tools etc).
|
# all the build tools etc).
|
||||||
FROM golang:1.27rc3 AS tinygo-compiler
|
FROM golang:1.27rc2 AS tinygo-compiler
|
||||||
|
|
||||||
# Copy tinygo build.
|
# Copy tinygo build.
|
||||||
COPY --from=tinygo-compiler-build /tinygo/build/release/tinygo /tinygo
|
COPY --from=tinygo-compiler-build /tinygo/build/release/tinygo /tinygo
|
||||||
|
|||||||
+9
-2
@@ -24,6 +24,7 @@ import (
|
|||||||
"sort"
|
"sort"
|
||||||
"strconv"
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
|
"sync"
|
||||||
|
|
||||||
"github.com/gofrs/flock"
|
"github.com/gofrs/flock"
|
||||||
"github.com/tinygo-org/tinygo/compileopts"
|
"github.com/tinygo-org/tinygo/compileopts"
|
||||||
@@ -269,6 +270,7 @@ func Build(pkgName, outpath, tmpdir string, config *compileopts.Config) (BuildRe
|
|||||||
// Create the *ssa.Program. This does not yet build the entire SSA of the
|
// Create the *ssa.Program. This does not yet build the entire SSA of the
|
||||||
// program so it's pretty fast and doesn't need to be parallelized.
|
// program so it's pretty fast and doesn't need to be parallelized.
|
||||||
program := lprogram.LoadSSA()
|
program := lprogram.LoadSSA()
|
||||||
|
buildProgram := sync.OnceFunc(program.Build)
|
||||||
|
|
||||||
// Add jobs to compile each package.
|
// Add jobs to compile each package.
|
||||||
// Packages that have a cache hit will not be compiled again.
|
// Packages that have a cache hit will not be compiled again.
|
||||||
@@ -398,8 +400,13 @@ func Build(pkgName, outpath, tmpdir string, config *compileopts.Config) (BuildRe
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// Compile AST to IR. The compiler.CompilePackage function will
|
// SSA package builds may run concurrently, but the resulting
|
||||||
// build the SSA as needed.
|
// functions cannot be inspected until all builds have finished:
|
||||||
|
// generic instances and wrappers can be shared across packages.
|
||||||
|
// Build the whole program once before compiling any package.
|
||||||
|
buildProgram()
|
||||||
|
|
||||||
|
// Compile AST to IR.
|
||||||
mod, errs := compiler.CompilePackage(pkg.ImportPath, pkg, program.Package(pkg.Pkg), machine, compilerConfig, config.DumpSSA())
|
mod, errs := compiler.CompilePackage(pkg.ImportPath, pkg, program.Package(pkg.Pkg), machine, compilerConfig, config.DumpSSA())
|
||||||
defer mod.Context().Dispose()
|
defer mod.Context().Dispose()
|
||||||
defer mod.Dispose()
|
defer mod.Dispose()
|
||||||
|
|||||||
@@ -296,6 +296,9 @@ func Sizes(machine llvm.TargetMachine) types.Sizes {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// CompilePackage compiles a single package to a LLVM module.
|
// CompilePackage compiles a single package to a LLVM module.
|
||||||
|
//
|
||||||
|
// The SSA package must already be built. When packages are compiled
|
||||||
|
// concurrently, the entire SSA program must be built before compilation starts.
|
||||||
func CompilePackage(moduleName string, pkg *loader.Package, ssaPkg *ssa.Package, machine llvm.TargetMachine, config *Config, dumpSSA bool) (llvm.Module, []error) {
|
func CompilePackage(moduleName string, pkg *loader.Package, ssaPkg *ssa.Package, machine llvm.TargetMachine, config *Config, dumpSSA bool) (llvm.Module, []error) {
|
||||||
c := newCompilerContext(moduleName, machine, config, dumpSSA)
|
c := newCompilerContext(moduleName, machine, config, dumpSSA)
|
||||||
defer c.dispose()
|
defer c.dispose()
|
||||||
@@ -306,9 +309,6 @@ func CompilePackage(moduleName string, pkg *loader.Package, ssaPkg *ssa.Package,
|
|||||||
c.runtimePkg = ssaPkg.Prog.ImportedPackage("runtime").Pkg
|
c.runtimePkg = ssaPkg.Prog.ImportedPackage("runtime").Pkg
|
||||||
c.program = ssaPkg.Prog
|
c.program = ssaPkg.Prog
|
||||||
|
|
||||||
// Convert AST to SSA.
|
|
||||||
ssaPkg.Build()
|
|
||||||
|
|
||||||
// Assign names to function-local named types before compiling the
|
// Assign names to function-local named types before compiling the
|
||||||
// package, so that types declared in different functions (or in
|
// package, so that types declared in different functions (or in
|
||||||
// different instantiations of a generic function) do not collide.
|
// different instantiations of a generic function) do not collide.
|
||||||
|
|||||||
@@ -115,7 +115,7 @@ func TestCompiler(t *testing.T) {
|
|||||||
|
|
||||||
// Update test if needed. Do not check the result.
|
// Update test if needed. Do not check the result.
|
||||||
if *flagUpdate {
|
if *flagUpdate {
|
||||||
err := os.WriteFile(outPath, []byte(mod.String()), 0666)
|
err := os.WriteFile(outPath, []byte(normalizeIR(mod.String())), 0666)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Error("failed to write updated output file:", err)
|
t.Error("failed to write updated output file:", err)
|
||||||
}
|
}
|
||||||
@@ -174,9 +174,8 @@ func TestOptimizedLargeAggregateABI(t *testing.T) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// normalizeIR canonicalizes LLVM IR so a single golden file keeps matching
|
// normalizeIR canonicalizes LLVM-version-specific IR spellings for comparison
|
||||||
// across LLVM versions. Golden files are written against LLVM <21; newer LLVM
|
// and when regenerating golden files.
|
||||||
// prints some attributes differently.
|
|
||||||
func normalizeIR(s string) string {
|
func normalizeIR(s string) string {
|
||||||
// Golden files are written using the pre-LLVM21 'nocapture' spelling,
|
// Golden files are written using the pre-LLVM21 'nocapture' spelling,
|
||||||
// which LLVM printed before any co-occurring attribute such as
|
// which LLVM printed before any co-occurring attribute such as
|
||||||
@@ -414,5 +413,7 @@ func testCompilePackage(t *testing.T, options *compileopts.Options, file string)
|
|||||||
// Compile AST to IR.
|
// Compile AST to IR.
|
||||||
program := lprogram.LoadSSA()
|
program := lprogram.LoadSSA()
|
||||||
pkg := lprogram.MainPkg()
|
pkg := lprogram.MainPkg()
|
||||||
return CompilePackage(file, pkg, program.Package(pkg.Pkg), machine, compilerConfig, false)
|
ssaPkg := program.Package(pkg.Pkg)
|
||||||
|
ssaPkg.Build()
|
||||||
|
return CompilePackage(file, pkg, ssaPkg, machine, compilerConfig, false)
|
||||||
}
|
}
|
||||||
|
|||||||
Vendored
+16
-16
@@ -19,33 +19,33 @@ define hidden void @main.chanIntSend(ptr dereferenceable_or_null(36) %ch, ptr %c
|
|||||||
entry:
|
entry:
|
||||||
%chan.op = alloca %runtime.channelOp, align 8
|
%chan.op = alloca %runtime.channelOp, align 8
|
||||||
%chan.value = alloca i32, align 4
|
%chan.value = alloca i32, align 4
|
||||||
call void @llvm.lifetime.start.p0(i64 4, ptr nonnull %chan.value)
|
call void @llvm.lifetime.start.p0(ptr nonnull %chan.value)
|
||||||
store i32 3, ptr %chan.value, align 4
|
store i32 3, ptr %chan.value, align 4
|
||||||
call void @llvm.lifetime.start.p0(i64 16, ptr nonnull %chan.op)
|
call void @llvm.lifetime.start.p0(ptr nonnull %chan.op)
|
||||||
call void @runtime.chanSend(ptr %ch, ptr nonnull %chan.value, ptr nonnull %chan.op, ptr undef) #3
|
call void @runtime.chanSend(ptr %ch, ptr nonnull %chan.value, ptr nonnull %chan.op, ptr undef) #3
|
||||||
call void @llvm.lifetime.end.p0(i64 16, ptr nonnull %chan.op)
|
call void @llvm.lifetime.end.p0(ptr nonnull %chan.op)
|
||||||
call void @llvm.lifetime.end.p0(i64 4, ptr nonnull %chan.value)
|
call void @llvm.lifetime.end.p0(ptr nonnull %chan.value)
|
||||||
ret void
|
ret void
|
||||||
}
|
}
|
||||||
|
|
||||||
; Function Attrs: nocallback nofree nosync nounwind willreturn memory(argmem: readwrite)
|
; Function Attrs: nocallback nofree nosync nounwind willreturn memory(argmem: readwrite)
|
||||||
declare void @llvm.lifetime.start.p0(i64 immarg, ptr nocapture) #2
|
declare void @llvm.lifetime.start.p0(ptr nocapture) #2
|
||||||
|
|
||||||
declare void @runtime.chanSend(ptr dereferenceable_or_null(36), ptr, ptr dereferenceable_or_null(16), ptr) #0
|
declare void @runtime.chanSend(ptr dereferenceable_or_null(36), ptr, ptr dereferenceable_or_null(16), ptr) #0
|
||||||
|
|
||||||
; Function Attrs: nocallback nofree nosync nounwind willreturn memory(argmem: readwrite)
|
; Function Attrs: nocallback nofree nosync nounwind willreturn memory(argmem: readwrite)
|
||||||
declare void @llvm.lifetime.end.p0(i64 immarg, ptr nocapture) #2
|
declare void @llvm.lifetime.end.p0(ptr nocapture) #2
|
||||||
|
|
||||||
; Function Attrs: nounwind
|
; Function Attrs: nounwind
|
||||||
define hidden void @main.chanIntRecv(ptr dereferenceable_or_null(36) %ch, ptr %context) unnamed_addr #1 {
|
define hidden void @main.chanIntRecv(ptr dereferenceable_or_null(36) %ch, ptr %context) unnamed_addr #1 {
|
||||||
entry:
|
entry:
|
||||||
%chan.op = alloca %runtime.channelOp, align 8
|
%chan.op = alloca %runtime.channelOp, align 8
|
||||||
%chan.value = alloca i32, align 4
|
%chan.value = alloca i32, align 4
|
||||||
call void @llvm.lifetime.start.p0(i64 4, ptr nonnull %chan.value)
|
call void @llvm.lifetime.start.p0(ptr nonnull %chan.value)
|
||||||
call void @llvm.lifetime.start.p0(i64 16, ptr nonnull %chan.op)
|
call void @llvm.lifetime.start.p0(ptr nonnull %chan.op)
|
||||||
%0 = call i1 @runtime.chanRecv(ptr %ch, ptr nonnull %chan.value, ptr nonnull %chan.op, ptr undef) #3
|
%0 = call i1 @runtime.chanRecv(ptr %ch, ptr nonnull %chan.value, ptr nonnull %chan.op, ptr undef) #3
|
||||||
call void @llvm.lifetime.end.p0(i64 4, ptr nonnull %chan.value)
|
call void @llvm.lifetime.end.p0(ptr nonnull %chan.value)
|
||||||
call void @llvm.lifetime.end.p0(i64 16, ptr nonnull %chan.op)
|
call void @llvm.lifetime.end.p0(ptr nonnull %chan.op)
|
||||||
ret void
|
ret void
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -55,9 +55,9 @@ declare i1 @runtime.chanRecv(ptr dereferenceable_or_null(36), ptr, ptr dereferen
|
|||||||
define hidden void @main.chanZeroSend(ptr dereferenceable_or_null(36) %ch, ptr %context) unnamed_addr #1 {
|
define hidden void @main.chanZeroSend(ptr dereferenceable_or_null(36) %ch, ptr %context) unnamed_addr #1 {
|
||||||
entry:
|
entry:
|
||||||
%chan.op = alloca %runtime.channelOp, align 8
|
%chan.op = alloca %runtime.channelOp, align 8
|
||||||
call void @llvm.lifetime.start.p0(i64 16, ptr nonnull %chan.op)
|
call void @llvm.lifetime.start.p0(ptr nonnull %chan.op)
|
||||||
call void @runtime.chanSend(ptr %ch, ptr null, ptr nonnull %chan.op, ptr undef) #3
|
call void @runtime.chanSend(ptr %ch, ptr null, ptr nonnull %chan.op, ptr undef) #3
|
||||||
call void @llvm.lifetime.end.p0(i64 16, ptr nonnull %chan.op)
|
call void @llvm.lifetime.end.p0(ptr nonnull %chan.op)
|
||||||
ret void
|
ret void
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -65,9 +65,9 @@ entry:
|
|||||||
define hidden void @main.chanZeroRecv(ptr dereferenceable_or_null(36) %ch, ptr %context) unnamed_addr #1 {
|
define hidden void @main.chanZeroRecv(ptr dereferenceable_or_null(36) %ch, ptr %context) unnamed_addr #1 {
|
||||||
entry:
|
entry:
|
||||||
%chan.op = alloca %runtime.channelOp, align 8
|
%chan.op = alloca %runtime.channelOp, align 8
|
||||||
call void @llvm.lifetime.start.p0(i64 16, ptr nonnull %chan.op)
|
call void @llvm.lifetime.start.p0(ptr nonnull %chan.op)
|
||||||
%0 = call i1 @runtime.chanRecv(ptr %ch, ptr null, ptr nonnull %chan.op, ptr undef) #3
|
%0 = call i1 @runtime.chanRecv(ptr %ch, ptr null, ptr nonnull %chan.op, ptr undef) #3
|
||||||
call void @llvm.lifetime.end.p0(i64 16, ptr nonnull %chan.op)
|
call void @llvm.lifetime.end.p0(ptr nonnull %chan.op)
|
||||||
ret void
|
ret void
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -77,7 +77,7 @@ entry:
|
|||||||
%select.states.alloca = alloca [2 x %runtime.chanSelectState], align 8
|
%select.states.alloca = alloca [2 x %runtime.chanSelectState], align 8
|
||||||
%select.send.value = alloca i32, align 4
|
%select.send.value = alloca i32, align 4
|
||||||
store i32 1, ptr %select.send.value, align 4
|
store i32 1, ptr %select.send.value, align 4
|
||||||
call void @llvm.lifetime.start.p0(i64 16, ptr nonnull %select.states.alloca)
|
call void @llvm.lifetime.start.p0(ptr nonnull %select.states.alloca)
|
||||||
store ptr %ch1, ptr %select.states.alloca, align 4
|
store ptr %ch1, ptr %select.states.alloca, align 4
|
||||||
%select.states.alloca.repack1 = getelementptr inbounds nuw i8, ptr %select.states.alloca, i32 4
|
%select.states.alloca.repack1 = getelementptr inbounds nuw i8, ptr %select.states.alloca, i32 4
|
||||||
store ptr %select.send.value, ptr %select.states.alloca.repack1, align 4
|
store ptr %select.send.value, ptr %select.states.alloca.repack1, align 4
|
||||||
@@ -86,7 +86,7 @@ entry:
|
|||||||
%.repack3 = getelementptr inbounds nuw i8, ptr %select.states.alloca, i32 12
|
%.repack3 = getelementptr inbounds nuw i8, ptr %select.states.alloca, i32 12
|
||||||
store ptr null, ptr %.repack3, align 4
|
store ptr null, ptr %.repack3, align 4
|
||||||
%select.result = call { i32, i1 } @runtime.chanSelect(ptr undef, ptr nonnull %select.states.alloca, i32 2, i32 2, ptr null, i32 0, i32 0, ptr undef) #3
|
%select.result = call { i32, i1 } @runtime.chanSelect(ptr undef, ptr nonnull %select.states.alloca, i32 2, i32 2, ptr null, i32 0, i32 0, ptr undef) #3
|
||||||
call void @llvm.lifetime.end.p0(i64 16, ptr nonnull %select.states.alloca)
|
call void @llvm.lifetime.end.p0(ptr nonnull %select.states.alloca)
|
||||||
%1 = extractvalue { i32, i1 } %select.result, 0
|
%1 = extractvalue { i32, i1 } %select.result, 0
|
||||||
%2 = icmp eq i32 %1, 0
|
%2 = icmp eq i32 %1, 0
|
||||||
br i1 %2, label %select.done, label %select.next
|
br i1 %2, label %select.done, label %select.next
|
||||||
|
|||||||
Vendored
+5
-5
@@ -15,7 +15,7 @@ target triple = "wasm32-unknown-wasi"
|
|||||||
@"reflect/types.type:basic:string" = linkonce_odr constant { i8, ptr } { i8 81, ptr @"reflect/types.type:pointer:basic:string" }, align 4
|
@"reflect/types.type:basic:string" = linkonce_odr constant { i8, ptr } { i8 81, ptr @"reflect/types.type:pointer:basic:string" }, align 4
|
||||||
@"reflect/types.type:pointer:basic:string" = linkonce_odr constant { i8, i16, ptr } { i8 -43, i16 0, ptr @"reflect/types.type:basic:string" }, align 4
|
@"reflect/types.type:pointer:basic:string" = linkonce_odr constant { i8, i16, ptr } { i8 -43, i16 0, ptr @"reflect/types.type:basic:string" }, align 4
|
||||||
|
|
||||||
declare void @runtime.trackPointer(ptr readonly captures(none), ptr, ptr) #0
|
declare void @runtime.trackPointer(ptr nocapture readonly, ptr, ptr) #0
|
||||||
|
|
||||||
; Function Attrs: nounwind
|
; Function Attrs: nounwind
|
||||||
define hidden void @main.init(ptr %context) unnamed_addr #1 {
|
define hidden void @main.init(ptr %context) unnamed_addr #1 {
|
||||||
@@ -31,7 +31,7 @@ entry:
|
|||||||
}
|
}
|
||||||
|
|
||||||
; Function Attrs: nocallback nofree nounwind willreturn memory(argmem: readwrite)
|
; Function Attrs: nocallback nofree nounwind willreturn memory(argmem: readwrite)
|
||||||
declare void @llvm.memcpy.p0.p0.i32(ptr noalias writeonly captures(none), ptr noalias readonly captures(none), i32, i1 immarg) #2
|
declare void @llvm.memcpy.p0.p0.i32(ptr noalias nocapture writeonly, ptr noalias nocapture readonly, i32, i1 immarg) #2
|
||||||
|
|
||||||
; Function Attrs: nounwind
|
; Function Attrs: nounwind
|
||||||
define hidden i8 @"(main.largeReceiver).readLargeValue"(ptr readonly dereferenceable_or_null(1025) %receiver, ptr readonly dereferenceable_or_null(1025) %value, ptr %context) unnamed_addr #1 {
|
define hidden i8 @"(main.largeReceiver).readLargeValue"(ptr readonly dereferenceable_or_null(1025) %receiver, ptr readonly dereferenceable_or_null(1025) %value, ptr %context) unnamed_addr #1 {
|
||||||
@@ -344,7 +344,7 @@ if.then: ; preds = %typeassert.next
|
|||||||
declare i1 @runtime.typeAssert(ptr, ptr dereferenceable_or_null(1), ptr) #0
|
declare i1 @runtime.typeAssert(ptr, ptr dereferenceable_or_null(1), ptr) #0
|
||||||
|
|
||||||
; Function Attrs: nocallback nofree nounwind willreturn memory(argmem: write)
|
; Function Attrs: nocallback nofree nounwind willreturn memory(argmem: write)
|
||||||
declare void @llvm.memset.p0.i32(ptr writeonly captures(none), i8, i32, i1 immarg) #7
|
declare void @llvm.memset.p0.i32(ptr nocapture writeonly, i8, i32, i1 immarg) #7
|
||||||
|
|
||||||
; Function Attrs: nounwind
|
; Function Attrs: nounwind
|
||||||
define hidden i8 @main.useLargeMap(ptr readonly dereferenceable_or_null(1025) %key, ptr readonly dereferenceable_or_null(1025) %value, ptr %context) unnamed_addr #1 {
|
define hidden i8 @main.useLargeMap(ptr readonly dereferenceable_or_null(1025) %key, ptr readonly dereferenceable_or_null(1025) %value, ptr %context) unnamed_addr #1 {
|
||||||
@@ -423,12 +423,12 @@ if.then: ; preds = %entry
|
|||||||
}
|
}
|
||||||
|
|
||||||
; Function Attrs: nocallback nofree nosync nounwind willreturn memory(argmem: readwrite)
|
; Function Attrs: nocallback nofree nosync nounwind willreturn memory(argmem: readwrite)
|
||||||
declare void @llvm.lifetime.start.p0(ptr captures(none)) #8
|
declare void @llvm.lifetime.start.p0(ptr nocapture) #8
|
||||||
|
|
||||||
declare void @runtime.chanSend(ptr dereferenceable_or_null(36), ptr, ptr dereferenceable_or_null(16), ptr) #0
|
declare void @runtime.chanSend(ptr dereferenceable_or_null(36), ptr, ptr dereferenceable_or_null(16), ptr) #0
|
||||||
|
|
||||||
; Function Attrs: nocallback nofree nosync nounwind willreturn memory(argmem: readwrite)
|
; Function Attrs: nocallback nofree nosync nounwind willreturn memory(argmem: readwrite)
|
||||||
declare void @llvm.lifetime.end.p0(ptr captures(none)) #8
|
declare void @llvm.lifetime.end.p0(ptr nocapture) #8
|
||||||
|
|
||||||
declare i1 @runtime.chanRecv(ptr dereferenceable_or_null(36), ptr, ptr dereferenceable_or_null(16), ptr) #0
|
declare i1 @runtime.chanRecv(ptr dereferenceable_or_null(36), ptr, ptr dereferenceable_or_null(16), ptr) #0
|
||||||
|
|
||||||
|
|||||||
Vendored
+18
-18
@@ -21,23 +21,23 @@ entry:
|
|||||||
%0 = insertvalue %main.hasPadding zeroinitializer, i1 %s.b1, 0
|
%0 = insertvalue %main.hasPadding zeroinitializer, i1 %s.b1, 0
|
||||||
%1 = insertvalue %main.hasPadding %0, i32 %s.i, 1
|
%1 = insertvalue %main.hasPadding %0, i32 %s.i, 1
|
||||||
%2 = insertvalue %main.hasPadding %1, i1 %s.b2, 2
|
%2 = insertvalue %main.hasPadding %1, i1 %s.b2, 2
|
||||||
call void @llvm.lifetime.start.p0(i64 4, ptr nonnull %hashmap.value)
|
call void @llvm.lifetime.start.p0(ptr nonnull %hashmap.value)
|
||||||
call void @llvm.lifetime.start.p0(i64 12, ptr nonnull %hashmap.key)
|
call void @llvm.lifetime.start.p0(ptr nonnull %hashmap.key)
|
||||||
store %main.hasPadding %2, ptr %hashmap.key, align 4
|
store %main.hasPadding %2, ptr %hashmap.key, align 4
|
||||||
%3 = call i1 @runtime.hashmapGenericGet(ptr %m, ptr nonnull %hashmap.key, ptr nonnull %hashmap.value, i32 4, ptr undef) #4
|
%3 = call i1 @runtime.hashmapGenericGet(ptr %m, ptr nonnull %hashmap.key, ptr nonnull %hashmap.value, i32 4, ptr undef) #4
|
||||||
call void @llvm.lifetime.end.p0(i64 12, ptr nonnull %hashmap.key)
|
call void @llvm.lifetime.end.p0(ptr nonnull %hashmap.key)
|
||||||
%4 = load i32, ptr %hashmap.value, align 4
|
%4 = load i32, ptr %hashmap.value, align 4
|
||||||
call void @llvm.lifetime.end.p0(i64 4, ptr nonnull %hashmap.value)
|
call void @llvm.lifetime.end.p0(ptr nonnull %hashmap.value)
|
||||||
ret i32 %4
|
ret i32 %4
|
||||||
}
|
}
|
||||||
|
|
||||||
; Function Attrs: nocallback nofree nosync nounwind willreturn memory(argmem: readwrite)
|
; Function Attrs: nocallback nofree nosync nounwind willreturn memory(argmem: readwrite)
|
||||||
declare void @llvm.lifetime.start.p0(i64 immarg, ptr nocapture) #3
|
declare void @llvm.lifetime.start.p0(ptr nocapture) #3
|
||||||
|
|
||||||
declare i1 @runtime.hashmapGenericGet(ptr dereferenceable_or_null(48), ptr nocapture, ptr nocapture, i32, ptr) #0
|
declare i1 @runtime.hashmapGenericGet(ptr dereferenceable_or_null(48), ptr nocapture, ptr nocapture, i32, ptr) #0
|
||||||
|
|
||||||
; Function Attrs: nocallback nofree nosync nounwind willreturn memory(argmem: readwrite)
|
; Function Attrs: nocallback nofree nosync nounwind willreturn memory(argmem: readwrite)
|
||||||
declare void @llvm.lifetime.end.p0(i64 immarg, ptr nocapture) #3
|
declare void @llvm.lifetime.end.p0(ptr nocapture) #3
|
||||||
|
|
||||||
; Function Attrs: noinline nounwind
|
; Function Attrs: noinline nounwind
|
||||||
define hidden void @main.testZeroSet(ptr dereferenceable_or_null(48) %m, i1 %s.b1, i32 %s.i, i1 %s.b2, ptr %context) unnamed_addr #2 {
|
define hidden void @main.testZeroSet(ptr dereferenceable_or_null(48) %m, i1 %s.b1, i32 %s.i, i1 %s.b2, ptr %context) unnamed_addr #2 {
|
||||||
@@ -47,13 +47,13 @@ entry:
|
|||||||
%0 = insertvalue %main.hasPadding zeroinitializer, i1 %s.b1, 0
|
%0 = insertvalue %main.hasPadding zeroinitializer, i1 %s.b1, 0
|
||||||
%1 = insertvalue %main.hasPadding %0, i32 %s.i, 1
|
%1 = insertvalue %main.hasPadding %0, i32 %s.i, 1
|
||||||
%2 = insertvalue %main.hasPadding %1, i1 %s.b2, 2
|
%2 = insertvalue %main.hasPadding %1, i1 %s.b2, 2
|
||||||
call void @llvm.lifetime.start.p0(i64 4, ptr nonnull %hashmap.value)
|
call void @llvm.lifetime.start.p0(ptr nonnull %hashmap.value)
|
||||||
store i32 5, ptr %hashmap.value, align 4
|
store i32 5, ptr %hashmap.value, align 4
|
||||||
call void @llvm.lifetime.start.p0(i64 12, ptr nonnull %hashmap.key)
|
call void @llvm.lifetime.start.p0(ptr nonnull %hashmap.key)
|
||||||
store %main.hasPadding %2, ptr %hashmap.key, align 4
|
store %main.hasPadding %2, ptr %hashmap.key, align 4
|
||||||
call void @runtime.hashmapGenericSet(ptr %m, ptr nonnull %hashmap.key, ptr nonnull %hashmap.value, ptr undef) #4
|
call void @runtime.hashmapGenericSet(ptr %m, ptr nonnull %hashmap.key, ptr nonnull %hashmap.value, ptr undef) #4
|
||||||
call void @llvm.lifetime.end.p0(i64 12, ptr nonnull %hashmap.key)
|
call void @llvm.lifetime.end.p0(ptr nonnull %hashmap.key)
|
||||||
call void @llvm.lifetime.end.p0(i64 4, ptr nonnull %hashmap.value)
|
call void @llvm.lifetime.end.p0(ptr nonnull %hashmap.value)
|
||||||
ret void
|
ret void
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -64,17 +64,17 @@ define hidden i32 @main.testZeroArrayGet(ptr dereferenceable_or_null(48) %m, [2
|
|||||||
entry:
|
entry:
|
||||||
%hashmap.key = alloca [2 x %main.hasPadding], align 8
|
%hashmap.key = alloca [2 x %main.hasPadding], align 8
|
||||||
%hashmap.value = alloca i32, align 4
|
%hashmap.value = alloca i32, align 4
|
||||||
call void @llvm.lifetime.start.p0(i64 4, ptr nonnull %hashmap.value)
|
call void @llvm.lifetime.start.p0(ptr nonnull %hashmap.value)
|
||||||
call void @llvm.lifetime.start.p0(i64 24, ptr nonnull %hashmap.key)
|
call void @llvm.lifetime.start.p0(ptr nonnull %hashmap.key)
|
||||||
%s.elt = extractvalue [2 x %main.hasPadding] %s, 0
|
%s.elt = extractvalue [2 x %main.hasPadding] %s, 0
|
||||||
store %main.hasPadding %s.elt, ptr %hashmap.key, align 4
|
store %main.hasPadding %s.elt, ptr %hashmap.key, align 4
|
||||||
%hashmap.key.repack1 = getelementptr inbounds nuw i8, ptr %hashmap.key, i32 12
|
%hashmap.key.repack1 = getelementptr inbounds nuw i8, ptr %hashmap.key, i32 12
|
||||||
%s.elt2 = extractvalue [2 x %main.hasPadding] %s, 1
|
%s.elt2 = extractvalue [2 x %main.hasPadding] %s, 1
|
||||||
store %main.hasPadding %s.elt2, ptr %hashmap.key.repack1, align 4
|
store %main.hasPadding %s.elt2, ptr %hashmap.key.repack1, align 4
|
||||||
%0 = call i1 @runtime.hashmapGenericGet(ptr %m, ptr nonnull %hashmap.key, ptr nonnull %hashmap.value, i32 4, ptr undef) #4
|
%0 = call i1 @runtime.hashmapGenericGet(ptr %m, ptr nonnull %hashmap.key, ptr nonnull %hashmap.value, i32 4, ptr undef) #4
|
||||||
call void @llvm.lifetime.end.p0(i64 24, ptr nonnull %hashmap.key)
|
call void @llvm.lifetime.end.p0(ptr nonnull %hashmap.key)
|
||||||
%1 = load i32, ptr %hashmap.value, align 4
|
%1 = load i32, ptr %hashmap.value, align 4
|
||||||
call void @llvm.lifetime.end.p0(i64 4, ptr nonnull %hashmap.value)
|
call void @llvm.lifetime.end.p0(ptr nonnull %hashmap.value)
|
||||||
ret i32 %1
|
ret i32 %1
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -83,17 +83,17 @@ define hidden void @main.testZeroArraySet(ptr dereferenceable_or_null(48) %m, [2
|
|||||||
entry:
|
entry:
|
||||||
%hashmap.key = alloca [2 x %main.hasPadding], align 8
|
%hashmap.key = alloca [2 x %main.hasPadding], align 8
|
||||||
%hashmap.value = alloca i32, align 4
|
%hashmap.value = alloca i32, align 4
|
||||||
call void @llvm.lifetime.start.p0(i64 4, ptr nonnull %hashmap.value)
|
call void @llvm.lifetime.start.p0(ptr nonnull %hashmap.value)
|
||||||
store i32 5, ptr %hashmap.value, align 4
|
store i32 5, ptr %hashmap.value, align 4
|
||||||
call void @llvm.lifetime.start.p0(i64 24, ptr nonnull %hashmap.key)
|
call void @llvm.lifetime.start.p0(ptr nonnull %hashmap.key)
|
||||||
%s.elt = extractvalue [2 x %main.hasPadding] %s, 0
|
%s.elt = extractvalue [2 x %main.hasPadding] %s, 0
|
||||||
store %main.hasPadding %s.elt, ptr %hashmap.key, align 4
|
store %main.hasPadding %s.elt, ptr %hashmap.key, align 4
|
||||||
%hashmap.key.repack1 = getelementptr inbounds nuw i8, ptr %hashmap.key, i32 12
|
%hashmap.key.repack1 = getelementptr inbounds nuw i8, ptr %hashmap.key, i32 12
|
||||||
%s.elt2 = extractvalue [2 x %main.hasPadding] %s, 1
|
%s.elt2 = extractvalue [2 x %main.hasPadding] %s, 1
|
||||||
store %main.hasPadding %s.elt2, ptr %hashmap.key.repack1, align 4
|
store %main.hasPadding %s.elt2, ptr %hashmap.key.repack1, align 4
|
||||||
call void @runtime.hashmapGenericSet(ptr %m, ptr nonnull %hashmap.key, ptr nonnull %hashmap.value, ptr undef) #4
|
call void @runtime.hashmapGenericSet(ptr %m, ptr nonnull %hashmap.key, ptr nonnull %hashmap.value, ptr undef) #4
|
||||||
call void @llvm.lifetime.end.p0(i64 24, ptr nonnull %hashmap.key)
|
call void @llvm.lifetime.end.p0(ptr nonnull %hashmap.key)
|
||||||
call void @llvm.lifetime.end.p0(i64 4, ptr nonnull %hashmap.value)
|
call void @llvm.lifetime.end.p0(ptr nonnull %hashmap.value)
|
||||||
ret void
|
ret void
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+29
-24
@@ -76,7 +76,7 @@ func testTransform(t *testing.T, pathPrefix string, transform func(mod llvm.Modu
|
|||||||
actual = actual[strings.Index(actual, "\ntarget datalayout = ")+1:]
|
actual = actual[strings.Index(actual, "\ntarget datalayout = ")+1:]
|
||||||
|
|
||||||
if *update {
|
if *update {
|
||||||
err := os.WriteFile(pathPrefix+".out.ll", []byte(actual), 0666)
|
err := os.WriteFile(pathPrefix+".out.ll", []byte(normalizeIR(actual)), 0666)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Error("failed to write out new output:", err)
|
t.Error("failed to write out new output:", err)
|
||||||
}
|
}
|
||||||
@@ -100,28 +100,8 @@ func testTransform(t *testing.T, pathPrefix string, transform func(mod llvm.Modu
|
|||||||
// equal. That means, only relevant lines are compared (excluding comments
|
// equal. That means, only relevant lines are compared (excluding comments
|
||||||
// etc.).
|
// etc.).
|
||||||
func fuzzyEqualIR(s1, s2 string) bool {
|
func fuzzyEqualIR(s1, s2 string) bool {
|
||||||
// Golden files are written using the pre-LLVM21 'nocapture' spelling,
|
s1 = normalizeIR(s1)
|
||||||
// which LLVM printed before any co-occurring attribute such as
|
s2 = normalizeIR(s2)
|
||||||
// 'readonly' (e.g. "ptr nocapture readonly"). LLVM 21+ prints the
|
|
||||||
// equivalent 'captures(none)' instead, and after such attributes (e.g.
|
|
||||||
// "ptr readonly captures(none)"). Normalize both name and position back
|
|
||||||
// to the old spelling to keep a single golden file working across LLVM
|
|
||||||
// versions.
|
|
||||||
s1 = normalizeCapturesAttr(s1)
|
|
||||||
s2 = normalizeCapturesAttr(s2)
|
|
||||||
|
|
||||||
// LLVM 21+ also added an explicit 'nocreateundeforpoison' attribute to
|
|
||||||
// certain intrinsic declarations (e.g. llvm.umin) that were implicitly
|
|
||||||
// assumed not to create undef/poison before. It's unrelated to the
|
|
||||||
// escape-analysis behavior under test, so ignore it for comparison.
|
|
||||||
s1 = strings.ReplaceAll(s1, "nocreateundeforpoison ", "")
|
|
||||||
s2 = strings.ReplaceAll(s2, "nocreateundeforpoison ", "")
|
|
||||||
|
|
||||||
// LLVM 22 dropped the (redundant) i64 size argument from
|
|
||||||
// llvm.lifetime.start/end. Normalize away that argument so golden files
|
|
||||||
// written against the two-argument form still match.
|
|
||||||
s1 = lifetimeSizeArgRe.ReplaceAllString(s1, "$1")
|
|
||||||
s2 = lifetimeSizeArgRe.ReplaceAllString(s2, "$1")
|
|
||||||
|
|
||||||
lines1 := filterIrrelevantIRLines(strings.Split(s1, "\n"))
|
lines1 := filterIrrelevantIRLines(strings.Split(s1, "\n"))
|
||||||
lines2 := filterIrrelevantIRLines(strings.Split(s2, "\n"))
|
lines2 := filterIrrelevantIRLines(strings.Split(s2, "\n"))
|
||||||
@@ -138,6 +118,29 @@ func fuzzyEqualIR(s1, s2 string) bool {
|
|||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func normalizeIR(s string) string {
|
||||||
|
// Golden files are written using the pre-LLVM21 'nocapture' spelling,
|
||||||
|
// which LLVM printed before any co-occurring attribute such as
|
||||||
|
// 'readonly' (e.g. "ptr nocapture readonly"). LLVM 21+ prints the
|
||||||
|
// equivalent 'captures(none)' instead, and after such attributes (e.g.
|
||||||
|
// "ptr readonly captures(none)"). Normalize both name and position back
|
||||||
|
// to the old spelling.
|
||||||
|
s = normalizeCapturesAttr(s)
|
||||||
|
|
||||||
|
// LLVM 21+ also added an explicit 'nocreateundeforpoison' attribute to
|
||||||
|
// certain intrinsic declarations (e.g. llvm.umin) that were implicitly
|
||||||
|
// assumed not to create undef/poison before. It's unrelated to the
|
||||||
|
// escape-analysis behavior under test, so ignore it for comparison.
|
||||||
|
s = strings.ReplaceAll(s, "nocreateundeforpoison ", "")
|
||||||
|
|
||||||
|
// LLVM 22 dropped the (redundant) i64 size argument from
|
||||||
|
// llvm.lifetime.start/end. Normalize away that argument so golden files
|
||||||
|
// written against the two-argument form still match.
|
||||||
|
s = lifetimeSizeArgRe.ReplaceAllString(s, "$1")
|
||||||
|
|
||||||
|
return s
|
||||||
|
}
|
||||||
|
|
||||||
// capturesNoneAttrRe matches a co-occurring attribute directly followed by
|
// capturesNoneAttrRe matches a co-occurring attribute directly followed by
|
||||||
// 'captures(none)', which is how LLVM 21+ orders these two attributes when
|
// 'captures(none)', which is how LLVM 21+ orders these two attributes when
|
||||||
// printing IR (the pre-LLVM21 'nocapture' attribute printed the other way
|
// printing IR (the pre-LLVM21 'nocapture' attribute printed the other way
|
||||||
@@ -221,7 +224,9 @@ func compileGoFileForTesting(t *testing.T, filename string) llvm.Module {
|
|||||||
// Compile AST to IR.
|
// Compile AST to IR.
|
||||||
program := lprogram.LoadSSA()
|
program := lprogram.LoadSSA()
|
||||||
pkg := lprogram.MainPkg()
|
pkg := lprogram.MainPkg()
|
||||||
mod, errs := compiler.CompilePackage(filename, pkg, program.Package(pkg.Pkg), machine, compilerConfig, false)
|
ssaPkg := program.Package(pkg.Pkg)
|
||||||
|
ssaPkg.Build()
|
||||||
|
mod, errs := compiler.CompilePackage(filename, pkg, ssaPkg, machine, compilerConfig, false)
|
||||||
if errs != nil {
|
if errs != nil {
|
||||||
for _, err := range errs {
|
for _, err := range errs {
|
||||||
t.Error(err)
|
t.Error(err)
|
||||||
|
|||||||
Reference in New Issue
Block a user