This commit switches to LLVM 15 everywhere by default, while still
keeping LLVM 14 support.
Этот коммит содержится в:
Ayke van Laethem 2022-09-22 13:39:51 +02:00 коммит произвёл Ron Evans
родитель 08a51535d4
коммит 2b7f562202
40 изменённых файлов: 895 добавлений и 881 удалений

6
.github/workflows/build-macos.yml предоставленный
Просмотреть файл

@ -40,7 +40,7 @@ jobs:
uses: actions/cache@v3 uses: actions/cache@v3
id: cache-llvm-source id: cache-llvm-source
with: with:
key: llvm-source-14-macos-v1 key: llvm-source-15-macos-v1
path: | path: |
llvm-project/clang/lib/Headers llvm-project/clang/lib/Headers
llvm-project/clang/include llvm-project/clang/include
@ -54,7 +54,7 @@ jobs:
uses: actions/cache@v3 uses: actions/cache@v3
id: cache-llvm-build id: cache-llvm-build
with: with:
key: llvm-build-14-macos-v1 key: llvm-build-15-macos-v1
path: llvm-build path: llvm-build
- name: Build LLVM - name: Build LLVM
if: steps.cache-llvm-build.outputs.cache-hit != 'true' if: steps.cache-llvm-build.outputs.cache-hit != 'true'
@ -108,7 +108,7 @@ jobs:
- name: Install LLVM - name: Install LLVM
shell: bash shell: bash
run: | run: |
HOMEBREW_NO_AUTO_UPDATE=1 brew install llvm@14 HOMEBREW_NO_AUTO_UPDATE=1 brew install llvm@15
- name: Checkout - name: Checkout
uses: actions/checkout@v2 uses: actions/checkout@v2
- name: Install Go - name: Install Go

16
.github/workflows/linux.yml предоставленный
Просмотреть файл

@ -43,7 +43,7 @@ jobs:
uses: actions/cache@v3 uses: actions/cache@v3
id: cache-llvm-source id: cache-llvm-source
with: with:
key: llvm-source-14-linux-alpine-v1 key: llvm-source-15-linux-alpine-v1
path: | path: |
llvm-project/clang/lib/Headers llvm-project/clang/lib/Headers
llvm-project/clang/include llvm-project/clang/include
@ -57,7 +57,7 @@ jobs:
uses: actions/cache@v3 uses: actions/cache@v3
id: cache-llvm-build id: cache-llvm-build
with: with:
key: llvm-build-14-linux-alpine-v1 key: llvm-build-15-linux-alpine-v1
path: llvm-build path: llvm-build
- name: Build LLVM - name: Build LLVM
if: steps.cache-llvm-build.outputs.cache-hit != 'true' if: steps.cache-llvm-build.outputs.cache-hit != 'true'
@ -185,7 +185,7 @@ jobs:
uses: actions/cache@v3 uses: actions/cache@v3
id: cache-llvm-source id: cache-llvm-source
with: with:
key: llvm-source-14-linux-asserts-v2 key: llvm-source-15-linux-asserts-v1
path: | path: |
llvm-project/clang/lib/Headers llvm-project/clang/lib/Headers
llvm-project/clang/include llvm-project/clang/include
@ -199,7 +199,7 @@ jobs:
uses: actions/cache@v3 uses: actions/cache@v3
id: cache-llvm-build id: cache-llvm-build
with: with:
key: llvm-build-14-linux-asserts-v1 key: llvm-build-15-linux-asserts-v1
path: llvm-build path: llvm-build
- name: Build LLVM - name: Build LLVM
if: steps.cache-llvm-build.outputs.cache-hit != 'true' if: steps.cache-llvm-build.outputs.cache-hit != 'true'
@ -277,7 +277,7 @@ jobs:
uses: actions/cache@v3 uses: actions/cache@v3
id: cache-llvm-source id: cache-llvm-source
with: with:
key: llvm-source-14-linux-v2 key: llvm-source-15-linux-v1
path: | path: |
llvm-project/clang/lib/Headers llvm-project/clang/lib/Headers
llvm-project/clang/include llvm-project/clang/include
@ -291,7 +291,7 @@ jobs:
uses: actions/cache@v3 uses: actions/cache@v3
id: cache-llvm-build id: cache-llvm-build
with: with:
key: llvm-build-14-linux-arm-v1 key: llvm-build-15-linux-arm-v1
path: llvm-build path: llvm-build
- name: Build LLVM - name: Build LLVM
if: steps.cache-llvm-build.outputs.cache-hit != 'true' if: steps.cache-llvm-build.outputs.cache-hit != 'true'
@ -377,7 +377,7 @@ jobs:
uses: actions/cache@v3 uses: actions/cache@v3
id: cache-llvm-source id: cache-llvm-source
with: with:
key: llvm-source-14-linux-v1 key: llvm-source-15-linux-v1
path: | path: |
llvm-project/clang/lib/Headers llvm-project/clang/lib/Headers
llvm-project/clang/include llvm-project/clang/include
@ -391,7 +391,7 @@ jobs:
uses: actions/cache@v3 uses: actions/cache@v3
id: cache-llvm-build id: cache-llvm-build
with: with:
key: llvm-build-14-linux-arm64-v1 key: llvm-build-15-linux-arm64-v1
path: llvm-build path: llvm-build
- name: Build LLVM - name: Build LLVM
if: steps.cache-llvm-build.outputs.cache-hit != 'true' if: steps.cache-llvm-build.outputs.cache-hit != 'true'

4
.github/workflows/windows.yml предоставленный
Просмотреть файл

@ -35,7 +35,7 @@ jobs:
uses: actions/cache@v3 uses: actions/cache@v3
id: cache-llvm-source id: cache-llvm-source
with: with:
key: llvm-source-14-windows-v2 key: llvm-source-15-windows-v1
path: | path: |
llvm-project/clang/lib/Headers llvm-project/clang/lib/Headers
llvm-project/clang/include llvm-project/clang/include
@ -49,7 +49,7 @@ jobs:
uses: actions/cache@v3 uses: actions/cache@v3
id: cache-llvm-build id: cache-llvm-build
with: with:
key: llvm-build-14-windows-v2 key: llvm-build-15-windows-v1
path: llvm-build path: llvm-build
- name: Build LLVM - name: Build LLVM
if: steps.cache-llvm-build.outputs.cache-hit != 'true' if: steps.cache-llvm-build.outputs.cache-hit != 'true'

Просмотреть файл

@ -113,7 +113,7 @@ endif
.PHONY: all tinygo test $(LLVM_BUILDDIR) llvm-source clean fmt gen-device gen-device-nrf gen-device-nxp gen-device-avr gen-device-rp .PHONY: all tinygo test $(LLVM_BUILDDIR) llvm-source clean fmt gen-device gen-device-nrf gen-device-nxp gen-device-avr gen-device-rp
LLVM_COMPONENTS = all-targets analysis asmparser asmprinter bitreader bitwriter codegen core coroutines coverage debuginfodwarf debuginfopdb executionengine frontendopenmp instrumentation interpreter ipo irreader libdriver linker lto mc mcjit objcarcopts option profiledata scalaropts support target windowsmanifest LLVM_COMPONENTS = all-targets analysis asmparser asmprinter bitreader bitwriter codegen core coroutines coverage debuginfodwarf debuginfopdb executionengine frontendopenmp instrumentation interpreter ipo irreader libdriver linker lto mc mcjit objcarcopts option profiledata scalaropts support target windowsdriver windowsmanifest
ifeq ($(OS),Windows_NT) ifeq ($(OS),Windows_NT)
EXE = .exe EXE = .exe
@ -148,7 +148,7 @@ else
endif endif
# Libraries that should be linked in for the statically linked Clang. # Libraries that should be linked in for the statically linked Clang.
CLANG_LIB_NAMES = clangAnalysis clangAST clangASTMatchers clangBasic clangCodeGen clangCrossTU clangDriver clangDynamicASTMatchers clangEdit clangFormat clangFrontend clangFrontendTool clangHandleCXX clangHandleLLVM clangIndex clangLex clangParse clangRewrite clangRewriteFrontend clangSema clangSerialization clangTooling clangToolingASTDiff clangToolingCore clangToolingInclusions CLANG_LIB_NAMES = clangAnalysis clangAST clangASTMatchers clangBasic clangCodeGen clangCrossTU clangDriver clangDynamicASTMatchers clangEdit clangExtractAPI clangFormat clangFrontend clangFrontendTool clangHandleCXX clangHandleLLVM clangIndex clangLex clangParse clangRewrite clangRewriteFrontend clangSema clangSerialization clangSupport clangTooling clangToolingASTDiff clangToolingCore clangToolingInclusions
CLANG_LIBS = $(START_GROUP) $(addprefix -l,$(CLANG_LIB_NAMES)) $(END_GROUP) -lstdc++ CLANG_LIBS = $(START_GROUP) $(addprefix -l,$(CLANG_LIB_NAMES)) $(END_GROUP) -lstdc++
# Libraries that should be linked in for the statically linked LLD. # Libraries that should be linked in for the statically linked LLD.
@ -236,7 +236,7 @@ gen-device-rp: build/gen-device-svd
# Get LLVM sources. # Get LLVM sources.
$(LLVM_PROJECTDIR)/llvm: $(LLVM_PROJECTDIR)/llvm:
git clone -b xtensa_release_14.0.0-patched --depth=1 https://github.com/tinygo-org/llvm-project $(LLVM_PROJECTDIR) git clone -b xtensa_release_15.x --depth=1 https://github.com/espressif/llvm-project $(LLVM_PROJECTDIR)
llvm-source: $(LLVM_PROJECTDIR)/llvm llvm-source: $(LLVM_PROJECTDIR)/llvm
# Configure LLVM. # Configure LLVM.

Просмотреть файл

@ -101,6 +101,9 @@ bool AssemblerInvocation::CreateFromArgs(AssemblerInvocation &Opts,
// Target Options // Target Options
Opts.Triple = llvm::Triple::normalize(Args.getLastArgValue(OPT_triple)); Opts.Triple = llvm::Triple::normalize(Args.getLastArgValue(OPT_triple));
if (Arg *A = Args.getLastArg(options::OPT_darwin_target_variant_triple))
Opts.DarwinTargetVariantTriple = llvm::Triple(A->getValue());
Opts.CPU = std::string(Args.getLastArgValue(OPT_target_cpu)); Opts.CPU = std::string(Args.getLastArgValue(OPT_target_cpu));
Opts.Features = Args.getAllArgValues(OPT_target_feature); Opts.Features = Args.getAllArgValues(OPT_target_feature);
@ -203,6 +206,14 @@ bool AssemblerInvocation::CreateFromArgs(AssemblerInvocation &Opts,
.Default(0); .Default(0);
} }
if (auto *A = Args.getLastArg(OPT_femit_dwarf_unwind_EQ)) {
Opts.EmitDwarfUnwind =
llvm::StringSwitch<EmitDwarfUnwindType>(A->getValue())
.Case("always", EmitDwarfUnwindType::Always)
.Case("no-compact-unwind", EmitDwarfUnwindType::NoCompactUnwind)
.Case("default", EmitDwarfUnwindType::Default);
}
return Success; return Success;
} }
@ -253,6 +264,8 @@ static bool ExecuteAssemblerImpl(AssemblerInvocation &Opts,
assert(MRI && "Unable to create target register info!"); assert(MRI && "Unable to create target register info!");
MCTargetOptions MCOptions; MCTargetOptions MCOptions;
MCOptions.EmitDwarfUnwind = Opts.EmitDwarfUnwind;
std::unique_ptr<MCAsmInfo> MAI( std::unique_ptr<MCAsmInfo> MAI(
TheTarget->createMCAsmInfo(*MRI, Opts.Triple, MCOptions)); TheTarget->createMCAsmInfo(*MRI, Opts.Triple, MCOptions));
assert(MAI && "Unable to create target asm info!"); assert(MAI && "Unable to create target asm info!");
@ -299,6 +312,8 @@ static bool ExecuteAssemblerImpl(AssemblerInvocation &Opts,
// MCObjectFileInfo needs a MCContext reference in order to initialize itself. // MCObjectFileInfo needs a MCContext reference in order to initialize itself.
std::unique_ptr<MCObjectFileInfo> MOFI( std::unique_ptr<MCObjectFileInfo> MOFI(
TheTarget->createMCObjectFileInfo(Ctx, PIC)); TheTarget->createMCObjectFileInfo(Ctx, PIC));
if (Opts.DarwinTargetVariantTriple)
MOFI->setDarwinTargetVariantTriple(*Opts.DarwinTargetVariantTriple);
Ctx.setObjectFileInfo(MOFI.get()); Ctx.setObjectFileInfo(MOFI.get());
if (Opts.SaveTemporaryLabels) if (Opts.SaveTemporaryLabels)
@ -347,7 +362,7 @@ static bool ExecuteAssemblerImpl(AssemblerInvocation &Opts,
std::unique_ptr<MCCodeEmitter> CE; std::unique_ptr<MCCodeEmitter> CE;
if (Opts.ShowEncoding) if (Opts.ShowEncoding)
CE.reset(TheTarget->createMCCodeEmitter(*MCII, *MRI, Ctx)); CE.reset(TheTarget->createMCCodeEmitter(*MCII, Ctx));
std::unique_ptr<MCAsmBackend> MAB( std::unique_ptr<MCAsmBackend> MAB(
TheTarget->createMCAsmBackend(*STI, *MRI, MCOptions)); TheTarget->createMCAsmBackend(*STI, *MRI, MCOptions));
@ -367,7 +382,7 @@ static bool ExecuteAssemblerImpl(AssemblerInvocation &Opts,
} }
std::unique_ptr<MCCodeEmitter> CE( std::unique_ptr<MCCodeEmitter> CE(
TheTarget->createMCCodeEmitter(*MCII, *MRI, Ctx)); TheTarget->createMCCodeEmitter(*MCII, Ctx));
std::unique_ptr<MCAsmBackend> MAB( std::unique_ptr<MCAsmBackend> MAB(
TheTarget->createMCAsmBackend(*STI, *MRI, MCOptions)); TheTarget->createMCAsmBackend(*STI, *MRI, MCOptions));
assert(MAB && "Unable to create asm backend!"); assert(MAB && "Unable to create asm backend!");
@ -389,7 +404,7 @@ static bool ExecuteAssemblerImpl(AssemblerInvocation &Opts,
if (Opts.EmbedBitcode && Ctx.getObjectFileType() == MCContext::IsMachO) { if (Opts.EmbedBitcode && Ctx.getObjectFileType() == MCContext::IsMachO) {
MCSection *AsmLabel = Ctx.getMachOSection( MCSection *AsmLabel = Ctx.getMachOSection(
"__LLVM", "__asm", MachO::S_REGULAR, 4, SectionKind::getReadOnly()); "__LLVM", "__asm", MachO::S_REGULAR, 4, SectionKind::getReadOnly());
Str.get()->SwitchSection(AsmLabel); Str.get()->switchSection(AsmLabel);
Str.get()->emitZeros(1); Str.get()->emitZeros(1);
} }

Просмотреть файл

@ -85,6 +85,9 @@ struct AssemblerInvocation {
unsigned IncrementalLinkerCompatible : 1; unsigned IncrementalLinkerCompatible : 1;
unsigned EmbedBitcode : 1; unsigned EmbedBitcode : 1;
/// Whether to emit DWARF unwind info.
EmitDwarfUnwindType EmitDwarfUnwind;
/// The name of the relocation model to use. /// The name of the relocation model to use.
std::string RelocationModel; std::string RelocationModel;
@ -92,6 +95,9 @@ struct AssemblerInvocation {
/// otherwise. /// otherwise.
std::string TargetABI; std::string TargetABI;
/// Darwin target variant triple, the variant of the deployment target
/// for which the code is being compiled.
llvm::Optional<llvm::Triple> DarwinTargetVariantTriple;
/// @} /// @}
public: public:
@ -112,6 +118,7 @@ public:
Dwarf64 = 0; Dwarf64 = 0;
DwarfVersion = 0; DwarfVersion = 0;
EmbedBitcode = 0; EmbedBitcode = 0;
EmitDwarfUnwind = EmitDwarfUnwindType::Default;
} }
static bool CreateFromArgs(AssemblerInvocation &Res, static bool CreateFromArgs(AssemblerInvocation &Res,

Просмотреть файл

@ -6,10 +6,12 @@ import (
"os" "os"
"path/filepath" "path/filepath"
"regexp" "regexp"
"strconv"
"strings" "strings"
"github.com/tinygo-org/tinygo/compileopts" "github.com/tinygo-org/tinygo/compileopts"
"github.com/tinygo-org/tinygo/goenv" "github.com/tinygo-org/tinygo/goenv"
"tinygo.org/x/go-llvm"
) )
var Musl = Library{ var Musl = Library{
@ -77,7 +79,7 @@ var Musl = Library{
cflags: func(target, headerPath string) []string { cflags: func(target, headerPath string) []string {
arch := compileopts.MuslArchitecture(target) arch := compileopts.MuslArchitecture(target)
muslDir := filepath.Join(goenv.Get("TINYGOROOT"), "lib/musl") muslDir := filepath.Join(goenv.Get("TINYGOROOT"), "lib/musl")
return []string{ cflags := []string{
"-std=c99", // same as in musl "-std=c99", // same as in musl
"-D_XOPEN_SOURCE=700", // same as in musl "-D_XOPEN_SOURCE=700", // same as in musl
// Musl triggers some warnings and we don't want to show any // Musl triggers some warnings and we don't want to show any
@ -104,6 +106,12 @@ var Musl = Library{
"-I" + muslDir + "/include", "-I" + muslDir + "/include",
"-fno-stack-protector", "-fno-stack-protector",
} }
llvmMajor, _ := strconv.Atoi(strings.SplitN(llvm.Version, ".", 2)[0])
if llvmMajor >= 15 {
// This flag was added in Clang 15. It is not present in LLVM 14.
cflags = append(cflags, "-Wno-deprecated-non-prototype")
}
return cflags
}, },
sourceDir: func() string { return filepath.Join(goenv.Get("TINYGOROOT"), "lib/musl/src") }, sourceDir: func() string { return filepath.Join(goenv.Get("TINYGOROOT"), "lib/musl/src") },
librarySources: func(target string) ([]string, error) { librarySources: func(target string) ([]string, error) {

Просмотреть файл

@ -1,5 +1,5 @@
//go:build !byollvm //go:build !byollvm && llvm14
// +build !byollvm // +build !byollvm,llvm14
package cgo package cgo

16
cgo/libclang_config_llvm15.go Обычный файл
Просмотреть файл

@ -0,0 +1,16 @@
//go:build !byollvm && !llvm14
// +build !byollvm,!llvm14
package cgo
/*
#cgo linux CFLAGS: -I/usr/lib/llvm-15/include
#cgo darwin,amd64 CFLAGS: -I/usr/local/opt/llvm@15/include
#cgo darwin,arm64 CFLAGS: -I/opt/homebrew/opt/llvm@15/include
#cgo freebsd CFLAGS: -I/usr/local/llvm15/include
#cgo linux LDFLAGS: -L/usr/lib/llvm-15/lib -lclang
#cgo darwin,amd64 LDFLAGS: -L/usr/local/opt/llvm@15/lib -lclang -lffi
#cgo darwin,arm64 LDFLAGS: -L/opt/homebrew/opt/llvm@15/lib -lclang -lffi
#cgo freebsd LDFLAGS: -L/usr/local/llvm15/lib -lclang
*/
import "C"

Просмотреть файл

@ -57,14 +57,15 @@ func (b *builder) extractFuncContext(funcValue llvm.Value) llvm.Value {
// value. This may be an expensive operation. // value. This may be an expensive operation.
func (b *builder) decodeFuncValue(funcValue llvm.Value, sig *types.Signature) (funcType llvm.Type, funcPtr, context llvm.Value) { func (b *builder) decodeFuncValue(funcValue llvm.Value, sig *types.Signature) (funcType llvm.Type, funcPtr, context llvm.Value) {
context = b.CreateExtractValue(funcValue, 0, "") context = b.CreateExtractValue(funcValue, 0, "")
bitcast := b.CreateExtractValue(funcValue, 1, "") funcPtr = b.CreateExtractValue(funcValue, 1, "")
if !bitcast.IsAConstantExpr().IsNil() && bitcast.Opcode() == llvm.BitCast { if !funcPtr.IsAConstantExpr().IsNil() && funcPtr.Opcode() == llvm.BitCast {
funcPtr = bitcast.Operand(0) funcPtr = funcPtr.Operand(0) // needed for LLVM 14 (no opaque pointers)
return }
if sig != nil {
funcType = b.getRawFuncType(sig)
llvmSig := llvm.PointerType(funcType, b.funcPtrAddrSpace)
funcPtr = b.CreateBitCast(funcPtr, llvmSig, "")
} }
funcType = b.getRawFuncType(sig)
llvmSig := llvm.PointerType(funcType, b.funcPtrAddrSpace)
funcPtr = b.CreateBitCast(bitcast, llvmSig, "")
return return
} }

Просмотреть файл

@ -7,6 +7,7 @@ import (
"strconv" "strconv"
"strings" "strings"
"github.com/tinygo-org/tinygo/compiler/llvmutil"
"tinygo.org/x/go-llvm" "tinygo.org/x/go-llvm"
) )
@ -44,7 +45,10 @@ func (b *builder) defineIntrinsicFunction() {
// and will otherwise be lowered to regular libc memcpy/memmove calls. // and will otherwise be lowered to regular libc memcpy/memmove calls.
func (b *builder) createMemoryCopyImpl() { func (b *builder) createMemoryCopyImpl() {
b.createFunctionStart(true) b.createFunctionStart(true)
fnName := "llvm." + b.fn.Name() + ".p0i8.p0i8.i" + strconv.Itoa(b.uintptrType.IntTypeWidth()) fnName := "llvm." + b.fn.Name() + ".p0.p0.i" + strconv.Itoa(b.uintptrType.IntTypeWidth())
if llvmutil.Major() < 15 { // compatibility with LLVM 14
fnName = "llvm." + b.fn.Name() + ".p0i8.p0i8.i" + strconv.Itoa(b.uintptrType.IntTypeWidth())
}
llvmFn := b.mod.NamedFunction(fnName) llvmFn := b.mod.NamedFunction(fnName)
if llvmFn.IsNil() { if llvmFn.IsNil() {
fnType := llvm.FunctionType(b.ctx.VoidType(), []llvm.Type{b.i8ptrType, b.i8ptrType, b.uintptrType, b.ctx.Int1Type()}, false) fnType := llvm.FunctionType(b.ctx.VoidType(), []llvm.Type{b.i8ptrType, b.i8ptrType, b.uintptrType, b.ctx.Int1Type()}, false)
@ -64,7 +68,10 @@ func (b *builder) createMemoryCopyImpl() {
// regular libc memset calls if they aren't optimized out in a different way. // regular libc memset calls if they aren't optimized out in a different way.
func (b *builder) createMemoryZeroImpl() { func (b *builder) createMemoryZeroImpl() {
b.createFunctionStart(true) b.createFunctionStart(true)
fnName := "llvm.memset.p0i8.i" + strconv.Itoa(b.uintptrType.IntTypeWidth()) fnName := "llvm.memset.p0.i" + strconv.Itoa(b.uintptrType.IntTypeWidth())
if llvmutil.Major() < 15 { // compatibility with LLVM 14
fnName = "llvm.memset.p0i8.i" + strconv.Itoa(b.uintptrType.IntTypeWidth())
}
llvmFn := b.mod.NamedFunction(fnName) llvmFn := b.mod.NamedFunction(fnName)
if llvmFn.IsNil() { if llvmFn.IsNil() {
fnType := llvm.FunctionType(b.ctx.VoidType(), []llvm.Type{b.i8ptrType, b.ctx.Int8Type(), b.uintptrType, b.ctx.Int1Type()}, false) fnType := llvm.FunctionType(b.ctx.VoidType(), []llvm.Type{b.i8ptrType, b.ctx.Int8Type(), b.uintptrType, b.ctx.Int1Type()}, false)

Просмотреть файл

@ -7,7 +7,22 @@
// places would be a big risk if only one of them is updated. // places would be a big risk if only one of them is updated.
package llvmutil package llvmutil
import "tinygo.org/x/go-llvm" import (
"strconv"
"strings"
"tinygo.org/x/go-llvm"
)
// Major returns the LLVM major version.
func Major() int {
llvmMajor, err := strconv.Atoi(strings.SplitN(llvm.Version, ".", 2)[0])
if err != nil {
// sanity check, should be unreachable
panic("could not parse LLVM version: " + err.Error())
}
return llvmMajor
}
// CreateEntryBlockAlloca creates a new alloca in the entry block, even though // CreateEntryBlockAlloca creates a new alloca in the entry block, even though
// the IR builder is located elsewhere. It assumes that the insert point is // the IR builder is located elsewhere. It assumes that the insert point is
@ -78,12 +93,16 @@ func EmitLifetimeEnd(builder llvm.Builder, mod llvm.Module, ptr, size llvm.Value
// getLifetimeStartFunc returns the llvm.lifetime.start intrinsic and creates it // getLifetimeStartFunc returns the llvm.lifetime.start intrinsic and creates it
// first if it doesn't exist yet. // first if it doesn't exist yet.
func getLifetimeStartFunc(mod llvm.Module) (llvm.Type, llvm.Value) { func getLifetimeStartFunc(mod llvm.Module) (llvm.Type, llvm.Value) {
fn := mod.NamedFunction("llvm.lifetime.start.p0i8") fnName := "llvm.lifetime.start.p0"
if Major() < 15 { // compatibility with LLVM 14
fnName = "llvm.lifetime.start.p0i8"
}
fn := mod.NamedFunction(fnName)
ctx := mod.Context() ctx := mod.Context()
i8ptrType := llvm.PointerType(ctx.Int8Type(), 0) i8ptrType := llvm.PointerType(ctx.Int8Type(), 0)
fnType := llvm.FunctionType(ctx.VoidType(), []llvm.Type{ctx.Int64Type(), i8ptrType}, false) fnType := llvm.FunctionType(ctx.VoidType(), []llvm.Type{ctx.Int64Type(), i8ptrType}, false)
if fn.IsNil() { if fn.IsNil() {
fn = llvm.AddFunction(mod, "llvm.lifetime.start.p0i8", fnType) fn = llvm.AddFunction(mod, fnName, fnType)
} }
return fnType, fn return fnType, fn
} }
@ -91,12 +110,16 @@ func getLifetimeStartFunc(mod llvm.Module) (llvm.Type, llvm.Value) {
// getLifetimeEndFunc returns the llvm.lifetime.end intrinsic and creates it // getLifetimeEndFunc returns the llvm.lifetime.end intrinsic and creates it
// first if it doesn't exist yet. // first if it doesn't exist yet.
func getLifetimeEndFunc(mod llvm.Module) (llvm.Type, llvm.Value) { func getLifetimeEndFunc(mod llvm.Module) (llvm.Type, llvm.Value) {
fn := mod.NamedFunction("llvm.lifetime.end.p0i8") fnName := "llvm.lifetime.end.p0"
if Major() < 15 {
fnName = "llvm.lifetime.end.p0i8"
}
fn := mod.NamedFunction(fnName)
ctx := mod.Context() ctx := mod.Context()
i8ptrType := llvm.PointerType(ctx.Int8Type(), 0) i8ptrType := llvm.PointerType(ctx.Int8Type(), 0)
fnType := llvm.FunctionType(ctx.VoidType(), []llvm.Type{ctx.Int64Type(), i8ptrType}, false) fnType := llvm.FunctionType(ctx.VoidType(), []llvm.Type{ctx.Int64Type(), i8ptrType}, false)
if fn.IsNil() { if fn.IsNil() {
fn = llvm.AddFunction(mod, "llvm.lifetime.end.p0i8", fnType) fn = llvm.AddFunction(mod, fnName, fnType)
} }
return fnType, fn return fnType, fn
} }

Просмотреть файл

@ -10,6 +10,7 @@ import (
"strconv" "strconv"
"strings" "strings"
"github.com/tinygo-org/tinygo/compiler/llvmutil"
"github.com/tinygo-org/tinygo/loader" "github.com/tinygo-org/tinygo/loader"
"golang.org/x/tools/go/ssa" "golang.org/x/tools/go/ssa"
"tinygo.org/x/go-llvm" "tinygo.org/x/go-llvm"
@ -353,7 +354,15 @@ func (c *compilerContext) addStandardDefinedAttributes(llvmFn llvm.Value) {
llvmFn.AddFunctionAttr(c.ctx.CreateEnumAttribute(llvm.AttributeKindID("nounwind"), 0)) llvmFn.AddFunctionAttr(c.ctx.CreateEnumAttribute(llvm.AttributeKindID("nounwind"), 0))
if strings.Split(c.Triple, "-")[0] == "x86_64" { if strings.Split(c.Triple, "-")[0] == "x86_64" {
// Required by the ABI. // Required by the ABI.
llvmFn.AddFunctionAttr(c.ctx.CreateEnumAttribute(llvm.AttributeKindID("uwtable"), 0)) if llvmutil.Major() < 15 {
// Needed for LLVM 14 support.
llvmFn.AddFunctionAttr(c.ctx.CreateEnumAttribute(llvm.AttributeKindID("uwtable"), 0))
} else {
// The uwtable has two possible values: sync (1) or async (2). We
// use sync because we currently don't use async unwind tables.
// For details, see: https://llvm.org/docs/LangRef.html#function-attributes
llvmFn.AddFunctionAttr(c.ctx.CreateEnumAttribute(llvm.AttributeKindID("uwtable"), 1))
}
} }
} }

12
compiler/testdata/basic.go предоставленный
Просмотреть файл

@ -75,14 +75,18 @@ func complexMul(x, y complex64) complex64 {
// A type 'kv' also exists in function foo. Test that these two types don't // A type 'kv' also exists in function foo. Test that these two types don't
// conflict with each other. // conflict with each other.
type kv struct { type kv struct {
v float32 v float32
x, y, z int
} }
func foo(a *kv) { var kvGlobal kv
func foo() {
// Define a new 'kv' type. // Define a new 'kv' type.
type kv struct { type kv struct {
v byte v byte
x, y, z int
} }
// Use this type. // Use this type.
func(b *kv) {}(nil) func(b kv) {}(kv{})
} }

69
compiler/testdata/basic.ll предоставленный
Просмотреть файл

@ -3,35 +3,37 @@ source_filename = "basic.go"
target datalayout = "e-m:e-p:32:32-p10:8:8-p20:8:8-i64:64-n32:64-S128-ni:1:10:20" target datalayout = "e-m:e-p:32:32-p10:8:8-p20:8:8-i64:64-n32:64-S128-ni:1:10:20"
target triple = "wasm32-unknown-wasi" target triple = "wasm32-unknown-wasi"
%main.kv = type { float } %main.kv = type { float, i32, i32, i32 }
%main.kv.0 = type { i8 } %main.kv.0 = type { i8, i32, i32, i32 }
declare noalias nonnull i8* @runtime.alloc(i32, i8*, i8*) #0 @main.kvGlobal = hidden global %main.kv zeroinitializer, align 4
declare void @runtime.trackPointer(i8* nocapture readonly, i8*) #0 declare noalias nonnull ptr @runtime.alloc(i32, ptr, ptr) #0
declare void @runtime.trackPointer(ptr nocapture readonly, ptr) #0
; Function Attrs: nounwind ; Function Attrs: nounwind
define hidden void @main.init(i8* %context) unnamed_addr #1 { define hidden void @main.init(ptr %context) unnamed_addr #1 {
entry: entry:
ret void ret void
} }
; Function Attrs: nounwind ; Function Attrs: nounwind
define hidden i32 @main.addInt(i32 %x, i32 %y, i8* %context) unnamed_addr #1 { define hidden i32 @main.addInt(i32 %x, i32 %y, ptr %context) unnamed_addr #1 {
entry: entry:
%0 = add i32 %x, %y %0 = add i32 %x, %y
ret i32 %0 ret i32 %0
} }
; Function Attrs: nounwind ; Function Attrs: nounwind
define hidden i1 @main.equalInt(i32 %x, i32 %y, i8* %context) unnamed_addr #1 { define hidden i1 @main.equalInt(i32 %x, i32 %y, ptr %context) unnamed_addr #1 {
entry: entry:
%0 = icmp eq i32 %x, %y %0 = icmp eq i32 %x, %y
ret i1 %0 ret i1 %0
} }
; Function Attrs: nounwind ; Function Attrs: nounwind
define hidden i32 @main.divInt(i32 %x, i32 %y, i8* %context) unnamed_addr #1 { define hidden i32 @main.divInt(i32 %x, i32 %y, ptr %context) unnamed_addr #1 {
entry: entry:
%0 = icmp eq i32 %y, 0 %0 = icmp eq i32 %y, 0
br i1 %0, label %divbyzero.throw, label %divbyzero.next br i1 %0, label %divbyzero.throw, label %divbyzero.next
@ -45,14 +47,14 @@ divbyzero.next: ; preds = %entry
ret i32 %5 ret i32 %5
divbyzero.throw: ; preds = %entry divbyzero.throw: ; preds = %entry
call void @runtime.divideByZeroPanic(i8* undef) #2 call void @runtime.divideByZeroPanic(ptr undef) #2
unreachable unreachable
} }
declare void @runtime.divideByZeroPanic(i8*) #0 declare void @runtime.divideByZeroPanic(ptr) #0
; Function Attrs: nounwind ; Function Attrs: nounwind
define hidden i32 @main.divUint(i32 %x, i32 %y, i8* %context) unnamed_addr #1 { define hidden i32 @main.divUint(i32 %x, i32 %y, ptr %context) unnamed_addr #1 {
entry: entry:
%0 = icmp eq i32 %y, 0 %0 = icmp eq i32 %y, 0
br i1 %0, label %divbyzero.throw, label %divbyzero.next br i1 %0, label %divbyzero.throw, label %divbyzero.next
@ -62,12 +64,12 @@ divbyzero.next: ; preds = %entry
ret i32 %1 ret i32 %1
divbyzero.throw: ; preds = %entry divbyzero.throw: ; preds = %entry
call void @runtime.divideByZeroPanic(i8* undef) #2 call void @runtime.divideByZeroPanic(ptr undef) #2
unreachable unreachable
} }
; Function Attrs: nounwind ; Function Attrs: nounwind
define hidden i32 @main.remInt(i32 %x, i32 %y, i8* %context) unnamed_addr #1 { define hidden i32 @main.remInt(i32 %x, i32 %y, ptr %context) unnamed_addr #1 {
entry: entry:
%0 = icmp eq i32 %y, 0 %0 = icmp eq i32 %y, 0
br i1 %0, label %divbyzero.throw, label %divbyzero.next br i1 %0, label %divbyzero.throw, label %divbyzero.next
@ -81,12 +83,12 @@ divbyzero.next: ; preds = %entry
ret i32 %5 ret i32 %5
divbyzero.throw: ; preds = %entry divbyzero.throw: ; preds = %entry
call void @runtime.divideByZeroPanic(i8* undef) #2 call void @runtime.divideByZeroPanic(ptr undef) #2
unreachable unreachable
} }
; Function Attrs: nounwind ; Function Attrs: nounwind
define hidden i32 @main.remUint(i32 %x, i32 %y, i8* %context) unnamed_addr #1 { define hidden i32 @main.remUint(i32 %x, i32 %y, ptr %context) unnamed_addr #1 {
entry: entry:
%0 = icmp eq i32 %y, 0 %0 = icmp eq i32 %y, 0
br i1 %0, label %divbyzero.throw, label %divbyzero.next br i1 %0, label %divbyzero.throw, label %divbyzero.next
@ -96,66 +98,66 @@ divbyzero.next: ; preds = %entry
ret i32 %1 ret i32 %1
divbyzero.throw: ; preds = %entry divbyzero.throw: ; preds = %entry
call void @runtime.divideByZeroPanic(i8* undef) #2 call void @runtime.divideByZeroPanic(ptr undef) #2
unreachable unreachable
} }
; Function Attrs: nounwind ; Function Attrs: nounwind
define hidden i1 @main.floatEQ(float %x, float %y, i8* %context) unnamed_addr #1 { define hidden i1 @main.floatEQ(float %x, float %y, ptr %context) unnamed_addr #1 {
entry: entry:
%0 = fcmp oeq float %x, %y %0 = fcmp oeq float %x, %y
ret i1 %0 ret i1 %0
} }
; Function Attrs: nounwind ; Function Attrs: nounwind
define hidden i1 @main.floatNE(float %x, float %y, i8* %context) unnamed_addr #1 { define hidden i1 @main.floatNE(float %x, float %y, ptr %context) unnamed_addr #1 {
entry: entry:
%0 = fcmp une float %x, %y %0 = fcmp une float %x, %y
ret i1 %0 ret i1 %0
} }
; Function Attrs: nounwind ; Function Attrs: nounwind
define hidden i1 @main.floatLower(float %x, float %y, i8* %context) unnamed_addr #1 { define hidden i1 @main.floatLower(float %x, float %y, ptr %context) unnamed_addr #1 {
entry: entry:
%0 = fcmp olt float %x, %y %0 = fcmp olt float %x, %y
ret i1 %0 ret i1 %0
} }
; Function Attrs: nounwind ; Function Attrs: nounwind
define hidden i1 @main.floatLowerEqual(float %x, float %y, i8* %context) unnamed_addr #1 { define hidden i1 @main.floatLowerEqual(float %x, float %y, ptr %context) unnamed_addr #1 {
entry: entry:
%0 = fcmp ole float %x, %y %0 = fcmp ole float %x, %y
ret i1 %0 ret i1 %0
} }
; Function Attrs: nounwind ; Function Attrs: nounwind
define hidden i1 @main.floatGreater(float %x, float %y, i8* %context) unnamed_addr #1 { define hidden i1 @main.floatGreater(float %x, float %y, ptr %context) unnamed_addr #1 {
entry: entry:
%0 = fcmp ogt float %x, %y %0 = fcmp ogt float %x, %y
ret i1 %0 ret i1 %0
} }
; Function Attrs: nounwind ; Function Attrs: nounwind
define hidden i1 @main.floatGreaterEqual(float %x, float %y, i8* %context) unnamed_addr #1 { define hidden i1 @main.floatGreaterEqual(float %x, float %y, ptr %context) unnamed_addr #1 {
entry: entry:
%0 = fcmp oge float %x, %y %0 = fcmp oge float %x, %y
ret i1 %0 ret i1 %0
} }
; Function Attrs: nounwind ; Function Attrs: nounwind
define hidden float @main.complexReal(float %x.r, float %x.i, i8* %context) unnamed_addr #1 { define hidden float @main.complexReal(float %x.r, float %x.i, ptr %context) unnamed_addr #1 {
entry: entry:
ret float %x.r ret float %x.r
} }
; Function Attrs: nounwind ; Function Attrs: nounwind
define hidden float @main.complexImag(float %x.r, float %x.i, i8* %context) unnamed_addr #1 { define hidden float @main.complexImag(float %x.r, float %x.i, ptr %context) unnamed_addr #1 {
entry: entry:
ret float %x.i ret float %x.i
} }
; Function Attrs: nounwind ; Function Attrs: nounwind
define hidden { float, float } @main.complexAdd(float %x.r, float %x.i, float %y.r, float %y.i, i8* %context) unnamed_addr #1 { define hidden { float, float } @main.complexAdd(float %x.r, float %x.i, float %y.r, float %y.i, ptr %context) unnamed_addr #1 {
entry: entry:
%0 = fadd float %x.r, %y.r %0 = fadd float %x.r, %y.r
%1 = fadd float %x.i, %y.i %1 = fadd float %x.i, %y.i
@ -165,7 +167,7 @@ entry:
} }
; Function Attrs: nounwind ; Function Attrs: nounwind
define hidden { float, float } @main.complexSub(float %x.r, float %x.i, float %y.r, float %y.i, i8* %context) unnamed_addr #1 { define hidden { float, float } @main.complexSub(float %x.r, float %x.i, float %y.r, float %y.i, ptr %context) unnamed_addr #1 {
entry: entry:
%0 = fsub float %x.r, %y.r %0 = fsub float %x.r, %y.r
%1 = fsub float %x.i, %y.i %1 = fsub float %x.i, %y.i
@ -175,7 +177,7 @@ entry:
} }
; Function Attrs: nounwind ; Function Attrs: nounwind
define hidden { float, float } @main.complexMul(float %x.r, float %x.i, float %y.r, float %y.i, i8* %context) unnamed_addr #1 { define hidden { float, float } @main.complexMul(float %x.r, float %x.i, float %y.r, float %y.i, ptr %context) unnamed_addr #1 {
entry: entry:
%0 = fmul float %x.r, %y.r %0 = fmul float %x.r, %y.r
%1 = fmul float %x.i, %y.i %1 = fmul float %x.i, %y.i
@ -189,15 +191,22 @@ entry:
} }
; Function Attrs: nounwind ; Function Attrs: nounwind
define hidden void @main.foo(%main.kv* dereferenceable_or_null(4) %a, i8* %context) unnamed_addr #1 { define hidden void @main.foo(ptr %context) unnamed_addr #1 {
entry: entry:
call void @"main.foo$1"(%main.kv.0* null, i8* undef) %complit = alloca %main.kv.0, align 8
store %main.kv.0 zeroinitializer, ptr %complit, align 8
call void @runtime.trackPointer(ptr nonnull %complit, ptr undef) #2
call void @"main.foo$1"(%main.kv.0 zeroinitializer, ptr undef)
ret void ret void
} }
; Function Attrs: nounwind ; Function Attrs: nounwind
define internal void @"main.foo$1"(%main.kv.0* dereferenceable_or_null(1) %b, i8* %context) unnamed_addr #1 { define internal void @"main.foo$1"(%main.kv.0 %b, ptr %context) unnamed_addr #1 {
entry: entry:
%b1 = alloca %main.kv.0, align 8
store %main.kv.0 zeroinitializer, ptr %b1, align 8
call void @runtime.trackPointer(ptr nonnull %b1, ptr undef) #2
store %main.kv.0 %b, ptr %b1, align 8
ret void ret void
} }

110
compiler/testdata/channel.ll предоставленный
Просмотреть файл

@ -3,110 +3,94 @@ source_filename = "channel.go"
target datalayout = "e-m:e-p:32:32-p10:8:8-p20:8:8-i64:64-n32:64-S128-ni:1:10:20" target datalayout = "e-m:e-p:32:32-p10:8:8-p20:8:8-i64:64-n32:64-S128-ni:1:10:20"
target triple = "wasm32-unknown-wasi" target triple = "wasm32-unknown-wasi"
%runtime.channel = type { i32, i32, i8, %runtime.channelBlockedList*, i32, i32, i32, i8* } %runtime.channelBlockedList = type { ptr, ptr, ptr, { ptr, i32, i32 } }
%runtime.channelBlockedList = type { %runtime.channelBlockedList*, %"internal/task.Task"*, %runtime.chanSelectState*, { %runtime.channelBlockedList*, i32, i32 } } %runtime.chanSelectState = type { ptr, ptr }
%"internal/task.Task" = type { %"internal/task.Task"*, i8*, i64, %"internal/task.gcData", %"internal/task.state", i8* }
%"internal/task.gcData" = type { i8* }
%"internal/task.state" = type { i32, i8*, %"internal/task.stackState", i1 }
%"internal/task.stackState" = type { i32, i32 }
%runtime.chanSelectState = type { %runtime.channel*, i8* }
declare noalias nonnull i8* @runtime.alloc(i32, i8*, i8*) #0 declare noalias nonnull ptr @runtime.alloc(i32, ptr, ptr) #0
declare void @runtime.trackPointer(i8* nocapture readonly, i8*) #0 declare void @runtime.trackPointer(ptr nocapture readonly, ptr) #0
; Function Attrs: nounwind ; Function Attrs: nounwind
define hidden void @main.init(i8* %context) unnamed_addr #1 { define hidden void @main.init(ptr %context) unnamed_addr #1 {
entry: entry:
ret void ret void
} }
; Function Attrs: nounwind ; Function Attrs: nounwind
define hidden void @main.chanIntSend(%runtime.channel* dereferenceable_or_null(32) %ch, i8* %context) unnamed_addr #1 { define hidden void @main.chanIntSend(ptr dereferenceable_or_null(32) %ch, ptr %context) unnamed_addr #1 {
entry: entry:
%chan.blockedList = alloca %runtime.channelBlockedList, align 8 %chan.blockedList = alloca %runtime.channelBlockedList, align 8
%chan.value = alloca i32, align 4 %chan.value = alloca i32, align 4
%chan.value.bitcast = bitcast i32* %chan.value to i8* call void @llvm.lifetime.start.p0(i64 4, ptr nonnull %chan.value)
call void @llvm.lifetime.start.p0i8(i64 4, i8* nonnull %chan.value.bitcast) store i32 3, ptr %chan.value, align 4
store i32 3, i32* %chan.value, align 4 call void @llvm.lifetime.start.p0(i64 24, ptr nonnull %chan.blockedList)
%chan.blockedList.bitcast = bitcast %runtime.channelBlockedList* %chan.blockedList to i8* call void @runtime.chanSend(ptr %ch, ptr nonnull %chan.value, ptr nonnull %chan.blockedList, ptr undef) #3
call void @llvm.lifetime.start.p0i8(i64 24, i8* nonnull %chan.blockedList.bitcast) call void @llvm.lifetime.end.p0(i64 24, ptr nonnull %chan.blockedList)
call void @runtime.chanSend(%runtime.channel* %ch, i8* nonnull %chan.value.bitcast, %runtime.channelBlockedList* nonnull %chan.blockedList, i8* undef) #3 call void @llvm.lifetime.end.p0(i64 4, ptr nonnull %chan.value)
call void @llvm.lifetime.end.p0i8(i64 24, i8* nonnull %chan.blockedList.bitcast)
call void @llvm.lifetime.end.p0i8(i64 4, i8* nonnull %chan.value.bitcast)
ret void ret void
} }
; Function Attrs: argmemonly nofree nosync nounwind willreturn ; Function Attrs: argmemonly nocallback nofree nosync nounwind willreturn
declare void @llvm.lifetime.start.p0i8(i64 immarg, i8* nocapture) #2 declare void @llvm.lifetime.start.p0(i64 immarg, ptr nocapture) #2
declare void @runtime.chanSend(%runtime.channel* dereferenceable_or_null(32), i8*, %runtime.channelBlockedList* dereferenceable_or_null(24), i8*) #0 declare void @runtime.chanSend(ptr dereferenceable_or_null(32), ptr, ptr dereferenceable_or_null(24), ptr) #0
; Function Attrs: argmemonly nofree nosync nounwind willreturn ; Function Attrs: argmemonly nocallback nofree nosync nounwind willreturn
declare void @llvm.lifetime.end.p0i8(i64 immarg, i8* nocapture) #2 declare void @llvm.lifetime.end.p0(i64 immarg, ptr nocapture) #2
; Function Attrs: nounwind ; Function Attrs: nounwind
define hidden void @main.chanIntRecv(%runtime.channel* dereferenceable_or_null(32) %ch, i8* %context) unnamed_addr #1 { define hidden void @main.chanIntRecv(ptr dereferenceable_or_null(32) %ch, ptr %context) unnamed_addr #1 {
entry: entry:
%chan.blockedList = alloca %runtime.channelBlockedList, align 8 %chan.blockedList = alloca %runtime.channelBlockedList, align 8
%chan.value = alloca i32, align 4 %chan.value = alloca i32, align 4
%chan.value.bitcast = bitcast i32* %chan.value to i8* call void @llvm.lifetime.start.p0(i64 4, ptr nonnull %chan.value)
call void @llvm.lifetime.start.p0i8(i64 4, i8* nonnull %chan.value.bitcast) call void @llvm.lifetime.start.p0(i64 24, ptr nonnull %chan.blockedList)
%chan.blockedList.bitcast = bitcast %runtime.channelBlockedList* %chan.blockedList to i8* %0 = call i1 @runtime.chanRecv(ptr %ch, ptr nonnull %chan.value, ptr nonnull %chan.blockedList, ptr undef) #3
call void @llvm.lifetime.start.p0i8(i64 24, i8* nonnull %chan.blockedList.bitcast) call void @llvm.lifetime.end.p0(i64 4, ptr nonnull %chan.value)
%0 = call i1 @runtime.chanRecv(%runtime.channel* %ch, i8* nonnull %chan.value.bitcast, %runtime.channelBlockedList* nonnull %chan.blockedList, i8* undef) #3 call void @llvm.lifetime.end.p0(i64 24, ptr nonnull %chan.blockedList)
call void @llvm.lifetime.end.p0i8(i64 4, i8* nonnull %chan.value.bitcast)
call void @llvm.lifetime.end.p0i8(i64 24, i8* nonnull %chan.blockedList.bitcast)
ret void ret void
} }
declare i1 @runtime.chanRecv(%runtime.channel* dereferenceable_or_null(32), i8*, %runtime.channelBlockedList* dereferenceable_or_null(24), i8*) #0 declare i1 @runtime.chanRecv(ptr dereferenceable_or_null(32), ptr, ptr dereferenceable_or_null(24), ptr) #0
; Function Attrs: nounwind ; Function Attrs: nounwind
define hidden void @main.chanZeroSend(%runtime.channel* dereferenceable_or_null(32) %ch, i8* %context) unnamed_addr #1 { define hidden void @main.chanZeroSend(ptr dereferenceable_or_null(32) %ch, ptr %context) unnamed_addr #1 {
entry: entry:
%complit = alloca {}, align 8 %complit = alloca {}, align 8
%chan.blockedList = alloca %runtime.channelBlockedList, align 8 %chan.blockedList = alloca %runtime.channelBlockedList, align 8
%0 = bitcast {}* %complit to i8* call void @runtime.trackPointer(ptr nonnull %complit, ptr undef) #3
call void @runtime.trackPointer(i8* nonnull %0, i8* undef) #3 call void @llvm.lifetime.start.p0(i64 24, ptr nonnull %chan.blockedList)
%chan.blockedList.bitcast = bitcast %runtime.channelBlockedList* %chan.blockedList to i8* call void @runtime.chanSend(ptr %ch, ptr null, ptr nonnull %chan.blockedList, ptr undef) #3
call void @llvm.lifetime.start.p0i8(i64 24, i8* nonnull %chan.blockedList.bitcast) call void @llvm.lifetime.end.p0(i64 24, ptr nonnull %chan.blockedList)
call void @runtime.chanSend(%runtime.channel* %ch, i8* null, %runtime.channelBlockedList* nonnull %chan.blockedList, i8* undef) #3
call void @llvm.lifetime.end.p0i8(i64 24, i8* nonnull %chan.blockedList.bitcast)
ret void ret void
} }
; Function Attrs: nounwind ; Function Attrs: nounwind
define hidden void @main.chanZeroRecv(%runtime.channel* dereferenceable_or_null(32) %ch, i8* %context) unnamed_addr #1 { define hidden void @main.chanZeroRecv(ptr dereferenceable_or_null(32) %ch, ptr %context) unnamed_addr #1 {
entry: entry:
%chan.blockedList = alloca %runtime.channelBlockedList, align 8 %chan.blockedList = alloca %runtime.channelBlockedList, align 8
%chan.blockedList.bitcast = bitcast %runtime.channelBlockedList* %chan.blockedList to i8* call void @llvm.lifetime.start.p0(i64 24, ptr nonnull %chan.blockedList)
call void @llvm.lifetime.start.p0i8(i64 24, i8* nonnull %chan.blockedList.bitcast) %0 = call i1 @runtime.chanRecv(ptr %ch, ptr null, ptr nonnull %chan.blockedList, ptr undef) #3
%0 = call i1 @runtime.chanRecv(%runtime.channel* %ch, i8* null, %runtime.channelBlockedList* nonnull %chan.blockedList, i8* undef) #3 call void @llvm.lifetime.end.p0(i64 24, ptr nonnull %chan.blockedList)
call void @llvm.lifetime.end.p0i8(i64 24, i8* nonnull %chan.blockedList.bitcast)
ret void ret void
} }
; Function Attrs: nounwind ; Function Attrs: nounwind
define hidden void @main.selectZeroRecv(%runtime.channel* dereferenceable_or_null(32) %ch1, %runtime.channel* dereferenceable_or_null(32) %ch2, i8* %context) unnamed_addr #1 { define hidden void @main.selectZeroRecv(ptr dereferenceable_or_null(32) %ch1, ptr dereferenceable_or_null(32) %ch2, ptr %context) unnamed_addr #1 {
entry: 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, i32* %select.send.value, align 4 store i32 1, ptr %select.send.value, align 4
%select.states.alloca.bitcast = bitcast [2 x %runtime.chanSelectState]* %select.states.alloca to i8* call void @llvm.lifetime.start.p0(i64 16, ptr nonnull %select.states.alloca)
call void @llvm.lifetime.start.p0i8(i64 16, i8* nonnull %select.states.alloca.bitcast) store ptr %ch1, ptr %select.states.alloca, align 8
%.repack = getelementptr inbounds [2 x %runtime.chanSelectState], [2 x %runtime.chanSelectState]* %select.states.alloca, i32 0, i32 0, i32 0 %select.states.alloca.repack1 = getelementptr inbounds %runtime.chanSelectState, ptr %select.states.alloca, i32 0, i32 1
store %runtime.channel* %ch1, %runtime.channel** %.repack, align 8 store ptr %select.send.value, ptr %select.states.alloca.repack1, align 4
%.repack1 = getelementptr inbounds [2 x %runtime.chanSelectState], [2 x %runtime.chanSelectState]* %select.states.alloca, i32 0, i32 0, i32 1 %0 = getelementptr inbounds [2 x %runtime.chanSelectState], ptr %select.states.alloca, i32 0, i32 1
%0 = bitcast i8** %.repack1 to i32** store ptr %ch2, ptr %0, align 8
store i32* %select.send.value, i32** %0, align 4 %.repack3 = getelementptr inbounds [2 x %runtime.chanSelectState], ptr %select.states.alloca, i32 0, i32 1, i32 1
%.repack3 = getelementptr inbounds [2 x %runtime.chanSelectState], [2 x %runtime.chanSelectState]* %select.states.alloca, i32 0, i32 1, i32 0 store ptr null, ptr %.repack3, align 4
store %runtime.channel* %ch2, %runtime.channel** %.repack3, align 8 %select.result = call { i32, i1 } @runtime.tryChanSelect(ptr undef, ptr nonnull %select.states.alloca, i32 2, i32 2, ptr undef) #3
%.repack4 = getelementptr inbounds [2 x %runtime.chanSelectState], [2 x %runtime.chanSelectState]* %select.states.alloca, i32 0, i32 1, i32 1 call void @llvm.lifetime.end.p0(i64 16, ptr nonnull %select.states.alloca)
store i8* null, i8** %.repack4, align 4
%select.states = getelementptr inbounds [2 x %runtime.chanSelectState], [2 x %runtime.chanSelectState]* %select.states.alloca, i32 0, i32 0
%select.result = call { i32, i1 } @runtime.tryChanSelect(i8* undef, %runtime.chanSelectState* nonnull %select.states, i32 2, i32 2, i8* undef) #3
call void @llvm.lifetime.end.p0i8(i64 16, i8* nonnull %select.states.alloca.bitcast)
%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
@ -122,9 +106,9 @@ select.body: ; preds = %select.next
br label %select.done br label %select.done
} }
declare { i32, i1 } @runtime.tryChanSelect(i8*, %runtime.chanSelectState*, i32, i32, i8*) #0 declare { i32, i1 } @runtime.tryChanSelect(ptr, ptr, i32, i32, ptr) #0
attributes #0 = { "target-features"="+bulk-memory,+nontrapping-fptoint,+sign-ext" } attributes #0 = { "target-features"="+bulk-memory,+nontrapping-fptoint,+sign-ext" }
attributes #1 = { nounwind "target-features"="+bulk-memory,+nontrapping-fptoint,+sign-ext" } attributes #1 = { nounwind "target-features"="+bulk-memory,+nontrapping-fptoint,+sign-ext" }
attributes #2 = { argmemonly nofree nosync nounwind willreturn } attributes #2 = { argmemonly nocallback nofree nosync nounwind willreturn }
attributes #3 = { nounwind } attributes #3 = { nounwind }

265
compiler/testdata/defer-cortex-m-qemu.ll предоставленный
Просмотреть файл

@ -3,103 +3,99 @@ source_filename = "defer.go"
target datalayout = "e-m:e-p:32:32-Fi8-i64:64-v128:64:128-a:0:32-n32-S64" target datalayout = "e-m:e-p:32:32-Fi8-i64:64-v128:64:128-a:0:32-n32-S64"
target triple = "thumbv7m-unknown-unknown-eabi" target triple = "thumbv7m-unknown-unknown-eabi"
%runtime._defer = type { i32, %runtime._defer* } %runtime.deferFrame = type { ptr, ptr, [0 x ptr], ptr, i1, %runtime._interface }
%runtime.deferFrame = type { i8*, i8*, [0 x i8*], %runtime.deferFrame*, i1, %runtime._interface } %runtime._interface = type { i32, ptr }
%runtime._interface = type { i32, i8* } %runtime._defer = type { i32, ptr }
declare noalias nonnull i8* @runtime.alloc(i32, i8*, i8*) #0 declare noalias nonnull ptr @runtime.alloc(i32, ptr, ptr) #0
; Function Attrs: nounwind ; Function Attrs: nounwind
define hidden void @main.init(i8* %context) unnamed_addr #1 { define hidden void @main.init(ptr %context) unnamed_addr #1 {
entry: entry:
ret void ret void
} }
declare void @main.external(i8*) #0 declare void @main.external(ptr) #0
; Function Attrs: nounwind ; Function Attrs: nounwind
define hidden void @main.deferSimple(i8* %context) unnamed_addr #1 { define hidden void @main.deferSimple(ptr %context) unnamed_addr #1 {
entry: entry:
%defer.alloca = alloca { i32, %runtime._defer* }, align 4 %defer.alloca = alloca { i32, ptr }, align 4
%deferPtr = alloca %runtime._defer*, align 4 %deferPtr = alloca ptr, align 4
store %runtime._defer* null, %runtime._defer** %deferPtr, align 4 store ptr null, ptr %deferPtr, align 4
%deferframe.buf = alloca %runtime.deferFrame, align 4 %deferframe.buf = alloca %runtime.deferFrame, align 4
%0 = call i8* @llvm.stacksave() %0 = call ptr @llvm.stacksave()
call void @runtime.setupDeferFrame(%runtime.deferFrame* nonnull %deferframe.buf, i8* %0, i8* undef) #3 call void @runtime.setupDeferFrame(ptr nonnull %deferframe.buf, ptr %0, ptr undef) #3
%defer.alloca.repack = getelementptr inbounds { i32, %runtime._defer* }, { i32, %runtime._defer* }* %defer.alloca, i32 0, i32 0 store i32 0, ptr %defer.alloca, align 4
store i32 0, i32* %defer.alloca.repack, align 4 %defer.alloca.repack15 = getelementptr inbounds { i32, ptr }, ptr %defer.alloca, i32 0, i32 1
%defer.alloca.repack16 = getelementptr inbounds { i32, %runtime._defer* }, { i32, %runtime._defer* }* %defer.alloca, i32 0, i32 1 store ptr null, ptr %defer.alloca.repack15, align 4
store %runtime._defer* null, %runtime._defer** %defer.alloca.repack16, align 4 store ptr %defer.alloca, ptr %deferPtr, align 4
%1 = bitcast %runtime._defer** %deferPtr to { i32, %runtime._defer* }** %setjmp = call i32 asm "\0Amovs r0, #0\0Amov r2, pc\0Astr r2, [r1, #4]", "={r0},{r1},~{r1},~{r2},~{r3},~{r4},~{r5},~{r6},~{r7},~{r8},~{r9},~{r10},~{r11},~{r12},~{lr},~{q0},~{q1},~{q2},~{q3},~{q4},~{q5},~{q6},~{q7},~{q8},~{q9},~{q10},~{q11},~{q12},~{q13},~{q14},~{q15},~{cpsr},~{memory}"(ptr nonnull %deferframe.buf) #4
store { i32, %runtime._defer* }* %defer.alloca, { i32, %runtime._defer* }** %1, align 4
%setjmp = call i32 asm "\0Amovs r0, #0\0Amov r2, pc\0Astr r2, [r1, #4]", "={r0},{r1},~{r1},~{r2},~{r3},~{r4},~{r5},~{r6},~{r7},~{r8},~{r9},~{r10},~{r11},~{r12},~{lr},~{q0},~{q1},~{q2},~{q3},~{q4},~{q5},~{q6},~{q7},~{q8},~{q9},~{q10},~{q11},~{q12},~{q13},~{q14},~{q15},~{cpsr},~{memory}"(%runtime.deferFrame* nonnull %deferframe.buf) #4
%setjmp.result = icmp eq i32 %setjmp, 0 %setjmp.result = icmp eq i32 %setjmp, 0
br i1 %setjmp.result, label %2, label %lpad br i1 %setjmp.result, label %1, label %lpad
2: ; preds = %entry 1: ; preds = %entry
call void @main.external(i8* undef) #3 call void @main.external(ptr undef) #3
br label %rundefers.loophead br label %rundefers.loophead
rundefers.loophead: ; preds = %4, %2 rundefers.loophead: ; preds = %3, %1
%3 = load %runtime._defer*, %runtime._defer** %deferPtr, align 4 %2 = load ptr, ptr %deferPtr, align 4
%stackIsNil = icmp eq %runtime._defer* %3, null %stackIsNil = icmp eq ptr %2, null
br i1 %stackIsNil, label %rundefers.end, label %rundefers.loop br i1 %stackIsNil, label %rundefers.end, label %rundefers.loop
rundefers.loop: ; preds = %rundefers.loophead rundefers.loop: ; preds = %rundefers.loophead
%stack.next.gep = getelementptr inbounds %runtime._defer, %runtime._defer* %3, i32 0, i32 1 %stack.next.gep = getelementptr inbounds %runtime._defer, ptr %2, i32 0, i32 1
%stack.next = load %runtime._defer*, %runtime._defer** %stack.next.gep, align 4 %stack.next = load ptr, ptr %stack.next.gep, align 4
store %runtime._defer* %stack.next, %runtime._defer** %deferPtr, align 4 store ptr %stack.next, ptr %deferPtr, align 4
%callback.gep = getelementptr inbounds %runtime._defer, %runtime._defer* %3, i32 0, i32 0 %callback = load i32, ptr %2, align 4
%callback = load i32, i32* %callback.gep, align 4
switch i32 %callback, label %rundefers.default [ switch i32 %callback, label %rundefers.default [
i32 0, label %rundefers.callback0 i32 0, label %rundefers.callback0
] ]
rundefers.callback0: ; preds = %rundefers.loop rundefers.callback0: ; preds = %rundefers.loop
%setjmp1 = call i32 asm "\0Amovs r0, #0\0Amov r2, pc\0Astr r2, [r1, #4]", "={r0},{r1},~{r1},~{r2},~{r3},~{r4},~{r5},~{r6},~{r7},~{r8},~{r9},~{r10},~{r11},~{r12},~{lr},~{q0},~{q1},~{q2},~{q3},~{q4},~{q5},~{q6},~{q7},~{q8},~{q9},~{q10},~{q11},~{q12},~{q13},~{q14},~{q15},~{cpsr},~{memory}"(%runtime.deferFrame* nonnull %deferframe.buf) #4 %setjmp1 = call i32 asm "\0Amovs r0, #0\0Amov r2, pc\0Astr r2, [r1, #4]", "={r0},{r1},~{r1},~{r2},~{r3},~{r4},~{r5},~{r6},~{r7},~{r8},~{r9},~{r10},~{r11},~{r12},~{lr},~{q0},~{q1},~{q2},~{q3},~{q4},~{q5},~{q6},~{q7},~{q8},~{q9},~{q10},~{q11},~{q12},~{q13},~{q14},~{q15},~{cpsr},~{memory}"(ptr nonnull %deferframe.buf) #4
%setjmp.result2 = icmp eq i32 %setjmp1, 0 %setjmp.result2 = icmp eq i32 %setjmp1, 0
br i1 %setjmp.result2, label %4, label %lpad br i1 %setjmp.result2, label %3, label %lpad
4: ; preds = %rundefers.callback0 3: ; preds = %rundefers.callback0
call void @"main.deferSimple$1"(i8* undef) call void @"main.deferSimple$1"(ptr undef)
br label %rundefers.loophead br label %rundefers.loophead
rundefers.default: ; preds = %rundefers.loop rundefers.default: ; preds = %rundefers.loop
unreachable unreachable
rundefers.end: ; preds = %rundefers.loophead rundefers.end: ; preds = %rundefers.loophead
call void @runtime.destroyDeferFrame(%runtime.deferFrame* nonnull %deferframe.buf, i8* undef) #3 call void @runtime.destroyDeferFrame(ptr nonnull %deferframe.buf, ptr undef) #3
ret void ret void
recover: ; preds = %rundefers.end3 recover: ; preds = %rundefers.end3
call void @runtime.destroyDeferFrame(%runtime.deferFrame* nonnull %deferframe.buf, i8* undef) #3 call void @runtime.destroyDeferFrame(ptr nonnull %deferframe.buf, ptr undef) #3
ret void ret void
lpad: ; preds = %rundefers.callback012, %rundefers.callback0, %entry lpad: ; preds = %rundefers.callback012, %rundefers.callback0, %entry
br label %rundefers.loophead6 br label %rundefers.loophead6
rundefers.loophead6: ; preds = %6, %lpad rundefers.loophead6: ; preds = %5, %lpad
%5 = load %runtime._defer*, %runtime._defer** %deferPtr, align 4 %4 = load ptr, ptr %deferPtr, align 4
%stackIsNil7 = icmp eq %runtime._defer* %5, null %stackIsNil7 = icmp eq ptr %4, null
br i1 %stackIsNil7, label %rundefers.end3, label %rundefers.loop5 br i1 %stackIsNil7, label %rundefers.end3, label %rundefers.loop5
rundefers.loop5: ; preds = %rundefers.loophead6 rundefers.loop5: ; preds = %rundefers.loophead6
%stack.next.gep8 = getelementptr inbounds %runtime._defer, %runtime._defer* %5, i32 0, i32 1 %stack.next.gep8 = getelementptr inbounds %runtime._defer, ptr %4, i32 0, i32 1
%stack.next9 = load %runtime._defer*, %runtime._defer** %stack.next.gep8, align 4 %stack.next9 = load ptr, ptr %stack.next.gep8, align 4
store %runtime._defer* %stack.next9, %runtime._defer** %deferPtr, align 4 store ptr %stack.next9, ptr %deferPtr, align 4
%callback.gep10 = getelementptr inbounds %runtime._defer, %runtime._defer* %5, i32 0, i32 0 %callback11 = load i32, ptr %4, align 4
%callback11 = load i32, i32* %callback.gep10, align 4
switch i32 %callback11, label %rundefers.default4 [ switch i32 %callback11, label %rundefers.default4 [
i32 0, label %rundefers.callback012 i32 0, label %rundefers.callback012
] ]
rundefers.callback012: ; preds = %rundefers.loop5 rundefers.callback012: ; preds = %rundefers.loop5
%setjmp14 = call i32 asm "\0Amovs r0, #0\0Amov r2, pc\0Astr r2, [r1, #4]", "={r0},{r1},~{r1},~{r2},~{r3},~{r4},~{r5},~{r6},~{r7},~{r8},~{r9},~{r10},~{r11},~{r12},~{lr},~{q0},~{q1},~{q2},~{q3},~{q4},~{q5},~{q6},~{q7},~{q8},~{q9},~{q10},~{q11},~{q12},~{q13},~{q14},~{q15},~{cpsr},~{memory}"(%runtime.deferFrame* nonnull %deferframe.buf) #4 %setjmp13 = call i32 asm "\0Amovs r0, #0\0Amov r2, pc\0Astr r2, [r1, #4]", "={r0},{r1},~{r1},~{r2},~{r3},~{r4},~{r5},~{r6},~{r7},~{r8},~{r9},~{r10},~{r11},~{r12},~{lr},~{q0},~{q1},~{q2},~{q3},~{q4},~{q5},~{q6},~{q7},~{q8},~{q9},~{q10},~{q11},~{q12},~{q13},~{q14},~{q15},~{cpsr},~{memory}"(ptr nonnull %deferframe.buf) #4
%setjmp.result15 = icmp eq i32 %setjmp14, 0 %setjmp.result14 = icmp eq i32 %setjmp13, 0
br i1 %setjmp.result15, label %6, label %lpad br i1 %setjmp.result14, label %5, label %lpad
6: ; preds = %rundefers.callback012 5: ; preds = %rundefers.callback012
call void @"main.deferSimple$1"(i8* undef) call void @"main.deferSimple$1"(ptr undef)
br label %rundefers.loophead6 br label %rundefers.loophead6
rundefers.default4: ; preds = %rundefers.loop5 rundefers.default4: ; preds = %rundefers.loop5
@ -109,158 +105,151 @@ rundefers.end3: ; preds = %rundefers.loophead6
br label %recover br label %recover
} }
; Function Attrs: nofree nosync nounwind willreturn ; Function Attrs: nocallback nofree nosync nounwind willreturn
declare i8* @llvm.stacksave() #2 declare ptr @llvm.stacksave() #2
declare void @runtime.setupDeferFrame(%runtime.deferFrame* dereferenceable_or_null(24), i8*, i8*) #0 declare void @runtime.setupDeferFrame(ptr dereferenceable_or_null(24), ptr, ptr) #0
; Function Attrs: nounwind ; Function Attrs: nounwind
define internal void @"main.deferSimple$1"(i8* %context) unnamed_addr #1 { define internal void @"main.deferSimple$1"(ptr %context) unnamed_addr #1 {
entry: entry:
call void @runtime.printint32(i32 3, i8* undef) #3 call void @runtime.printint32(i32 3, ptr undef) #3
ret void ret void
} }
declare void @runtime.destroyDeferFrame(%runtime.deferFrame* dereferenceable_or_null(24), i8*) #0 declare void @runtime.destroyDeferFrame(ptr dereferenceable_or_null(24), ptr) #0
declare void @runtime.printint32(i32, i8*) #0 declare void @runtime.printint32(i32, ptr) #0
; Function Attrs: nounwind ; Function Attrs: nounwind
define hidden void @main.deferMultiple(i8* %context) unnamed_addr #1 { define hidden void @main.deferMultiple(ptr %context) unnamed_addr #1 {
entry: entry:
%defer.alloca2 = alloca { i32, %runtime._defer* }, align 4 %defer.alloca2 = alloca { i32, ptr }, align 4
%defer.alloca = alloca { i32, %runtime._defer* }, align 4 %defer.alloca = alloca { i32, ptr }, align 4
%deferPtr = alloca %runtime._defer*, align 4 %deferPtr = alloca ptr, align 4
store %runtime._defer* null, %runtime._defer** %deferPtr, align 4 store ptr null, ptr %deferPtr, align 4
%deferframe.buf = alloca %runtime.deferFrame, align 4 %deferframe.buf = alloca %runtime.deferFrame, align 4
%0 = call i8* @llvm.stacksave() %0 = call ptr @llvm.stacksave()
call void @runtime.setupDeferFrame(%runtime.deferFrame* nonnull %deferframe.buf, i8* %0, i8* undef) #3 call void @runtime.setupDeferFrame(ptr nonnull %deferframe.buf, ptr %0, ptr undef) #3
%defer.alloca.repack = getelementptr inbounds { i32, %runtime._defer* }, { i32, %runtime._defer* }* %defer.alloca, i32 0, i32 0 store i32 0, ptr %defer.alloca, align 4
store i32 0, i32* %defer.alloca.repack, align 4 %defer.alloca.repack22 = getelementptr inbounds { i32, ptr }, ptr %defer.alloca, i32 0, i32 1
%defer.alloca.repack26 = getelementptr inbounds { i32, %runtime._defer* }, { i32, %runtime._defer* }* %defer.alloca, i32 0, i32 1 store ptr null, ptr %defer.alloca.repack22, align 4
store %runtime._defer* null, %runtime._defer** %defer.alloca.repack26, align 4 store ptr %defer.alloca, ptr %deferPtr, align 4
%1 = bitcast %runtime._defer** %deferPtr to { i32, %runtime._defer* }** store i32 1, ptr %defer.alloca2, align 4
store { i32, %runtime._defer* }* %defer.alloca, { i32, %runtime._defer* }** %1, align 4 %defer.alloca2.repack23 = getelementptr inbounds { i32, ptr }, ptr %defer.alloca2, i32 0, i32 1
%defer.alloca2.repack = getelementptr inbounds { i32, %runtime._defer* }, { i32, %runtime._defer* }* %defer.alloca2, i32 0, i32 0 store ptr %defer.alloca, ptr %defer.alloca2.repack23, align 4
store i32 1, i32* %defer.alloca2.repack, align 4 store ptr %defer.alloca2, ptr %deferPtr, align 4
%defer.alloca2.repack27 = getelementptr inbounds { i32, %runtime._defer* }, { i32, %runtime._defer* }* %defer.alloca2, i32 0, i32 1 %setjmp = call i32 asm "\0Amovs r0, #0\0Amov r2, pc\0Astr r2, [r1, #4]", "={r0},{r1},~{r1},~{r2},~{r3},~{r4},~{r5},~{r6},~{r7},~{r8},~{r9},~{r10},~{r11},~{r12},~{lr},~{q0},~{q1},~{q2},~{q3},~{q4},~{q5},~{q6},~{q7},~{q8},~{q9},~{q10},~{q11},~{q12},~{q13},~{q14},~{q15},~{cpsr},~{memory}"(ptr nonnull %deferframe.buf) #4
%2 = bitcast %runtime._defer** %defer.alloca2.repack27 to { i32, %runtime._defer* }**
store { i32, %runtime._defer* }* %defer.alloca, { i32, %runtime._defer* }** %2, align 4
%3 = bitcast %runtime._defer** %deferPtr to { i32, %runtime._defer* }**
store { i32, %runtime._defer* }* %defer.alloca2, { i32, %runtime._defer* }** %3, align 4
%setjmp = call i32 asm "\0Amovs r0, #0\0Amov r2, pc\0Astr r2, [r1, #4]", "={r0},{r1},~{r1},~{r2},~{r3},~{r4},~{r5},~{r6},~{r7},~{r8},~{r9},~{r10},~{r11},~{r12},~{lr},~{q0},~{q1},~{q2},~{q3},~{q4},~{q5},~{q6},~{q7},~{q8},~{q9},~{q10},~{q11},~{q12},~{q13},~{q14},~{q15},~{cpsr},~{memory}"(%runtime.deferFrame* nonnull %deferframe.buf) #4
%setjmp.result = icmp eq i32 %setjmp, 0 %setjmp.result = icmp eq i32 %setjmp, 0
br i1 %setjmp.result, label %4, label %lpad br i1 %setjmp.result, label %1, label %lpad
4: ; preds = %entry 1: ; preds = %entry
call void @main.external(i8* undef) #3 call void @main.external(ptr undef) #3
br label %rundefers.loophead br label %rundefers.loophead
rundefers.loophead: ; preds = %7, %6, %4 rundefers.loophead: ; preds = %4, %3, %1
%5 = load %runtime._defer*, %runtime._defer** %deferPtr, align 4 %2 = load ptr, ptr %deferPtr, align 4
%stackIsNil = icmp eq %runtime._defer* %5, null %stackIsNil = icmp eq ptr %2, null
br i1 %stackIsNil, label %rundefers.end, label %rundefers.loop br i1 %stackIsNil, label %rundefers.end, label %rundefers.loop
rundefers.loop: ; preds = %rundefers.loophead rundefers.loop: ; preds = %rundefers.loophead
%stack.next.gep = getelementptr inbounds %runtime._defer, %runtime._defer* %5, i32 0, i32 1 %stack.next.gep = getelementptr inbounds %runtime._defer, ptr %2, i32 0, i32 1
%stack.next = load %runtime._defer*, %runtime._defer** %stack.next.gep, align 4 %stack.next = load ptr, ptr %stack.next.gep, align 4
store %runtime._defer* %stack.next, %runtime._defer** %deferPtr, align 4 store ptr %stack.next, ptr %deferPtr, align 4
%callback.gep = getelementptr inbounds %runtime._defer, %runtime._defer* %5, i32 0, i32 0 %callback = load i32, ptr %2, align 4
%callback = load i32, i32* %callback.gep, align 4
switch i32 %callback, label %rundefers.default [ switch i32 %callback, label %rundefers.default [
i32 0, label %rundefers.callback0 i32 0, label %rundefers.callback0
i32 1, label %rundefers.callback1 i32 1, label %rundefers.callback1
] ]
rundefers.callback0: ; preds = %rundefers.loop rundefers.callback0: ; preds = %rundefers.loop
%setjmp4 = call i32 asm "\0Amovs r0, #0\0Amov r2, pc\0Astr r2, [r1, #4]", "={r0},{r1},~{r1},~{r2},~{r3},~{r4},~{r5},~{r6},~{r7},~{r8},~{r9},~{r10},~{r11},~{r12},~{lr},~{q0},~{q1},~{q2},~{q3},~{q4},~{q5},~{q6},~{q7},~{q8},~{q9},~{q10},~{q11},~{q12},~{q13},~{q14},~{q15},~{cpsr},~{memory}"(%runtime.deferFrame* nonnull %deferframe.buf) #4 %setjmp3 = call i32 asm "\0Amovs r0, #0\0Amov r2, pc\0Astr r2, [r1, #4]", "={r0},{r1},~{r1},~{r2},~{r3},~{r4},~{r5},~{r6},~{r7},~{r8},~{r9},~{r10},~{r11},~{r12},~{lr},~{q0},~{q1},~{q2},~{q3},~{q4},~{q5},~{q6},~{q7},~{q8},~{q9},~{q10},~{q11},~{q12},~{q13},~{q14},~{q15},~{cpsr},~{memory}"(ptr nonnull %deferframe.buf) #4
%setjmp.result5 = icmp eq i32 %setjmp4, 0 %setjmp.result4 = icmp eq i32 %setjmp3, 0
br i1 %setjmp.result5, label %6, label %lpad br i1 %setjmp.result4, label %3, label %lpad
6: ; preds = %rundefers.callback0 3: ; preds = %rundefers.callback0
call void @"main.deferMultiple$1"(i8* undef) call void @"main.deferMultiple$1"(ptr undef)
br label %rundefers.loophead br label %rundefers.loophead
rundefers.callback1: ; preds = %rundefers.loop rundefers.callback1: ; preds = %rundefers.loop
%setjmp7 = call i32 asm "\0Amovs r0, #0\0Amov r2, pc\0Astr r2, [r1, #4]", "={r0},{r1},~{r1},~{r2},~{r3},~{r4},~{r5},~{r6},~{r7},~{r8},~{r9},~{r10},~{r11},~{r12},~{lr},~{q0},~{q1},~{q2},~{q3},~{q4},~{q5},~{q6},~{q7},~{q8},~{q9},~{q10},~{q11},~{q12},~{q13},~{q14},~{q15},~{cpsr},~{memory}"(%runtime.deferFrame* nonnull %deferframe.buf) #4 %setjmp5 = call i32 asm "\0Amovs r0, #0\0Amov r2, pc\0Astr r2, [r1, #4]", "={r0},{r1},~{r1},~{r2},~{r3},~{r4},~{r5},~{r6},~{r7},~{r8},~{r9},~{r10},~{r11},~{r12},~{lr},~{q0},~{q1},~{q2},~{q3},~{q4},~{q5},~{q6},~{q7},~{q8},~{q9},~{q10},~{q11},~{q12},~{q13},~{q14},~{q15},~{cpsr},~{memory}"(ptr nonnull %deferframe.buf) #4
%setjmp.result8 = icmp eq i32 %setjmp7, 0 %setjmp.result6 = icmp eq i32 %setjmp5, 0
br i1 %setjmp.result8, label %7, label %lpad br i1 %setjmp.result6, label %4, label %lpad
7: ; preds = %rundefers.callback1 4: ; preds = %rundefers.callback1
call void @"main.deferMultiple$2"(i8* undef) call void @"main.deferMultiple$2"(ptr undef)
br label %rundefers.loophead br label %rundefers.loophead
rundefers.default: ; preds = %rundefers.loop rundefers.default: ; preds = %rundefers.loop
unreachable unreachable
rundefers.end: ; preds = %rundefers.loophead rundefers.end: ; preds = %rundefers.loophead
call void @runtime.destroyDeferFrame(%runtime.deferFrame* nonnull %deferframe.buf, i8* undef) #3 call void @runtime.destroyDeferFrame(ptr nonnull %deferframe.buf, ptr undef) #3
ret void ret void
recover: ; preds = %rundefers.end9 recover: ; preds = %rundefers.end7
call void @runtime.destroyDeferFrame(%runtime.deferFrame* nonnull %deferframe.buf, i8* undef) #3 call void @runtime.destroyDeferFrame(ptr nonnull %deferframe.buf, ptr undef) #3
ret void ret void
lpad: ; preds = %rundefers.callback122, %rundefers.callback018, %rundefers.callback1, %rundefers.callback0, %entry lpad: ; preds = %rundefers.callback119, %rundefers.callback016, %rundefers.callback1, %rundefers.callback0, %entry
br label %rundefers.loophead12 br label %rundefers.loophead10
rundefers.loophead12: ; preds = %10, %9, %lpad rundefers.loophead10: ; preds = %7, %6, %lpad
%8 = load %runtime._defer*, %runtime._defer** %deferPtr, align 4 %5 = load ptr, ptr %deferPtr, align 4
%stackIsNil13 = icmp eq %runtime._defer* %8, null %stackIsNil11 = icmp eq ptr %5, null
br i1 %stackIsNil13, label %rundefers.end9, label %rundefers.loop11 br i1 %stackIsNil11, label %rundefers.end7, label %rundefers.loop9
rundefers.loop11: ; preds = %rundefers.loophead12 rundefers.loop9: ; preds = %rundefers.loophead10
%stack.next.gep14 = getelementptr inbounds %runtime._defer, %runtime._defer* %8, i32 0, i32 1 %stack.next.gep12 = getelementptr inbounds %runtime._defer, ptr %5, i32 0, i32 1
%stack.next15 = load %runtime._defer*, %runtime._defer** %stack.next.gep14, align 4 %stack.next13 = load ptr, ptr %stack.next.gep12, align 4
store %runtime._defer* %stack.next15, %runtime._defer** %deferPtr, align 4 store ptr %stack.next13, ptr %deferPtr, align 4
%callback.gep16 = getelementptr inbounds %runtime._defer, %runtime._defer* %8, i32 0, i32 0 %callback15 = load i32, ptr %5, align 4
%callback17 = load i32, i32* %callback.gep16, align 4 switch i32 %callback15, label %rundefers.default8 [
switch i32 %callback17, label %rundefers.default10 [ i32 0, label %rundefers.callback016
i32 0, label %rundefers.callback018 i32 1, label %rundefers.callback119
i32 1, label %rundefers.callback122
] ]
rundefers.callback018: ; preds = %rundefers.loop11 rundefers.callback016: ; preds = %rundefers.loop9
%setjmp20 = call i32 asm "\0Amovs r0, #0\0Amov r2, pc\0Astr r2, [r1, #4]", "={r0},{r1},~{r1},~{r2},~{r3},~{r4},~{r5},~{r6},~{r7},~{r8},~{r9},~{r10},~{r11},~{r12},~{lr},~{q0},~{q1},~{q2},~{q3},~{q4},~{q5},~{q6},~{q7},~{q8},~{q9},~{q10},~{q11},~{q12},~{q13},~{q14},~{q15},~{cpsr},~{memory}"(%runtime.deferFrame* nonnull %deferframe.buf) #4 %setjmp17 = call i32 asm "\0Amovs r0, #0\0Amov r2, pc\0Astr r2, [r1, #4]", "={r0},{r1},~{r1},~{r2},~{r3},~{r4},~{r5},~{r6},~{r7},~{r8},~{r9},~{r10},~{r11},~{r12},~{lr},~{q0},~{q1},~{q2},~{q3},~{q4},~{q5},~{q6},~{q7},~{q8},~{q9},~{q10},~{q11},~{q12},~{q13},~{q14},~{q15},~{cpsr},~{memory}"(ptr nonnull %deferframe.buf) #4
%setjmp.result18 = icmp eq i32 %setjmp17, 0
br i1 %setjmp.result18, label %6, label %lpad
6: ; preds = %rundefers.callback016
call void @"main.deferMultiple$1"(ptr undef)
br label %rundefers.loophead10
rundefers.callback119: ; preds = %rundefers.loop9
%setjmp20 = call i32 asm "\0Amovs r0, #0\0Amov r2, pc\0Astr r2, [r1, #4]", "={r0},{r1},~{r1},~{r2},~{r3},~{r4},~{r5},~{r6},~{r7},~{r8},~{r9},~{r10},~{r11},~{r12},~{lr},~{q0},~{q1},~{q2},~{q3},~{q4},~{q5},~{q6},~{q7},~{q8},~{q9},~{q10},~{q11},~{q12},~{q13},~{q14},~{q15},~{cpsr},~{memory}"(ptr nonnull %deferframe.buf) #4
%setjmp.result21 = icmp eq i32 %setjmp20, 0 %setjmp.result21 = icmp eq i32 %setjmp20, 0
br i1 %setjmp.result21, label %9, label %lpad br i1 %setjmp.result21, label %7, label %lpad
9: ; preds = %rundefers.callback018 7: ; preds = %rundefers.callback119
call void @"main.deferMultiple$1"(i8* undef) call void @"main.deferMultiple$2"(ptr undef)
br label %rundefers.loophead12 br label %rundefers.loophead10
rundefers.callback122: ; preds = %rundefers.loop11 rundefers.default8: ; preds = %rundefers.loop9
%setjmp24 = call i32 asm "\0Amovs r0, #0\0Amov r2, pc\0Astr r2, [r1, #4]", "={r0},{r1},~{r1},~{r2},~{r3},~{r4},~{r5},~{r6},~{r7},~{r8},~{r9},~{r10},~{r11},~{r12},~{lr},~{q0},~{q1},~{q2},~{q3},~{q4},~{q5},~{q6},~{q7},~{q8},~{q9},~{q10},~{q11},~{q12},~{q13},~{q14},~{q15},~{cpsr},~{memory}"(%runtime.deferFrame* nonnull %deferframe.buf) #4
%setjmp.result25 = icmp eq i32 %setjmp24, 0
br i1 %setjmp.result25, label %10, label %lpad
10: ; preds = %rundefers.callback122
call void @"main.deferMultiple$2"(i8* undef)
br label %rundefers.loophead12
rundefers.default10: ; preds = %rundefers.loop11
unreachable unreachable
rundefers.end9: ; preds = %rundefers.loophead12 rundefers.end7: ; preds = %rundefers.loophead10
br label %recover br label %recover
} }
; Function Attrs: nounwind ; Function Attrs: nounwind
define internal void @"main.deferMultiple$1"(i8* %context) unnamed_addr #1 { define internal void @"main.deferMultiple$1"(ptr %context) unnamed_addr #1 {
entry: entry:
call void @runtime.printint32(i32 3, i8* undef) #3 call void @runtime.printint32(i32 3, ptr undef) #3
ret void ret void
} }
; Function Attrs: nounwind ; Function Attrs: nounwind
define internal void @"main.deferMultiple$2"(i8* %context) unnamed_addr #1 { define internal void @"main.deferMultiple$2"(ptr %context) unnamed_addr #1 {
entry: entry:
call void @runtime.printint32(i32 5, i8* undef) #3 call void @runtime.printint32(i32 5, ptr undef) #3
ret void ret void
} }
attributes #0 = { "target-features"="+armv7-m,+hwdiv,+soft-float,+strict-align,+thumb-mode,-aes,-bf16,-cdecp0,-cdecp1,-cdecp2,-cdecp3,-cdecp4,-cdecp5,-cdecp6,-cdecp7,-crc,-crypto,-d32,-dotprod,-dsp,-fp-armv8,-fp-armv8d16,-fp-armv8d16sp,-fp-armv8sp,-fp16,-fp16fml,-fp64,-fpregs,-fullfp16,-hwdiv-arm,-i8mm,-lob,-mve,-mve.fp,-neon,-pacbti,-ras,-sb,-sha2,-vfp2,-vfp2sp,-vfp3,-vfp3d16,-vfp3d16sp,-vfp3sp,-vfp4,-vfp4d16,-vfp4d16sp,-vfp4sp" } attributes #0 = { "target-features"="+armv7-m,+hwdiv,+soft-float,+strict-align,+thumb-mode,-aes,-bf16,-cdecp0,-cdecp1,-cdecp2,-cdecp3,-cdecp4,-cdecp5,-cdecp6,-cdecp7,-crc,-crypto,-d32,-dotprod,-dsp,-fp-armv8,-fp-armv8d16,-fp-armv8d16sp,-fp-armv8sp,-fp16,-fp16fml,-fp64,-fpregs,-fullfp16,-hwdiv-arm,-i8mm,-lob,-mve,-mve.fp,-neon,-pacbti,-ras,-sb,-sha2,-vfp2,-vfp2sp,-vfp3,-vfp3d16,-vfp3d16sp,-vfp3sp,-vfp4,-vfp4d16,-vfp4d16sp,-vfp4sp" }
attributes #1 = { nounwind "target-features"="+armv7-m,+hwdiv,+soft-float,+strict-align,+thumb-mode,-aes,-bf16,-cdecp0,-cdecp1,-cdecp2,-cdecp3,-cdecp4,-cdecp5,-cdecp6,-cdecp7,-crc,-crypto,-d32,-dotprod,-dsp,-fp-armv8,-fp-armv8d16,-fp-armv8d16sp,-fp-armv8sp,-fp16,-fp16fml,-fp64,-fpregs,-fullfp16,-hwdiv-arm,-i8mm,-lob,-mve,-mve.fp,-neon,-pacbti,-ras,-sb,-sha2,-vfp2,-vfp2sp,-vfp3,-vfp3d16,-vfp3d16sp,-vfp3sp,-vfp4,-vfp4d16,-vfp4d16sp,-vfp4sp" } attributes #1 = { nounwind "target-features"="+armv7-m,+hwdiv,+soft-float,+strict-align,+thumb-mode,-aes,-bf16,-cdecp0,-cdecp1,-cdecp2,-cdecp3,-cdecp4,-cdecp5,-cdecp6,-cdecp7,-crc,-crypto,-d32,-dotprod,-dsp,-fp-armv8,-fp-armv8d16,-fp-armv8d16sp,-fp-armv8sp,-fp16,-fp16fml,-fp64,-fpregs,-fullfp16,-hwdiv-arm,-i8mm,-lob,-mve,-mve.fp,-neon,-pacbti,-ras,-sb,-sha2,-vfp2,-vfp2sp,-vfp3,-vfp3d16,-vfp3d16sp,-vfp3sp,-vfp4,-vfp4d16,-vfp4d16sp,-vfp4sp" }
attributes #2 = { nofree nosync nounwind willreturn } attributes #2 = { nocallback nofree nosync nounwind willreturn }
attributes #3 = { nounwind } attributes #3 = { nounwind }
attributes #4 = { nounwind returns_twice } attributes #4 = { nounwind returns_twice }

22
compiler/testdata/float.ll предоставленный
Просмотреть файл

@ -3,18 +3,18 @@ source_filename = "float.go"
target datalayout = "e-m:e-p:32:32-p10:8:8-p20:8:8-i64:64-n32:64-S128-ni:1:10:20" target datalayout = "e-m:e-p:32:32-p10:8:8-p20:8:8-i64:64-n32:64-S128-ni:1:10:20"
target triple = "wasm32-unknown-wasi" target triple = "wasm32-unknown-wasi"
declare noalias nonnull i8* @runtime.alloc(i32, i8*, i8*) #0 declare noalias nonnull ptr @runtime.alloc(i32, ptr, ptr) #0
declare void @runtime.trackPointer(i8* nocapture readonly, i8*) #0 declare void @runtime.trackPointer(ptr nocapture readonly, ptr) #0
; Function Attrs: nounwind ; Function Attrs: nounwind
define hidden void @main.init(i8* %context) unnamed_addr #1 { define hidden void @main.init(ptr %context) unnamed_addr #1 {
entry: entry:
ret void ret void
} }
; Function Attrs: nounwind ; Function Attrs: nounwind
define hidden i32 @main.f32tou32(float %v, i8* %context) unnamed_addr #1 { define hidden i32 @main.f32tou32(float %v, ptr %context) unnamed_addr #1 {
entry: entry:
%positive = fcmp oge float %v, 0.000000e+00 %positive = fcmp oge float %v, 0.000000e+00
%withinmax = fcmp ole float %v, 0x41EFFFFFC0000000 %withinmax = fcmp ole float %v, 0x41EFFFFFC0000000
@ -26,25 +26,25 @@ entry:
} }
; Function Attrs: nounwind ; Function Attrs: nounwind
define hidden float @main.maxu32f(i8* %context) unnamed_addr #1 { define hidden float @main.maxu32f(ptr %context) unnamed_addr #1 {
entry: entry:
ret float 0x41F0000000000000 ret float 0x41F0000000000000
} }
; Function Attrs: nounwind ; Function Attrs: nounwind
define hidden i32 @main.maxu32tof32(i8* %context) unnamed_addr #1 { define hidden i32 @main.maxu32tof32(ptr %context) unnamed_addr #1 {
entry: entry:
ret i32 -1 ret i32 -1
} }
; Function Attrs: nounwind ; Function Attrs: nounwind
define hidden { i32, i32, i32, i32 } @main.inftoi32(i8* %context) unnamed_addr #1 { define hidden { i32, i32, i32, i32 } @main.inftoi32(ptr %context) unnamed_addr #1 {
entry: entry:
ret { i32, i32, i32, i32 } { i32 -1, i32 0, i32 2147483647, i32 -2147483648 } ret { i32, i32, i32, i32 } { i32 -1, i32 0, i32 2147483647, i32 -2147483648 }
} }
; Function Attrs: nounwind ; Function Attrs: nounwind
define hidden i32 @main.u32tof32tou32(i32 %v, i8* %context) unnamed_addr #1 { define hidden i32 @main.u32tof32tou32(i32 %v, ptr %context) unnamed_addr #1 {
entry: entry:
%0 = uitofp i32 %v to float %0 = uitofp i32 %v to float
%withinmax = fcmp ole float %0, 0x41EFFFFFC0000000 %withinmax = fcmp ole float %0, 0x41EFFFFFC0000000
@ -54,7 +54,7 @@ entry:
} }
; Function Attrs: nounwind ; Function Attrs: nounwind
define hidden float @main.f32tou32tof32(float %v, i8* %context) unnamed_addr #1 { define hidden float @main.f32tou32tof32(float %v, ptr %context) unnamed_addr #1 {
entry: entry:
%positive = fcmp oge float %v, 0.000000e+00 %positive = fcmp oge float %v, 0.000000e+00
%withinmax = fcmp ole float %v, 0x41EFFFFFC0000000 %withinmax = fcmp ole float %v, 0x41EFFFFFC0000000
@ -67,7 +67,7 @@ entry:
} }
; Function Attrs: nounwind ; Function Attrs: nounwind
define hidden i8 @main.f32tou8(float %v, i8* %context) unnamed_addr #1 { define hidden i8 @main.f32tou8(float %v, ptr %context) unnamed_addr #1 {
entry: entry:
%positive = fcmp oge float %v, 0.000000e+00 %positive = fcmp oge float %v, 0.000000e+00
%withinmax = fcmp ole float %v, 2.550000e+02 %withinmax = fcmp ole float %v, 2.550000e+02
@ -79,7 +79,7 @@ entry:
} }
; Function Attrs: nounwind ; Function Attrs: nounwind
define hidden i8 @main.f32toi8(float %v, i8* %context) unnamed_addr #1 { define hidden i8 @main.f32toi8(float %v, ptr %context) unnamed_addr #1 {
entry: entry:
%abovemin = fcmp oge float %v, -1.280000e+02 %abovemin = fcmp oge float %v, -1.280000e+02
%belowmax = fcmp ole float %v, 1.270000e+02 %belowmax = fcmp ole float %v, 1.270000e+02

23
compiler/testdata/func.ll предоставленный
Просмотреть файл

@ -3,43 +3,42 @@ source_filename = "func.go"
target datalayout = "e-m:e-p:32:32-p10:8:8-p20:8:8-i64:64-n32:64-S128-ni:1:10:20" target datalayout = "e-m:e-p:32:32-p10:8:8-p20:8:8-i64:64-n32:64-S128-ni:1:10:20"
target triple = "wasm32-unknown-wasi" target triple = "wasm32-unknown-wasi"
declare noalias nonnull i8* @runtime.alloc(i32, i8*, i8*) #0 declare noalias nonnull ptr @runtime.alloc(i32, ptr, ptr) #0
declare void @runtime.trackPointer(i8* nocapture readonly, i8*) #0 declare void @runtime.trackPointer(ptr nocapture readonly, ptr) #0
; Function Attrs: nounwind ; Function Attrs: nounwind
define hidden void @main.init(i8* %context) unnamed_addr #1 { define hidden void @main.init(ptr %context) unnamed_addr #1 {
entry: entry:
ret void ret void
} }
; Function Attrs: nounwind ; Function Attrs: nounwind
define hidden void @main.foo(i8* %callback.context, void ()* %callback.funcptr, i8* %context) unnamed_addr #1 { define hidden void @main.foo(ptr %callback.context, ptr %callback.funcptr, ptr %context) unnamed_addr #1 {
entry: entry:
%0 = icmp eq void ()* %callback.funcptr, null %0 = icmp eq ptr %callback.funcptr, null
br i1 %0, label %fpcall.throw, label %fpcall.next br i1 %0, label %fpcall.throw, label %fpcall.next
fpcall.next: ; preds = %entry fpcall.next: ; preds = %entry
%1 = bitcast void ()* %callback.funcptr to void (i32, i8*)* call void %callback.funcptr(i32 3, ptr %callback.context) #2
call void %1(i32 3, i8* %callback.context) #2
ret void ret void
fpcall.throw: ; preds = %entry fpcall.throw: ; preds = %entry
call void @runtime.nilPanic(i8* undef) #2 call void @runtime.nilPanic(ptr undef) #2
unreachable unreachable
} }
declare void @runtime.nilPanic(i8*) #0 declare void @runtime.nilPanic(ptr) #0
; Function Attrs: nounwind ; Function Attrs: nounwind
define hidden void @main.bar(i8* %context) unnamed_addr #1 { define hidden void @main.bar(ptr %context) unnamed_addr #1 {
entry: entry:
call void @main.foo(i8* undef, void ()* bitcast (void (i32, i8*)* @main.someFunc to void ()*), i8* undef) call void @main.foo(ptr undef, ptr nonnull @main.someFunc, ptr undef)
ret void ret void
} }
; Function Attrs: nounwind ; Function Attrs: nounwind
define hidden void @main.someFunc(i32 %arg0, i8* %context) unnamed_addr #1 { define hidden void @main.someFunc(i32 %arg0, ptr %context) unnamed_addr #1 {
entry: entry:
ret void ret void
} }

176
compiler/testdata/gc.ll предоставленный
Просмотреть файл

@ -3,133 +3,129 @@ source_filename = "gc.go"
target datalayout = "e-m:e-p:32:32-p10:8:8-p20:8:8-i64:64-n32:64-S128-ni:1:10:20" target datalayout = "e-m:e-p:32:32-p10:8:8-p20:8:8-i64:64-n32:64-S128-ni:1:10:20"
target triple = "wasm32-unknown-wasi" target triple = "wasm32-unknown-wasi"
%runtime.typecodeID = type { %runtime.typecodeID*, i32, %runtime.interfaceMethodInfo*, %runtime.typecodeID*, i32 } %runtime.typecodeID = type { ptr, i32, ptr, ptr, i32 }
%runtime.interfaceMethodInfo = type { i8*, i32 } %runtime._interface = type { i32, ptr }
%runtime._interface = type { i32, i8* }
@main.scalar1 = hidden global i8* null, align 4 @main.scalar1 = hidden global ptr null, align 4
@main.scalar2 = hidden global i32* null, align 4 @main.scalar2 = hidden global ptr null, align 4
@main.scalar3 = hidden global i64* null, align 4 @main.scalar3 = hidden global ptr null, align 4
@main.scalar4 = hidden global float* null, align 4 @main.scalar4 = hidden global ptr null, align 4
@main.array1 = hidden global [3 x i8]* null, align 4 @main.array1 = hidden global ptr null, align 4
@main.array2 = hidden global [71 x i8]* null, align 4 @main.array2 = hidden global ptr null, align 4
@main.array3 = hidden global [3 x i8*]* null, align 4 @main.array3 = hidden global ptr null, align 4
@main.struct1 = hidden global {}* null, align 4 @main.struct1 = hidden global ptr null, align 4
@main.struct2 = hidden global { i32, i32 }* null, align 4 @main.struct2 = hidden global ptr null, align 4
@main.struct3 = hidden global { i8*, [60 x i32], i8* }* null, align 4 @main.struct3 = hidden global ptr null, align 4
@main.struct4 = hidden global { i8*, [61 x i32] }* null, align 4 @main.struct4 = hidden global ptr null, align 4
@main.slice1 = hidden global { i8*, i32, i32 } zeroinitializer, align 8 @main.slice1 = hidden global { ptr, i32, i32 } zeroinitializer, align 8
@main.slice2 = hidden global { i32**, i32, i32 } zeroinitializer, align 8 @main.slice2 = hidden global { ptr, i32, i32 } zeroinitializer, align 8
@main.slice3 = hidden global { { i8*, i32, i32 }*, i32, i32 } zeroinitializer, align 8 @main.slice3 = hidden global { ptr, i32, i32 } zeroinitializer, align 8
@"runtime/gc.layout:62-2000000000000001" = linkonce_odr unnamed_addr constant { i32, [8 x i8] } { i32 62, [8 x i8] c" \00\00\00\00\00\00\01" } @"runtime/gc.layout:62-2000000000000001" = linkonce_odr unnamed_addr constant { i32, [8 x i8] } { i32 62, [8 x i8] c" \00\00\00\00\00\00\01" }
@"runtime/gc.layout:62-0001" = linkonce_odr unnamed_addr constant { i32, [8 x i8] } { i32 62, [8 x i8] c"\00\00\00\00\00\00\00\01" } @"runtime/gc.layout:62-0001" = linkonce_odr unnamed_addr constant { i32, [8 x i8] } { i32 62, [8 x i8] c"\00\00\00\00\00\00\00\01" }
@"reflect/types.type:basic:complex128" = linkonce_odr constant %runtime.typecodeID { %runtime.typecodeID* null, i32 0, %runtime.interfaceMethodInfo* null, %runtime.typecodeID* @"reflect/types.type:pointer:basic:complex128", i32 0 } @"reflect/types.type:basic:complex128" = linkonce_odr constant %runtime.typecodeID { ptr null, i32 0, ptr null, ptr @"reflect/types.type:pointer:basic:complex128", i32 0 }
@"reflect/types.type:pointer:basic:complex128" = linkonce_odr constant %runtime.typecodeID { %runtime.typecodeID* @"reflect/types.type:basic:complex128", i32 0, %runtime.interfaceMethodInfo* null, %runtime.typecodeID* null, i32 0 } @"reflect/types.type:pointer:basic:complex128" = linkonce_odr constant %runtime.typecodeID { ptr @"reflect/types.type:basic:complex128", i32 0, ptr null, ptr null, i32 0 }
declare noalias nonnull i8* @runtime.alloc(i32, i8*, i8*) #0 declare noalias nonnull ptr @runtime.alloc(i32, ptr, ptr) #0
declare void @runtime.trackPointer(i8* nocapture readonly, i8*) #0 declare void @runtime.trackPointer(ptr nocapture readonly, ptr) #0
; Function Attrs: nounwind ; Function Attrs: nounwind
define hidden void @main.init(i8* %context) unnamed_addr #1 { define hidden void @main.init(ptr %context) unnamed_addr #1 {
entry: entry:
ret void ret void
} }
; Function Attrs: nounwind ; Function Attrs: nounwind
define hidden void @main.newScalar(i8* %context) unnamed_addr #1 { define hidden void @main.newScalar(ptr %context) unnamed_addr #1 {
entry: entry:
%new = call i8* @runtime.alloc(i32 1, i8* nonnull inttoptr (i32 3 to i8*), i8* undef) #2 %new = call ptr @runtime.alloc(i32 1, ptr nonnull inttoptr (i32 3 to ptr), ptr undef) #2
call void @runtime.trackPointer(i8* nonnull %new, i8* undef) #2 call void @runtime.trackPointer(ptr nonnull %new, ptr undef) #2
store i8* %new, i8** @main.scalar1, align 4 store ptr %new, ptr @main.scalar1, align 4
%new1 = call i8* @runtime.alloc(i32 4, i8* nonnull inttoptr (i32 3 to i8*), i8* undef) #2 %new1 = call ptr @runtime.alloc(i32 4, ptr nonnull inttoptr (i32 3 to ptr), ptr undef) #2
call void @runtime.trackPointer(i8* nonnull %new1, i8* undef) #2 call void @runtime.trackPointer(ptr nonnull %new1, ptr undef) #2
store i8* %new1, i8** bitcast (i32** @main.scalar2 to i8**), align 4 store ptr %new1, ptr @main.scalar2, align 4
%new2 = call i8* @runtime.alloc(i32 8, i8* nonnull inttoptr (i32 3 to i8*), i8* undef) #2 %new2 = call ptr @runtime.alloc(i32 8, ptr nonnull inttoptr (i32 3 to ptr), ptr undef) #2
call void @runtime.trackPointer(i8* nonnull %new2, i8* undef) #2 call void @runtime.trackPointer(ptr nonnull %new2, ptr undef) #2
store i8* %new2, i8** bitcast (i64** @main.scalar3 to i8**), align 4 store ptr %new2, ptr @main.scalar3, align 4
%new3 = call i8* @runtime.alloc(i32 4, i8* nonnull inttoptr (i32 3 to i8*), i8* undef) #2 %new3 = call ptr @runtime.alloc(i32 4, ptr nonnull inttoptr (i32 3 to ptr), ptr undef) #2
call void @runtime.trackPointer(i8* nonnull %new3, i8* undef) #2 call void @runtime.trackPointer(ptr nonnull %new3, ptr undef) #2
store i8* %new3, i8** bitcast (float** @main.scalar4 to i8**), align 4 store ptr %new3, ptr @main.scalar4, align 4
ret void ret void
} }
; Function Attrs: nounwind ; Function Attrs: nounwind
define hidden void @main.newArray(i8* %context) unnamed_addr #1 { define hidden void @main.newArray(ptr %context) unnamed_addr #1 {
entry: entry:
%new = call i8* @runtime.alloc(i32 3, i8* nonnull inttoptr (i32 3 to i8*), i8* undef) #2 %new = call ptr @runtime.alloc(i32 3, ptr nonnull inttoptr (i32 3 to ptr), ptr undef) #2
call void @runtime.trackPointer(i8* nonnull %new, i8* undef) #2 call void @runtime.trackPointer(ptr nonnull %new, ptr undef) #2
store i8* %new, i8** bitcast ([3 x i8]** @main.array1 to i8**), align 4 store ptr %new, ptr @main.array1, align 4
%new1 = call i8* @runtime.alloc(i32 71, i8* nonnull inttoptr (i32 3 to i8*), i8* undef) #2 %new1 = call ptr @runtime.alloc(i32 71, ptr nonnull inttoptr (i32 3 to ptr), ptr undef) #2
call void @runtime.trackPointer(i8* nonnull %new1, i8* undef) #2 call void @runtime.trackPointer(ptr nonnull %new1, ptr undef) #2
store i8* %new1, i8** bitcast ([71 x i8]** @main.array2 to i8**), align 4 store ptr %new1, ptr @main.array2, align 4
%new2 = call i8* @runtime.alloc(i32 12, i8* nonnull inttoptr (i32 67 to i8*), i8* undef) #2 %new2 = call ptr @runtime.alloc(i32 12, ptr nonnull inttoptr (i32 67 to ptr), ptr undef) #2
call void @runtime.trackPointer(i8* nonnull %new2, i8* undef) #2 call void @runtime.trackPointer(ptr nonnull %new2, ptr undef) #2
store i8* %new2, i8** bitcast ([3 x i8*]** @main.array3 to i8**), align 4 store ptr %new2, ptr @main.array3, align 4
ret void ret void
} }
; Function Attrs: nounwind ; Function Attrs: nounwind
define hidden void @main.newStruct(i8* %context) unnamed_addr #1 { define hidden void @main.newStruct(ptr %context) unnamed_addr #1 {
entry: entry:
%new = call i8* @runtime.alloc(i32 0, i8* nonnull inttoptr (i32 3 to i8*), i8* undef) #2 %new = call ptr @runtime.alloc(i32 0, ptr nonnull inttoptr (i32 3 to ptr), ptr undef) #2
call void @runtime.trackPointer(i8* nonnull %new, i8* undef) #2 call void @runtime.trackPointer(ptr nonnull %new, ptr undef) #2
store i8* %new, i8** bitcast ({}** @main.struct1 to i8**), align 4 store ptr %new, ptr @main.struct1, align 4
%new1 = call i8* @runtime.alloc(i32 8, i8* nonnull inttoptr (i32 3 to i8*), i8* undef) #2 %new1 = call ptr @runtime.alloc(i32 8, ptr nonnull inttoptr (i32 3 to ptr), ptr undef) #2
call void @runtime.trackPointer(i8* nonnull %new1, i8* undef) #2 call void @runtime.trackPointer(ptr nonnull %new1, ptr undef) #2
store i8* %new1, i8** bitcast ({ i32, i32 }** @main.struct2 to i8**), align 4 store ptr %new1, ptr @main.struct2, align 4
%new2 = call i8* @runtime.alloc(i32 248, i8* bitcast ({ i32, [8 x i8] }* @"runtime/gc.layout:62-2000000000000001" to i8*), i8* undef) #2 %new2 = call ptr @runtime.alloc(i32 248, ptr nonnull @"runtime/gc.layout:62-2000000000000001", ptr undef) #2
call void @runtime.trackPointer(i8* nonnull %new2, i8* undef) #2 call void @runtime.trackPointer(ptr nonnull %new2, ptr undef) #2
store i8* %new2, i8** bitcast ({ i8*, [60 x i32], i8* }** @main.struct3 to i8**), align 4 store ptr %new2, ptr @main.struct3, align 4
%new3 = call i8* @runtime.alloc(i32 248, i8* bitcast ({ i32, [8 x i8] }* @"runtime/gc.layout:62-0001" to i8*), i8* undef) #2 %new3 = call ptr @runtime.alloc(i32 248, ptr nonnull @"runtime/gc.layout:62-0001", ptr undef) #2
call void @runtime.trackPointer(i8* nonnull %new3, i8* undef) #2 call void @runtime.trackPointer(ptr nonnull %new3, ptr undef) #2
store i8* %new3, i8** bitcast ({ i8*, [61 x i32] }** @main.struct4 to i8**), align 4 store ptr %new3, ptr @main.struct4, align 4
ret void ret void
} }
; Function Attrs: nounwind ; Function Attrs: nounwind
define hidden { i8*, void ()* }* @main.newFuncValue(i8* %context) unnamed_addr #1 { define hidden ptr @main.newFuncValue(ptr %context) unnamed_addr #1 {
entry: entry:
%new = call i8* @runtime.alloc(i32 8, i8* nonnull inttoptr (i32 197 to i8*), i8* undef) #2 %new = call ptr @runtime.alloc(i32 8, ptr nonnull inttoptr (i32 197 to ptr), ptr undef) #2
%0 = bitcast i8* %new to { i8*, void ()* }* call void @runtime.trackPointer(ptr nonnull %new, ptr undef) #2
call void @runtime.trackPointer(i8* nonnull %new, i8* undef) #2 ret ptr %new
ret { i8*, void ()* }* %0
} }
; Function Attrs: nounwind ; Function Attrs: nounwind
define hidden void @main.makeSlice(i8* %context) unnamed_addr #1 { define hidden void @main.makeSlice(ptr %context) unnamed_addr #1 {
entry: entry:
%makeslice = call i8* @runtime.alloc(i32 5, i8* nonnull inttoptr (i32 3 to i8*), i8* undef) #2 %makeslice = call ptr @runtime.alloc(i32 5, ptr nonnull inttoptr (i32 3 to ptr), ptr undef) #2
call void @runtime.trackPointer(i8* nonnull %makeslice, i8* undef) #2 call void @runtime.trackPointer(ptr nonnull %makeslice, ptr undef) #2
store i8* %makeslice, i8** getelementptr inbounds ({ i8*, i32, i32 }, { i8*, i32, i32 }* @main.slice1, i32 0, i32 0), align 8 store ptr %makeslice, ptr @main.slice1, align 8
store i32 5, i32* getelementptr inbounds ({ i8*, i32, i32 }, { i8*, i32, i32 }* @main.slice1, i32 0, i32 1), align 4 store i32 5, ptr getelementptr inbounds ({ ptr, i32, i32 }, ptr @main.slice1, i32 0, i32 1), align 4
store i32 5, i32* getelementptr inbounds ({ i8*, i32, i32 }, { i8*, i32, i32 }* @main.slice1, i32 0, i32 2), align 8 store i32 5, ptr getelementptr inbounds ({ ptr, i32, i32 }, ptr @main.slice1, i32 0, i32 2), align 8
%makeslice1 = call i8* @runtime.alloc(i32 20, i8* nonnull inttoptr (i32 67 to i8*), i8* undef) #2 %makeslice1 = call ptr @runtime.alloc(i32 20, ptr nonnull inttoptr (i32 67 to ptr), ptr undef) #2
call void @runtime.trackPointer(i8* nonnull %makeslice1, i8* undef) #2 call void @runtime.trackPointer(ptr nonnull %makeslice1, ptr undef) #2
store i8* %makeslice1, i8** bitcast ({ i32**, i32, i32 }* @main.slice2 to i8**), align 8 store ptr %makeslice1, ptr @main.slice2, align 8
store i32 5, i32* getelementptr inbounds ({ i32**, i32, i32 }, { i32**, i32, i32 }* @main.slice2, i32 0, i32 1), align 4 store i32 5, ptr getelementptr inbounds ({ ptr, i32, i32 }, ptr @main.slice2, i32 0, i32 1), align 4
store i32 5, i32* getelementptr inbounds ({ i32**, i32, i32 }, { i32**, i32, i32 }* @main.slice2, i32 0, i32 2), align 8 store i32 5, ptr getelementptr inbounds ({ ptr, i32, i32 }, ptr @main.slice2, i32 0, i32 2), align 8
%makeslice3 = call i8* @runtime.alloc(i32 60, i8* nonnull inttoptr (i32 71 to i8*), i8* undef) #2 %makeslice3 = call ptr @runtime.alloc(i32 60, ptr nonnull inttoptr (i32 71 to ptr), ptr undef) #2
call void @runtime.trackPointer(i8* nonnull %makeslice3, i8* undef) #2 call void @runtime.trackPointer(ptr nonnull %makeslice3, ptr undef) #2
store i8* %makeslice3, i8** bitcast ({ { i8*, i32, i32 }*, i32, i32 }* @main.slice3 to i8**), align 8 store ptr %makeslice3, ptr @main.slice3, align 8
store i32 5, i32* getelementptr inbounds ({ { i8*, i32, i32 }*, i32, i32 }, { { i8*, i32, i32 }*, i32, i32 }* @main.slice3, i32 0, i32 1), align 4 store i32 5, ptr getelementptr inbounds ({ ptr, i32, i32 }, ptr @main.slice3, i32 0, i32 1), align 4
store i32 5, i32* getelementptr inbounds ({ { i8*, i32, i32 }*, i32, i32 }, { { i8*, i32, i32 }*, i32, i32 }* @main.slice3, i32 0, i32 2), align 8 store i32 5, ptr getelementptr inbounds ({ ptr, i32, i32 }, ptr @main.slice3, i32 0, i32 2), align 8
ret void ret void
} }
; Function Attrs: nounwind ; Function Attrs: nounwind
define hidden %runtime._interface @main.makeInterface(double %v.r, double %v.i, i8* %context) unnamed_addr #1 { define hidden %runtime._interface @main.makeInterface(double %v.r, double %v.i, ptr %context) unnamed_addr #1 {
entry: entry:
%0 = call i8* @runtime.alloc(i32 16, i8* null, i8* undef) #2 %0 = call ptr @runtime.alloc(i32 16, ptr null, ptr undef) #2
call void @runtime.trackPointer(i8* nonnull %0, i8* undef) #2 call void @runtime.trackPointer(ptr nonnull %0, ptr undef) #2
%.repack = bitcast i8* %0 to double* store double %v.r, ptr %0, align 8
store double %v.r, double* %.repack, align 8 %.repack1 = getelementptr inbounds { double, double }, ptr %0, i32 0, i32 1
%.repack1 = getelementptr inbounds i8, i8* %0, i32 8 store double %v.i, ptr %.repack1, align 8
%1 = bitcast i8* %.repack1 to double* %1 = insertvalue %runtime._interface { i32 ptrtoint (ptr @"reflect/types.type:basic:complex128" to i32), ptr undef }, ptr %0, 1
store double %v.i, double* %1, align 8 call void @runtime.trackPointer(ptr nonnull %0, ptr undef) #2
%2 = insertvalue %runtime._interface { i32 ptrtoint (%runtime.typecodeID* @"reflect/types.type:basic:complex128" to i32), i8* undef }, i8* %0, 1 ret %runtime._interface %1
call void @runtime.trackPointer(i8* nonnull %0, i8* undef) #2
ret %runtime._interface %2
} }
attributes #0 = { "target-features"="+bulk-memory,+nontrapping-fptoint,+sign-ext" } attributes #0 = { "target-features"="+bulk-memory,+nontrapping-fptoint,+sign-ext" }

189
compiler/testdata/goroutine-cortex-m-qemu-tasks.ll предоставленный
Просмотреть файл

@ -3,201 +3,176 @@ source_filename = "goroutine.go"
target datalayout = "e-m:e-p:32:32-Fi8-i64:64-v128:64:128-a:0:32-n32-S64" target datalayout = "e-m:e-p:32:32-Fi8-i64:64-v128:64:128-a:0:32-n32-S64"
target triple = "thumbv7m-unknown-unknown-eabi" target triple = "thumbv7m-unknown-unknown-eabi"
%runtime.channel = type { i32, i32, i8, %runtime.channelBlockedList*, i32, i32, i32, i8* } %runtime._string = type { ptr, i32 }
%runtime.channelBlockedList = type { %runtime.channelBlockedList*, %"internal/task.Task"*, %runtime.chanSelectState*, { %runtime.channelBlockedList*, i32, i32 } }
%"internal/task.Task" = type { %"internal/task.Task"*, i8*, i64, %"internal/task.gcData", %"internal/task.state", i8* }
%"internal/task.gcData" = type {}
%"internal/task.state" = type { i32, i32* }
%runtime.chanSelectState = type { %runtime.channel*, i8* }
@"main$string" = internal unnamed_addr constant [4 x i8] c"test", align 1 @"main$string" = internal unnamed_addr constant [4 x i8] c"test", align 1
declare noalias nonnull i8* @runtime.alloc(i32, i8*, i8*) #0 declare noalias nonnull ptr @runtime.alloc(i32, ptr, ptr) #0
; Function Attrs: nounwind ; Function Attrs: nounwind
define hidden void @main.init(i8* %context) unnamed_addr #1 { define hidden void @main.init(ptr %context) unnamed_addr #1 {
entry: entry:
ret void ret void
} }
; Function Attrs: nounwind ; Function Attrs: nounwind
define hidden void @main.regularFunctionGoroutine(i8* %context) unnamed_addr #1 { define hidden void @main.regularFunctionGoroutine(ptr %context) unnamed_addr #1 {
entry: entry:
%stacksize = call i32 @"internal/task.getGoroutineStackSize"(i32 ptrtoint (void (i8*)* @"main.regularFunction$gowrapper" to i32), i8* undef) #8 %stacksize = call i32 @"internal/task.getGoroutineStackSize"(i32 ptrtoint (ptr @"main.regularFunction$gowrapper" to i32), ptr undef) #8
call void @"internal/task.start"(i32 ptrtoint (void (i8*)* @"main.regularFunction$gowrapper" to i32), i8* nonnull inttoptr (i32 5 to i8*), i32 %stacksize, i8* undef) #8 call void @"internal/task.start"(i32 ptrtoint (ptr @"main.regularFunction$gowrapper" to i32), ptr nonnull inttoptr (i32 5 to ptr), i32 %stacksize, ptr undef) #8
ret void ret void
} }
declare void @main.regularFunction(i32, i8*) #0 declare void @main.regularFunction(i32, ptr) #0
; Function Attrs: nounwind ; Function Attrs: nounwind
define linkonce_odr void @"main.regularFunction$gowrapper"(i8* %0) unnamed_addr #2 { define linkonce_odr void @"main.regularFunction$gowrapper"(ptr %0) unnamed_addr #2 {
entry: entry:
%unpack.int = ptrtoint i8* %0 to i32 %unpack.int = ptrtoint ptr %0 to i32
call void @main.regularFunction(i32 %unpack.int, i8* undef) #8 call void @main.regularFunction(i32 %unpack.int, ptr undef) #8
ret void ret void
} }
declare i32 @"internal/task.getGoroutineStackSize"(i32, i8*) #0 declare i32 @"internal/task.getGoroutineStackSize"(i32, ptr) #0
declare void @"internal/task.start"(i32, i8*, i32, i8*) #0 declare void @"internal/task.start"(i32, ptr, i32, ptr) #0
; Function Attrs: nounwind ; Function Attrs: nounwind
define hidden void @main.inlineFunctionGoroutine(i8* %context) unnamed_addr #1 { define hidden void @main.inlineFunctionGoroutine(ptr %context) unnamed_addr #1 {
entry: entry:
%stacksize = call i32 @"internal/task.getGoroutineStackSize"(i32 ptrtoint (void (i8*)* @"main.inlineFunctionGoroutine$1$gowrapper" to i32), i8* undef) #8 %stacksize = call i32 @"internal/task.getGoroutineStackSize"(i32 ptrtoint (ptr @"main.inlineFunctionGoroutine$1$gowrapper" to i32), ptr undef) #8
call void @"internal/task.start"(i32 ptrtoint (void (i8*)* @"main.inlineFunctionGoroutine$1$gowrapper" to i32), i8* nonnull inttoptr (i32 5 to i8*), i32 %stacksize, i8* undef) #8 call void @"internal/task.start"(i32 ptrtoint (ptr @"main.inlineFunctionGoroutine$1$gowrapper" to i32), ptr nonnull inttoptr (i32 5 to ptr), i32 %stacksize, ptr undef) #8
ret void ret void
} }
; Function Attrs: nounwind ; Function Attrs: nounwind
define internal void @"main.inlineFunctionGoroutine$1"(i32 %x, i8* %context) unnamed_addr #1 { define internal void @"main.inlineFunctionGoroutine$1"(i32 %x, ptr %context) unnamed_addr #1 {
entry: entry:
ret void ret void
} }
; Function Attrs: nounwind ; Function Attrs: nounwind
define linkonce_odr void @"main.inlineFunctionGoroutine$1$gowrapper"(i8* %0) unnamed_addr #3 { define linkonce_odr void @"main.inlineFunctionGoroutine$1$gowrapper"(ptr %0) unnamed_addr #3 {
entry: entry:
%unpack.int = ptrtoint i8* %0 to i32 %unpack.int = ptrtoint ptr %0 to i32
call void @"main.inlineFunctionGoroutine$1"(i32 %unpack.int, i8* undef) call void @"main.inlineFunctionGoroutine$1"(i32 %unpack.int, ptr undef)
ret void ret void
} }
; Function Attrs: nounwind ; Function Attrs: nounwind
define hidden void @main.closureFunctionGoroutine(i8* %context) unnamed_addr #1 { define hidden void @main.closureFunctionGoroutine(ptr %context) unnamed_addr #1 {
entry: entry:
%n = call i8* @runtime.alloc(i32 4, i8* nonnull inttoptr (i32 3 to i8*), i8* undef) #8 %n = call ptr @runtime.alloc(i32 4, ptr nonnull inttoptr (i32 3 to ptr), ptr undef) #8
%0 = bitcast i8* %n to i32* store i32 3, ptr %n, align 4
store i32 3, i32* %0, align 4 %0 = call ptr @runtime.alloc(i32 8, ptr null, ptr undef) #8
%1 = call i8* @runtime.alloc(i32 8, i8* null, i8* undef) #8 store i32 5, ptr %0, align 4
%2 = bitcast i8* %1 to i32* %1 = getelementptr inbounds { i32, ptr }, ptr %0, i32 0, i32 1
store i32 5, i32* %2, align 4 store ptr %n, ptr %1, align 4
%3 = getelementptr inbounds i8, i8* %1, i32 4 %stacksize = call i32 @"internal/task.getGoroutineStackSize"(i32 ptrtoint (ptr @"main.closureFunctionGoroutine$1$gowrapper" to i32), ptr undef) #8
%4 = bitcast i8* %3 to i8** call void @"internal/task.start"(i32 ptrtoint (ptr @"main.closureFunctionGoroutine$1$gowrapper" to i32), ptr nonnull %0, i32 %stacksize, ptr undef) #8
store i8* %n, i8** %4, align 4 %2 = load i32, ptr %n, align 4
%stacksize = call i32 @"internal/task.getGoroutineStackSize"(i32 ptrtoint (void (i8*)* @"main.closureFunctionGoroutine$1$gowrapper" to i32), i8* undef) #8 call void @runtime.printint32(i32 %2, ptr undef) #8
call void @"internal/task.start"(i32 ptrtoint (void (i8*)* @"main.closureFunctionGoroutine$1$gowrapper" to i32), i8* nonnull %1, i32 %stacksize, i8* undef) #8
%5 = load i32, i32* %0, align 4
call void @runtime.printint32(i32 %5, i8* undef) #8
ret void ret void
} }
; Function Attrs: nounwind ; Function Attrs: nounwind
define internal void @"main.closureFunctionGoroutine$1"(i32 %x, i8* %context) unnamed_addr #1 { define internal void @"main.closureFunctionGoroutine$1"(i32 %x, ptr %context) unnamed_addr #1 {
entry: entry:
%unpack.ptr = bitcast i8* %context to i32* store i32 7, ptr %context, align 4
store i32 7, i32* %unpack.ptr, align 4
ret void ret void
} }
; Function Attrs: nounwind ; Function Attrs: nounwind
define linkonce_odr void @"main.closureFunctionGoroutine$1$gowrapper"(i8* %0) unnamed_addr #4 { define linkonce_odr void @"main.closureFunctionGoroutine$1$gowrapper"(ptr %0) unnamed_addr #4 {
entry: entry:
%1 = bitcast i8* %0 to i32* %1 = load i32, ptr %0, align 4
%2 = load i32, i32* %1, align 4 %2 = getelementptr inbounds { i32, ptr }, ptr %0, i32 0, i32 1
%3 = getelementptr inbounds i8, i8* %0, i32 4 %3 = load ptr, ptr %2, align 4
%4 = bitcast i8* %3 to i8** call void @"main.closureFunctionGoroutine$1"(i32 %1, ptr %3)
%5 = load i8*, i8** %4, align 4
call void @"main.closureFunctionGoroutine$1"(i32 %2, i8* %5)
ret void ret void
} }
declare void @runtime.printint32(i32, i8*) #0 declare void @runtime.printint32(i32, ptr) #0
; Function Attrs: nounwind ; Function Attrs: nounwind
define hidden void @main.funcGoroutine(i8* %fn.context, void ()* %fn.funcptr, i8* %context) unnamed_addr #1 { define hidden void @main.funcGoroutine(ptr %fn.context, ptr %fn.funcptr, ptr %context) unnamed_addr #1 {
entry: entry:
%0 = call i8* @runtime.alloc(i32 12, i8* null, i8* undef) #8 %0 = call ptr @runtime.alloc(i32 12, ptr null, ptr undef) #8
%1 = bitcast i8* %0 to i32* store i32 5, ptr %0, align 4
store i32 5, i32* %1, align 4 %1 = getelementptr inbounds { i32, ptr, ptr }, ptr %0, i32 0, i32 1
%2 = getelementptr inbounds i8, i8* %0, i32 4 store ptr %fn.context, ptr %1, align 4
%3 = bitcast i8* %2 to i8** %2 = getelementptr inbounds { i32, ptr, ptr }, ptr %0, i32 0, i32 2
store i8* %fn.context, i8** %3, align 4 store ptr %fn.funcptr, ptr %2, align 4
%4 = getelementptr inbounds i8, i8* %0, i32 8 %stacksize = call i32 @"internal/task.getGoroutineStackSize"(i32 ptrtoint (ptr @main.funcGoroutine.gowrapper to i32), ptr undef) #8
%5 = bitcast i8* %4 to void ()** call void @"internal/task.start"(i32 ptrtoint (ptr @main.funcGoroutine.gowrapper to i32), ptr nonnull %0, i32 %stacksize, ptr undef) #8
store void ()* %fn.funcptr, void ()** %5, align 4
%stacksize = call i32 @"internal/task.getGoroutineStackSize"(i32 ptrtoint (void (i8*)* @main.funcGoroutine.gowrapper to i32), i8* undef) #8
call void @"internal/task.start"(i32 ptrtoint (void (i8*)* @main.funcGoroutine.gowrapper to i32), i8* nonnull %0, i32 %stacksize, i8* undef) #8
ret void ret void
} }
; Function Attrs: nounwind ; Function Attrs: nounwind
define linkonce_odr void @main.funcGoroutine.gowrapper(i8* %0) unnamed_addr #5 { define linkonce_odr void @main.funcGoroutine.gowrapper(ptr %0) unnamed_addr #5 {
entry: entry:
%1 = bitcast i8* %0 to i32* %1 = load i32, ptr %0, align 4
%2 = load i32, i32* %1, align 4 %2 = getelementptr inbounds { i32, ptr, ptr }, ptr %0, i32 0, i32 1
%3 = getelementptr inbounds i8, i8* %0, i32 4 %3 = load ptr, ptr %2, align 4
%4 = bitcast i8* %3 to i8** %4 = getelementptr inbounds { i32, ptr, ptr }, ptr %0, i32 0, i32 2
%5 = load i8*, i8** %4, align 4 %5 = load ptr, ptr %4, align 4
%6 = getelementptr inbounds i8, i8* %0, i32 8 call void %5(i32 %1, ptr %3) #8
%7 = bitcast i8* %6 to void (i32, i8*)**
%8 = load void (i32, i8*)*, void (i32, i8*)** %7, align 4
call void %8(i32 %2, i8* %5) #8
ret void ret void
} }
; Function Attrs: nounwind ; Function Attrs: nounwind
define hidden void @main.recoverBuiltinGoroutine(i8* %context) unnamed_addr #1 { define hidden void @main.recoverBuiltinGoroutine(ptr %context) unnamed_addr #1 {
entry: entry:
ret void ret void
} }
; Function Attrs: nounwind ; Function Attrs: nounwind
define hidden void @main.copyBuiltinGoroutine(i8* %dst.data, i32 %dst.len, i32 %dst.cap, i8* %src.data, i32 %src.len, i32 %src.cap, i8* %context) unnamed_addr #1 { 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 {
entry: entry:
%copy.n = call i32 @runtime.sliceCopy(i8* %dst.data, i8* %src.data, i32 %dst.len, i32 %src.len, i32 1, i8* undef) #8 %copy.n = call i32 @runtime.sliceCopy(ptr %dst.data, ptr %src.data, i32 %dst.len, i32 %src.len, i32 1, ptr undef) #8
ret void ret void
} }
declare i32 @runtime.sliceCopy(i8* nocapture writeonly, i8* nocapture readonly, i32, i32, i32, i8*) #0 declare i32 @runtime.sliceCopy(ptr nocapture writeonly, ptr nocapture readonly, i32, i32, i32, ptr) #0
; Function Attrs: nounwind ; Function Attrs: nounwind
define hidden void @main.closeBuiltinGoroutine(%runtime.channel* dereferenceable_or_null(32) %ch, i8* %context) unnamed_addr #1 { define hidden void @main.closeBuiltinGoroutine(ptr dereferenceable_or_null(32) %ch, ptr %context) unnamed_addr #1 {
entry: entry:
call void @runtime.chanClose(%runtime.channel* %ch, i8* undef) #8 call void @runtime.chanClose(ptr %ch, ptr undef) #8
ret void ret void
} }
declare void @runtime.chanClose(%runtime.channel* dereferenceable_or_null(32), i8*) #0 declare void @runtime.chanClose(ptr dereferenceable_or_null(32), ptr) #0
; Function Attrs: nounwind ; Function Attrs: nounwind
define hidden void @main.startInterfaceMethod(i32 %itf.typecode, i8* %itf.value, i8* %context) unnamed_addr #1 { define hidden void @main.startInterfaceMethod(i32 %itf.typecode, ptr %itf.value, ptr %context) unnamed_addr #1 {
entry: entry:
%0 = call i8* @runtime.alloc(i32 16, i8* null, i8* undef) #8 %0 = call ptr @runtime.alloc(i32 16, ptr null, ptr undef) #8
%1 = bitcast i8* %0 to i8** store ptr %itf.value, ptr %0, align 4
store i8* %itf.value, i8** %1, align 4 %1 = getelementptr inbounds { ptr, %runtime._string, i32 }, ptr %0, i32 0, i32 1
%2 = getelementptr inbounds i8, i8* %0, i32 4 store ptr @"main$string", ptr %1, align 4
%.repack = bitcast i8* %2 to i8** %.repack1 = getelementptr inbounds { ptr, %runtime._string, i32 }, ptr %0, i32 0, i32 1, i32 1
store i8* getelementptr inbounds ([4 x i8], [4 x i8]* @"main$string", i32 0, i32 0), i8** %.repack, align 4 store i32 4, ptr %.repack1, align 4
%.repack1 = getelementptr inbounds i8, i8* %0, i32 8 %2 = getelementptr inbounds { ptr, %runtime._string, i32 }, ptr %0, i32 0, i32 2
%3 = bitcast i8* %.repack1 to i32* store i32 %itf.typecode, ptr %2, align 4
store i32 4, i32* %3, align 4 %stacksize = call i32 @"internal/task.getGoroutineStackSize"(i32 ptrtoint (ptr @"interface:{Print:func:{basic:string}{}}.Print$invoke$gowrapper" to i32), ptr undef) #8
%4 = getelementptr inbounds i8, i8* %0, i32 12 call void @"internal/task.start"(i32 ptrtoint (ptr @"interface:{Print:func:{basic:string}{}}.Print$invoke$gowrapper" to i32), ptr nonnull %0, i32 %stacksize, ptr undef) #8
%5 = bitcast i8* %4 to i32*
store i32 %itf.typecode, i32* %5, align 4
%stacksize = call i32 @"internal/task.getGoroutineStackSize"(i32 ptrtoint (void (i8*)* @"interface:{Print:func:{basic:string}{}}.Print$invoke$gowrapper" to i32), i8* undef) #8
call void @"internal/task.start"(i32 ptrtoint (void (i8*)* @"interface:{Print:func:{basic:string}{}}.Print$invoke$gowrapper" to i32), i8* nonnull %0, i32 %stacksize, i8* undef) #8
ret void ret void
} }
declare void @"interface:{Print:func:{basic:string}{}}.Print$invoke"(i8*, i8*, i32, i32, i8*) #6 declare void @"interface:{Print:func:{basic:string}{}}.Print$invoke"(ptr, ptr, i32, i32, ptr) #6
; Function Attrs: nounwind ; Function Attrs: nounwind
define linkonce_odr void @"interface:{Print:func:{basic:string}{}}.Print$invoke$gowrapper"(i8* %0) unnamed_addr #7 { define linkonce_odr void @"interface:{Print:func:{basic:string}{}}.Print$invoke$gowrapper"(ptr %0) unnamed_addr #7 {
entry: entry:
%1 = bitcast i8* %0 to i8** %1 = load ptr, ptr %0, align 4
%2 = load i8*, i8** %1, align 4 %2 = getelementptr inbounds { ptr, ptr, i32, i32 }, ptr %0, i32 0, i32 1
%3 = getelementptr inbounds i8, i8* %0, i32 4 %3 = load ptr, ptr %2, align 4
%4 = bitcast i8* %3 to i8** %4 = getelementptr inbounds { ptr, ptr, i32, i32 }, ptr %0, i32 0, i32 2
%5 = load i8*, i8** %4, align 4 %5 = load i32, ptr %4, align 4
%6 = getelementptr inbounds i8, i8* %0, i32 8 %6 = getelementptr inbounds { ptr, ptr, i32, i32 }, ptr %0, i32 0, i32 3
%7 = bitcast i8* %6 to i32* %7 = load i32, ptr %6, align 4
%8 = load i32, i32* %7, align 4 call void @"interface:{Print:func:{basic:string}{}}.Print$invoke"(ptr %1, ptr %3, i32 %5, i32 %7, ptr undef) #8
%9 = getelementptr inbounds i8, i8* %0, i32 12
%10 = bitcast i8* %9 to i32*
%11 = load i32, i32* %10, align 4
call void @"interface:{Print:func:{basic:string}{}}.Print$invoke"(i8* %2, i8* %5, i32 %8, i32 %11, i8* undef) #8
ret void ret void
} }

204
compiler/testdata/goroutine-wasm-asyncify.ll предоставленный
Просмотреть файл

@ -3,210 +3,184 @@ source_filename = "goroutine.go"
target datalayout = "e-m:e-p:32:32-p10:8:8-p20:8:8-i64:64-n32:64-S128-ni:1:10:20" target datalayout = "e-m:e-p:32:32-p10:8:8-p20:8:8-i64:64-n32:64-S128-ni:1:10:20"
target triple = "wasm32-unknown-wasi" target triple = "wasm32-unknown-wasi"
%runtime.channel = type { i32, i32, i8, %runtime.channelBlockedList*, i32, i32, i32, i8* } %runtime._string = type { ptr, i32 }
%runtime.channelBlockedList = type { %runtime.channelBlockedList*, %"internal/task.Task"*, %runtime.chanSelectState*, { %runtime.channelBlockedList*, i32, i32 } }
%"internal/task.Task" = type { %"internal/task.Task"*, i8*, i64, %"internal/task.gcData", %"internal/task.state", i8* }
%"internal/task.gcData" = type { i8* }
%"internal/task.state" = type { i32, i8*, %"internal/task.stackState", i1 }
%"internal/task.stackState" = type { i32, i32 }
%runtime.chanSelectState = type { %runtime.channel*, i8* }
@"main$string" = internal unnamed_addr constant [4 x i8] c"test", align 1 @"main$string" = internal unnamed_addr constant [4 x i8] c"test", align 1
declare noalias nonnull i8* @runtime.alloc(i32, i8*, i8*) #0 declare noalias nonnull ptr @runtime.alloc(i32, ptr, ptr) #0
declare void @runtime.trackPointer(i8* nocapture readonly, i8*) #0 declare void @runtime.trackPointer(ptr nocapture readonly, ptr) #0
; Function Attrs: nounwind ; Function Attrs: nounwind
define hidden void @main.init(i8* %context) unnamed_addr #1 { define hidden void @main.init(ptr %context) unnamed_addr #1 {
entry: entry:
ret void ret void
} }
; Function Attrs: nounwind ; Function Attrs: nounwind
define hidden void @main.regularFunctionGoroutine(i8* %context) unnamed_addr #1 { define hidden void @main.regularFunctionGoroutine(ptr %context) unnamed_addr #1 {
entry: entry:
call void @"internal/task.start"(i32 ptrtoint (void (i8*)* @"main.regularFunction$gowrapper" to i32), i8* nonnull inttoptr (i32 5 to i8*), i32 16384, i8* undef) #8 call void @"internal/task.start"(i32 ptrtoint (ptr @"main.regularFunction$gowrapper" to i32), ptr nonnull inttoptr (i32 5 to ptr), i32 16384, ptr undef) #8
ret void ret void
} }
declare void @main.regularFunction(i32, i8*) #0 declare void @main.regularFunction(i32, ptr) #0
declare void @runtime.deadlock(i8*) #0 declare void @runtime.deadlock(ptr) #0
; Function Attrs: nounwind ; Function Attrs: nounwind
define linkonce_odr void @"main.regularFunction$gowrapper"(i8* %0) unnamed_addr #2 { define linkonce_odr void @"main.regularFunction$gowrapper"(ptr %0) unnamed_addr #2 {
entry: entry:
%unpack.int = ptrtoint i8* %0 to i32 %unpack.int = ptrtoint ptr %0 to i32
call void @main.regularFunction(i32 %unpack.int, i8* undef) #8 call void @main.regularFunction(i32 %unpack.int, ptr undef) #8
call void @runtime.deadlock(i8* undef) #8 call void @runtime.deadlock(ptr undef) #8
unreachable unreachable
} }
declare void @"internal/task.start"(i32, i8*, i32, i8*) #0 declare void @"internal/task.start"(i32, ptr, i32, ptr) #0
; Function Attrs: nounwind ; Function Attrs: nounwind
define hidden void @main.inlineFunctionGoroutine(i8* %context) unnamed_addr #1 { define hidden void @main.inlineFunctionGoroutine(ptr %context) unnamed_addr #1 {
entry: entry:
call void @"internal/task.start"(i32 ptrtoint (void (i8*)* @"main.inlineFunctionGoroutine$1$gowrapper" to i32), i8* nonnull inttoptr (i32 5 to i8*), i32 16384, i8* undef) #8 call void @"internal/task.start"(i32 ptrtoint (ptr @"main.inlineFunctionGoroutine$1$gowrapper" to i32), ptr nonnull inttoptr (i32 5 to ptr), i32 16384, ptr undef) #8
ret void ret void
} }
; Function Attrs: nounwind ; Function Attrs: nounwind
define internal void @"main.inlineFunctionGoroutine$1"(i32 %x, i8* %context) unnamed_addr #1 { define internal void @"main.inlineFunctionGoroutine$1"(i32 %x, ptr %context) unnamed_addr #1 {
entry: entry:
ret void ret void
} }
; Function Attrs: nounwind ; Function Attrs: nounwind
define linkonce_odr void @"main.inlineFunctionGoroutine$1$gowrapper"(i8* %0) unnamed_addr #3 { define linkonce_odr void @"main.inlineFunctionGoroutine$1$gowrapper"(ptr %0) unnamed_addr #3 {
entry: entry:
%unpack.int = ptrtoint i8* %0 to i32 %unpack.int = ptrtoint ptr %0 to i32
call void @"main.inlineFunctionGoroutine$1"(i32 %unpack.int, i8* undef) call void @"main.inlineFunctionGoroutine$1"(i32 %unpack.int, ptr undef)
call void @runtime.deadlock(i8* undef) #8 call void @runtime.deadlock(ptr undef) #8
unreachable unreachable
} }
; Function Attrs: nounwind ; Function Attrs: nounwind
define hidden void @main.closureFunctionGoroutine(i8* %context) unnamed_addr #1 { define hidden void @main.closureFunctionGoroutine(ptr %context) unnamed_addr #1 {
entry: entry:
%n = call i8* @runtime.alloc(i32 4, i8* nonnull inttoptr (i32 3 to i8*), i8* undef) #8 %n = call ptr @runtime.alloc(i32 4, ptr nonnull inttoptr (i32 3 to ptr), ptr undef) #8
%0 = bitcast i8* %n to i32* call void @runtime.trackPointer(ptr nonnull %n, ptr undef) #8
call void @runtime.trackPointer(i8* nonnull %n, i8* undef) #8 store i32 3, ptr %n, align 4
store i32 3, i32* %0, align 4 call void @runtime.trackPointer(ptr nonnull %n, ptr undef) #8
call void @runtime.trackPointer(i8* nonnull %n, i8* undef) #8 call void @runtime.trackPointer(ptr nonnull @"main.closureFunctionGoroutine$1", ptr undef) #8
call void @runtime.trackPointer(i8* bitcast (void (i32, i8*)* @"main.closureFunctionGoroutine$1" to i8*), i8* undef) #8 %0 = call ptr @runtime.alloc(i32 8, ptr null, ptr undef) #8
%1 = call i8* @runtime.alloc(i32 8, i8* null, i8* undef) #8 call void @runtime.trackPointer(ptr nonnull %0, ptr undef) #8
call void @runtime.trackPointer(i8* nonnull %1, i8* undef) #8 store i32 5, ptr %0, align 4
%2 = bitcast i8* %1 to i32* %1 = getelementptr inbounds { i32, ptr }, ptr %0, i32 0, i32 1
store i32 5, i32* %2, align 4 store ptr %n, ptr %1, align 4
%3 = getelementptr inbounds i8, i8* %1, i32 4 call void @"internal/task.start"(i32 ptrtoint (ptr @"main.closureFunctionGoroutine$1$gowrapper" to i32), ptr nonnull %0, i32 16384, ptr undef) #8
%4 = bitcast i8* %3 to i8** %2 = load i32, ptr %n, align 4
store i8* %n, i8** %4, align 4 call void @runtime.printint32(i32 %2, ptr undef) #8
call void @"internal/task.start"(i32 ptrtoint (void (i8*)* @"main.closureFunctionGoroutine$1$gowrapper" to i32), i8* nonnull %1, i32 16384, i8* undef) #8
%5 = load i32, i32* %0, align 4
call void @runtime.printint32(i32 %5, i8* undef) #8
ret void ret void
} }
; Function Attrs: nounwind ; Function Attrs: nounwind
define internal void @"main.closureFunctionGoroutine$1"(i32 %x, i8* %context) unnamed_addr #1 { define internal void @"main.closureFunctionGoroutine$1"(i32 %x, ptr %context) unnamed_addr #1 {
entry: entry:
%unpack.ptr = bitcast i8* %context to i32* store i32 7, ptr %context, align 4
store i32 7, i32* %unpack.ptr, align 4
ret void ret void
} }
; Function Attrs: nounwind ; Function Attrs: nounwind
define linkonce_odr void @"main.closureFunctionGoroutine$1$gowrapper"(i8* %0) unnamed_addr #4 { define linkonce_odr void @"main.closureFunctionGoroutine$1$gowrapper"(ptr %0) unnamed_addr #4 {
entry: entry:
%1 = bitcast i8* %0 to i32* %1 = load i32, ptr %0, align 4
%2 = load i32, i32* %1, align 4 %2 = getelementptr inbounds { i32, ptr }, ptr %0, i32 0, i32 1
%3 = getelementptr inbounds i8, i8* %0, i32 4 %3 = load ptr, ptr %2, align 4
%4 = bitcast i8* %3 to i8** call void @"main.closureFunctionGoroutine$1"(i32 %1, ptr %3)
%5 = load i8*, i8** %4, align 4 call void @runtime.deadlock(ptr undef) #8
call void @"main.closureFunctionGoroutine$1"(i32 %2, i8* %5)
call void @runtime.deadlock(i8* undef) #8
unreachable unreachable
} }
declare void @runtime.printint32(i32, i8*) #0 declare void @runtime.printint32(i32, ptr) #0
; Function Attrs: nounwind ; Function Attrs: nounwind
define hidden void @main.funcGoroutine(i8* %fn.context, void ()* %fn.funcptr, i8* %context) unnamed_addr #1 { define hidden void @main.funcGoroutine(ptr %fn.context, ptr %fn.funcptr, ptr %context) unnamed_addr #1 {
entry: entry:
%0 = call i8* @runtime.alloc(i32 12, i8* null, i8* undef) #8 %0 = call ptr @runtime.alloc(i32 12, ptr null, ptr undef) #8
call void @runtime.trackPointer(i8* nonnull %0, i8* undef) #8 call void @runtime.trackPointer(ptr nonnull %0, ptr undef) #8
%1 = bitcast i8* %0 to i32* store i32 5, ptr %0, align 4
store i32 5, i32* %1, align 4 %1 = getelementptr inbounds { i32, ptr, ptr }, ptr %0, i32 0, i32 1
%2 = getelementptr inbounds i8, i8* %0, i32 4 store ptr %fn.context, ptr %1, align 4
%3 = bitcast i8* %2 to i8** %2 = getelementptr inbounds { i32, ptr, ptr }, ptr %0, i32 0, i32 2
store i8* %fn.context, i8** %3, align 4 store ptr %fn.funcptr, ptr %2, align 4
%4 = getelementptr inbounds i8, i8* %0, i32 8 call void @"internal/task.start"(i32 ptrtoint (ptr @main.funcGoroutine.gowrapper to i32), ptr nonnull %0, i32 16384, ptr undef) #8
%5 = bitcast i8* %4 to void ()**
store void ()* %fn.funcptr, void ()** %5, align 4
call void @"internal/task.start"(i32 ptrtoint (void (i8*)* @main.funcGoroutine.gowrapper to i32), i8* nonnull %0, i32 16384, i8* undef) #8
ret void ret void
} }
; Function Attrs: nounwind ; Function Attrs: nounwind
define linkonce_odr void @main.funcGoroutine.gowrapper(i8* %0) unnamed_addr #5 { define linkonce_odr void @main.funcGoroutine.gowrapper(ptr %0) unnamed_addr #5 {
entry: entry:
%1 = bitcast i8* %0 to i32* %1 = load i32, ptr %0, align 4
%2 = load i32, i32* %1, align 4 %2 = getelementptr inbounds { i32, ptr, ptr }, ptr %0, i32 0, i32 1
%3 = getelementptr inbounds i8, i8* %0, i32 4 %3 = load ptr, ptr %2, align 4
%4 = bitcast i8* %3 to i8** %4 = getelementptr inbounds { i32, ptr, ptr }, ptr %0, i32 0, i32 2
%5 = load i8*, i8** %4, align 4 %5 = load ptr, ptr %4, align 4
%6 = getelementptr inbounds i8, i8* %0, i32 8 call void %5(i32 %1, ptr %3) #8
%7 = bitcast i8* %6 to void (i32, i8*)** call void @runtime.deadlock(ptr undef) #8
%8 = load void (i32, i8*)*, void (i32, i8*)** %7, align 4
call void %8(i32 %2, i8* %5) #8
call void @runtime.deadlock(i8* undef) #8
unreachable unreachable
} }
; Function Attrs: nounwind ; Function Attrs: nounwind
define hidden void @main.recoverBuiltinGoroutine(i8* %context) unnamed_addr #1 { define hidden void @main.recoverBuiltinGoroutine(ptr %context) unnamed_addr #1 {
entry: entry:
ret void ret void
} }
; Function Attrs: nounwind ; Function Attrs: nounwind
define hidden void @main.copyBuiltinGoroutine(i8* %dst.data, i32 %dst.len, i32 %dst.cap, i8* %src.data, i32 %src.len, i32 %src.cap, i8* %context) unnamed_addr #1 { 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 {
entry: entry:
%copy.n = call i32 @runtime.sliceCopy(i8* %dst.data, i8* %src.data, i32 %dst.len, i32 %src.len, i32 1, i8* undef) #8 %copy.n = call i32 @runtime.sliceCopy(ptr %dst.data, ptr %src.data, i32 %dst.len, i32 %src.len, i32 1, ptr undef) #8
ret void ret void
} }
declare i32 @runtime.sliceCopy(i8* nocapture writeonly, i8* nocapture readonly, i32, i32, i32, i8*) #0 declare i32 @runtime.sliceCopy(ptr nocapture writeonly, ptr nocapture readonly, i32, i32, i32, ptr) #0
; Function Attrs: nounwind ; Function Attrs: nounwind
define hidden void @main.closeBuiltinGoroutine(%runtime.channel* dereferenceable_or_null(32) %ch, i8* %context) unnamed_addr #1 { define hidden void @main.closeBuiltinGoroutine(ptr dereferenceable_or_null(32) %ch, ptr %context) unnamed_addr #1 {
entry: entry:
call void @runtime.chanClose(%runtime.channel* %ch, i8* undef) #8 call void @runtime.chanClose(ptr %ch, ptr undef) #8
ret void ret void
} }
declare void @runtime.chanClose(%runtime.channel* dereferenceable_or_null(32), i8*) #0 declare void @runtime.chanClose(ptr dereferenceable_or_null(32), ptr) #0
; Function Attrs: nounwind ; Function Attrs: nounwind
define hidden void @main.startInterfaceMethod(i32 %itf.typecode, i8* %itf.value, i8* %context) unnamed_addr #1 { define hidden void @main.startInterfaceMethod(i32 %itf.typecode, ptr %itf.value, ptr %context) unnamed_addr #1 {
entry: entry:
%0 = call i8* @runtime.alloc(i32 16, i8* null, i8* undef) #8 %0 = call ptr @runtime.alloc(i32 16, ptr null, ptr undef) #8
call void @runtime.trackPointer(i8* nonnull %0, i8* undef) #8 call void @runtime.trackPointer(ptr nonnull %0, ptr undef) #8
%1 = bitcast i8* %0 to i8** store ptr %itf.value, ptr %0, align 4
store i8* %itf.value, i8** %1, align 4 %1 = getelementptr inbounds { ptr, %runtime._string, i32 }, ptr %0, i32 0, i32 1
%2 = getelementptr inbounds i8, i8* %0, i32 4 store ptr @"main$string", ptr %1, align 4
%.repack = bitcast i8* %2 to i8** %.repack1 = getelementptr inbounds { ptr, %runtime._string, i32 }, ptr %0, i32 0, i32 1, i32 1
store i8* getelementptr inbounds ([4 x i8], [4 x i8]* @"main$string", i32 0, i32 0), i8** %.repack, align 4 store i32 4, ptr %.repack1, align 4
%.repack1 = getelementptr inbounds i8, i8* %0, i32 8 %2 = getelementptr inbounds { ptr, %runtime._string, i32 }, ptr %0, i32 0, i32 2
%3 = bitcast i8* %.repack1 to i32* store i32 %itf.typecode, ptr %2, align 4
store i32 4, i32* %3, align 4 call void @"internal/task.start"(i32 ptrtoint (ptr @"interface:{Print:func:{basic:string}{}}.Print$invoke$gowrapper" to i32), ptr nonnull %0, i32 16384, ptr undef) #8
%4 = getelementptr inbounds i8, i8* %0, i32 12
%5 = bitcast i8* %4 to i32*
store i32 %itf.typecode, i32* %5, align 4
call void @"internal/task.start"(i32 ptrtoint (void (i8*)* @"interface:{Print:func:{basic:string}{}}.Print$invoke$gowrapper" to i32), i8* nonnull %0, i32 16384, i8* undef) #8
ret void ret void
} }
declare void @"interface:{Print:func:{basic:string}{}}.Print$invoke"(i8*, i8*, i32, i32, i8*) #6 declare void @"interface:{Print:func:{basic:string}{}}.Print$invoke"(ptr, ptr, i32, i32, ptr) #6
; Function Attrs: nounwind ; Function Attrs: nounwind
define linkonce_odr void @"interface:{Print:func:{basic:string}{}}.Print$invoke$gowrapper"(i8* %0) unnamed_addr #7 { define linkonce_odr void @"interface:{Print:func:{basic:string}{}}.Print$invoke$gowrapper"(ptr %0) unnamed_addr #7 {
entry: entry:
%1 = bitcast i8* %0 to i8** %1 = load ptr, ptr %0, align 4
%2 = load i8*, i8** %1, align 4 %2 = getelementptr inbounds { ptr, ptr, i32, i32 }, ptr %0, i32 0, i32 1
%3 = getelementptr inbounds i8, i8* %0, i32 4 %3 = load ptr, ptr %2, align 4
%4 = bitcast i8* %3 to i8** %4 = getelementptr inbounds { ptr, ptr, i32, i32 }, ptr %0, i32 0, i32 2
%5 = load i8*, i8** %4, align 4 %5 = load i32, ptr %4, align 4
%6 = getelementptr inbounds i8, i8* %0, i32 8 %6 = getelementptr inbounds { ptr, ptr, i32, i32 }, ptr %0, i32 0, i32 3
%7 = bitcast i8* %6 to i32* %7 = load i32, ptr %6, align 4
%8 = load i32, i32* %7, align 4 call void @"interface:{Print:func:{basic:string}{}}.Print$invoke"(ptr %1, ptr %3, i32 %5, i32 %7, ptr undef) #8
%9 = getelementptr inbounds i8, i8* %0, i32 12 call void @runtime.deadlock(ptr undef) #8
%10 = bitcast i8* %9 to i32*
%11 = load i32, i32* %10, align 4
call void @"interface:{Print:func:{basic:string}{}}.Print$invoke"(i8* %2, i8* %5, i32 %8, i32 %11, i8* undef) #8
call void @runtime.deadlock(i8* undef) #8
unreachable unreachable
} }

81
compiler/testdata/interface.ll предоставленный
Просмотреть файл

@ -3,71 +3,70 @@ source_filename = "interface.go"
target datalayout = "e-m:e-p:32:32-p10:8:8-p20:8:8-i64:64-n32:64-S128-ni:1:10:20" target datalayout = "e-m:e-p:32:32-p10:8:8-p20:8:8-i64:64-n32:64-S128-ni:1:10:20"
target triple = "wasm32-unknown-wasi" target triple = "wasm32-unknown-wasi"
%runtime.typecodeID = type { %runtime.typecodeID*, i32, %runtime.interfaceMethodInfo*, %runtime.typecodeID*, i32 } %runtime.typecodeID = type { ptr, i32, ptr, ptr, i32 }
%runtime.interfaceMethodInfo = type { i8*, i32 } %runtime._interface = type { i32, ptr }
%runtime._interface = type { i32, i8* } %runtime._string = type { ptr, i32 }
%runtime._string = type { i8*, i32 }
@"reflect/types.type:basic:int" = linkonce_odr constant %runtime.typecodeID { %runtime.typecodeID* null, i32 0, %runtime.interfaceMethodInfo* null, %runtime.typecodeID* @"reflect/types.type:pointer:basic:int", i32 0 } @"reflect/types.type:basic:int" = linkonce_odr constant %runtime.typecodeID { ptr null, i32 0, ptr null, ptr @"reflect/types.type:pointer:basic:int", i32 0 }
@"reflect/types.type:pointer:basic:int" = linkonce_odr constant %runtime.typecodeID { %runtime.typecodeID* @"reflect/types.type:basic:int", i32 0, %runtime.interfaceMethodInfo* null, %runtime.typecodeID* null, i32 0 } @"reflect/types.type:pointer:basic:int" = linkonce_odr constant %runtime.typecodeID { ptr @"reflect/types.type:basic:int", i32 0, ptr null, ptr null, i32 0 }
@"reflect/types.type:pointer:named:error" = linkonce_odr constant %runtime.typecodeID { %runtime.typecodeID* @"reflect/types.type:named:error", i32 0, %runtime.interfaceMethodInfo* null, %runtime.typecodeID* null, i32 0 } @"reflect/types.type:pointer:named:error" = linkonce_odr constant %runtime.typecodeID { ptr @"reflect/types.type:named:error", i32 0, ptr null, ptr null, i32 0 }
@"reflect/types.type:named:error" = linkonce_odr constant %runtime.typecodeID { %runtime.typecodeID* @"reflect/types.type:interface:{Error:func:{}{basic:string}}", i32 0, %runtime.interfaceMethodInfo* null, %runtime.typecodeID* @"reflect/types.type:pointer:named:error", i32 ptrtoint (i1 (i32)* @"interface:{Error:func:{}{basic:string}}.$typeassert" to i32) } @"reflect/types.type:named:error" = linkonce_odr constant %runtime.typecodeID { ptr @"reflect/types.type:interface:{Error:func:{}{basic:string}}", i32 0, ptr null, ptr @"reflect/types.type:pointer:named:error", i32 ptrtoint (ptr @"interface:{Error:func:{}{basic:string}}.$typeassert" to i32) }
@"reflect/types.type:interface:{Error:func:{}{basic:string}}" = linkonce_odr constant %runtime.typecodeID { %runtime.typecodeID* bitcast ([1 x i8*]* @"reflect/types.interface:interface{Error() string}$interface" to %runtime.typecodeID*), i32 0, %runtime.interfaceMethodInfo* null, %runtime.typecodeID* @"reflect/types.type:pointer:interface:{Error:func:{}{basic:string}}", i32 ptrtoint (i1 (i32)* @"interface:{Error:func:{}{basic:string}}.$typeassert" to i32) } @"reflect/types.type:interface:{Error:func:{}{basic:string}}" = linkonce_odr constant %runtime.typecodeID { ptr @"reflect/types.interface:interface{Error() string}$interface", i32 0, ptr null, ptr @"reflect/types.type:pointer:interface:{Error:func:{}{basic:string}}", i32 ptrtoint (ptr @"interface:{Error:func:{}{basic:string}}.$typeassert" to i32) }
@"reflect/methods.Error() string" = linkonce_odr constant i8 0, align 1 @"reflect/methods.Error() string" = linkonce_odr constant i8 0, align 1
@"reflect/types.interface:interface{Error() string}$interface" = linkonce_odr constant [1 x i8*] [i8* @"reflect/methods.Error() string"] @"reflect/types.interface:interface{Error() string}$interface" = linkonce_odr constant [1 x ptr] [ptr @"reflect/methods.Error() string"]
@"reflect/types.type:pointer:interface:{Error:func:{}{basic:string}}" = linkonce_odr constant %runtime.typecodeID { %runtime.typecodeID* @"reflect/types.type:interface:{Error:func:{}{basic:string}}", i32 0, %runtime.interfaceMethodInfo* null, %runtime.typecodeID* null, i32 0 } @"reflect/types.type:pointer:interface:{Error:func:{}{basic:string}}" = linkonce_odr constant %runtime.typecodeID { ptr @"reflect/types.type:interface:{Error:func:{}{basic:string}}", i32 0, ptr null, ptr null, i32 0 }
@"reflect/types.type:pointer:interface:{String:func:{}{basic:string}}" = linkonce_odr constant %runtime.typecodeID { %runtime.typecodeID* @"reflect/types.type:interface:{String:func:{}{basic:string}}", i32 0, %runtime.interfaceMethodInfo* null, %runtime.typecodeID* null, i32 0 } @"reflect/types.type:pointer:interface:{String:func:{}{basic:string}}" = linkonce_odr constant %runtime.typecodeID { ptr @"reflect/types.type:interface:{String:func:{}{basic:string}}", i32 0, ptr null, ptr null, i32 0 }
@"reflect/types.type:interface:{String:func:{}{basic:string}}" = linkonce_odr constant %runtime.typecodeID { %runtime.typecodeID* bitcast ([1 x i8*]* @"reflect/types.interface:interface{String() string}$interface" to %runtime.typecodeID*), i32 0, %runtime.interfaceMethodInfo* null, %runtime.typecodeID* @"reflect/types.type:pointer:interface:{String:func:{}{basic:string}}", i32 ptrtoint (i1 (i32)* @"interface:{String:func:{}{basic:string}}.$typeassert" to i32) } @"reflect/types.type:interface:{String:func:{}{basic:string}}" = linkonce_odr constant %runtime.typecodeID { ptr @"reflect/types.interface:interface{String() string}$interface", i32 0, ptr null, ptr @"reflect/types.type:pointer:interface:{String:func:{}{basic:string}}", i32 ptrtoint (ptr @"interface:{String:func:{}{basic:string}}.$typeassert" to i32) }
@"reflect/methods.String() string" = linkonce_odr constant i8 0, align 1 @"reflect/methods.String() string" = linkonce_odr constant i8 0, align 1
@"reflect/types.interface:interface{String() string}$interface" = linkonce_odr constant [1 x i8*] [i8* @"reflect/methods.String() string"] @"reflect/types.interface:interface{String() string}$interface" = linkonce_odr constant [1 x ptr] [ptr @"reflect/methods.String() string"]
@"reflect/types.typeid:basic:int" = external constant i8 @"reflect/types.typeid:basic:int" = external constant i8
declare noalias nonnull i8* @runtime.alloc(i32, i8*, i8*) #0 declare noalias nonnull ptr @runtime.alloc(i32, ptr, ptr) #0
declare void @runtime.trackPointer(i8* nocapture readonly, i8*) #0 declare void @runtime.trackPointer(ptr nocapture readonly, ptr) #0
; Function Attrs: nounwind ; Function Attrs: nounwind
define hidden void @main.init(i8* %context) unnamed_addr #1 { define hidden void @main.init(ptr %context) unnamed_addr #1 {
entry: entry:
ret void ret void
} }
; Function Attrs: nounwind ; Function Attrs: nounwind
define hidden %runtime._interface @main.simpleType(i8* %context) unnamed_addr #1 { define hidden %runtime._interface @main.simpleType(ptr %context) unnamed_addr #1 {
entry: entry:
call void @runtime.trackPointer(i8* null, i8* undef) #6 call void @runtime.trackPointer(ptr null, ptr undef) #6
ret %runtime._interface { i32 ptrtoint (%runtime.typecodeID* @"reflect/types.type:basic:int" to i32), i8* null } ret %runtime._interface { i32 ptrtoint (ptr @"reflect/types.type:basic:int" to i32), ptr null }
} }
; Function Attrs: nounwind ; Function Attrs: nounwind
define hidden %runtime._interface @main.pointerType(i8* %context) unnamed_addr #1 { define hidden %runtime._interface @main.pointerType(ptr %context) unnamed_addr #1 {
entry: entry:
call void @runtime.trackPointer(i8* null, i8* undef) #6 call void @runtime.trackPointer(ptr null, ptr undef) #6
ret %runtime._interface { i32 ptrtoint (%runtime.typecodeID* @"reflect/types.type:pointer:basic:int" to i32), i8* null } ret %runtime._interface { i32 ptrtoint (ptr @"reflect/types.type:pointer:basic:int" to i32), ptr null }
} }
; Function Attrs: nounwind ; Function Attrs: nounwind
define hidden %runtime._interface @main.interfaceType(i8* %context) unnamed_addr #1 { define hidden %runtime._interface @main.interfaceType(ptr %context) unnamed_addr #1 {
entry: entry:
call void @runtime.trackPointer(i8* null, i8* undef) #6 call void @runtime.trackPointer(ptr null, ptr undef) #6
ret %runtime._interface { i32 ptrtoint (%runtime.typecodeID* @"reflect/types.type:pointer:named:error" to i32), i8* null } ret %runtime._interface { i32 ptrtoint (ptr @"reflect/types.type:pointer:named:error" to i32), ptr null }
} }
declare i1 @"interface:{Error:func:{}{basic:string}}.$typeassert"(i32) #2 declare i1 @"interface:{Error:func:{}{basic:string}}.$typeassert"(i32) #2
; Function Attrs: nounwind ; Function Attrs: nounwind
define hidden %runtime._interface @main.anonymousInterfaceType(i8* %context) unnamed_addr #1 { define hidden %runtime._interface @main.anonymousInterfaceType(ptr %context) unnamed_addr #1 {
entry: entry:
call void @runtime.trackPointer(i8* null, i8* undef) #6 call void @runtime.trackPointer(ptr null, ptr undef) #6
ret %runtime._interface { i32 ptrtoint (%runtime.typecodeID* @"reflect/types.type:pointer:interface:{String:func:{}{basic:string}}" to i32), i8* null } ret %runtime._interface { i32 ptrtoint (ptr @"reflect/types.type:pointer:interface:{String:func:{}{basic:string}}" to i32), ptr null }
} }
declare i1 @"interface:{String:func:{}{basic:string}}.$typeassert"(i32) #3 declare i1 @"interface:{String:func:{}{basic:string}}.$typeassert"(i32) #3
; Function Attrs: nounwind ; Function Attrs: nounwind
define hidden i1 @main.isInt(i32 %itf.typecode, i8* %itf.value, i8* %context) unnamed_addr #1 { define hidden i1 @main.isInt(i32 %itf.typecode, ptr %itf.value, ptr %context) unnamed_addr #1 {
entry: entry:
%typecode = call i1 @runtime.typeAssert(i32 %itf.typecode, i8* nonnull @"reflect/types.typeid:basic:int", i8* undef) #6 %typecode = call i1 @runtime.typeAssert(i32 %itf.typecode, ptr nonnull @"reflect/types.typeid:basic:int", ptr undef) #6
br i1 %typecode, label %typeassert.ok, label %typeassert.next br i1 %typecode, label %typeassert.ok, label %typeassert.next
typeassert.next: ; preds = %typeassert.ok, %entry typeassert.next: ; preds = %typeassert.ok, %entry
@ -77,10 +76,10 @@ typeassert.ok: ; preds = %entry
br label %typeassert.next br label %typeassert.next
} }
declare i1 @runtime.typeAssert(i32, i8* dereferenceable_or_null(1), i8*) #0 declare i1 @runtime.typeAssert(i32, ptr dereferenceable_or_null(1), ptr) #0
; Function Attrs: nounwind ; Function Attrs: nounwind
define hidden i1 @main.isError(i32 %itf.typecode, i8* %itf.value, i8* %context) unnamed_addr #1 { define hidden i1 @main.isError(i32 %itf.typecode, ptr %itf.value, ptr %context) unnamed_addr #1 {
entry: entry:
%0 = call i1 @"interface:{Error:func:{}{basic:string}}.$typeassert"(i32 %itf.typecode) #6 %0 = call i1 @"interface:{Error:func:{}{basic:string}}.$typeassert"(i32 %itf.typecode) #6
br i1 %0, label %typeassert.ok, label %typeassert.next br i1 %0, label %typeassert.ok, label %typeassert.next
@ -93,7 +92,7 @@ typeassert.ok: ; preds = %entry
} }
; Function Attrs: nounwind ; Function Attrs: nounwind
define hidden i1 @main.isStringer(i32 %itf.typecode, i8* %itf.value, i8* %context) unnamed_addr #1 { define hidden i1 @main.isStringer(i32 %itf.typecode, ptr %itf.value, ptr %context) unnamed_addr #1 {
entry: entry:
%0 = call i1 @"interface:{String:func:{}{basic:string}}.$typeassert"(i32 %itf.typecode) #6 %0 = call i1 @"interface:{String:func:{}{basic:string}}.$typeassert"(i32 %itf.typecode) #6
br i1 %0, label %typeassert.ok, label %typeassert.next br i1 %0, label %typeassert.ok, label %typeassert.next
@ -106,24 +105,24 @@ typeassert.ok: ; preds = %entry
} }
; Function Attrs: nounwind ; Function Attrs: nounwind
define hidden i8 @main.callFooMethod(i32 %itf.typecode, i8* %itf.value, i8* %context) unnamed_addr #1 { define hidden i8 @main.callFooMethod(i32 %itf.typecode, ptr %itf.value, ptr %context) unnamed_addr #1 {
entry: entry:
%0 = call i8 @"interface:{String:func:{}{basic:string},main.foo:func:{basic:int}{basic:uint8}}.foo$invoke"(i8* %itf.value, i32 3, i32 %itf.typecode, i8* undef) #6 %0 = call i8 @"interface:{String:func:{}{basic:string},main.foo:func:{basic:int}{basic:uint8}}.foo$invoke"(ptr %itf.value, i32 3, i32 %itf.typecode, ptr undef) #6
ret i8 %0 ret i8 %0
} }
declare i8 @"interface:{String:func:{}{basic:string},main.foo:func:{basic:int}{basic:uint8}}.foo$invoke"(i8*, i32, i32, i8*) #4 declare i8 @"interface:{String:func:{}{basic:string},main.foo:func:{basic:int}{basic:uint8}}.foo$invoke"(ptr, i32, i32, ptr) #4
; Function Attrs: nounwind ; Function Attrs: nounwind
define hidden %runtime._string @main.callErrorMethod(i32 %itf.typecode, i8* %itf.value, i8* %context) unnamed_addr #1 { define hidden %runtime._string @main.callErrorMethod(i32 %itf.typecode, ptr %itf.value, ptr %context) unnamed_addr #1 {
entry: entry:
%0 = call %runtime._string @"interface:{Error:func:{}{basic:string}}.Error$invoke"(i8* %itf.value, i32 %itf.typecode, i8* undef) #6 %0 = call %runtime._string @"interface:{Error:func:{}{basic:string}}.Error$invoke"(ptr %itf.value, i32 %itf.typecode, ptr undef) #6
%1 = extractvalue %runtime._string %0, 0 %1 = extractvalue %runtime._string %0, 0
call void @runtime.trackPointer(i8* %1, i8* undef) #6 call void @runtime.trackPointer(ptr %1, ptr undef) #6
ret %runtime._string %0 ret %runtime._string %0
} }
declare %runtime._string @"interface:{Error:func:{}{basic:string}}.Error$invoke"(i8*, i32, i8*) #5 declare %runtime._string @"interface:{Error:func:{}{basic:string}}.Error$invoke"(ptr, i32, ptr) #5
attributes #0 = { "target-features"="+bulk-memory,+nontrapping-fptoint,+sign-ext" } attributes #0 = { "target-features"="+bulk-memory,+nontrapping-fptoint,+sign-ext" }
attributes #1 = { nounwind "target-features"="+bulk-memory,+nontrapping-fptoint,+sign-ext" } attributes #1 = { nounwind "target-features"="+bulk-memory,+nontrapping-fptoint,+sign-ext" }

68
compiler/testdata/pointer.ll предоставленный
Просмотреть файл

@ -3,76 +3,72 @@ source_filename = "pointer.go"
target datalayout = "e-m:e-p:32:32-p10:8:8-p20:8:8-i64:64-n32:64-S128-ni:1:10:20" target datalayout = "e-m:e-p:32:32-p10:8:8-p20:8:8-i64:64-n32:64-S128-ni:1:10:20"
target triple = "wasm32-unknown-wasi" target triple = "wasm32-unknown-wasi"
declare noalias nonnull i8* @runtime.alloc(i32, i8*, i8*) #0 declare noalias nonnull ptr @runtime.alloc(i32, ptr, ptr) #0
declare void @runtime.trackPointer(i8* nocapture readonly, i8*) #0 declare void @runtime.trackPointer(ptr nocapture readonly, ptr) #0
; Function Attrs: nounwind ; Function Attrs: nounwind
define hidden void @main.init(i8* %context) unnamed_addr #1 { define hidden void @main.init(ptr %context) unnamed_addr #1 {
entry: entry:
ret void ret void
} }
; Function Attrs: nounwind ; Function Attrs: nounwind
define hidden [0 x i32] @main.pointerDerefZero([0 x i32]* %x, i8* %context) unnamed_addr #1 { define hidden [0 x i32] @main.pointerDerefZero(ptr %x, ptr %context) unnamed_addr #1 {
entry: entry:
ret [0 x i32] zeroinitializer ret [0 x i32] zeroinitializer
} }
; Function Attrs: nounwind ; Function Attrs: nounwind
define hidden i32* @main.pointerCastFromUnsafe(i8* %x, i8* %context) unnamed_addr #1 { define hidden ptr @main.pointerCastFromUnsafe(ptr %x, ptr %context) unnamed_addr #1 {
entry: entry:
%0 = bitcast i8* %x to i32* call void @runtime.trackPointer(ptr %x, ptr undef) #2
call void @runtime.trackPointer(i8* %x, i8* undef) #2 ret ptr %x
ret i32* %0
} }
; Function Attrs: nounwind ; Function Attrs: nounwind
define hidden i8* @main.pointerCastToUnsafe(i32* dereferenceable_or_null(4) %x, i8* %context) unnamed_addr #1 { define hidden ptr @main.pointerCastToUnsafe(ptr dereferenceable_or_null(4) %x, ptr %context) unnamed_addr #1 {
entry: entry:
%0 = bitcast i32* %x to i8* call void @runtime.trackPointer(ptr %x, ptr undef) #2
call void @runtime.trackPointer(i8* %0, i8* undef) #2 ret ptr %x
ret i8* %0
} }
; Function Attrs: nounwind ; Function Attrs: nounwind
define hidden i8* @main.pointerCastToUnsafeNoop(i8* dereferenceable_or_null(1) %x, i8* %context) unnamed_addr #1 { define hidden ptr @main.pointerCastToUnsafeNoop(ptr dereferenceable_or_null(1) %x, ptr %context) unnamed_addr #1 {
entry: entry:
call void @runtime.trackPointer(i8* %x, i8* undef) #2 call void @runtime.trackPointer(ptr %x, ptr undef) #2
ret i8* %x ret ptr %x
} }
; Function Attrs: nounwind ; Function Attrs: nounwind
define hidden i8* @main.pointerUnsafeGEPFixedOffset(i8* dereferenceable_or_null(1) %ptr, i8* %context) unnamed_addr #1 { define hidden ptr @main.pointerUnsafeGEPFixedOffset(ptr dereferenceable_or_null(1) %ptr, ptr %context) unnamed_addr #1 {
entry: entry:
call void @runtime.trackPointer(i8* %ptr, i8* undef) #2 call void @runtime.trackPointer(ptr %ptr, ptr undef) #2
%0 = getelementptr inbounds i8, i8* %ptr, i32 10 %0 = getelementptr inbounds i8, ptr %ptr, i32 10
call void @runtime.trackPointer(i8* nonnull %0, i8* undef) #2 call void @runtime.trackPointer(ptr nonnull %0, ptr undef) #2
call void @runtime.trackPointer(i8* nonnull %0, i8* undef) #2 call void @runtime.trackPointer(ptr nonnull %0, ptr undef) #2
ret i8* %0 ret ptr %0
} }
; Function Attrs: nounwind ; Function Attrs: nounwind
define hidden i8* @main.pointerUnsafeGEPByteOffset(i8* dereferenceable_or_null(1) %ptr, i32 %offset, i8* %context) unnamed_addr #1 { define hidden ptr @main.pointerUnsafeGEPByteOffset(ptr dereferenceable_or_null(1) %ptr, i32 %offset, ptr %context) unnamed_addr #1 {
entry: entry:
call void @runtime.trackPointer(i8* %ptr, i8* undef) #2 call void @runtime.trackPointer(ptr %ptr, ptr undef) #2
%0 = getelementptr inbounds i8, i8* %ptr, i32 %offset %0 = getelementptr inbounds i8, ptr %ptr, i32 %offset
call void @runtime.trackPointer(i8* %0, i8* undef) #2 call void @runtime.trackPointer(ptr %0, ptr undef) #2
call void @runtime.trackPointer(i8* %0, i8* undef) #2 call void @runtime.trackPointer(ptr %0, ptr undef) #2
ret i8* %0 ret ptr %0
} }
; Function Attrs: nounwind ; Function Attrs: nounwind
define hidden i32* @main.pointerUnsafeGEPIntOffset(i32* dereferenceable_or_null(4) %ptr, i32 %offset, i8* %context) unnamed_addr #1 { define hidden ptr @main.pointerUnsafeGEPIntOffset(ptr dereferenceable_or_null(4) %ptr, i32 %offset, ptr %context) unnamed_addr #1 {
entry: entry:
%0 = bitcast i32* %ptr to i8* call void @runtime.trackPointer(ptr %ptr, ptr undef) #2
call void @runtime.trackPointer(i8* %0, i8* undef) #2 %0 = shl i32 %offset, 2
%1 = getelementptr i32, i32* %ptr, i32 %offset %1 = getelementptr inbounds i8, ptr %ptr, i32 %0
%2 = bitcast i32* %1 to i8* call void @runtime.trackPointer(ptr %1, ptr undef) #2
call void @runtime.trackPointer(i8* %2, i8* undef) #2 call void @runtime.trackPointer(ptr %1, ptr undef) #2
%3 = bitcast i32* %1 to i8* ret ptr %1
call void @runtime.trackPointer(i8* %3, i8* undef) #2
ret i32* %1
} }
attributes #0 = { "target-features"="+bulk-memory,+nontrapping-fptoint,+sign-ext" } attributes #0 = { "target-features"="+bulk-memory,+nontrapping-fptoint,+sign-ext" }

18
compiler/testdata/pragma.ll предоставленный
Просмотреть файл

@ -10,12 +10,12 @@ target triple = "wasm32-unknown-wasi"
@undefinedGlobalNotInSection = external global i32, align 4 @undefinedGlobalNotInSection = external global i32, align 4
@main.multipleGlobalPragmas = hidden global i32 0, section ".global_section", align 1024 @main.multipleGlobalPragmas = hidden global i32 0, section ".global_section", align 1024
declare noalias nonnull i8* @runtime.alloc(i32, i8*, i8*) #0 declare noalias nonnull ptr @runtime.alloc(i32, ptr, ptr) #0
declare void @runtime.trackPointer(i8* nocapture readonly, i8*) #0 declare void @runtime.trackPointer(ptr nocapture readonly, ptr) #0
; Function Attrs: nounwind ; Function Attrs: nounwind
define hidden void @main.init(i8* %context) unnamed_addr #1 { define hidden void @main.init(ptr %context) unnamed_addr #1 {
entry: entry:
ret void ret void
} }
@ -27,27 +27,27 @@ entry:
} }
; Function Attrs: nounwind ; Function Attrs: nounwind
define hidden void @somepkg.someFunction1(i8* %context) unnamed_addr #1 { define hidden void @somepkg.someFunction1(ptr %context) unnamed_addr #1 {
entry: entry:
ret void ret void
} }
declare void @somepkg.someFunction2(i8*) #0 declare void @somepkg.someFunction2(ptr) #0
; Function Attrs: inlinehint nounwind ; Function Attrs: inlinehint nounwind
define hidden void @main.inlineFunc(i8* %context) unnamed_addr #3 { define hidden void @main.inlineFunc(ptr %context) unnamed_addr #3 {
entry: entry:
ret void ret void
} }
; Function Attrs: noinline nounwind ; Function Attrs: noinline nounwind
define hidden void @main.noinlineFunc(i8* %context) unnamed_addr #4 { define hidden void @main.noinlineFunc(ptr %context) unnamed_addr #4 {
entry: entry:
ret void ret void
} }
; Function Attrs: nounwind ; Function Attrs: nounwind
define hidden void @main.functionInSection(i8* %context) unnamed_addr #1 section ".special_function_section" { define hidden void @main.functionInSection(ptr %context) unnamed_addr #1 section ".special_function_section" {
entry: entry:
ret void ret void
} }
@ -58,7 +58,7 @@ entry:
ret void ret void
} }
declare void @main.undefinedFunctionNotInSection(i8*) #0 declare void @main.undefinedFunctionNotInSection(ptr) #0
attributes #0 = { "target-features"="+bulk-memory,+nontrapping-fptoint,+sign-ext" } attributes #0 = { "target-features"="+bulk-memory,+nontrapping-fptoint,+sign-ext" }
attributes #1 = { nounwind "target-features"="+bulk-memory,+nontrapping-fptoint,+sign-ext" } attributes #1 = { nounwind "target-features"="+bulk-memory,+nontrapping-fptoint,+sign-ext" }

264
compiler/testdata/slice.ll предоставленный
Просмотреть файл

@ -3,286 +3,270 @@ source_filename = "slice.go"
target datalayout = "e-m:e-p:32:32-p10:8:8-p20:8:8-i64:64-n32:64-S128-ni:1:10:20" target datalayout = "e-m:e-p:32:32-p10:8:8-p20:8:8-i64:64-n32:64-S128-ni:1:10:20"
target triple = "wasm32-unknown-wasi" target triple = "wasm32-unknown-wasi"
declare noalias nonnull i8* @runtime.alloc(i32, i8*, i8*) #0 declare noalias nonnull ptr @runtime.alloc(i32, ptr, ptr) #0
declare void @runtime.trackPointer(i8* nocapture readonly, i8*) #0 declare void @runtime.trackPointer(ptr nocapture readonly, ptr) #0
; Function Attrs: nounwind ; Function Attrs: nounwind
define hidden void @main.init(i8* %context) unnamed_addr #1 { define hidden void @main.init(ptr %context) unnamed_addr #1 {
entry: entry:
ret void ret void
} }
; Function Attrs: nounwind ; Function Attrs: nounwind
define hidden i32 @main.sliceLen(i32* %ints.data, i32 %ints.len, i32 %ints.cap, i8* %context) unnamed_addr #1 { define hidden i32 @main.sliceLen(ptr %ints.data, i32 %ints.len, i32 %ints.cap, ptr %context) unnamed_addr #1 {
entry: entry:
ret i32 %ints.len ret i32 %ints.len
} }
; Function Attrs: nounwind ; Function Attrs: nounwind
define hidden i32 @main.sliceCap(i32* %ints.data, i32 %ints.len, i32 %ints.cap, i8* %context) unnamed_addr #1 { define hidden i32 @main.sliceCap(ptr %ints.data, i32 %ints.len, i32 %ints.cap, ptr %context) unnamed_addr #1 {
entry: entry:
ret i32 %ints.cap ret i32 %ints.cap
} }
; Function Attrs: nounwind ; Function Attrs: nounwind
define hidden i32 @main.sliceElement(i32* %ints.data, i32 %ints.len, i32 %ints.cap, i32 %index, i8* %context) unnamed_addr #1 { define hidden i32 @main.sliceElement(ptr %ints.data, i32 %ints.len, i32 %ints.cap, i32 %index, ptr %context) unnamed_addr #1 {
entry: entry:
%.not = icmp ult i32 %index, %ints.len %.not = icmp ult i32 %index, %ints.len
br i1 %.not, label %lookup.next, label %lookup.throw br i1 %.not, label %lookup.next, label %lookup.throw
lookup.next: ; preds = %entry lookup.next: ; preds = %entry
%0 = getelementptr inbounds i32, i32* %ints.data, i32 %index %0 = getelementptr inbounds i32, ptr %ints.data, i32 %index
%1 = load i32, i32* %0, align 4 %1 = load i32, ptr %0, align 4
ret i32 %1 ret i32 %1
lookup.throw: ; preds = %entry lookup.throw: ; preds = %entry
call void @runtime.lookupPanic(i8* undef) #2 call void @runtime.lookupPanic(ptr undef) #2
unreachable unreachable
} }
declare void @runtime.lookupPanic(i8*) #0 declare void @runtime.lookupPanic(ptr) #0
; Function Attrs: nounwind ; Function Attrs: nounwind
define hidden { i32*, i32, i32 } @main.sliceAppendValues(i32* %ints.data, i32 %ints.len, i32 %ints.cap, i8* %context) unnamed_addr #1 { define hidden { ptr, i32, i32 } @main.sliceAppendValues(ptr %ints.data, i32 %ints.len, i32 %ints.cap, ptr %context) unnamed_addr #1 {
entry: entry:
%varargs = call i8* @runtime.alloc(i32 12, i8* nonnull inttoptr (i32 3 to i8*), i8* undef) #2 %varargs = call ptr @runtime.alloc(i32 12, ptr nonnull inttoptr (i32 3 to ptr), ptr undef) #2
call void @runtime.trackPointer(i8* nonnull %varargs, i8* undef) #2 call void @runtime.trackPointer(ptr nonnull %varargs, ptr undef) #2
%0 = bitcast i8* %varargs to i32* store i32 1, ptr %varargs, align 4
store i32 1, i32* %0, align 4 %0 = getelementptr inbounds [3 x i32], ptr %varargs, i32 0, i32 1
%1 = getelementptr inbounds i8, i8* %varargs, i32 4 store i32 2, ptr %0, align 4
%2 = bitcast i8* %1 to i32* %1 = getelementptr inbounds [3 x i32], ptr %varargs, i32 0, i32 2
store i32 2, i32* %2, align 4 store i32 3, ptr %1, align 4
%3 = getelementptr inbounds i8, i8* %varargs, i32 8 %append.new = call { ptr, i32, i32 } @runtime.sliceAppend(ptr %ints.data, ptr nonnull %varargs, i32 %ints.len, i32 %ints.cap, i32 3, i32 4, ptr undef) #2
%4 = bitcast i8* %3 to i32* %append.newPtr = extractvalue { ptr, i32, i32 } %append.new, 0
store i32 3, i32* %4, align 4 %append.newLen = extractvalue { ptr, i32, i32 } %append.new, 1
%append.srcPtr = bitcast i32* %ints.data to i8* %append.newCap = extractvalue { ptr, i32, i32 } %append.new, 2
%append.new = call { i8*, i32, i32 } @runtime.sliceAppend(i8* %append.srcPtr, i8* nonnull %varargs, i32 %ints.len, i32 %ints.cap, i32 3, i32 4, i8* undef) #2 %2 = insertvalue { ptr, i32, i32 } undef, ptr %append.newPtr, 0
%append.newPtr = extractvalue { i8*, i32, i32 } %append.new, 0 %3 = insertvalue { ptr, i32, i32 } %2, i32 %append.newLen, 1
%append.newBuf = bitcast i8* %append.newPtr to i32* %4 = insertvalue { ptr, i32, i32 } %3, i32 %append.newCap, 2
%append.newLen = extractvalue { i8*, i32, i32 } %append.new, 1 call void @runtime.trackPointer(ptr %append.newPtr, ptr undef) #2
%append.newCap = extractvalue { i8*, i32, i32 } %append.new, 2 ret { ptr, i32, i32 } %4
%5 = insertvalue { i32*, i32, i32 } undef, i32* %append.newBuf, 0
%6 = insertvalue { i32*, i32, i32 } %5, i32 %append.newLen, 1
%7 = insertvalue { i32*, i32, i32 } %6, i32 %append.newCap, 2
call void @runtime.trackPointer(i8* %append.newPtr, i8* undef) #2
ret { i32*, i32, i32 } %7
} }
declare { i8*, i32, i32 } @runtime.sliceAppend(i8*, i8* nocapture readonly, i32, i32, i32, i32, i8*) #0 declare { ptr, i32, i32 } @runtime.sliceAppend(ptr, ptr nocapture readonly, i32, i32, i32, i32, ptr) #0
; Function Attrs: nounwind ; Function Attrs: nounwind
define hidden { i32*, i32, i32 } @main.sliceAppendSlice(i32* %ints.data, i32 %ints.len, i32 %ints.cap, i32* %added.data, i32 %added.len, i32 %added.cap, i8* %context) unnamed_addr #1 { 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 #1 {
entry: entry:
%append.srcPtr = bitcast i32* %ints.data to i8* %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 undef) #2
%append.srcPtr1 = bitcast i32* %added.data to i8* %append.newPtr = extractvalue { ptr, i32, i32 } %append.new, 0
%append.new = call { i8*, i32, i32 } @runtime.sliceAppend(i8* %append.srcPtr, i8* %append.srcPtr1, i32 %ints.len, i32 %ints.cap, i32 %added.len, i32 4, i8* undef) #2 %append.newLen = extractvalue { ptr, i32, i32 } %append.new, 1
%append.newPtr = extractvalue { i8*, i32, i32 } %append.new, 0 %append.newCap = extractvalue { ptr, i32, i32 } %append.new, 2
%append.newBuf = bitcast i8* %append.newPtr to i32* %0 = insertvalue { ptr, i32, i32 } undef, ptr %append.newPtr, 0
%append.newLen = extractvalue { i8*, i32, i32 } %append.new, 1 %1 = insertvalue { ptr, i32, i32 } %0, i32 %append.newLen, 1
%append.newCap = extractvalue { i8*, i32, i32 } %append.new, 2 %2 = insertvalue { ptr, i32, i32 } %1, i32 %append.newCap, 2
%0 = insertvalue { i32*, i32, i32 } undef, i32* %append.newBuf, 0 call void @runtime.trackPointer(ptr %append.newPtr, ptr undef) #2
%1 = insertvalue { i32*, i32, i32 } %0, i32 %append.newLen, 1 ret { ptr, i32, i32 } %2
%2 = insertvalue { i32*, i32, i32 } %1, i32 %append.newCap, 2
call void @runtime.trackPointer(i8* %append.newPtr, i8* undef) #2
ret { i32*, i32, i32 } %2
} }
; Function Attrs: nounwind ; Function Attrs: nounwind
define hidden i32 @main.sliceCopy(i32* %dst.data, i32 %dst.len, i32 %dst.cap, i32* %src.data, i32 %src.len, i32 %src.cap, i8* %context) unnamed_addr #1 { 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 #1 {
entry: entry:
%copy.dstPtr = bitcast i32* %dst.data to i8* %copy.n = call i32 @runtime.sliceCopy(ptr %dst.data, ptr %src.data, i32 %dst.len, i32 %src.len, i32 4, ptr undef) #2
%copy.srcPtr = bitcast i32* %src.data to i8*
%copy.n = call i32 @runtime.sliceCopy(i8* %copy.dstPtr, i8* %copy.srcPtr, i32 %dst.len, i32 %src.len, i32 4, i8* undef) #2
ret i32 %copy.n ret i32 %copy.n
} }
declare i32 @runtime.sliceCopy(i8* nocapture writeonly, i8* nocapture readonly, i32, i32, i32, i8*) #0 declare i32 @runtime.sliceCopy(ptr nocapture writeonly, ptr nocapture readonly, i32, i32, i32, ptr) #0
; Function Attrs: nounwind ; Function Attrs: nounwind
define hidden { i8*, i32, i32 } @main.makeByteSlice(i32 %len, i8* %context) unnamed_addr #1 { define hidden { ptr, i32, i32 } @main.makeByteSlice(i32 %len, ptr %context) unnamed_addr #1 {
entry: entry:
%slice.maxcap = icmp slt i32 %len, 0 %slice.maxcap = icmp slt i32 %len, 0
br i1 %slice.maxcap, label %slice.throw, label %slice.next br i1 %slice.maxcap, label %slice.throw, label %slice.next
slice.next: ; preds = %entry slice.next: ; preds = %entry
%makeslice.buf = call i8* @runtime.alloc(i32 %len, i8* nonnull inttoptr (i32 3 to i8*), i8* undef) #2 %makeslice.buf = call ptr @runtime.alloc(i32 %len, ptr nonnull inttoptr (i32 3 to ptr), ptr undef) #2
%0 = insertvalue { i8*, i32, i32 } undef, i8* %makeslice.buf, 0 %0 = insertvalue { ptr, i32, i32 } undef, ptr %makeslice.buf, 0
%1 = insertvalue { i8*, i32, i32 } %0, i32 %len, 1 %1 = insertvalue { ptr, i32, i32 } %0, i32 %len, 1
%2 = insertvalue { i8*, i32, i32 } %1, i32 %len, 2 %2 = insertvalue { ptr, i32, i32 } %1, i32 %len, 2
call void @runtime.trackPointer(i8* nonnull %makeslice.buf, i8* undef) #2 call void @runtime.trackPointer(ptr nonnull %makeslice.buf, ptr undef) #2
ret { i8*, i32, i32 } %2 ret { ptr, i32, i32 } %2
slice.throw: ; preds = %entry slice.throw: ; preds = %entry
call void @runtime.slicePanic(i8* undef) #2 call void @runtime.slicePanic(ptr undef) #2
unreachable unreachable
} }
declare void @runtime.slicePanic(i8*) #0 declare void @runtime.slicePanic(ptr) #0
; Function Attrs: nounwind ; Function Attrs: nounwind
define hidden { i16*, i32, i32 } @main.makeInt16Slice(i32 %len, i8* %context) unnamed_addr #1 { define hidden { ptr, i32, i32 } @main.makeInt16Slice(i32 %len, ptr %context) unnamed_addr #1 {
entry: entry:
%slice.maxcap = icmp slt i32 %len, 0 %slice.maxcap = icmp slt i32 %len, 0
br i1 %slice.maxcap, label %slice.throw, label %slice.next br i1 %slice.maxcap, label %slice.throw, label %slice.next
slice.next: ; preds = %entry slice.next: ; preds = %entry
%makeslice.cap = shl i32 %len, 1 %makeslice.cap = shl i32 %len, 1
%makeslice.buf = call i8* @runtime.alloc(i32 %makeslice.cap, i8* nonnull inttoptr (i32 3 to i8*), i8* undef) #2 %makeslice.buf = call ptr @runtime.alloc(i32 %makeslice.cap, ptr nonnull inttoptr (i32 3 to ptr), ptr undef) #2
%makeslice.array = bitcast i8* %makeslice.buf to i16* %0 = insertvalue { ptr, i32, i32 } undef, ptr %makeslice.buf, 0
%0 = insertvalue { i16*, i32, i32 } undef, i16* %makeslice.array, 0 %1 = insertvalue { ptr, i32, i32 } %0, i32 %len, 1
%1 = insertvalue { i16*, i32, i32 } %0, i32 %len, 1 %2 = insertvalue { ptr, i32, i32 } %1, i32 %len, 2
%2 = insertvalue { i16*, i32, i32 } %1, i32 %len, 2 call void @runtime.trackPointer(ptr nonnull %makeslice.buf, ptr undef) #2
call void @runtime.trackPointer(i8* nonnull %makeslice.buf, i8* undef) #2 ret { ptr, i32, i32 } %2
ret { i16*, i32, i32 } %2
slice.throw: ; preds = %entry slice.throw: ; preds = %entry
call void @runtime.slicePanic(i8* undef) #2 call void @runtime.slicePanic(ptr undef) #2
unreachable unreachable
} }
; Function Attrs: nounwind ; Function Attrs: nounwind
define hidden { [3 x i8]*, i32, i32 } @main.makeArraySlice(i32 %len, i8* %context) unnamed_addr #1 { define hidden { ptr, i32, i32 } @main.makeArraySlice(i32 %len, ptr %context) unnamed_addr #1 {
entry: entry:
%slice.maxcap = icmp ugt i32 %len, 1431655765 %slice.maxcap = icmp ugt i32 %len, 1431655765
br i1 %slice.maxcap, label %slice.throw, label %slice.next br i1 %slice.maxcap, label %slice.throw, label %slice.next
slice.next: ; preds = %entry slice.next: ; preds = %entry
%makeslice.cap = mul i32 %len, 3 %makeslice.cap = mul i32 %len, 3
%makeslice.buf = call i8* @runtime.alloc(i32 %makeslice.cap, i8* nonnull inttoptr (i32 3 to i8*), i8* undef) #2 %makeslice.buf = call ptr @runtime.alloc(i32 %makeslice.cap, ptr nonnull inttoptr (i32 3 to ptr), ptr undef) #2
%makeslice.array = bitcast i8* %makeslice.buf to [3 x i8]* %0 = insertvalue { ptr, i32, i32 } undef, ptr %makeslice.buf, 0
%0 = insertvalue { [3 x i8]*, i32, i32 } undef, [3 x i8]* %makeslice.array, 0 %1 = insertvalue { ptr, i32, i32 } %0, i32 %len, 1
%1 = insertvalue { [3 x i8]*, i32, i32 } %0, i32 %len, 1 %2 = insertvalue { ptr, i32, i32 } %1, i32 %len, 2
%2 = insertvalue { [3 x i8]*, i32, i32 } %1, i32 %len, 2 call void @runtime.trackPointer(ptr nonnull %makeslice.buf, ptr undef) #2
call void @runtime.trackPointer(i8* nonnull %makeslice.buf, i8* undef) #2 ret { ptr, i32, i32 } %2
ret { [3 x i8]*, i32, i32 } %2
slice.throw: ; preds = %entry slice.throw: ; preds = %entry
call void @runtime.slicePanic(i8* undef) #2 call void @runtime.slicePanic(ptr undef) #2
unreachable unreachable
} }
; Function Attrs: nounwind ; Function Attrs: nounwind
define hidden { i32*, i32, i32 } @main.makeInt32Slice(i32 %len, i8* %context) unnamed_addr #1 { define hidden { ptr, i32, i32 } @main.makeInt32Slice(i32 %len, ptr %context) unnamed_addr #1 {
entry: entry:
%slice.maxcap = icmp ugt i32 %len, 1073741823 %slice.maxcap = icmp ugt i32 %len, 1073741823
br i1 %slice.maxcap, label %slice.throw, label %slice.next br i1 %slice.maxcap, label %slice.throw, label %slice.next
slice.next: ; preds = %entry slice.next: ; preds = %entry
%makeslice.cap = shl i32 %len, 2 %makeslice.cap = shl i32 %len, 2
%makeslice.buf = call i8* @runtime.alloc(i32 %makeslice.cap, i8* nonnull inttoptr (i32 3 to i8*), i8* undef) #2 %makeslice.buf = call ptr @runtime.alloc(i32 %makeslice.cap, ptr nonnull inttoptr (i32 3 to ptr), ptr undef) #2
%makeslice.array = bitcast i8* %makeslice.buf to i32* %0 = insertvalue { ptr, i32, i32 } undef, ptr %makeslice.buf, 0
%0 = insertvalue { i32*, i32, i32 } undef, i32* %makeslice.array, 0 %1 = insertvalue { ptr, i32, i32 } %0, i32 %len, 1
%1 = insertvalue { i32*, i32, i32 } %0, i32 %len, 1 %2 = insertvalue { ptr, i32, i32 } %1, i32 %len, 2
%2 = insertvalue { i32*, i32, i32 } %1, i32 %len, 2 call void @runtime.trackPointer(ptr nonnull %makeslice.buf, ptr undef) #2
call void @runtime.trackPointer(i8* nonnull %makeslice.buf, i8* undef) #2 ret { ptr, i32, i32 } %2
ret { i32*, i32, i32 } %2
slice.throw: ; preds = %entry slice.throw: ; preds = %entry
call void @runtime.slicePanic(i8* undef) #2 call void @runtime.slicePanic(ptr undef) #2
unreachable unreachable
} }
; Function Attrs: nounwind ; Function Attrs: nounwind
define hidden i8* @main.Add32(i8* %p, i32 %len, i8* %context) unnamed_addr #1 { define hidden ptr @main.Add32(ptr %p, i32 %len, ptr %context) unnamed_addr #1 {
entry: entry:
%0 = getelementptr i8, i8* %p, i32 %len %0 = getelementptr i8, ptr %p, i32 %len
call void @runtime.trackPointer(i8* %0, i8* undef) #2 call void @runtime.trackPointer(ptr %0, ptr undef) #2
ret i8* %0 ret ptr %0
} }
; Function Attrs: nounwind ; Function Attrs: nounwind
define hidden i8* @main.Add64(i8* %p, i64 %len, i8* %context) unnamed_addr #1 { define hidden ptr @main.Add64(ptr %p, i64 %len, ptr %context) unnamed_addr #1 {
entry: entry:
%0 = trunc i64 %len to i32 %0 = trunc i64 %len to i32
%1 = getelementptr i8, i8* %p, i32 %0 %1 = getelementptr i8, ptr %p, i32 %0
call void @runtime.trackPointer(i8* %1, i8* undef) #2 call void @runtime.trackPointer(ptr %1, ptr undef) #2
ret i8* %1 ret ptr %1
} }
; Function Attrs: nounwind ; Function Attrs: nounwind
define hidden [4 x i32]* @main.SliceToArray(i32* %s.data, i32 %s.len, i32 %s.cap, i8* %context) unnamed_addr #1 { define hidden ptr @main.SliceToArray(ptr %s.data, i32 %s.len, i32 %s.cap, ptr %context) unnamed_addr #1 {
entry: entry:
%0 = icmp ult i32 %s.len, 4 %0 = icmp ult i32 %s.len, 4
br i1 %0, label %slicetoarray.throw, label %slicetoarray.next br i1 %0, label %slicetoarray.throw, label %slicetoarray.next
slicetoarray.next: ; preds = %entry slicetoarray.next: ; preds = %entry
%1 = bitcast i32* %s.data to [4 x i32]* ret ptr %s.data
ret [4 x i32]* %1
slicetoarray.throw: ; preds = %entry slicetoarray.throw: ; preds = %entry
call void @runtime.sliceToArrayPointerPanic(i8* undef) #2 call void @runtime.sliceToArrayPointerPanic(ptr undef) #2
unreachable unreachable
} }
declare void @runtime.sliceToArrayPointerPanic(i8*) #0 declare void @runtime.sliceToArrayPointerPanic(ptr) #0
; Function Attrs: nounwind ; Function Attrs: nounwind
define hidden [4 x i32]* @main.SliceToArrayConst(i8* %context) unnamed_addr #1 { define hidden ptr @main.SliceToArrayConst(ptr %context) unnamed_addr #1 {
entry: entry:
%makeslice = call i8* @runtime.alloc(i32 24, i8* nonnull inttoptr (i32 3 to i8*), i8* undef) #2 %makeslice = call ptr @runtime.alloc(i32 24, ptr nonnull inttoptr (i32 3 to ptr), ptr undef) #2
call void @runtime.trackPointer(i8* nonnull %makeslice, i8* undef) #2 call void @runtime.trackPointer(ptr nonnull %makeslice, ptr undef) #2
br i1 false, label %slicetoarray.throw, label %slicetoarray.next br i1 false, label %slicetoarray.throw, label %slicetoarray.next
slicetoarray.next: ; preds = %entry slicetoarray.next: ; preds = %entry
%0 = bitcast i8* %makeslice to [4 x i32]* ret ptr %makeslice
ret [4 x i32]* %0
slicetoarray.throw: ; preds = %entry slicetoarray.throw: ; preds = %entry
unreachable unreachable
} }
; Function Attrs: nounwind ; Function Attrs: nounwind
define hidden { i32*, i32, i32 } @main.SliceInt(i32* dereferenceable_or_null(4) %ptr, i32 %len, i8* %context) unnamed_addr #1 { define hidden { ptr, i32, i32 } @main.SliceInt(ptr dereferenceable_or_null(4) %ptr, i32 %len, ptr %context) unnamed_addr #1 {
entry: entry:
%0 = icmp ugt i32 %len, 1073741823 %0 = icmp ugt i32 %len, 1073741823
%1 = icmp eq i32* %ptr, null %1 = icmp eq ptr %ptr, null
%2 = icmp ne i32 %len, 0 %2 = icmp ne i32 %len, 0
%3 = and i1 %1, %2 %3 = and i1 %1, %2
%4 = or i1 %3, %0 %4 = or i1 %3, %0
br i1 %4, label %unsafe.Slice.throw, label %unsafe.Slice.next br i1 %4, label %unsafe.Slice.throw, label %unsafe.Slice.next
unsafe.Slice.next: ; preds = %entry unsafe.Slice.next: ; preds = %entry
%5 = insertvalue { i32*, i32, i32 } undef, i32* %ptr, 0 %5 = insertvalue { ptr, i32, i32 } undef, ptr %ptr, 0
%6 = insertvalue { i32*, i32, i32 } %5, i32 %len, 1 %6 = insertvalue { ptr, i32, i32 } %5, i32 %len, 1
%7 = insertvalue { i32*, i32, i32 } %6, i32 %len, 2 %7 = insertvalue { ptr, i32, i32 } %6, i32 %len, 2
%8 = bitcast i32* %ptr to i8* call void @runtime.trackPointer(ptr %ptr, ptr undef) #2
call void @runtime.trackPointer(i8* %8, i8* undef) #2 ret { ptr, i32, i32 } %7
ret { i32*, i32, i32 } %7
unsafe.Slice.throw: ; preds = %entry unsafe.Slice.throw: ; preds = %entry
call void @runtime.unsafeSlicePanic(i8* undef) #2 call void @runtime.unsafeSlicePanic(ptr undef) #2
unreachable unreachable
} }
declare void @runtime.unsafeSlicePanic(i8*) #0 declare void @runtime.unsafeSlicePanic(ptr) #0
; Function Attrs: nounwind ; Function Attrs: nounwind
define hidden { i8*, i32, i32 } @main.SliceUint16(i8* dereferenceable_or_null(1) %ptr, i16 %len, i8* %context) unnamed_addr #1 { define hidden { ptr, i32, i32 } @main.SliceUint16(ptr dereferenceable_or_null(1) %ptr, i16 %len, ptr %context) unnamed_addr #1 {
entry: entry:
%0 = icmp eq i8* %ptr, null %0 = icmp eq ptr %ptr, null
%1 = icmp ne i16 %len, 0 %1 = icmp ne i16 %len, 0
%2 = and i1 %0, %1 %2 = and i1 %0, %1
br i1 %2, label %unsafe.Slice.throw, label %unsafe.Slice.next br i1 %2, label %unsafe.Slice.throw, label %unsafe.Slice.next
unsafe.Slice.next: ; preds = %entry unsafe.Slice.next: ; preds = %entry
%3 = zext i16 %len to i32 %3 = zext i16 %len to i32
%4 = insertvalue { i8*, i32, i32 } undef, i8* %ptr, 0 %4 = insertvalue { ptr, i32, i32 } undef, ptr %ptr, 0
%5 = insertvalue { i8*, i32, i32 } %4, i32 %3, 1 %5 = insertvalue { ptr, i32, i32 } %4, i32 %3, 1
%6 = insertvalue { i8*, i32, i32 } %5, i32 %3, 2 %6 = insertvalue { ptr, i32, i32 } %5, i32 %3, 2
call void @runtime.trackPointer(i8* %ptr, i8* undef) #2 call void @runtime.trackPointer(ptr %ptr, ptr undef) #2
ret { i8*, i32, i32 } %6 ret { ptr, i32, i32 } %6
unsafe.Slice.throw: ; preds = %entry unsafe.Slice.throw: ; preds = %entry
call void @runtime.unsafeSlicePanic(i8* undef) #2 call void @runtime.unsafeSlicePanic(ptr undef) #2
unreachable unreachable
} }
; Function Attrs: nounwind ; Function Attrs: nounwind
define hidden { i32*, i32, i32 } @main.SliceUint64(i32* dereferenceable_or_null(4) %ptr, i64 %len, i8* %context) unnamed_addr #1 { define hidden { ptr, i32, i32 } @main.SliceUint64(ptr dereferenceable_or_null(4) %ptr, i64 %len, ptr %context) unnamed_addr #1 {
entry: entry:
%0 = icmp ugt i64 %len, 1073741823 %0 = icmp ugt i64 %len, 1073741823
%1 = icmp eq i32* %ptr, null %1 = icmp eq ptr %ptr, null
%2 = icmp ne i64 %len, 0 %2 = icmp ne i64 %len, 0
%3 = and i1 %1, %2 %3 = and i1 %1, %2
%4 = or i1 %3, %0 %4 = or i1 %3, %0
@ -290,23 +274,22 @@ entry:
unsafe.Slice.next: ; preds = %entry unsafe.Slice.next: ; preds = %entry
%5 = trunc i64 %len to i32 %5 = trunc i64 %len to i32
%6 = insertvalue { i32*, i32, i32 } undef, i32* %ptr, 0 %6 = insertvalue { ptr, i32, i32 } undef, ptr %ptr, 0
%7 = insertvalue { i32*, i32, i32 } %6, i32 %5, 1 %7 = insertvalue { ptr, i32, i32 } %6, i32 %5, 1
%8 = insertvalue { i32*, i32, i32 } %7, i32 %5, 2 %8 = insertvalue { ptr, i32, i32 } %7, i32 %5, 2
%9 = bitcast i32* %ptr to i8* call void @runtime.trackPointer(ptr %ptr, ptr undef) #2
call void @runtime.trackPointer(i8* %9, i8* undef) #2 ret { ptr, i32, i32 } %8
ret { i32*, i32, i32 } %8
unsafe.Slice.throw: ; preds = %entry unsafe.Slice.throw: ; preds = %entry
call void @runtime.unsafeSlicePanic(i8* undef) #2 call void @runtime.unsafeSlicePanic(ptr undef) #2
unreachable unreachable
} }
; Function Attrs: nounwind ; Function Attrs: nounwind
define hidden { i32*, i32, i32 } @main.SliceInt64(i32* dereferenceable_or_null(4) %ptr, i64 %len, i8* %context) unnamed_addr #1 { define hidden { ptr, i32, i32 } @main.SliceInt64(ptr dereferenceable_or_null(4) %ptr, i64 %len, ptr %context) unnamed_addr #1 {
entry: entry:
%0 = icmp ugt i64 %len, 1073741823 %0 = icmp ugt i64 %len, 1073741823
%1 = icmp eq i32* %ptr, null %1 = icmp eq ptr %ptr, null
%2 = icmp ne i64 %len, 0 %2 = icmp ne i64 %len, 0
%3 = and i1 %1, %2 %3 = and i1 %1, %2
%4 = or i1 %3, %0 %4 = or i1 %3, %0
@ -314,15 +297,14 @@ entry:
unsafe.Slice.next: ; preds = %entry unsafe.Slice.next: ; preds = %entry
%5 = trunc i64 %len to i32 %5 = trunc i64 %len to i32
%6 = insertvalue { i32*, i32, i32 } undef, i32* %ptr, 0 %6 = insertvalue { ptr, i32, i32 } undef, ptr %ptr, 0
%7 = insertvalue { i32*, i32, i32 } %6, i32 %5, 1 %7 = insertvalue { ptr, i32, i32 } %6, i32 %5, 1
%8 = insertvalue { i32*, i32, i32 } %7, i32 %5, 2 %8 = insertvalue { ptr, i32, i32 } %7, i32 %5, 2
%9 = bitcast i32* %ptr to i8* call void @runtime.trackPointer(ptr %ptr, ptr undef) #2
call void @runtime.trackPointer(i8* %9, i8* undef) #2 ret { ptr, i32, i32 } %8
ret { i32*, i32, i32 } %8
unsafe.Slice.throw: ; preds = %entry unsafe.Slice.throw: ; preds = %entry
call void @runtime.unsafeSlicePanic(i8* undef) #2 call void @runtime.unsafeSlicePanic(ptr undef) #2
unreachable unreachable
} }

50
compiler/testdata/string.ll предоставленный
Просмотреть файл

@ -3,96 +3,96 @@ source_filename = "string.go"
target datalayout = "e-m:e-p:32:32-p10:8:8-p20:8:8-i64:64-n32:64-S128-ni:1:10:20" target datalayout = "e-m:e-p:32:32-p10:8:8-p20:8:8-i64:64-n32:64-S128-ni:1:10:20"
target triple = "wasm32-unknown-wasi" target triple = "wasm32-unknown-wasi"
%runtime._string = type { i8*, i32 } %runtime._string = type { ptr, i32 }
@"main$string" = internal unnamed_addr constant [3 x i8] c"foo", align 1 @"main$string" = internal unnamed_addr constant [3 x i8] c"foo", align 1
declare noalias nonnull i8* @runtime.alloc(i32, i8*, i8*) #0 declare noalias nonnull ptr @runtime.alloc(i32, ptr, ptr) #0
declare void @runtime.trackPointer(i8* nocapture readonly, i8*) #0 declare void @runtime.trackPointer(ptr nocapture readonly, ptr) #0
; Function Attrs: nounwind ; Function Attrs: nounwind
define hidden void @main.init(i8* %context) unnamed_addr #1 { define hidden void @main.init(ptr %context) unnamed_addr #1 {
entry: entry:
ret void ret void
} }
; Function Attrs: nounwind ; Function Attrs: nounwind
define hidden %runtime._string @main.someString(i8* %context) unnamed_addr #1 { define hidden %runtime._string @main.someString(ptr %context) unnamed_addr #1 {
entry: entry:
ret %runtime._string { i8* getelementptr inbounds ([3 x i8], [3 x i8]* @"main$string", i32 0, i32 0), i32 3 } ret %runtime._string { ptr @"main$string", i32 3 }
} }
; Function Attrs: nounwind ; Function Attrs: nounwind
define hidden %runtime._string @main.zeroLengthString(i8* %context) unnamed_addr #1 { define hidden %runtime._string @main.zeroLengthString(ptr %context) unnamed_addr #1 {
entry: entry:
ret %runtime._string zeroinitializer ret %runtime._string zeroinitializer
} }
; Function Attrs: nounwind ; Function Attrs: nounwind
define hidden i32 @main.stringLen(i8* %s.data, i32 %s.len, i8* %context) unnamed_addr #1 { define hidden i32 @main.stringLen(ptr %s.data, i32 %s.len, ptr %context) unnamed_addr #1 {
entry: entry:
ret i32 %s.len ret i32 %s.len
} }
; Function Attrs: nounwind ; Function Attrs: nounwind
define hidden i8 @main.stringIndex(i8* %s.data, i32 %s.len, i32 %index, i8* %context) unnamed_addr #1 { define hidden i8 @main.stringIndex(ptr %s.data, i32 %s.len, i32 %index, ptr %context) unnamed_addr #1 {
entry: entry:
%.not = icmp ult i32 %index, %s.len %.not = icmp ult i32 %index, %s.len
br i1 %.not, label %lookup.next, label %lookup.throw br i1 %.not, label %lookup.next, label %lookup.throw
lookup.next: ; preds = %entry lookup.next: ; preds = %entry
%0 = getelementptr inbounds i8, i8* %s.data, i32 %index %0 = getelementptr inbounds i8, ptr %s.data, i32 %index
%1 = load i8, i8* %0, align 1 %1 = load i8, ptr %0, align 1
ret i8 %1 ret i8 %1
lookup.throw: ; preds = %entry lookup.throw: ; preds = %entry
call void @runtime.lookupPanic(i8* undef) #2 call void @runtime.lookupPanic(ptr undef) #2
unreachable unreachable
} }
declare void @runtime.lookupPanic(i8*) #0 declare void @runtime.lookupPanic(ptr) #0
; Function Attrs: nounwind ; Function Attrs: nounwind
define hidden i1 @main.stringCompareEqual(i8* %s1.data, i32 %s1.len, i8* %s2.data, i32 %s2.len, i8* %context) unnamed_addr #1 { define hidden i1 @main.stringCompareEqual(ptr %s1.data, i32 %s1.len, ptr %s2.data, i32 %s2.len, ptr %context) unnamed_addr #1 {
entry: entry:
%0 = call i1 @runtime.stringEqual(i8* %s1.data, i32 %s1.len, i8* %s2.data, i32 %s2.len, i8* undef) #2 %0 = call i1 @runtime.stringEqual(ptr %s1.data, i32 %s1.len, ptr %s2.data, i32 %s2.len, ptr undef) #2
ret i1 %0 ret i1 %0
} }
declare i1 @runtime.stringEqual(i8*, i32, i8*, i32, i8*) #0 declare i1 @runtime.stringEqual(ptr, i32, ptr, i32, ptr) #0
; Function Attrs: nounwind ; Function Attrs: nounwind
define hidden i1 @main.stringCompareUnequal(i8* %s1.data, i32 %s1.len, i8* %s2.data, i32 %s2.len, i8* %context) unnamed_addr #1 { define hidden i1 @main.stringCompareUnequal(ptr %s1.data, i32 %s1.len, ptr %s2.data, i32 %s2.len, ptr %context) unnamed_addr #1 {
entry: entry:
%0 = call i1 @runtime.stringEqual(i8* %s1.data, i32 %s1.len, i8* %s2.data, i32 %s2.len, i8* undef) #2 %0 = call i1 @runtime.stringEqual(ptr %s1.data, i32 %s1.len, ptr %s2.data, i32 %s2.len, ptr undef) #2
%1 = xor i1 %0, true %1 = xor i1 %0, true
ret i1 %1 ret i1 %1
} }
; Function Attrs: nounwind ; Function Attrs: nounwind
define hidden i1 @main.stringCompareLarger(i8* %s1.data, i32 %s1.len, i8* %s2.data, i32 %s2.len, i8* %context) unnamed_addr #1 { define hidden i1 @main.stringCompareLarger(ptr %s1.data, i32 %s1.len, ptr %s2.data, i32 %s2.len, ptr %context) unnamed_addr #1 {
entry: entry:
%0 = call i1 @runtime.stringLess(i8* %s2.data, i32 %s2.len, i8* %s1.data, i32 %s1.len, i8* undef) #2 %0 = call i1 @runtime.stringLess(ptr %s2.data, i32 %s2.len, ptr %s1.data, i32 %s1.len, ptr undef) #2
ret i1 %0 ret i1 %0
} }
declare i1 @runtime.stringLess(i8*, i32, i8*, i32, i8*) #0 declare i1 @runtime.stringLess(ptr, i32, ptr, i32, ptr) #0
; Function Attrs: nounwind ; Function Attrs: nounwind
define hidden i8 @main.stringLookup(i8* %s.data, i32 %s.len, i8 %x, i8* %context) unnamed_addr #1 { define hidden i8 @main.stringLookup(ptr %s.data, i32 %s.len, i8 %x, ptr %context) unnamed_addr #1 {
entry: entry:
%0 = zext i8 %x to i32 %0 = zext i8 %x to i32
%.not = icmp ult i32 %0, %s.len %.not = icmp ult i32 %0, %s.len
br i1 %.not, label %lookup.next, label %lookup.throw br i1 %.not, label %lookup.next, label %lookup.throw
lookup.next: ; preds = %entry lookup.next: ; preds = %entry
%1 = getelementptr inbounds i8, i8* %s.data, i32 %0 %1 = getelementptr inbounds i8, ptr %s.data, i32 %0
%2 = load i8, i8* %1, align 1 %2 = load i8, ptr %1, align 1
ret i8 %2 ret i8 %2
lookup.throw: ; preds = %entry lookup.throw: ; preds = %entry
call void @runtime.lookupPanic(i8* undef) #2 call void @runtime.lookupPanic(ptr undef) #2
unreachable unreachable
} }

2
go.mod
Просмотреть файл

@ -17,7 +17,7 @@ require (
golang.org/x/sys v0.0.0-20220829200755-d48e67d00261 golang.org/x/sys v0.0.0-20220829200755-d48e67d00261
golang.org/x/tools v0.1.11 golang.org/x/tools v0.1.11
gopkg.in/yaml.v2 v2.4.0 gopkg.in/yaml.v2 v2.4.0
tinygo.org/x/go-llvm v0.0.0-20220922113433-4b5ad7ff76ec tinygo.org/x/go-llvm v0.0.0-20220922115213-dcb078a26266
) )
require ( require (

4
go.sum
Просмотреть файл

@ -64,5 +64,5 @@ gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8
gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY= gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY=
gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ= gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ=
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c h1:dUUwHk2QECo/6vqA44rthZ8ie2QXMNeKRTHCNY2nXvo= gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c h1:dUUwHk2QECo/6vqA44rthZ8ie2QXMNeKRTHCNY2nXvo=
tinygo.org/x/go-llvm v0.0.0-20220922113433-4b5ad7ff76ec h1:FYtAFrw/YQPc644uNN65dW50FrEuVNaPBf70x23ApY4= tinygo.org/x/go-llvm v0.0.0-20220922115213-dcb078a26266 h1:vg4sYKEM+w6epr5S1nXqP/7UhMYcc8nRt7Ohkq28rok=
tinygo.org/x/go-llvm v0.0.0-20220922113433-4b5ad7ff76ec/go.mod h1:GFbusT2VTA4I+l4j80b17KFK+6whv69Wtny5U+T8RR0= tinygo.org/x/go-llvm v0.0.0-20220922115213-dcb078a26266/go.mod h1:GFbusT2VTA4I+l4j80b17KFK+6whv69Wtny5U+T8RR0=

Просмотреть файл

@ -356,7 +356,7 @@ func (r *runner) run(fn *function, params []value, parentMem *memoryView, indent
default: default:
panic("unknown integer type width") panic("unknown integer type width")
} }
case strings.HasPrefix(callFn.name, "llvm.memcpy.p0i8.p0i8.") || strings.HasPrefix(callFn.name, "llvm.memmove.p0i8.p0i8."): case strings.HasPrefix(callFn.name, "llvm.memcpy.p0") || strings.HasPrefix(callFn.name, "llvm.memmove.p0"):
// Copy a block of memory from one pointer to another. // Copy a block of memory from one pointer to another.
dst, err := operands[1].asPointer(r) dst, err := operands[1].asPointer(r)
if err != nil { if err != nil {
@ -496,7 +496,7 @@ func (r *runner) run(fn *function, params []value, parentMem *memoryView, indent
typecodeID := typecodeIDBitCast.Operand(0).Initializer() typecodeID := typecodeIDBitCast.Operand(0).Initializer()
// Load the method set, which is part of the typecodeID object. // Load the method set, which is part of the typecodeID object.
methodSet := r.builder.CreateExtractValue(typecodeID, 2, "").Operand(0).Initializer() methodSet := stripPointerCasts(r.builder.CreateExtractValue(typecodeID, 2, "")).Initializer()
// We don't need to load the interface method set. // We don't need to load the interface method set.
@ -1095,3 +1095,15 @@ func intPredicateString(predicate llvm.IntPredicate) string {
return "cmp?" return "cmp?"
} }
} }
// Strip some pointer casts. This is probably unnecessary once support for
// LLVM 14 (non-opaque pointers) is dropped.
func stripPointerCasts(value llvm.Value) llvm.Value {
if !value.IsAConstantExpr().IsNil() {
switch value.Opcode() {
case llvm.GetElementPtr, llvm.BitCast:
return stripPointerCasts(value.Operand(0))
}
}
return value
}

Просмотреть файл

@ -27,18 +27,18 @@ func GOROOT() string {
// Copy size bytes from src to dst. The memory areas must not overlap. // Copy size bytes from src to dst. The memory areas must not overlap.
// This function is implemented by the compiler as a call to a LLVM intrinsic // This function is implemented by the compiler as a call to a LLVM intrinsic
// like llvm.memcpy.p0i8.p0i8.i32(dst, src, size, false). // like llvm.memcpy.p0.p0.i32(dst, src, size, false).
func memcpy(dst, src unsafe.Pointer, size uintptr) func memcpy(dst, src unsafe.Pointer, size uintptr)
// Copy size bytes from src to dst. The memory areas may overlap and will do the // Copy size bytes from src to dst. The memory areas may overlap and will do the
// correct thing. // correct thing.
// This function is implemented by the compiler as a call to a LLVM intrinsic // This function is implemented by the compiler as a call to a LLVM intrinsic
// like llvm.memmove.p0i8.p0i8.i32(dst, src, size, false). // like llvm.memmove.p0.p0.i32(dst, src, size, false).
func memmove(dst, src unsafe.Pointer, size uintptr) func memmove(dst, src unsafe.Pointer, size uintptr)
// Set the given number of bytes to zero. // Set the given number of bytes to zero.
// This function is implemented by the compiler as a call to a LLVM intrinsic // This function is implemented by the compiler as a call to a LLVM intrinsic
// like llvm.memset.p0i8.i32(ptr, 0, size, false). // like llvm.memset.p0.i32(ptr, 0, size, false).
func memzero(ptr unsafe.Pointer, size uintptr) func memzero(ptr unsafe.Pointer, size uintptr)
// This intrinsic returns the current stack pointer. // This intrinsic returns the current stack pointer.

Просмотреть файл

@ -1,6 +1,6 @@
{ {
"inherits": ["riscv32"], "inherits": ["riscv32"],
"features": "+c,+m", "features": "+c,+m,-relax,-save-restore",
"build-tags": ["esp32c3", "esp"], "build-tags": ["esp32c3", "esp"],
"serial": "uart", "serial": "uart",
"rtlib": "compiler-rt", "rtlib": "compiler-rt",

Просмотреть файл

@ -1,6 +1,6 @@
{ {
"inherits": ["riscv32"], "inherits": ["riscv32"],
"cpu": "sifive-e31", "cpu": "sifive-e31",
"features": "+a,+c,+m", "features": "+a,+c,+m,-64bit,-relax,-save-restore",
"build-tags": ["fe310", "sifive"] "build-tags": ["fe310", "sifive"]
} }

Просмотреть файл

@ -1,6 +1,6 @@
{ {
"inherits": ["riscv64"], "inherits": ["riscv64"],
"features": "+64bit,+a,+c,+d,+f,+m", "features": "+64bit,+a,+c,+d,+f,+m,-relax,-save-restore",
"build-tags": ["k210", "kendryte"], "build-tags": ["k210", "kendryte"],
"code-model": "medium" "code-model": "medium"
} }

Просмотреть файл

@ -1,6 +1,6 @@
{ {
"inherits": ["riscv32"], "inherits": ["riscv32"],
"features": "+a,+c,+m", "features": "+a,+c,+m,-relax,-save-restore",
"build-tags": ["virt", "qemu"], "build-tags": ["virt", "qemu"],
"default-stack-size": 4096, "default-stack-size": 4096,
"linkerscript": "targets/riscv-qemu.ld", "linkerscript": "targets/riscv-qemu.ld",

Просмотреть файл

@ -305,7 +305,9 @@ func (p *lowerInterfacesPass) addTypeMethods(t *typeInfo, methodSet llvm.Value)
// no methods or methods already read // no methods or methods already read
return return
} }
methodSet = methodSet.Operand(0) // get global from GEP if !methodSet.IsAConstantExpr().IsNil() && methodSet.Opcode() == llvm.GetElementPtr {
methodSet = methodSet.Operand(0) // get global from GEP, for LLVM 14 (non-opaque pointers)
}
// This type has methods, collect all methods of this type. // This type has methods, collect all methods of this type.
t.methodSet = methodSet t.methodSet = methodSet

Просмотреть файл

@ -36,9 +36,8 @@ func LowerInterrupts(mod llvm.Module) []error {
handleMap := map[int64][]llvm.Value{} handleMap := map[int64][]llvm.Value{}
handleType := mod.GetTypeByName("runtime/interrupt.handle") handleType := mod.GetTypeByName("runtime/interrupt.handle")
if !handleType.IsNil() { if !handleType.IsNil() {
handlePtrType := llvm.PointerType(handleType, 0)
for global := mod.FirstGlobal(); !global.IsNil(); global = llvm.NextGlobal(global) { for global := mod.FirstGlobal(); !global.IsNil(); global = llvm.NextGlobal(global) {
if global.Type() != handlePtrType { if global.GlobalValueType() != handleType {
continue continue
} }

Просмотреть файл

@ -80,6 +80,12 @@ func replaceGlobalIntWithArray(mod llvm.Module, name string, buf interface{}) ll
// stripPointerCasts strips instruction pointer casts (getelementptr and // stripPointerCasts strips instruction pointer casts (getelementptr and
// bitcast) and returns the original value without the casts. // bitcast) and returns the original value without the casts.
func stripPointerCasts(value llvm.Value) llvm.Value { func stripPointerCasts(value llvm.Value) llvm.Value {
if !value.IsAConstantExpr().IsNil() {
switch value.Opcode() {
case llvm.GetElementPtr, llvm.BitCast:
return stripPointerCasts(value.Operand(0))
}
}
if !value.IsAInstruction().IsNil() { if !value.IsAInstruction().IsNil() {
switch value.InstructionOpcode() { switch value.InstructionOpcode() {
case llvm.GetElementPtr, llvm.BitCast: case llvm.GetElementPtr, llvm.BitCast:

Просмотреть файл

@ -251,7 +251,10 @@ func LowerReflect(mod llvm.Module) {
// a pointer to a runtime.structField array and therefore a // a pointer to a runtime.structField array and therefore a
// bitcast. This global should be erased separately, otherwise // bitcast. This global should be erased separately, otherwise
// typecode objects cannot be erased. // typecode objects cannot be erased.
structFields := references.Operand(0) structFields := references
if !structFields.IsAConstantExpr().IsNil() && structFields.Opcode() == llvm.BitCast {
structFields = structFields.Operand(0) // get global from bitcast, for LLVM 14 compatibility (non-opaque pointers)
}
structFields.EraseFromParentAsGlobal() structFields.EraseFromParentAsGlobal()
} }
} }
@ -460,7 +463,7 @@ func (state *typeCodeAssignmentState) getStructTypeNum(typecode llvm.Value) int
// Get the fields this struct type contains. // Get the fields this struct type contains.
// The struct number will be the start index of // The struct number will be the start index of
structTypeGlobal := state.builder.CreateExtractValue(typecode.Initializer(), 0, "").Operand(0).Initializer() structTypeGlobal := stripPointerCasts(state.builder.CreateExtractValue(typecode.Initializer(), 0, "")).Initializer()
numFields := structTypeGlobal.Type().ArrayLength() numFields := structTypeGlobal.Type().ArrayLength()
// The first data that is stored in the struct sidetable is the number of // The first data that is stored in the struct sidetable is the number of
@ -483,7 +486,7 @@ func (state *typeCodeAssignmentState) getStructTypeNum(typecode llvm.Value) int
if nameGlobal == llvm.ConstPointerNull(nameGlobal.Type()) { if nameGlobal == llvm.ConstPointerNull(nameGlobal.Type()) {
panic("compiler: no name for this struct field") panic("compiler: no name for this struct field")
} }
fieldNameBytes := getGlobalBytes(nameGlobal.Operand(0), state.builder) fieldNameBytes := getGlobalBytes(stripPointerCasts(nameGlobal), state.builder)
fieldNameNumber := state.getStructNameNumber(fieldNameBytes) fieldNameNumber := state.getStructNameNumber(fieldNameBytes)
// See whether this struct field has an associated tag, and if so, // See whether this struct field has an associated tag, and if so,
@ -493,7 +496,7 @@ func (state *typeCodeAssignmentState) getStructTypeNum(typecode llvm.Value) int
tagNumber := 0 tagNumber := 0
if tagGlobal != llvm.ConstPointerNull(tagGlobal.Type()) { if tagGlobal != llvm.ConstPointerNull(tagGlobal.Type()) {
hasTag = true hasTag = true
tagBytes := getGlobalBytes(tagGlobal.Operand(0), state.builder) tagBytes := getGlobalBytes(stripPointerCasts(tagGlobal), state.builder)
tagNumber = state.getStructNameNumber(tagBytes) tagNumber = state.getStructNameNumber(tagBytes)
} }

Просмотреть файл

@ -139,14 +139,13 @@ func OptimizeReflectImplements(mod llvm.Module) {
if call.IsACallInst().IsNil() { if call.IsACallInst().IsNil() {
continue continue
} }
interfaceTypeBitCast := call.Operand(2) interfaceType := stripPointerCasts(call.Operand(2))
if interfaceTypeBitCast.IsAConstantExpr().IsNil() || interfaceTypeBitCast.Opcode() != llvm.BitCast { if interfaceType.IsAGlobalVariable().IsNil() {
// The asserted interface is not constant, so can't optimize this // The asserted interface is not constant, so can't optimize this
// code. // code.
continue continue
} }
interfaceType := interfaceTypeBitCast.Operand(0)
if strings.HasPrefix(interfaceType.Name(), "reflect/types.type:named:") { if strings.HasPrefix(interfaceType.Name(), "reflect/types.type:named:") {
// Get the underlying type. // Get the underlying type.
interfaceType = builder.CreateExtractValue(interfaceType.Initializer(), 0, "") interfaceType = builder.CreateExtractValue(interfaceType.Initializer(), 0, "")