From aff2665cd7e863e77f110fdc1b010f43367de0b6 Mon Sep 17 00:00:00 2001 From: ZhouGuangyuan Date: Thu, 30 Jul 2026 08:06:38 +0800 Subject: [PATCH 01/73] build: split package compilation stages --- internal/build/build.go | 291 +++++++++++++++++---------- internal/build/collect.go | 43 ++-- internal/build/dependencies.go | 50 +++++ internal/build/dependencies_test.go | 46 +++++ internal/build/package_build.go | 64 ++++++ internal/build/package_build_test.go | 101 ++++++++++ 6 files changed, 475 insertions(+), 120 deletions(-) create mode 100644 internal/build/dependencies.go create mode 100644 internal/build/dependencies_test.go create mode 100644 internal/build/package_build.go create mode 100644 internal/build/package_build_test.go diff --git a/internal/build/build.go b/internal/build/build.go index 9607c9d00a..4e4d78d5bc 100644 --- a/internal/build/build.go +++ b/internal/build/build.go @@ -347,6 +347,13 @@ func (c *Config) packageMetaEnabled() bool { return c.CollectPackageMeta || c.deadcodeDropEnabled() } +func (c *Config) parallelism() int { + if c != nil && c.BuildParallelism > 0 { + return c.BuildParallelism + } + return max(1, runtime.GOMAXPROCS(0)) +} + // ----------------------------------------------------------------------------- const ( @@ -597,7 +604,7 @@ func Build(inv Invocation) ([]Package, error) { } progSSA := ssa.NewProgram(initial[0].Fset, buildMode) patches := make(cl.Patches, len(altPkgPaths)) - altSSAPkgs(progSSA, patches, altPkgs[1:], conf, verbose) + altEntries := registerAltSSAPkgs(progSSA, patches, altPkgs[1:], conf, verbose) output := conf.OutFile != "" ctx := &context{conf: cfg, progSSA: progSSA, prog: prog, dedup: dedup, @@ -619,14 +626,15 @@ func Build(inv Invocation) ([]Package, error) { // default runtime globals must be registered before packages are built addGlobalString(conf, "runtime.defaultGOROOT="+runtime.GOROOT(), nil) addGlobalString(conf, "runtime.buildVersion="+runtime.Version(), nil) - pkgs, err := buildSSAPkgs(ctx, initial, verbose) + pkgs, pkgEntries, err := registerSSAPkgs(ctx, initial, verbose) if err != nil { return nil, err } - depPkgs, err := buildSSAPkgs(ctx, altPkgs, verbose) + depPkgs, depEntries, err := registerSSAPkgs(ctx, altPkgs, verbose) if err != nil { return nil, err } + buildSSAPkgs(ctx, append(append(altEntries, pkgEntries...), depEntries...)) allPkgs := append([]*aPackage{}, pkgs...) allPkgs = append(allPkgs, depPkgs...) @@ -859,6 +867,7 @@ type context struct { callerTracking *cl.CallerTracking built map[string]none fingerprinting map[string]bool + cacheDisabled map[string]none initial []*packages.Package pkgs map[*packages.Package]Package // cache for lookup pkgByID map[string]Package // cache for lookup by pkg.ID @@ -969,106 +978,34 @@ func normalizeToArchive(ctx *context, aPkg *aPackage, verbose bool) error { } func buildAllPkgs(ctx *context, pkgs []*aPackage, verbose bool) ([]*aPackage, error) { - built := ctx.built - // Split packages into runtime tree vs others so we can defer runtime build. - var runtimePkgs []*aPackage - var normalPkgs []*aPackage + var runtimePkgs []packageBuildSpec + var normalPkgs []packageBuildSpec for _, p := range pkgs { - if isRuntimePkg(p.PkgPath) { - runtimePkgs = append(runtimePkgs, p) + spec := newPackageBuildSpec(p) + if spec.runtime { + runtimePkgs = append(runtimePkgs, spec) } else { - normalPkgs = append(normalPkgs, p) + normalPkgs = append(normalPkgs, spec) } } var needRuntime, needPyInit bool - buildOne := func(aPkg *aPackage) error { - pkg := aPkg.Package - if _, ok := built[pkg.ID]; ok { - // Already built, skip but keep ExportFile for linking - return nil - } - built[pkg.ID] = none{} - - switch kind, param := cl.PkgKindOf(pkg.Types); kind { - case cl.PkgDeclOnly: - pkg.ExportFile = "" - case cl.PkgLinkIR, cl.PkgLinkExtern, cl.PkgPyModule: - if len(pkg.GoFiles) > 0 { - if err := ctx.collectFingerprint(aPkg); err != nil { - return err - } - ctx.tryLoadFromCache(aPkg) - if verbose { - if aPkg.CacheHit { - fmt.Fprintf(os.Stderr, "CACHE HIT: %s\n", pkg.PkgPath) - } else { - fmt.Fprintf(os.Stderr, "CACHE MISS: %s\n", pkg.PkgPath) - } - } - if err := buildPkg(ctx, aPkg, verbose); err != nil { - return err - } - if !aPkg.CacheHit { - if err := normalizeToArchive(ctx, aPkg, verbose); err != nil { - return err - } - if kind == cl.PkgLinkExtern { - appendExternalLinkArgs(ctx, aPkg, param) - } - if err := ctx.saveToCache(aPkg); err != nil && verbose { - fmt.Fprintf(os.Stderr, "warning: failed to save cache for %s: %v\n", pkg.PkgPath, err) - } - } - } else { - pkg.ExportFile = "" - if kind == cl.PkgLinkExtern { - appendExternalLinkArgs(ctx, aPkg, param) - } - } - default: - if err := ctx.collectFingerprint(aPkg); err != nil { - return err - } - ctx.tryLoadFromCache(aPkg) - if verbose { - if aPkg.CacheHit { - fmt.Fprintf(os.Stderr, "CACHE HIT: %s\n", pkg.PkgPath) - } else { - fmt.Fprintf(os.Stderr, "CACHE MISS: %s\n", pkg.PkgPath) - } - } - if err := buildPkg(ctx, aPkg, verbose); err != nil { - return err - } - aPkg.setNeedRuntimeOrPyInit(aPkg.LPkg.NeedRuntime, aPkg.LPkg.NeedPyInit) - needRuntime = needRuntime || aPkg.NeedRt - needPyInit = needPyInit || aPkg.NeedPyInit - if !aPkg.CacheHit { - if err := normalizeToArchive(ctx, aPkg, verbose); err != nil { - return err - } - if err := ctx.saveToCache(aPkg); err != nil && verbose { - fmt.Fprintf(os.Stderr, "warning: failed to save cache for %s: %v\n", pkg.PkgPath, err) - } - } - } - return nil - } - // Build non-runtime packages first, so we know whether runtime is actually needed. - for _, p := range normalPkgs { - if err := buildOne(p); err != nil { + for _, spec := range normalPkgs { + result, err := buildOnePackage(ctx, spec, verbose) + if err != nil { return nil, err } + needRuntime = needRuntime || result.needRuntime + needPyInit = needPyInit || result.needPyInit } // Only build runtime packages when required (or host build with empty Target). if needRuntime || needPyInit || ctx.buildConf.Target == "" { - for _, p := range runtimePkgs { - if err := buildOne(p); err != nil { + for _, spec := range runtimePkgs { + if _, err := buildOnePackage(ctx, spec, verbose); err != nil { return nil, err } } @@ -1077,6 +1014,85 @@ func buildAllPkgs(ctx *context, pkgs []*aPackage, verbose bool) ([]*aPackage, er return pkgs, nil } +// buildOnePackage is the serial package pipeline. Its explicit stages are the +// contract used by later package workers; this commit deliberately preserves +// serial LLVM execution. +func buildOnePackage(ctx *context, spec packageBuildSpec, verbose bool) (packageBuildResult, error) { + skip, err := preflightPackageBuild(ctx, spec, verbose) + if err != nil || skip { + return packageBuildResultFor(spec), err + } + if err := executePackageBuild(ctx, spec, verbose); err != nil { + return packageBuildResultFor(spec), err + } + return finalizePackageBuild(ctx, spec, verbose) +} + +// preflightPackageBuild performs classification, fingerprinting, and cache +// lookup without creating or transforming an LLVM module. +func preflightPackageBuild(ctx *context, spec packageBuildSpec, verbose bool) (skip bool, err error) { + aPkg := spec.pkg + pkg := aPkg.Package + if _, ok := ctx.built[pkg.ID]; ok { + return true, nil + } + ctx.built[pkg.ID] = none{} + if spec.isDeclOnly() { + pkg.ExportFile = "" + return true, nil + } + if spec.isLinkOnly() && !spec.hasSource() { + pkg.ExportFile = "" + if spec.kind == cl.PkgLinkExtern { + appendExternalLinkArgs(ctx, aPkg, spec.kindParam) + } + return true, nil + } + if err := ctx.collectFingerprint(aPkg); err != nil { + return false, err + } + ctx.tryLoadFromCache(aPkg) + if verbose { + status := "MISS" + if aPkg.CacheHit { + status = "HIT" + } + fmt.Fprintf(os.Stderr, "CACHE %s: %s\n", status, pkg.PkgPath) + } + return false, nil +} + +// executePackageBuild creates the package module and runs its LLVM backend. +func executePackageBuild(ctx *context, spec packageBuildSpec, verbose bool) error { + aPkg := spec.pkg + if err := buildPkg(ctx, aPkg, verbose); err != nil { + return err + } + if spec.needsRuntimeSignals() { + aPkg.setNeedRuntimeOrPyInit(aPkg.LPkg.NeedRuntime, aPkg.LPkg.NeedPyInit) + } + return nil +} + +// finalizePackageBuild publishes the archive and cache metadata. Cache hits +// already carry both and therefore require no publication. +func finalizePackageBuild(ctx *context, spec packageBuildSpec, verbose bool) (packageBuildResult, error) { + aPkg := spec.pkg + if aPkg.CacheHit { + return packageBuildResultFor(spec), nil + } + if err := normalizeToArchive(ctx, aPkg, verbose); err != nil { + return packageBuildResultFor(spec), err + } + if spec.kind == cl.PkgLinkExtern { + appendExternalLinkArgs(ctx, aPkg, spec.kindParam) + } + if err := ctx.saveToCache(aPkg); err != nil && verbose { + fmt.Fprintf(os.Stderr, "warning: failed to save cache for %s: %v\n", aPkg.PkgPath, err) + } + return packageBuildResultFor(spec), nil +} + func appendExternalLinkArgs(ctx *context, aPkg *aPackage, spec string) { // need to be linked with external library // format: ';' separated alternative link methods. e.g. @@ -1790,6 +1806,15 @@ func is32Bits(goarch string) bool { } func buildPkg(ctx *context, aPkg *aPackage, verbose bool) error { + externs, err := preparePackageModule(ctx, aPkg, verbose) + if err != nil || aPkg.CacheHit || aPkg.LPkg == nil { + return err + } + return compilePackageModule(ctx, aPkg, externs, verbose) +} + +// preparePackageModule runs the frontend and creates the package LLVM module. +func preparePackageModule(ctx *context, aPkg *aPackage, verbose bool) ([]string, error) { pkg := aPkg.Package pkgPath := pkg.PkgPath if debugBuild || verbose { @@ -1799,7 +1824,7 @@ func buildPkg(ctx *context, aPkg *aPackage, verbose bool) error { } if llruntime.SkipToBuild(pkgPath) { pkg.ExportFile = "" - return nil + return nil, nil } var syntax = pkg.Syntax if altPkg := aPkg.AltPkg; altPkg != nil { @@ -1812,7 +1837,7 @@ func buildPkg(ctx *context, aPkg *aPackage, verbose bool) error { } embedMap, err := goembed.LoadDirectives(ctx.conf.Fset, syntax) if err != nil { - return fmt.Errorf("load go:embed directives for %s failed: %w", pkgPath, err) + return nil, fmt.Errorf("load go:embed directives for %s failed: %w", pkgPath, err) } ret, externs, err := cl.NewPackageExWithEmbedMetaOptions( ctx.prog, ctx.callerTracking, ctx.patches, aPkg.rewriteVars, @@ -1829,8 +1854,16 @@ func buildPkg(ctx *context, aPkg *aPackage, verbose bool) error { // If cache hit, we only needed to register types - skip compilation if aPkg.CacheHit { - return nil + return nil, nil } + return externs, nil +} + +// compilePackageModule applies LLVM transforms and emits package objects. +func compilePackageModule(ctx *context, aPkg *aPackage, externs []string, verbose bool) error { + pkg := aPkg.Package + pkgPath := pkg.PkgPath + ret := aPkg.LPkg ctx.cTransformer.SetSkipFuncs(cabiSkipFuncsForPlan9Asm(ctx, pkgPath, ret.Module())) llabi.LowerLargeAggregates(ctx.prog.TargetData(), ret.Module()) @@ -1844,7 +1877,7 @@ func buildPkg(ctx *context, aPkg *aPackage, verbose bool) error { mod.SetTarget(ctx.prog.Target().Spec().Triple) pbo := gllvm.NewPassBuilderOptions() defer pbo.Dispose() - if err = gllvm.VerifyModule(mod, gllvm.ReturnStatusAction); err != nil { + if err := gllvm.VerifyModule(mod, gllvm.ReturnStatusAction); err != nil { return fmt.Errorf("verify LLVM module for %v failed: %w", pkgPath, err) } if err := mod.RunPasses(llvmPassPipeline(ctx.buildConf.OptLevel, ctx.buildConf.ltoMode()), ctx.prog.TargetMachine(), pbo); err != nil { @@ -2129,13 +2162,21 @@ func prepareLocalVariables(prog llssa.Program, groups ...[]*packages.Package) er return nil } -func altSSAPkgs(prog *ssa.Program, patches cl.Patches, alts []*packages.Package, conf *Config, verbose bool) { +type ssaBuildEntry struct { + pkg *ssa.Package + syntax []*ast.File + fixOrder bool +} + +func registerAltSSAPkgs(prog *ssa.Program, patches cl.Patches, alts []*packages.Package, conf *Config, verbose bool) []ssaBuildEntry { + var entries []ssaBuildEntry packages.Visit(alts, nil, func(p *packages.Package) { if typs := p.Types; typs != nil && !p.IllTyped { if debugBuild || verbose { log.Println("==> BuildSSA", p.ID) } pkgSSA := prog.CreatePackage(typs, p.Syntax, p.TypesInfo, true) + entries = append(entries, ssaBuildEntry{pkg: pkgSSA, syntax: p.Syntax}) if strings.HasPrefix(p.ID, altPkgPathPrefix) { path := p.ID[len(altPkgPathPrefix):] // Even if an alt package exists and is pulled in as a dependency of other @@ -2151,7 +2192,7 @@ func altSSAPkgs(prog *ssa.Program, patches cl.Patches, alts []*packages.Package, } } }) - prog.Build() + return entries } type aPackage struct { @@ -2177,9 +2218,10 @@ type aPackage struct { type Package = *aPackage -func buildSSAPkgs(ctx *context, initial []*packages.Package, verbose bool) ([]*aPackage, error) { +func registerSSAPkgs(ctx *context, initial []*packages.Package, verbose bool) ([]*aPackage, []ssaBuildEntry, error) { prog := ctx.progSSA var all []*aPackage + var entries []ssaBuildEntry var errs []*packages.Package packages.Visit(initial, nil, func(p *packages.Package) { if p.Types != nil && !p.IllTyped { @@ -2189,7 +2231,10 @@ func buildSSAPkgs(ctx *context, initial []*packages.Package, verbose bool) ([]*a return } var altPkg *packages.Cached - var ssaPkg = createSSAPkg(ctx, prog, p, verbose) + ssaPkg, created := createSSAPkg(ctx, prog, p, verbose) + if created { + entries = append(entries, ssaBuildEntry{pkg: ssaPkg, syntax: p.Syntax, fixOrder: true}) + } if ctx.hasAltPkg(pkgPath) { if altPkg = ctx.dedup.Check(altPkgPathPrefix + pkgPath); altPkg == nil { return @@ -2221,9 +2266,51 @@ func buildSSAPkgs(ctx *context, initial []*packages.Package, verbose bool) ([]*a } fmt.Fprintln(os.Stderr, "cannot build SSA for package", errPkg) } - return nil, fmt.Errorf("cannot build SSA for packages") + return nil, nil, fmt.Errorf("cannot build SSA for packages") + } + return all, entries, nil +} + +// buildSSAPkgs builds registered packages with the requested bound, then +// performs ordering repair serially because it mutates instruction slices. +func buildSSAPkgs(ctx *context, entries []ssaBuildEntry) { + if len(entries) == 0 { + return + } + unique := make([]ssaBuildEntry, 0, len(entries)) + index := make(map[*ssa.Package]int, len(entries)) + for _, entry := range entries { + if entry.pkg == nil { + continue + } + if i, ok := index[entry.pkg]; ok { + unique[i].fixOrder = unique[i].fixOrder || entry.fixOrder + continue + } + index[entry.pkg] = len(unique) + unique = append(unique, entry) + } + jobs := make(chan ssaBuildEntry, len(unique)) + var wg sync.WaitGroup + for range min(ctx.buildConf.parallelism(), len(unique)) { + wg.Add(1) + go func() { + defer wg.Done() + for entry := range jobs { + entry.pkg.Build() + } + }() + } + for _, entry := range unique { + jobs <- entry + } + close(jobs) + wg.Wait() + for _, entry := range unique { + if entry.fixOrder { + fixSSAOrder(entry.pkg, entry.syntax) + } } - return all, nil } func formatPackageError(err packages.Error, noColumn bool) string { @@ -2371,7 +2458,7 @@ func applyPatches(ctx *context, p *packages.Package, verbose bool) { } } -func createSSAPkg(ctx *context, prog *ssa.Program, p *packages.Package, verbose bool) *ssa.Package { +func createSSAPkg(ctx *context, prog *ssa.Program, p *packages.Package, verbose bool) (*ssa.Package, bool) { pkgSSA := prog.ImportedPackage(p.ID) if pkgSSA == nil { if debugBuild || verbose { @@ -2379,11 +2466,9 @@ func createSSAPkg(ctx *context, prog *ssa.Program, p *packages.Package, verbose } applyPatches(ctx, p, verbose) pkgSSA = prog.CreatePackage(p.Types, p.Syntax, p.TypesInfo, true) - pkgSSA.Build() // TODO(xsw): build concurrently - // Apply local SSA fixups once when package SSA is first built. - fixSSAOrder(pkgSSA, p.Syntax) + return pkgSSA, true } - return pkgSSA + return pkgSSA, false } /* diff --git a/internal/build/collect.go b/internal/build/collect.go index 66da887c21..d8dcee7b1f 100644 --- a/internal/build/collect.go +++ b/internal/build/collect.go @@ -23,7 +23,6 @@ import ( "os/exec" "path/filepath" "runtime" - "sort" "strconv" "strings" @@ -42,7 +41,11 @@ func (c *context) collectFingerprint(pkg *aPackage) error { c.fingerprinting = make(map[string]bool) } if c.fingerprinting[pkg.ID] { - return fmt.Errorf("fingerprint cycle detected for %s", pkg.ID) + // Alternate runtime replacements can close a cycle after the complete + // SSA graph is registered. Such a cycle has no stable per-package key, + // so rebuild its members instead of reporting a false cache hit. + c.disablePackageCache(c.fingerprinting) + return nil } c.fingerprinting[pkg.ID] = true defer delete(c.fingerprinting, pkg.ID) @@ -70,6 +73,20 @@ func (c *context) collectFingerprint(pkg *aPackage) error { return nil } +func (c *context) disablePackageCache(pkgs map[string]bool) { + if c.cacheDisabled == nil { + c.cacheDisabled = make(map[string]none, len(pkgs)) + } + for id := range pkgs { + c.cacheDisabled[id] = none{} + } +} + +func (c *context) packageCacheDisabled(id string) bool { + _, disabled := c.cacheDisabled[id] + return disabled +} + // collectEnvInputs collects environment-related inputs. func (c *context) collectEnvInputs(m *manifestBuilder) { m.env.Goos = c.buildConf.Goos @@ -197,21 +214,7 @@ func (c *context) collectPackageInputs(m *manifestBuilder, pkg *aPackage) error // collectDependencyInputs adds dependency fingerprints/versions into manifest. func (c *context) collectDependencyInputs(m *manifestBuilder, pkg *aPackage) error { - if len(pkg.Imports) == 0 { - return nil - } - - deps := make([]*packages.Package, 0, len(pkg.Imports)) - for _, dep := range pkg.Imports { - if dep == nil || dep.ID == pkg.ID { - continue - } - deps = append(deps, dep) - } - - sort.Slice(deps, func(i, j int) bool { return deps[i].ID < deps[j].ID }) - - for _, dep := range deps { + for _, dep := range effectiveDependencies(pkg) { depEntry, err := c.dependencyFingerprint(dep) if err != nil { return err @@ -328,6 +331,9 @@ func (c *context) tryLoadFromCache(pkg *aPackage) bool { if !cacheEnabled() { return false } + if c.packageCacheDisabled(pkg.ID) { + return false + } // Main packages are intentionally not written to the build cache because // each executable's entry module is linked against the current main archive. @@ -453,6 +459,9 @@ func (c *context) saveToCache(pkg *aPackage) error { if !cacheEnabled() { return nil } + if c.packageCacheDisabled(pkg.ID) { + return nil + } if pkg.Fingerprint == "" || pkg.Manifest == "" { return nil diff --git a/internal/build/dependencies.go b/internal/build/dependencies.go new file mode 100644 index 0000000000..39f5233217 --- /dev/null +++ b/internal/build/dependencies.go @@ -0,0 +1,50 @@ +/* + * Copyright (c) 2026 The XGo Authors (xgo.dev). All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package build + +import ( + "sort" + + "github.com/goplus/llgo/internal/packages" +) + +// effectiveDependencies returns every package whose source contributes to an +// aPackage. Alternate packages may add imports absent from the original graph. +func effectiveDependencies(pkg *aPackage) []*packages.Package { + if pkg == nil || pkg.Package == nil { + return nil + } + deps := make(map[string]*packages.Package) + add := func(imports map[string]*packages.Package) { + for _, dep := range imports { + if dep == nil || dep.ID == pkg.ID || (pkg.AltPkg != nil && dep.ID == pkg.AltPkg.ID) { + continue + } + deps[dep.ID] = dep + } + } + add(pkg.Imports) + if pkg.AltPkg != nil { + add(pkg.AltPkg.Imports) + } + ret := make([]*packages.Package, 0, len(deps)) + for _, dep := range deps { + ret = append(ret, dep) + } + sort.Slice(ret, func(i, j int) bool { return ret[i].ID < ret[j].ID }) + return ret +} diff --git a/internal/build/dependencies_test.go b/internal/build/dependencies_test.go new file mode 100644 index 0000000000..7f083eb13d --- /dev/null +++ b/internal/build/dependencies_test.go @@ -0,0 +1,46 @@ +/* + * Copyright (c) 2026 The XGo Authors (xgo.dev). All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package build + +import ( + "reflect" + "testing" + + "github.com/goplus/llgo/internal/packages" +) + +func TestEffectiveDependenciesIncludesAlternateImports(t *testing.T) { + base := &packages.Package{ID: "base"} + shared := &packages.Package{ID: "shared"} + altOnly := &packages.Package{ID: "alt-only"} + alt := &packages.Package{ + ID: "alt", + Imports: map[string]*packages.Package{"shared": shared, "alt-only": altOnly}, + } + pkg := &aPackage{ + Package: &packages.Package{ID: "pkg", Imports: map[string]*packages.Package{"base": base, "shared": shared}}, + AltPkg: &packages.Cached{Package: alt}, + } + deps := effectiveDependencies(pkg) + got := make([]string, len(deps)) + for i, dep := range deps { + got[i] = dep.ID + } + if want := []string{"alt-only", "base", "shared"}; !reflect.DeepEqual(got, want) { + t.Fatalf("effectiveDependencies = %v, want %v", got, want) + } +} diff --git a/internal/build/package_build.go b/internal/build/package_build.go new file mode 100644 index 0000000000..a5ccc0ab38 --- /dev/null +++ b/internal/build/package_build.go @@ -0,0 +1,64 @@ +/* + * Copyright (c) 2026 The XGo Authors (xgo.dev). All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package build + +import "github.com/goplus/llgo/cl" + +type packageBuildSpec struct { + pkg *aPackage + kind int + kindParam string + runtime bool +} + +func newPackageBuildSpec(pkg *aPackage) packageBuildSpec { + kind, kindParam := cl.PkgKindOf(pkg.Types) + return packageBuildSpec{ + pkg: pkg, + kind: kind, + kindParam: kindParam, + runtime: isRuntimePkg(pkg.PkgPath), + } +} + +func (s packageBuildSpec) isDeclOnly() bool { + return s.kind == cl.PkgDeclOnly +} + +func (s packageBuildSpec) isLinkOnly() bool { + return s.kind == cl.PkgLinkIR || s.kind == cl.PkgLinkExtern || s.kind == cl.PkgPyModule +} + +func (s packageBuildSpec) hasSource() bool { + return len(s.pkg.GoFiles) > 0 +} + +func (s packageBuildSpec) needsRuntimeSignals() bool { + return !s.isLinkOnly() && !s.isDeclOnly() +} + +type packageBuildResult struct { + needRuntime bool + needPyInit bool +} + +func packageBuildResultFor(spec packageBuildSpec) packageBuildResult { + return packageBuildResult{ + needRuntime: spec.pkg.NeedRt, + needPyInit: spec.pkg.NeedPyInit, + } +} diff --git a/internal/build/package_build_test.go b/internal/build/package_build_test.go new file mode 100644 index 0000000000..c2c160ceeb --- /dev/null +++ b/internal/build/package_build_test.go @@ -0,0 +1,101 @@ +/* + * Copyright (c) 2026 The XGo Authors (xgo.dev). All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package build + +import ( + "go/ast" + "go/parser" + "go/token" + "go/types" + "path/filepath" + "strings" + "testing" + + "github.com/goplus/llgo/internal/env" + "github.com/goplus/llgo/internal/packages" +) + +func TestPackageBuildSpecAndResult(t *testing.T) { + pkg := &aPackage{Package: &packages.Package{ + PkgPath: "example.com/p", + GoFiles: []string{"p.go"}, + Types: types.NewPackage("example.com/p", "p"), + }, NeedRt: true, NeedPyInit: true} + spec := newPackageBuildSpec(pkg) + if spec.isDeclOnly() || spec.isLinkOnly() || !spec.hasSource() || spec.runtime || !spec.needsRuntimeSignals() { + t.Fatalf("unexpected normal package spec: %+v", spec) + } + result := packageBuildResultFor(spec) + if !result.needRuntime || !result.needPyInit { + t.Fatalf("unexpected package result: %+v", result) + } +} + +func TestPackageBuildSpecSpecialKinds(t *testing.T) { + decl := newPackageBuildSpec(&aPackage{Package: &packages.Package{ + PkgPath: "unsafe", + Types: types.Unsafe, + }}) + if !decl.isDeclOnly() || decl.needsRuntimeSignals() { + t.Fatalf("unexpected declaration-only spec: %+v", decl) + } + runtime := newPackageBuildSpec(&aPackage{Package: &packages.Package{ + PkgPath: env.LLGoRuntimePkg, + Types: types.NewPackage(env.LLGoRuntimePkg, "runtime"), + }}) + if !runtime.runtime { + t.Fatalf("runtime package was not marked runtime: %+v", runtime) + } +} + +func TestConfigParallelism(t *testing.T) { + if got := (&Config{BuildParallelism: 3}).parallelism(); got != 3 { + t.Fatalf("parallelism = %d, want 3", got) + } + if got := (&Config{}).parallelism(); got < 1 { + t.Fatalf("default parallelism = %d, want positive value", got) + } +} + +func TestPreparePackageModuleReturnsEmbedError(t *testing.T) { + fset := token.NewFileSet() + filename := filepath.Join(t.TempDir(), "p.go") + file, err := parser.ParseFile(fset, filename, `package p + +//go:embed missing.txt +var content string +`, parser.ParseComments) + if err != nil { + t.Fatal(err) + } + pkg := &aPackage{Package: &packages.Package{ + ID: "example.com/p", + PkgPath: "example.com/p", + Syntax: []*ast.File{file}, + }} + ctx := &context{ + conf: &packages.Config{Fset: fset}, + buildConf: &Config{}, + } + externs, err := preparePackageModule(ctx, pkg, true) + if err == nil || !strings.Contains(err.Error(), "only allowed in Go files that import") { + t.Fatalf("preparePackageModule embed error = %v", err) + } + if externs != nil { + t.Fatalf("preparePackageModule externs = %v, want nil", externs) + } +} From 36de60c18a87b9b2a80447f7ee3fad08659e4c3a Mon Sep 17 00:00:00 2001 From: ZhouGuangyuan Date: Fri, 31 Jul 2026 00:39:38 +0800 Subject: [PATCH 02/73] test: cover package build stage boundaries --- internal/build/collect_test.go | 17 ++++++++ internal/build/package_build_test.go | 58 ++++++++++++++++++++++++++++ 2 files changed, 75 insertions(+) diff --git a/internal/build/collect_test.go b/internal/build/collect_test.go index d6a8c585d5..5b6294f1f4 100644 --- a/internal/build/collect_test.go +++ b/internal/build/collect_test.go @@ -135,6 +135,23 @@ func TestCollectFingerprintDeterminism(t *testing.T) { } } +func TestDisablePackageCache(t *testing.T) { + ctx := &context{} + ctx.disablePackageCache(map[string]bool{ + "example.com/a": true, + "example.com/b": false, + }) + + for _, id := range []string{"example.com/a", "example.com/b"} { + if !ctx.packageCacheDisabled(id) { + t.Fatalf("package cache for %q remains enabled", id) + } + } + if ctx.packageCacheDisabled("example.com/c") { + t.Fatal("unlisted package cache was disabled") + } +} + func TestCollectFingerprintIncludesEmitDWARF(t *testing.T) { td := t.TempDir() goFile := filepath.Join(td, "main.go") diff --git a/internal/build/package_build_test.go b/internal/build/package_build_test.go index c2c160ceeb..84988cd718 100644 --- a/internal/build/package_build_test.go +++ b/internal/build/package_build_test.go @@ -99,3 +99,61 @@ var content string t.Fatalf("preparePackageModule externs = %v, want nil", externs) } } + +func TestBuildOnePackageSkipsAlreadyBuiltPackage(t *testing.T) { + pkg := &aPackage{Package: &packages.Package{ + ID: "example.com/already-built", + PkgPath: "example.com/already-built", + GoFiles: []string{"already.go"}, + Types: types.NewPackage("example.com/already-built", "already"), + }, NeedRt: true} + ctx := &context{built: map[string]none{pkg.ID: {}}} + + result, err := buildOnePackage(ctx, newPackageBuildSpec(pkg), false) + if err != nil { + t.Fatal(err) + } + if !result.needRuntime { + t.Fatalf("build result = %+v, want runtime requirement preserved", result) + } +} + +func TestPreflightPackageBuildSkipsDeclarationOnlyPackage(t *testing.T) { + pkg := &aPackage{Package: &packages.Package{ + ID: "unsafe", + PkgPath: "unsafe", + Types: types.Unsafe, + ExportFile: "stale.a", + }} + ctx := &context{built: make(map[string]none)} + + skip, err := preflightPackageBuild(ctx, newPackageBuildSpec(pkg), false) + if err != nil { + t.Fatal(err) + } + if !skip { + t.Fatal("declaration-only package was not skipped") + } + if pkg.ExportFile != "" { + t.Fatalf("ExportFile = %q, want empty", pkg.ExportFile) + } + if _, ok := ctx.built[pkg.ID]; !ok { + t.Fatal("declaration-only package was not recorded as built") + } +} + +func TestFinalizePackageBuildReturnsCachedResult(t *testing.T) { + pkg := &aPackage{Package: &packages.Package{ + ID: "example.com/cached", + PkgPath: "example.com/cached", + Types: types.NewPackage("example.com/cached", "cached"), + }, CacheHit: true, NeedPyInit: true} + + result, err := finalizePackageBuild(&context{}, newPackageBuildSpec(pkg), false) + if err != nil { + t.Fatal(err) + } + if !result.needPyInit { + t.Fatalf("build result = %+v, want Python initialization requirement preserved", result) + } +} From 0be401463bbf0caa62f74a10fffee0aca5320674 Mon Sep 17 00:00:00 2001 From: ZhouGuangyuan Date: Fri, 31 Jul 2026 01:20:51 +0800 Subject: [PATCH 03/73] test: cover empty package dependencies --- internal/build/dependencies_test.go | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/internal/build/dependencies_test.go b/internal/build/dependencies_test.go index 7f083eb13d..78fa352e56 100644 --- a/internal/build/dependencies_test.go +++ b/internal/build/dependencies_test.go @@ -44,3 +44,9 @@ func TestEffectiveDependenciesIncludesAlternateImports(t *testing.T) { t.Fatalf("effectiveDependencies = %v, want %v", got, want) } } + +func TestEffectiveDependenciesHandlesNilPackage(t *testing.T) { + if deps := effectiveDependencies(nil); deps != nil { + t.Fatalf("effectiveDependencies(nil) = %v, want nil", deps) + } +} From d84ca29700cd063919cc7c65e0c677164eaf0671 Mon Sep 17 00:00:00 2001 From: ZhouGuangyuan Date: Fri, 31 Jul 2026 04:13:51 +0800 Subject: [PATCH 04/73] test: cover cgo command environment parsing --- internal/build/cgo_test.go | 46 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 46 insertions(+) diff --git a/internal/build/cgo_test.go b/internal/build/cgo_test.go index 91fba3f534..8ccbb79d0d 100644 --- a/internal/build/cgo_test.go +++ b/internal/build/cgo_test.go @@ -77,6 +77,52 @@ func TestParseCgoDeclFlags(t *testing.T) { } } +func TestParseCgoDeclWithCommandEnvBranches(t *testing.T) { + commands := commandEnv{dir: t.TempDir(), environ: []string{"CGO_TEST_MARKER=1"}} + tests := []struct { + name string + line string + want []cgoDecl + wantErr string + }{ + { + name: "LDFLAGS with tag", + line: "#cgo darwin LDFLAGS: -framework CoreFoundation -lz", + want: []cgoDecl{{tag: "darwin", ldflags: []string{"-framework CoreFoundation", "-lz"}}}, + }, + {name: "missing colon", line: "#cgo CFLAGS -I/missing", wantErr: "invalid cgo format"}, + {name: "missing directive", line: "CFLAGS: -I/missing", wantErr: "invalid cgo directive"}, + {name: "unsupported flag", line: "#cgo FOOFLAGS: -unsupported", wantErr: "unsupported cgo flag type"}, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + got, err := parseCgoDeclWithCommandEnv(commands, tt.line) + if tt.wantErr != "" { + if err == nil || !strings.Contains(err.Error(), tt.wantErr) { + t.Fatalf("parseCgoDeclWithCommandEnv(%q) error = %v, want %q", tt.line, err, tt.wantErr) + } + return + } + if err != nil { + t.Fatal(err) + } + if !reflect.DeepEqual(got, tt.want) { + t.Fatalf("parseCgoDeclWithCommandEnv(%q) = %#v, want %#v", tt.line, got, tt.want) + } + }) + } +} + +func TestParseCgoPreambleDelegatesToCommandEnvParser(t *testing.T) { + preamble, decls, err := parseCgoPreamble(token.Position{Filename: "request.go", Line: 7}, "#cgo CFLAGS: -I/request/include") + if err != nil { + t.Fatal(err) + } + if preamble.goFile != "request.go" || preamble.src == "" || !reflect.DeepEqual(decls, []cgoDecl{{cflags: []string{"-I/request/include"}}}) { + t.Fatalf("parseCgoPreamble() = %#v, %#v", preamble, decls) + } +} + func TestCollectCgoSymbolsStripsPackagePrefix(t *testing.T) { externs := []string{ "command-line-arguments._cgo_96608f8de8c8_Cfunc_fputs", From 6d29a370e5847a56b4ffdc422424f22d3abe7f27 Mon Sep 17 00:00:00 2001 From: ZhouGuangyuan Date: Fri, 31 Jul 2026 05:10:44 +0800 Subject: [PATCH 05/73] test: cover cgo pkg-config invocation --- internal/build/cgo_test.go | 34 ++++++++++++++++++++++++++++++++++ 1 file changed, 34 insertions(+) diff --git a/internal/build/cgo_test.go b/internal/build/cgo_test.go index 8ccbb79d0d..9127c6f92a 100644 --- a/internal/build/cgo_test.go +++ b/internal/build/cgo_test.go @@ -113,6 +113,40 @@ func TestParseCgoDeclWithCommandEnvBranches(t *testing.T) { } } +func TestParseCgoDeclWithCommandEnvPkgConfig(t *testing.T) { + if runtime.GOOS == "windows" { + t.Skip("test helper uses a shell script") + } + + dir := t.TempDir() + tool := filepath.Join(dir, "pkg-config") + script := `#!/bin/sh +if [ "$1" = "--libs" ]; then + printf '%s\n' '-L/request/lib -lrequest' + exit 0 +fi +printf '%s\n' '-I/request/include -DREQUEST="request value"' +` + if err := os.WriteFile(tool, []byte(script), 0o755); err != nil { + t.Fatal(err) + } + t.Setenv("PATH", dir) + + commands := commandEnv{dir: dir, environ: []string{"PATH=" + dir}} + got, err := parseCgoDeclWithCommandEnv(commands, "#cgo linux pkg-config: request") + if err != nil { + t.Fatal(err) + } + want := []cgoDecl{{ + tag: "linux", + cflags: []string{"-I/request/include", `-DREQUEST="request value"`}, + ldflags: []string{"-L/request/lib", "-lrequest"}, + }} + if !reflect.DeepEqual(got, want) { + t.Fatalf("parseCgoDeclWithCommandEnv(pkg-config) = %#v, want %#v", got, want) + } +} + func TestParseCgoPreambleDelegatesToCommandEnvParser(t *testing.T) { preamble, decls, err := parseCgoPreamble(token.Position{Filename: "request.go", Line: 7}, "#cgo CFLAGS: -I/request/include") if err != nil { From d24eb12a1dfc8389023036c2b93d5e5df547d0c5 Mon Sep 17 00:00:00 2001 From: ZhouGuangyuan Date: Fri, 31 Jul 2026 08:07:45 +0800 Subject: [PATCH 06/73] test: cover cgo pkg-config failures --- internal/build/cgo_test.go | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/internal/build/cgo_test.go b/internal/build/cgo_test.go index 9127c6f92a..926b30b518 100644 --- a/internal/build/cgo_test.go +++ b/internal/build/cgo_test.go @@ -121,6 +121,9 @@ func TestParseCgoDeclWithCommandEnvPkgConfig(t *testing.T) { dir := t.TempDir() tool := filepath.Join(dir, "pkg-config") script := `#!/bin/sh +if [ "$PKG_CONFIG_TEST_FAIL" = "$1" ]; then + exit 1 +fi if [ "$1" = "--libs" ]; then printf '%s\n' '-L/request/lib -lrequest' exit 0 @@ -145,6 +148,15 @@ printf '%s\n' '-I/request/include -DREQUEST="request value"' if !reflect.DeepEqual(got, want) { t.Fatalf("parseCgoDeclWithCommandEnv(pkg-config) = %#v, want %#v", got, want) } + + for _, arg := range []string{"--libs", "--cflags"} { + t.Run("failed "+arg, func(t *testing.T) { + commands := commandEnv{dir: dir, environ: []string{"PATH=" + dir, "PKG_CONFIG_TEST_FAIL=" + arg}} + if _, err := parseCgoDeclWithCommandEnv(commands, "#cgo pkg-config: request"); err == nil || !strings.Contains(err.Error(), "pkg-config") { + t.Fatalf("parseCgoDeclWithCommandEnv(pkg-config) error = %v, want pkg-config failure", err) + } + }) + } } func TestParseCgoPreambleDelegatesToCommandEnvParser(t *testing.T) { From e67a38418f41833dc1a0bd9afae719f9f3d65f25 Mon Sep 17 00:00:00 2001 From: ZhouGuangyuan Date: Fri, 31 Jul 2026 16:55:18 +0800 Subject: [PATCH 07/73] build: archive LLVM package objects in memory --- go.mod | 2 + go.sum | 4 +- internal/build/build.go | 58 ++++++++++-- internal/build/package_archive.go | 99 ++++++++++++++++++++ internal/build/package_archive_test.go | 123 +++++++++++++++++++++++++ 5 files changed, 275 insertions(+), 11 deletions(-) create mode 100644 internal/build/package_archive.go create mode 100644 internal/build/package_archive_test.go diff --git a/go.mod b/go.mod index c55f42ffd4..23ba621674 100644 --- a/go.mod +++ b/go.mod @@ -26,3 +26,5 @@ require ( ) replace github.com/goplus/llgo/runtime => ./runtime + +replace github.com/xgo-dev/llvm => github.com/zhouguangyuan0718/go-llvm v0.0.0-20260731084524-d8f8a2aa851e diff --git a/go.sum b/go.sum index db139c2acc..fa2dd992cd 100644 --- a/go.sum +++ b/go.sum @@ -22,10 +22,10 @@ github.com/qiniu/x v1.18.0 h1:iMfc7Gqy1au+akr+Tl5Z40px7TR8VBLLkJsIeajKIbc= github.com/qiniu/x v1.18.0/go.mod h1:Sx3Wy+0GI9OsX4a53mYj6A0o7mHJ94PUvraqGYb4EIs= github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk= github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= -github.com/xgo-dev/llvm v0.9.5 h1:RijI/6vGu7DGw5ldlaqvpK2uFcg9OXY9OXB/RmywtEk= -github.com/xgo-dev/llvm v0.9.5/go.mod h1:42vav2/cI5BAIcL543DZSMO9do8/aCK2z7JERH+AE+M= github.com/xgo-dev/plan9asm v0.3.5 h1:886BmpjMK6JfJ03VWA3nPK01jkVZA1a7/mZia3BOsdg= github.com/xgo-dev/plan9asm v0.3.5/go.mod h1:0yM4CCIp2PyT8h+Ro3Ukro3lHL8ji9mzHEv5yfhOckc= +github.com/zhouguangyuan0718/go-llvm v0.0.0-20260731084524-d8f8a2aa851e h1:O9Hz3E3WoZv6XXL4+4Gn1EkaEqN9+/F61WiwOJA5F5c= +github.com/zhouguangyuan0718/go-llvm v0.0.0-20260731084524-d8f8a2aa851e/go.mod h1:42vav2/cI5BAIcL543DZSMO9do8/aCK2z7JERH+AE+M= go.bug.st/serial v1.6.4 h1:7FmqNPgVp3pu2Jz5PoPtbZ9jJO5gnEnZIvnI1lzve8A= go.bug.st/serial v1.6.4/go.mod h1:nofMJxTeNVny/m6+KaafC6vJGj3miwQZ6vW4BZUGJPI= go.yaml.in/yaml/v3 v3.0.5 h1:N6y/pJk8buWs9NY5ERU2HSMfm+IuD/OtfdAnq6kESPw= diff --git a/internal/build/build.go b/internal/build/build.go index 4e4d78d5bc..44ab45aa75 100644 --- a/internal/build/build.go +++ b/internal/build/build.go @@ -622,6 +622,7 @@ func Build(inv Invocation) ([]Package, error) { cTransformer: cabi.NewTransformer(prog, export.LLVMTarget, export.TargetABI, conf.AbiMode, cabiOptimize), } defer ctx.closePackageMetas() + defer ctx.closePackageArchiveBuffers() // default runtime globals must be registered before packages are built addGlobalString(conf, "runtime.defaultGOROOT="+runtime.GOROOT(), nil) @@ -953,12 +954,13 @@ func (c *context) hasAltPkg(pkgPath string) bool { return hasAltPkgForTarget(c.buildConf, pkgPath) } -// normalizeToArchive creates an archive from object files and sets ArchiveFile. +// normalizeToArchive creates an archive from file and memory members and sets ArchiveFile. // This ensures the link step always consumes .a archives regardless of cache state. func normalizeToArchive(ctx *context, aPkg *aPackage, verbose bool) error { - if len(aPkg.ObjFiles) == 0 { + if len(aPkg.ObjFiles) == 0 && len(aPkg.ObjBuffers) == 0 { return nil } + defer aPkg.disposeArchiveBuffers() archiveFile, err := os.CreateTemp("", "pkg-*.a") if err != nil { @@ -967,7 +969,7 @@ func normalizeToArchive(ctx *context, aPkg *aPackage, verbose bool) error { archiveFile.Close() archivePath := archiveFile.Name() - if err := ctx.createArchiveFile(archivePath, aPkg.ObjFiles, verbose); err != nil { + if err := ctx.createPackageArchiveFile(archivePath, aPkg, verbose); err != nil { os.Remove(archivePath) return fmt.Errorf("create archive for %s: %w", aPkg.PkgPath, err) } @@ -1929,11 +1931,15 @@ func compilePackageModule(ctx *context, aPkg *aPackage, externs []string, verbos aPkg.LinkArgs = append(aPkg.LinkArgs, goCgoLinkArgs(ctx.buildConf.Goos, aPkg.AltPkg.Syntax)...) } if pkg.ExportFile != "" { - exportFile, err := exportObject(ctx, pkg.PkgPath, pkg.ExportFile, ret) + exportFile, exportBuffer, err := exportPackageObject(ctx, pkg.PkgPath, pkg.ExportFile, ret) if err != nil { return fmt.Errorf("export object of %v failed: %v", pkgPath, err) } - aPkg.ObjFiles = append(aPkg.ObjFiles, exportFile) + if exportFile != "" { + aPkg.ObjFiles = append(aPkg.ObjFiles, exportFile) + } else { + aPkg.ObjBuffers = append(aPkg.ObjBuffers, exportBuffer) + } if debugBuild || verbose { fmt.Fprintf(os.Stderr, "==> Export %s: %s\n", aPkg.PkgPath, pkg.ExportFile) } @@ -1954,6 +1960,28 @@ func exportObject(ctx *context, pkgPath string, exportFile string, pkg llssa.Pac return exportObjectWithClang(ctx, pkgPath, exportFile, []byte(pkg.String())) } +func exportPackageObject(ctx *context, pkgPath string, exportFile string, pkg llssa.Package) (string, packageArchiveBuffer, error) { + if !useInMemoryNativeCodegen(ctx) { + path, err := exportObjectWithClang(ctx, pkgPath, exportFile, []byte(pkg.String())) + return path, packageArchiveBuffer{}, err + } + if ctx.buildConf.CheckLLFiles || ctx.buildConf.GenLL { + if err := dumpLLVMIRIfNeeded(ctx, pkgPath, exportFile, pkg.String()); err != nil { + return "", packageArchiveBuffer{}, err + } + } + buf, kind, err := emitObjectToMemoryBuffer(ctx, pkg) + if err != nil { + return "", packageArchiveBuffer{}, err + } + name := filepath.Base(exportFile) + ".o" + if ctx.shouldPrintCommands(false) { + fmt.Fprintf(os.Stderr, "# compiling archive member %s for pkg: %s\n", name, pkgPath) + fmt.Fprintf(os.Stderr, "# using %s\n", kind) + } + return "", packageArchiveBuffer{name: name, buffer: buf}, nil +} + func useInMemoryNativeCodegen(ctx *context) bool { return useInMemoryNativeCodegenConf(ctx.buildConf) } @@ -2010,6 +2038,15 @@ func exportObjectInMemory(ctx *context, pkgPath string, exportFile string, pkg l return "", err } } + buf, kind, err := emitObjectToMemoryBuffer(ctx, pkg) + if err != nil { + return "", err + } + defer buf.Dispose() + return writeObjectBufferToFile(ctx, pkgPath, exportFile, buf, kind) +} + +func emitObjectToMemoryBuffer(ctx *context, pkg llssa.Package) (gllvm.MemoryBuffer, string, error) { ltoMode := ctx.buildConf.ltoMode() var ( buf gllvm.MemoryBuffer @@ -2028,11 +2065,13 @@ func exportObjectInMemory(ctx *context, pkgPath string, exportFile string, pkg l default: buf, err = ctx.prog.TargetMachine().EmitToMemoryBuffer(pkg.Module(), gllvm.ObjectFile) if err != nil { - return "", err + return gllvm.MemoryBuffer{}, "", err } } - defer buf.Dispose() + return buf, kind, nil +} +func writeObjectBufferToFile(ctx *context, pkgPath, exportFile string, buf gllvm.MemoryBuffer, kind string) (string, error) { base := filepath.Base(exportFile) objFile, err := os.CreateTemp("", base+"-*.o") if err != nil { @@ -2205,8 +2244,9 @@ type aPackage struct { NeedPyInit bool LinkArgs []string - ObjFiles []string // object files: .o or .ll (output of compiler, input to archiver) - ArchiveFile string // archive file: .a (output of archiver, used for linking) + ObjFiles []string // file-backed archive members: .o or .ll + ObjBuffers []packageArchiveBuffer // LLVM-produced in-memory archive members + ArchiveFile string // archive file: .a (output of archiver, used for linking) Meta *meta.PackageMeta rewriteVars map[string]string diff --git a/internal/build/package_archive.go b/internal/build/package_archive.go new file mode 100644 index 0000000000..87b732d7f5 --- /dev/null +++ b/internal/build/package_archive.go @@ -0,0 +1,99 @@ +/* + * Copyright (c) 2026 The XGo Authors (xgo.dev). All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package build + +import ( + "fmt" + "os" + "path/filepath" + + gllvm "github.com/xgo-dev/llvm" +) + +// packageArchiveBuffer owns an LLVM-produced archive member until package +// publication. +type packageArchiveBuffer struct { + name string + buffer gllvm.MemoryBuffer +} + +func (p *aPackage) disposeArchiveBuffers() { + for i := range p.ObjBuffers { + member := &p.ObjBuffers[i] + if member.buffer.IsNil() { + continue + } + member.buffer.Dispose() + member.buffer = gllvm.MemoryBuffer{} + } + p.ObjBuffers = nil +} + +func (c *context) closePackageArchiveBuffers() { + for _, pkg := range c.pkgs { + pkg.disposeArchiveBuffers() + } +} + +// createPackageArchiveFile writes path-backed auxiliary objects and +// LLVM-produced memory buffers into one archive. LLVM performs archive symbol +// indexing in-process; no temporary object is needed for memory members. +func (c *context) createPackageArchiveFile(archivePath string, pkg *aPackage, verbose bool) error { + if len(pkg.ObjFiles) == 0 && len(pkg.ObjBuffers) == 0 { + return fmt.Errorf("no object files provided for archive %s", archivePath) + } + if len(pkg.ObjBuffers) == 0 { + return c.createArchiveFile(archivePath, pkg.ObjFiles, verbose) + } + + if err := os.MkdirAll(filepath.Dir(archivePath), 0o755); err != nil { + return err + } + tmp, err := os.CreateTemp(filepath.Dir(archivePath), filepath.Base(archivePath)+".tmp-*") + if err != nil { + return err + } + tmpName := tmp.Name() + if err := tmp.Close(); err != nil { + os.Remove(tmpName) + return err + } + if err := os.Remove(tmpName); err != nil { + return err + } + + members := make([]gllvm.ArchiveMember, 0, len(pkg.ObjFiles)+len(pkg.ObjBuffers)) + for _, path := range pkg.ObjFiles { + members = append(members, gllvm.NewArchiveMemberFromFile(path)) + } + for _, member := range pkg.ObjBuffers { + members = append(members, gllvm.NewArchiveMemberFromMemoryBuffer(member.name, member.buffer)) + } + if c.shouldPrintCommands(verbose) { + fmt.Fprintf(os.Stderr, "# llvm archive %s (%d file members, %d memory members)\n", + tmpName, len(pkg.ObjFiles), len(pkg.ObjBuffers)) + } + if err := gllvm.WriteArchive(tmpName, c.targetTriple(), members); err != nil { + os.Remove(tmpName) + return fmt.Errorf("create archive %s: %w", archivePath, err) + } + if err := os.Rename(tmpName, archivePath); err != nil { + os.Remove(tmpName) + return fmt.Errorf("publish archive %s: %w", archivePath, err) + } + return nil +} diff --git a/internal/build/package_archive_test.go b/internal/build/package_archive_test.go new file mode 100644 index 0000000000..9668a9c650 --- /dev/null +++ b/internal/build/package_archive_test.go @@ -0,0 +1,123 @@ +//go:build !llgo +// +build !llgo + +/* + * Copyright (c) 2026 The XGo Authors (xgo.dev). All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package build + +import ( + "bytes" + "os" + "path/filepath" + "strings" + "testing" + + "github.com/goplus/llgo/internal/crosscompile" + "github.com/goplus/llgo/internal/packages" + gllvm "github.com/xgo-dev/llvm" +) + +func TestNormalizeToArchiveUsesMemoryBuffer(t *testing.T) { + llvmCtx := gllvm.NewContext() + defer llvmCtx.Dispose() + mod := llvmCtx.NewModule("archive") + defer mod.Dispose() + mod.SetTarget("x86_64-unknown-linux-gnu") + gllvm.AddFunction(mod, "memory_symbol", gllvm.FunctionType(llvmCtx.Int32Type(), nil, false)) + + memoryBuf := gllvm.WriteBitcodeToMemoryBuffer(mod) + ctx := &context{ + buildConf: &Config{Goos: "linux", Goarch: "amd64"}, + crossCompile: crosscompile.Export{ + LLVMTarget: "x86_64-unknown-linux-gnu", + }, + } + fileBuf := gllvm.WriteBitcodeToMemoryBuffer(mod) + defer fileBuf.Dispose() + filePath := filepath.Join(t.TempDir(), "file-member.bc") + if err := os.WriteFile(filePath, fileBuf.Bytes(), 0o644); err != nil { + memoryBuf.Dispose() + t.Fatal(err) + } + + pkg := &aPackage{ + Package: &packages.Package{PkgPath: "example.com/archive"}, + ObjFiles: []string{filePath}, + ObjBuffers: []packageArchiveBuffer{{ + name: "memory-member.bc", + buffer: memoryBuf, + }}, + } + if err := normalizeToArchive(ctx, pkg, false); err != nil { + t.Fatal(err) + } + defer os.Remove(pkg.ArchiveFile) + + if len(pkg.ObjFiles) != 0 || len(pkg.ObjBuffers) != 0 { + t.Fatalf("package members were not released: files=%v buffers=%v", pkg.ObjFiles, pkg.ObjBuffers) + } + data, err := os.ReadFile(pkg.ArchiveFile) + if err != nil { + t.Fatal(err) + } + if !bytes.HasPrefix(data, []byte("!\n")) { + t.Fatalf("archive has invalid magic: %q", data[:8]) + } + for _, name := range []string{"file-member.bc", "memory-member.bc"} { + if !bytes.Contains(data, []byte(name)) { + t.Errorf("archive does not contain member %q", name) + } + } +} + +func TestNormalizeToArchiveFailsWithoutObjectFallback(t *testing.T) { + llvmCtx := gllvm.NewContext() + defer llvmCtx.Dispose() + mod := llvmCtx.NewModule("archive-error") + defer mod.Dispose() + mod.SetTarget("x86_64-unknown-linux-gnu") + gllvm.AddFunction(mod, "memory_symbol", gllvm.FunctionType(llvmCtx.Int32Type(), nil, false)) + + memoryBuf := gllvm.WriteBitcodeToMemoryBuffer(mod) + ctx := &context{ + buildConf: &Config{Goos: "linux", Goarch: "amd64"}, + crossCompile: crosscompile.Export{ + LLVMTarget: "x86_64-unknown-linux-gnu", + }, + } + pkg := &aPackage{ + Package: &packages.Package{PkgPath: "example.com/archive-error"}, + ObjFiles: []string{filepath.Join(t.TempDir(), "missing.o")}, + ObjBuffers: []packageArchiveBuffer{{ + name: "memory-member.bc", + buffer: memoryBuf, + }}, + } + err := normalizeToArchive(ctx, pkg, false) + if err == nil { + t.Fatal("normalizeToArchive succeeded with a missing member") + } + if !strings.Contains(err.Error(), "missing.o") { + t.Fatalf("normalizeToArchive error = %v, want missing member", err) + } + if len(pkg.ObjBuffers) != 0 { + t.Fatal("memory buffer was retained after archive failure") + } + if pkg.ArchiveFile != "" { + t.Fatalf("ArchiveFile = %q after failure", pkg.ArchiveFile) + } +} From dcf4cca45c13639d9156f7d99eaabce949dd31dc Mon Sep 17 00:00:00 2001 From: ZhouGuangyuan Date: Sat, 1 Aug 2026 08:06:11 +0800 Subject: [PATCH 08/73] test: cover package stage and archive branches --- internal/build/collect_test.go | 29 ++++++++++++++++ internal/build/package_archive_test.go | 48 +++++++++++++++++++++++++- internal/build/package_build_test.go | 34 ++++++++++++++++++ 3 files changed, 110 insertions(+), 1 deletion(-) diff --git a/internal/build/collect_test.go b/internal/build/collect_test.go index 5b6294f1f4..cc9785518f 100644 --- a/internal/build/collect_test.go +++ b/internal/build/collect_test.go @@ -152,6 +152,35 @@ func TestDisablePackageCache(t *testing.T) { } } +func TestDisabledPackageCacheSkipsLoadAndSave(t *testing.T) { + t.Setenv(llgoBuildCache, "1") + pkg := &aPackage{Package: &packages.Package{ID: "example.com/disabled", PkgPath: "example.com/disabled"}} + ctx := &context{buildConf: &Config{}, cacheDisabled: map[string]none{pkg.ID: {}}} + if ctx.tryLoadFromCache(pkg) { + t.Fatal("tryLoadFromCache loaded a disabled package") + } + if err := ctx.saveToCache(pkg); err != nil { + t.Fatalf("saveToCache disabled package: %v", err) + } + + ctx.cacheDisabled = nil + ctx.buildConf.BuildMode = BuildModeCArchive + if ctx.tryLoadFromCache(pkg) { + t.Fatal("tryLoadFromCache loaded a C archive package") + } +} + +func TestCollectFingerprintDisablesCycles(t *testing.T) { + pkg := &aPackage{Package: &packages.Package{ID: "example.com/cycle", PkgPath: "example.com/cycle"}} + ctx := &context{fingerprinting: map[string]bool{pkg.ID: true}} + if err := ctx.collectFingerprint(pkg); err != nil { + t.Fatal(err) + } + if !ctx.packageCacheDisabled(pkg.ID) { + t.Fatal("fingerprint cycle did not disable package cache") + } +} + func TestCollectFingerprintIncludesEmitDWARF(t *testing.T) { td := t.TempDir() goFile := filepath.Join(td, "main.go") diff --git a/internal/build/package_archive_test.go b/internal/build/package_archive_test.go index 9668a9c650..e0d644a896 100644 --- a/internal/build/package_archive_test.go +++ b/internal/build/package_archive_test.go @@ -62,7 +62,7 @@ func TestNormalizeToArchiveUsesMemoryBuffer(t *testing.T) { buffer: memoryBuf, }}, } - if err := normalizeToArchive(ctx, pkg, false); err != nil { + if err := normalizeToArchive(ctx, pkg, true); err != nil { t.Fatal(err) } defer os.Remove(pkg.ArchiveFile) @@ -84,6 +84,52 @@ func TestNormalizeToArchiveUsesMemoryBuffer(t *testing.T) { } } +func TestPackageArchiveEdgeCases(t *testing.T) { + empty := &aPackage{} + if err := (&context{}).createPackageArchiveFile(filepath.Join(t.TempDir(), "empty.a"), empty, false); err == nil { + t.Fatal("createPackageArchiveFile succeeded without members") + } + fileOnly := &aPackage{ObjFiles: []string{filepath.Join(t.TempDir(), "missing.o")}} + if err := (&context{buildConf: &Config{Goos: "linux", Goarch: "amd64"}}).createPackageArchiveFile(filepath.Join(t.TempDir(), "file-only.a"), fileOnly, false); err == nil { + t.Fatal("file-only archive succeeded with a missing member") + } + empty.ObjBuffers = []packageArchiveBuffer{{}} + empty.disposeArchiveBuffers() + if empty.ObjBuffers != nil { + t.Fatal("disposeArchiveBuffers retained nil members") + } + + llvmCtx := gllvm.NewContext() + defer llvmCtx.Dispose() + mod := llvmCtx.NewModule("archive-errors") + defer mod.Dispose() + mod.SetTarget("x86_64-unknown-linux-gnu") + gllvm.AddFunction(mod, "archive_error_symbol", gllvm.FunctionType(llvmCtx.Int32Type(), nil, false)) + buffer := gllvm.WriteBitcodeToMemoryBuffer(mod) + defer buffer.Dispose() + pkg := &aPackage{ObjBuffers: []packageArchiveBuffer{{name: "member.bc", buffer: buffer}}} + ctx := &context{ + buildConf: &Config{Goos: "linux", Goarch: "amd64"}, + crossCompile: crosscompile.Export{LLVMTarget: "x86_64-unknown-linux-gnu"}, + } + + blocker := filepath.Join(t.TempDir(), "blocker") + if err := os.WriteFile(blocker, []byte("not a directory"), 0o644); err != nil { + t.Fatal(err) + } + if err := ctx.createPackageArchiveFile(filepath.Join(blocker, "archive.a"), pkg, false); err == nil { + t.Fatal("createPackageArchiveFile succeeded below a regular file") + } + + archiveDir := filepath.Join(t.TempDir(), "archive.a") + if err := os.Mkdir(archiveDir, 0o755); err != nil { + t.Fatal(err) + } + if err := ctx.createPackageArchiveFile(archiveDir, pkg, false); err == nil { + t.Fatal("createPackageArchiveFile replaced a directory") + } +} + func TestNormalizeToArchiveFailsWithoutObjectFallback(t *testing.T) { llvmCtx := gllvm.NewContext() defer llvmCtx.Dispose() diff --git a/internal/build/package_build_test.go b/internal/build/package_build_test.go index 84988cd718..d1ce18f415 100644 --- a/internal/build/package_build_test.go +++ b/internal/build/package_build_test.go @@ -25,8 +25,10 @@ import ( "strings" "testing" + "github.com/goplus/llgo/cl" "github.com/goplus/llgo/internal/env" "github.com/goplus/llgo/internal/packages" + "golang.org/x/tools/go/ssa" ) func TestPackageBuildSpecAndResult(t *testing.T) { @@ -142,6 +144,28 @@ func TestPreflightPackageBuildSkipsDeclarationOnlyPackage(t *testing.T) { } } +func TestPreflightPackageBuildSkipsExternalLinkOnlyPackage(t *testing.T) { + pkg := &aPackage{Package: &packages.Package{ + ID: "example.com/linkonly", + PkgPath: "example.com/linkonly", + Name: "linkonly", + Types: types.NewPackage("example.com/linkonly", "linkonly"), + ExportFile: "stale.a", + }} + ctx := &context{buildConf: &Config{}, built: make(map[string]none)} + spec := packageBuildSpec{pkg: pkg, kind: cl.PkgLinkExtern, kindParam: "-lexample"} + skip, err := preflightPackageBuild(ctx, spec, false) + if err != nil { + t.Fatal(err) + } + if !skip || pkg.ExportFile != "" { + t.Fatalf("external link-only preflight = skip %v, export %q", skip, pkg.ExportFile) + } + if len(pkg.LinkArgs) != 1 || pkg.LinkArgs[0] != "-lexample" { + t.Fatalf("external link args = %q, want [-lexample]", pkg.LinkArgs) + } +} + func TestFinalizePackageBuildReturnsCachedResult(t *testing.T) { pkg := &aPackage{Package: &packages.Package{ ID: "example.com/cached", @@ -157,3 +181,13 @@ func TestFinalizePackageBuildReturnsCachedResult(t *testing.T) { t.Fatalf("build result = %+v, want Python initialization requirement preserved", result) } } + +func TestBuildSSAPkgsEmptyAndNilEntries(t *testing.T) { + ctx := &context{buildConf: &Config{}} + buildSSAPkgs(ctx, nil) + buildSSAPkgs(ctx, []ssaBuildEntry{{}, {fixOrder: true}}) + + prog := ssa.NewProgram(token.NewFileSet(), ssa.SanityCheckFunctions) + pkg := prog.CreatePackage(types.NewPackage("example.com/ssa", "ssa"), nil, nil, true) + buildSSAPkgs(ctx, []ssaBuildEntry{{pkg: pkg}, {pkg: pkg}}) +} From 7b39688faa07f853d5326bbd688f2107c28e4fc7 Mon Sep 17 00:00:00 2001 From: ZhouGuangyuan Date: Sun, 2 Aug 2026 11:19:50 +0800 Subject: [PATCH 09/73] test: cover package pipeline error paths --- internal/build/llvm_emit_test.go | 54 +++++++++++++++++ internal/build/package_archive_test.go | 8 ++- internal/build/package_build_test.go | 81 ++++++++++++++++++++++++++ 3 files changed, 141 insertions(+), 2 deletions(-) diff --git a/internal/build/llvm_emit_test.go b/internal/build/llvm_emit_test.go index 40bfb45bb1..2e30777172 100644 --- a/internal/build/llvm_emit_test.go +++ b/internal/build/llvm_emit_test.go @@ -1,10 +1,15 @@ package build import ( + "os" + "path/filepath" "runtime" + "strings" "testing" + "github.com/goplus/llgo/internal/crosscompile" "github.com/goplus/llgo/internal/lto" + llssa "github.com/goplus/llgo/ssa" ) func TestUseInMemoryNativeCodegenConf(t *testing.T) { @@ -55,3 +60,52 @@ func TestUseInMemoryNativeCodegenConf(t *testing.T) { } }) } + +func TestExportPackageObjectErrors(t *testing.T) { + prog := llssa.NewProgram(nil) + defer prog.Dispose() + pkg := prog.NewPackage("p", "example.com/p") + + t.Run("clang", func(t *testing.T) { + ctx := &context{ + buildConf: &Config{Target: "embedded"}, + crossCompile: crosscompile.Export{ + CC: filepath.Join(t.TempDir(), "missing-clang"), + }, + commands: commandEnv{environ: os.Environ()}, + } + path, member, err := exportPackageObject(ctx, pkg.Path(), "p.o", pkg) + if path != "" { + defer os.Remove(path) + } + if err == nil { + member.buffer.Dispose() + t.Fatal("exportPackageObject succeeded with a missing clang") + } + if !member.buffer.IsNil() { + member.buffer.Dispose() + t.Fatal("clang export returned an in-memory archive member") + } + }) + + t.Run("IR dump", func(t *testing.T) { + ctx := &context{buildConf: &Config{ + Goos: runtime.GOOS, + Goarch: runtime.GOARCH, + CheckLLFiles: true, + }} + exportFile := strings.Repeat("x", 300) + path, member, err := exportPackageObject(ctx, pkg.Path(), exportFile, pkg) + if path != "" { + defer os.Remove(path) + } + if err == nil { + member.buffer.Dispose() + t.Fatal("exportPackageObject succeeded with an overlong IR dump prefix") + } + if !member.buffer.IsNil() { + member.buffer.Dispose() + t.Fatal("failed IR dump returned an in-memory archive member") + } + }) +} diff --git a/internal/build/package_archive_test.go b/internal/build/package_archive_test.go index e0d644a896..477963da86 100644 --- a/internal/build/package_archive_test.go +++ b/internal/build/package_archive_test.go @@ -120,6 +120,10 @@ func TestPackageArchiveEdgeCases(t *testing.T) { if err := ctx.createPackageArchiveFile(filepath.Join(blocker, "archive.a"), pkg, false); err == nil { t.Fatal("createPackageArchiveFile succeeded below a regular file") } + tooLong := filepath.Join(t.TempDir(), strings.Repeat("a", 300)+".a") + if err := ctx.createPackageArchiveFile(tooLong, pkg, false); err == nil { + t.Fatal("createPackageArchiveFile succeeded with an overlong temporary-file prefix") + } archiveDir := filepath.Join(t.TempDir(), "archive.a") if err := os.Mkdir(archiveDir, 0o755); err != nil { @@ -153,9 +157,9 @@ func TestNormalizeToArchiveFailsWithoutObjectFallback(t *testing.T) { buffer: memoryBuf, }}, } - err := normalizeToArchive(ctx, pkg, false) + _, err := finalizePackageBuild(ctx, packageBuildSpec{pkg: pkg}, false) if err == nil { - t.Fatal("normalizeToArchive succeeded with a missing member") + t.Fatal("finalizePackageBuild succeeded with a missing member") } if !strings.Contains(err.Error(), "missing.o") { t.Fatalf("normalizeToArchive error = %v, want missing member", err) diff --git a/internal/build/package_build_test.go b/internal/build/package_build_test.go index d1ce18f415..5a8711370d 100644 --- a/internal/build/package_build_test.go +++ b/internal/build/package_build_test.go @@ -102,6 +102,87 @@ var content string } } +func TestBuildOnePackageReturnsFrontendError(t *testing.T) { + t.Setenv(llgoBuildCache, "off") + fset := token.NewFileSet() + filename := filepath.Join(t.TempDir(), "p.go") + file, err := parser.ParseFile(fset, filename, `package p + +//go:embed missing.txt +var content string +`, parser.ParseComments) + if err != nil { + t.Fatal(err) + } + pkg := &aPackage{ + Package: &packages.Package{ + ID: "example.com/frontend-error", + PkgPath: "example.com/frontend-error", + GoFiles: []string{filename}, + Syntax: []*ast.File{file}, + Types: types.NewPackage("example.com/frontend-error", "p"), + }, + Manifest: "already fingerprinted", + Fingerprint: "frontend-error", + } + ctx := &context{ + conf: &packages.Config{Fset: fset}, + buildConf: &Config{}, + built: make(map[string]none), + } + + _, err = buildOnePackage(ctx, newPackageBuildSpec(pkg), false) + if err == nil || !strings.Contains(err.Error(), "only allowed in Go files that import") { + t.Fatalf("buildOnePackage frontend error = %v", err) + } +} + +func TestPreflightPackageBuildErrorsAndCacheHit(t *testing.T) { + t.Run("fingerprint error", func(t *testing.T) { + pkg := &aPackage{Package: &packages.Package{ + ID: "example.com/missing-source", + PkgPath: "example.com/missing-source", + GoFiles: []string{filepath.Join(t.TempDir(), "missing.go")}, + Types: types.NewPackage("example.com/missing-source", "missing"), + }} + ctx := &context{ + buildConf: &Config{}, + built: make(map[string]none), + llvmVersion: "test", + } + skip, err := preflightPackageBuild(ctx, newPackageBuildSpec(pkg), false) + if err == nil || !strings.Contains(err.Error(), "digest go files") { + t.Fatalf("preflight fingerprint error = %v", err) + } + if skip { + t.Fatal("preflight skipped package after fingerprint error") + } + }) + + t.Run("cache hit", func(t *testing.T) { + t.Setenv(llgoBuildCache, "off") + pkg := &aPackage{ + Package: &packages.Package{ + ID: "example.com/cache-hit", + PkgPath: "example.com/cache-hit", + GoFiles: []string{"cached.go"}, + Types: types.NewPackage("example.com/cache-hit", "cached"), + }, + Manifest: "already fingerprinted", + Fingerprint: "cache-hit", + CacheHit: true, + } + ctx := &context{buildConf: &Config{}, built: make(map[string]none)} + skip, err := preflightPackageBuild(ctx, newPackageBuildSpec(pkg), true) + if err != nil { + t.Fatal(err) + } + if skip || !pkg.CacheHit { + t.Fatalf("preflight cache hit = skip %v, cache hit %v", skip, pkg.CacheHit) + } + }) +} + func TestBuildOnePackageSkipsAlreadyBuiltPackage(t *testing.T) { pkg := &aPackage{Package: &packages.Package{ ID: "example.com/already-built", From 39ffae9785fefdabb1c21ea6ef487379d48e2e8f Mon Sep 17 00:00:00 2001 From: ZhouGuangyuan Date: Sun, 2 Aug 2026 13:02:30 +0800 Subject: [PATCH 10/73] build: update LLVM bindings to v0.9.6 --- go.mod | 4 +--- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 5 deletions(-) diff --git a/go.mod b/go.mod index 23ba621674..4c5087f7a1 100644 --- a/go.mod +++ b/go.mod @@ -10,7 +10,7 @@ require ( github.com/goplus/mod v0.21.1 github.com/mattn/go-tty v0.0.8 github.com/qiniu/x v1.18.0 - github.com/xgo-dev/llvm v0.9.5 + github.com/xgo-dev/llvm v0.9.6 github.com/xgo-dev/plan9asm v0.3.5 go.bug.st/serial v1.6.4 go.yaml.in/yaml/v3 v3.0.5 @@ -26,5 +26,3 @@ require ( ) replace github.com/goplus/llgo/runtime => ./runtime - -replace github.com/xgo-dev/llvm => github.com/zhouguangyuan0718/go-llvm v0.0.0-20260731084524-d8f8a2aa851e diff --git a/go.sum b/go.sum index fa2dd992cd..435f9955c4 100644 --- a/go.sum +++ b/go.sum @@ -22,10 +22,10 @@ github.com/qiniu/x v1.18.0 h1:iMfc7Gqy1au+akr+Tl5Z40px7TR8VBLLkJsIeajKIbc= github.com/qiniu/x v1.18.0/go.mod h1:Sx3Wy+0GI9OsX4a53mYj6A0o7mHJ94PUvraqGYb4EIs= github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk= github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= +github.com/xgo-dev/llvm v0.9.6 h1:DtjcgENgDItbf7LyUukssMwnnWXDpERSzGQ9jRQ1CRM= +github.com/xgo-dev/llvm v0.9.6/go.mod h1:42vav2/cI5BAIcL543DZSMO9do8/aCK2z7JERH+AE+M= github.com/xgo-dev/plan9asm v0.3.5 h1:886BmpjMK6JfJ03VWA3nPK01jkVZA1a7/mZia3BOsdg= github.com/xgo-dev/plan9asm v0.3.5/go.mod h1:0yM4CCIp2PyT8h+Ro3Ukro3lHL8ji9mzHEv5yfhOckc= -github.com/zhouguangyuan0718/go-llvm v0.0.0-20260731084524-d8f8a2aa851e h1:O9Hz3E3WoZv6XXL4+4Gn1EkaEqN9+/F61WiwOJA5F5c= -github.com/zhouguangyuan0718/go-llvm v0.0.0-20260731084524-d8f8a2aa851e/go.mod h1:42vav2/cI5BAIcL543DZSMO9do8/aCK2z7JERH+AE+M= go.bug.st/serial v1.6.4 h1:7FmqNPgVp3pu2Jz5PoPtbZ9jJO5gnEnZIvnI1lzve8A= go.bug.st/serial v1.6.4/go.mod h1:nofMJxTeNVny/m6+KaafC6vJGj3miwQZ6vW4BZUGJPI= go.yaml.in/yaml/v3 v3.0.5 h1:N6y/pJk8buWs9NY5ERU2HSMfm+IuD/OtfdAnq6kESPw= From 275f153a4797fa23e8095b2a9b90587146e4a565 Mon Sep 17 00:00:00 2001 From: ZhouGuangyuan Date: Sun, 2 Aug 2026 14:08:26 +0800 Subject: [PATCH 11/73] ci: retry macOS docs install From 4b7324f56bc31ea92e5d394f8a180a6a5ad51bc1 Mon Sep 17 00:00:00 2001 From: ZhouGuangyuan Date: Sun, 2 Aug 2026 22:19:44 +0800 Subject: [PATCH 12/73] build: unify package task state --- internal/build/build.go | 80 +++++++++++++------------- internal/build/package_archive_test.go | 2 +- internal/build/package_build.go | 35 +++++------ internal/build/package_build_test.go | 61 ++++++++++---------- 4 files changed, 93 insertions(+), 85 deletions(-) diff --git a/internal/build/build.go b/internal/build/build.go index 44ab45aa75..db46d50186 100644 --- a/internal/build/build.go +++ b/internal/build/build.go @@ -981,22 +981,22 @@ func normalizeToArchive(ctx *context, aPkg *aPackage, verbose bool) error { func buildAllPkgs(ctx *context, pkgs []*aPackage, verbose bool) ([]*aPackage, error) { // Split packages into runtime tree vs others so we can defer runtime build. - var runtimePkgs []packageBuildSpec - var normalPkgs []packageBuildSpec + var runtimePkgs []*packageBuildTask + var normalPkgs []*packageBuildTask for _, p := range pkgs { - spec := newPackageBuildSpec(p) - if spec.runtime { - runtimePkgs = append(runtimePkgs, spec) + task := newPackageBuildTask(p) + if task.isRuntime() { + runtimePkgs = append(runtimePkgs, task) } else { - normalPkgs = append(normalPkgs, spec) + normalPkgs = append(normalPkgs, task) } } var needRuntime, needPyInit bool // Build non-runtime packages first, so we know whether runtime is actually needed. - for _, spec := range normalPkgs { - result, err := buildOnePackage(ctx, spec, verbose) + for _, task := range normalPkgs { + result, err := buildOnePackage(ctx, task, verbose) if err != nil { return nil, err } @@ -1006,8 +1006,8 @@ func buildAllPkgs(ctx *context, pkgs []*aPackage, verbose bool) ([]*aPackage, er // Only build runtime packages when required (or host build with empty Target). if needRuntime || needPyInit || ctx.buildConf.Target == "" { - for _, spec := range runtimePkgs { - if _, err := buildOnePackage(ctx, spec, verbose); err != nil { + for _, task := range runtimePkgs { + if _, err := buildOnePackage(ctx, task, verbose); err != nil { return nil, err } } @@ -1019,39 +1019,41 @@ func buildAllPkgs(ctx *context, pkgs []*aPackage, verbose bool) ([]*aPackage, er // buildOnePackage is the serial package pipeline. Its explicit stages are the // contract used by later package workers; this commit deliberately preserves // serial LLVM execution. -func buildOnePackage(ctx *context, spec packageBuildSpec, verbose bool) (packageBuildResult, error) { - skip, err := preflightPackageBuild(ctx, spec, verbose) - if err != nil || skip { - return packageBuildResultFor(spec), err +func buildOnePackage(ctx *context, task *packageBuildTask, verbose bool) (packageBuildResult, error) { + if err := prePackageBuild(ctx, task, verbose); err != nil || task.skip { + return packageBuildResultFor(task), err } - if err := executePackageBuild(ctx, spec, verbose); err != nil { - return packageBuildResultFor(spec), err + if err := executePackageBuild(ctx, task, verbose); err != nil { + return packageBuildResultFor(task), err } - return finalizePackageBuild(ctx, spec, verbose) + return finalizePackageBuild(ctx, task, verbose) } -// preflightPackageBuild performs classification, fingerprinting, and cache +// prePackageBuild performs classification, fingerprinting, and cache // lookup without creating or transforming an LLVM module. -func preflightPackageBuild(ctx *context, spec packageBuildSpec, verbose bool) (skip bool, err error) { - aPkg := spec.pkg +func prePackageBuild(ctx *context, task *packageBuildTask, verbose bool) error { + aPkg := task.pkg pkg := aPkg.Package if _, ok := ctx.built[pkg.ID]; ok { - return true, nil + task.skip = true + return nil } ctx.built[pkg.ID] = none{} - if spec.isDeclOnly() { + if task.isDeclOnly() { pkg.ExportFile = "" - return true, nil + task.skip = true + return nil } - if spec.isLinkOnly() && !spec.hasSource() { + if task.isLinkOnly() && !task.hasSource() { pkg.ExportFile = "" - if spec.kind == cl.PkgLinkExtern { - appendExternalLinkArgs(ctx, aPkg, spec.kindParam) + if task.kind == cl.PkgLinkExtern { + appendExternalLinkArgs(ctx, aPkg, task.kindParam) } - return true, nil + task.skip = true + return nil } if err := ctx.collectFingerprint(aPkg); err != nil { - return false, err + return err } ctx.tryLoadFromCache(aPkg) if verbose { @@ -1061,16 +1063,16 @@ func preflightPackageBuild(ctx *context, spec packageBuildSpec, verbose bool) (s } fmt.Fprintf(os.Stderr, "CACHE %s: %s\n", status, pkg.PkgPath) } - return false, nil + return nil } // executePackageBuild creates the package module and runs its LLVM backend. -func executePackageBuild(ctx *context, spec packageBuildSpec, verbose bool) error { - aPkg := spec.pkg +func executePackageBuild(ctx *context, task *packageBuildTask, verbose bool) error { + aPkg := task.pkg if err := buildPkg(ctx, aPkg, verbose); err != nil { return err } - if spec.needsRuntimeSignals() { + if task.needsRuntimeSignals() { aPkg.setNeedRuntimeOrPyInit(aPkg.LPkg.NeedRuntime, aPkg.LPkg.NeedPyInit) } return nil @@ -1078,21 +1080,21 @@ func executePackageBuild(ctx *context, spec packageBuildSpec, verbose bool) erro // finalizePackageBuild publishes the archive and cache metadata. Cache hits // already carry both and therefore require no publication. -func finalizePackageBuild(ctx *context, spec packageBuildSpec, verbose bool) (packageBuildResult, error) { - aPkg := spec.pkg +func finalizePackageBuild(ctx *context, task *packageBuildTask, verbose bool) (packageBuildResult, error) { + aPkg := task.pkg if aPkg.CacheHit { - return packageBuildResultFor(spec), nil + return packageBuildResultFor(task), nil } if err := normalizeToArchive(ctx, aPkg, verbose); err != nil { - return packageBuildResultFor(spec), err + return packageBuildResultFor(task), err } - if spec.kind == cl.PkgLinkExtern { - appendExternalLinkArgs(ctx, aPkg, spec.kindParam) + if task.kind == cl.PkgLinkExtern { + appendExternalLinkArgs(ctx, aPkg, task.kindParam) } if err := ctx.saveToCache(aPkg); err != nil && verbose { fmt.Fprintf(os.Stderr, "warning: failed to save cache for %s: %v\n", aPkg.PkgPath, err) } - return packageBuildResultFor(spec), nil + return packageBuildResultFor(task), nil } func appendExternalLinkArgs(ctx *context, aPkg *aPackage, spec string) { diff --git a/internal/build/package_archive_test.go b/internal/build/package_archive_test.go index 477963da86..f76987b88b 100644 --- a/internal/build/package_archive_test.go +++ b/internal/build/package_archive_test.go @@ -157,7 +157,7 @@ func TestNormalizeToArchiveFailsWithoutObjectFallback(t *testing.T) { buffer: memoryBuf, }}, } - _, err := finalizePackageBuild(ctx, packageBuildSpec{pkg: pkg}, false) + _, err := finalizePackageBuild(ctx, &packageBuildTask{pkg: pkg}, false) if err == nil { t.Fatal("finalizePackageBuild succeeded with a missing member") } diff --git a/internal/build/package_build.go b/internal/build/package_build.go index a5ccc0ab38..12942f2c68 100644 --- a/internal/build/package_build.go +++ b/internal/build/package_build.go @@ -18,37 +18,40 @@ package build import "github.com/goplus/llgo/cl" -type packageBuildSpec struct { +type packageBuildTask struct { pkg *aPackage kind int kindParam string - runtime bool + skip bool } -func newPackageBuildSpec(pkg *aPackage) packageBuildSpec { +func newPackageBuildTask(pkg *aPackage) *packageBuildTask { kind, kindParam := cl.PkgKindOf(pkg.Types) - return packageBuildSpec{ + return &packageBuildTask{ pkg: pkg, kind: kind, kindParam: kindParam, - runtime: isRuntimePkg(pkg.PkgPath), } } -func (s packageBuildSpec) isDeclOnly() bool { - return s.kind == cl.PkgDeclOnly +func (t *packageBuildTask) isRuntime() bool { + return isRuntimePkg(t.pkg.PkgPath) } -func (s packageBuildSpec) isLinkOnly() bool { - return s.kind == cl.PkgLinkIR || s.kind == cl.PkgLinkExtern || s.kind == cl.PkgPyModule +func (t *packageBuildTask) isDeclOnly() bool { + return t.kind == cl.PkgDeclOnly } -func (s packageBuildSpec) hasSource() bool { - return len(s.pkg.GoFiles) > 0 +func (t *packageBuildTask) isLinkOnly() bool { + return t.kind == cl.PkgLinkIR || t.kind == cl.PkgLinkExtern || t.kind == cl.PkgPyModule } -func (s packageBuildSpec) needsRuntimeSignals() bool { - return !s.isLinkOnly() && !s.isDeclOnly() +func (t *packageBuildTask) hasSource() bool { + return len(t.pkg.GoFiles) > 0 +} + +func (t *packageBuildTask) needsRuntimeSignals() bool { + return !t.isLinkOnly() && !t.isDeclOnly() } type packageBuildResult struct { @@ -56,9 +59,9 @@ type packageBuildResult struct { needPyInit bool } -func packageBuildResultFor(spec packageBuildSpec) packageBuildResult { +func packageBuildResultFor(task *packageBuildTask) packageBuildResult { return packageBuildResult{ - needRuntime: spec.pkg.NeedRt, - needPyInit: spec.pkg.NeedPyInit, + needRuntime: task.pkg.NeedRt, + needPyInit: task.pkg.NeedPyInit, } } diff --git a/internal/build/package_build_test.go b/internal/build/package_build_test.go index 5a8711370d..235e77e7cc 100644 --- a/internal/build/package_build_test.go +++ b/internal/build/package_build_test.go @@ -31,35 +31,35 @@ import ( "golang.org/x/tools/go/ssa" ) -func TestPackageBuildSpecAndResult(t *testing.T) { +func TestPackageBuildTaskAndResult(t *testing.T) { pkg := &aPackage{Package: &packages.Package{ PkgPath: "example.com/p", GoFiles: []string{"p.go"}, Types: types.NewPackage("example.com/p", "p"), }, NeedRt: true, NeedPyInit: true} - spec := newPackageBuildSpec(pkg) - if spec.isDeclOnly() || spec.isLinkOnly() || !spec.hasSource() || spec.runtime || !spec.needsRuntimeSignals() { - t.Fatalf("unexpected normal package spec: %+v", spec) + task := newPackageBuildTask(pkg) + if task.isDeclOnly() || task.isLinkOnly() || !task.hasSource() || task.isRuntime() || !task.needsRuntimeSignals() { + t.Fatalf("unexpected normal package task: %+v", task) } - result := packageBuildResultFor(spec) + result := packageBuildResultFor(task) if !result.needRuntime || !result.needPyInit { t.Fatalf("unexpected package result: %+v", result) } } -func TestPackageBuildSpecSpecialKinds(t *testing.T) { - decl := newPackageBuildSpec(&aPackage{Package: &packages.Package{ +func TestPackageBuildTaskSpecialKinds(t *testing.T) { + decl := newPackageBuildTask(&aPackage{Package: &packages.Package{ PkgPath: "unsafe", Types: types.Unsafe, }}) if !decl.isDeclOnly() || decl.needsRuntimeSignals() { - t.Fatalf("unexpected declaration-only spec: %+v", decl) + t.Fatalf("unexpected declaration-only task: %+v", decl) } - runtime := newPackageBuildSpec(&aPackage{Package: &packages.Package{ + runtime := newPackageBuildTask(&aPackage{Package: &packages.Package{ PkgPath: env.LLGoRuntimePkg, Types: types.NewPackage(env.LLGoRuntimePkg, "runtime"), }}) - if !runtime.runtime { + if !runtime.isRuntime() { t.Fatalf("runtime package was not marked runtime: %+v", runtime) } } @@ -131,13 +131,13 @@ var content string built: make(map[string]none), } - _, err = buildOnePackage(ctx, newPackageBuildSpec(pkg), false) + _, err = buildOnePackage(ctx, newPackageBuildTask(pkg), false) if err == nil || !strings.Contains(err.Error(), "only allowed in Go files that import") { t.Fatalf("buildOnePackage frontend error = %v", err) } } -func TestPreflightPackageBuildErrorsAndCacheHit(t *testing.T) { +func TestPrePackageBuildErrorsAndCacheHit(t *testing.T) { t.Run("fingerprint error", func(t *testing.T) { pkg := &aPackage{Package: &packages.Package{ ID: "example.com/missing-source", @@ -150,12 +150,13 @@ func TestPreflightPackageBuildErrorsAndCacheHit(t *testing.T) { built: make(map[string]none), llvmVersion: "test", } - skip, err := preflightPackageBuild(ctx, newPackageBuildSpec(pkg), false) + task := newPackageBuildTask(pkg) + err := prePackageBuild(ctx, task, false) if err == nil || !strings.Contains(err.Error(), "digest go files") { - t.Fatalf("preflight fingerprint error = %v", err) + t.Fatalf("pre fingerprint error = %v", err) } - if skip { - t.Fatal("preflight skipped package after fingerprint error") + if task.skip { + t.Fatal("pre skipped package after fingerprint error") } }) @@ -173,12 +174,13 @@ func TestPreflightPackageBuildErrorsAndCacheHit(t *testing.T) { CacheHit: true, } ctx := &context{buildConf: &Config{}, built: make(map[string]none)} - skip, err := preflightPackageBuild(ctx, newPackageBuildSpec(pkg), true) + task := newPackageBuildTask(pkg) + err := prePackageBuild(ctx, task, true) if err != nil { t.Fatal(err) } - if skip || !pkg.CacheHit { - t.Fatalf("preflight cache hit = skip %v, cache hit %v", skip, pkg.CacheHit) + if task.skip || !pkg.CacheHit { + t.Fatalf("pre cache hit = skip %v, cache hit %v", task.skip, pkg.CacheHit) } }) } @@ -192,7 +194,7 @@ func TestBuildOnePackageSkipsAlreadyBuiltPackage(t *testing.T) { }, NeedRt: true} ctx := &context{built: map[string]none{pkg.ID: {}}} - result, err := buildOnePackage(ctx, newPackageBuildSpec(pkg), false) + result, err := buildOnePackage(ctx, newPackageBuildTask(pkg), false) if err != nil { t.Fatal(err) } @@ -201,7 +203,7 @@ func TestBuildOnePackageSkipsAlreadyBuiltPackage(t *testing.T) { } } -func TestPreflightPackageBuildSkipsDeclarationOnlyPackage(t *testing.T) { +func TestPrePackageBuildSkipsDeclarationOnlyPackage(t *testing.T) { pkg := &aPackage{Package: &packages.Package{ ID: "unsafe", PkgPath: "unsafe", @@ -210,11 +212,12 @@ func TestPreflightPackageBuildSkipsDeclarationOnlyPackage(t *testing.T) { }} ctx := &context{built: make(map[string]none)} - skip, err := preflightPackageBuild(ctx, newPackageBuildSpec(pkg), false) + task := newPackageBuildTask(pkg) + err := prePackageBuild(ctx, task, false) if err != nil { t.Fatal(err) } - if !skip { + if !task.skip { t.Fatal("declaration-only package was not skipped") } if pkg.ExportFile != "" { @@ -225,7 +228,7 @@ func TestPreflightPackageBuildSkipsDeclarationOnlyPackage(t *testing.T) { } } -func TestPreflightPackageBuildSkipsExternalLinkOnlyPackage(t *testing.T) { +func TestPrePackageBuildSkipsExternalLinkOnlyPackage(t *testing.T) { pkg := &aPackage{Package: &packages.Package{ ID: "example.com/linkonly", PkgPath: "example.com/linkonly", @@ -234,13 +237,13 @@ func TestPreflightPackageBuildSkipsExternalLinkOnlyPackage(t *testing.T) { ExportFile: "stale.a", }} ctx := &context{buildConf: &Config{}, built: make(map[string]none)} - spec := packageBuildSpec{pkg: pkg, kind: cl.PkgLinkExtern, kindParam: "-lexample"} - skip, err := preflightPackageBuild(ctx, spec, false) + task := &packageBuildTask{pkg: pkg, kind: cl.PkgLinkExtern, kindParam: "-lexample"} + err := prePackageBuild(ctx, task, false) if err != nil { t.Fatal(err) } - if !skip || pkg.ExportFile != "" { - t.Fatalf("external link-only preflight = skip %v, export %q", skip, pkg.ExportFile) + if !task.skip || pkg.ExportFile != "" { + t.Fatalf("external link-only pre = skip %v, export %q", task.skip, pkg.ExportFile) } if len(pkg.LinkArgs) != 1 || pkg.LinkArgs[0] != "-lexample" { t.Fatalf("external link args = %q, want [-lexample]", pkg.LinkArgs) @@ -254,7 +257,7 @@ func TestFinalizePackageBuildReturnsCachedResult(t *testing.T) { Types: types.NewPackage("example.com/cached", "cached"), }, CacheHit: true, NeedPyInit: true} - result, err := finalizePackageBuild(&context{}, newPackageBuildSpec(pkg), false) + result, err := finalizePackageBuild(&context{}, newPackageBuildTask(pkg), false) if err != nil { t.Fatal(err) } From db979b9d6cefef76088e748fb070aebec7a86936 Mon Sep 17 00:00:00 2001 From: Li Jie Date: Fri, 31 Jul 2026 15:30:54 +0800 Subject: [PATCH 13/73] feat: add hidden closure environment ABI --- chore/litgen/rewrite.go | 36 +- chore/litgen/rewrite_test.go | 42 +- chore/pclnpost/main.go | 4 +- cl/_testdata/foo/foo.go | 6 - cl/_testdata/llgointrinsics/in.go | 2 +- cl/_testdata/print/in.go | 42 - cl/_testdata/print/out.ll | 1258 ----------------- cl/_testdata/vargs/in.go | 6 - cl/_testgo/abimethod/in.go | 606 -------- cl/_testgo/cgobasic/cgobasic.go | 8 +- cl/_testgo/cgodefer/cgodefer.go | 10 +- cl/_testgo/closure/in.go | 7 +- cl/_testgo/closure2/in.go | 10 +- cl/_testgo/closureall/in.go | 77 +- cl/_testgo/closureenv/expect.txt | 1 + cl/_testgo/closureenv/in.go | 255 ++++ cl/_testgo/cursor/in.go | 34 +- cl/_testgo/deferiface/expect.txt | 2 + cl/_testgo/deferiface/in.go | 148 ++ cl/_testgo/equal/in.go | 2 +- cl/_testgo/genericembediface/in.go | 48 - cl/_testgo/genericiter/in.go | 5 +- cl/_testgo/goroutine/in.go | 5 +- cl/_testgo/ifaceconv/in.go | 54 - cl/_testgo/ifaceprom/in.go | 58 +- cl/_testgo/invoke/in.go | 125 +- cl/_testgo/reader/in.go | 144 -- cl/_testgo/reflect/in.go | 60 +- cl/_testgo/reflectfn/in.go | 8 +- cl/_testgo/reflectmk/in.go | 6 - cl/_testgo/reflectmkfn/in.go | 3 +- cl/_testgo/selects/in.go | 5 +- cl/_testgo/tpinst/main.go | 42 - cl/_testgo/tpnamed/in.go | 38 +- cl/_testgo/tprecur/out.ll | 147 -- cl/_testgo/tprecurfn/in.go | 5 +- cl/_testgo/typerecur/in.go | 7 +- cl/_testlibgo/strings/in.go | 4 +- cl/_testmeta/ifaceuse_basic/meta-expect.txt | 6 +- .../interface_anyonmous/meta-expect.txt | 30 +- .../interface_exported_var/meta-expect.txt | 154 +- .../interface_generic/meta-expect.txt | 20 +- .../meta-expect.txt | 42 +- .../interface_imported/meta-expect.txt | 60 +- cl/_testmeta/interface_named/meta-expect.txt | 22 +- .../interface_unexported/meta-expect.txt | 22 +- .../methodinfo_imported/meta-expect.txt | 214 +-- cl/_testmeta/reflect_dynamic/meta-expect.txt | 16 +- cl/_testmeta/reflect_named/meta-expect.txt | 24 +- .../typechildren_basic/meta-expect.txt | 16 +- cl/_testrt/any/in.go | 12 - cl/_testrt/builtin/in.go | 16 +- cl/_testrt/callback/in.go | 12 +- cl/_testrt/closure/in.go | 16 +- cl/_testrt/closurebound/in.go | 30 +- cl/_testrt/closureconv/in.go | 41 +- cl/_testrt/closureiface/in.go | 5 +- cl/_testrt/eface/in.go | 6 - cl/_testrt/freevars/in.go | 19 +- cl/_testrt/funcdecl/in.go | 10 +- cl/_testrt/intgen/in.go | 14 +- cl/_testrt/makemap/in.go | 18 - cl/_testrt/mapclosure/in.go | 12 +- cl/_testrt/methodthunk/in.go | 22 +- cl/_testrt/named/in.go | 8 +- cl/_testrt/reflectclosureenv/expect.txt | 1 + cl/_testrt/reflectclosureenv/in.go | 89 ++ cl/_testrt/result/in.go | 31 +- cl/_testrt/tpabi/in.go | 30 - cl/_testrt/tpfunc/in.go | 6 - cl/_testrt/tpmethod/in.go | 28 +- cl/_testrt/typed/in.go | 6 - cl/compile.go | 109 +- cl/compile_test.go | 4 + cl/import.go | 1 + cl/instr.go | 13 +- cl/rewrite_internal_test.go | 62 +- cl/zero_size_deref_test.go | 48 + doc/closure.md | 164 ++- doc/design/pclntab-linkphase.md | 6 +- internal/abi/large.go | 12 + internal/abi/large_test.go | 83 ++ internal/build/build.go | 20 +- internal/build/funcinfo_table.go | 207 +-- internal/build/funcinfo_table_test.go | 113 +- internal/build/main_module.go | 3 +- internal/build/pcln_mode_test.go | 9 +- internal/build/pclntab_external.go | 9 +- .../build/pclntab_modes_integration_test.go | 29 +- internal/cabi/cabi.go | 81 +- internal/cabi/cabi_patch_test.go | 134 ++ internal/pclnmap/pclnmap.go | 18 +- internal/pclnmap/pclnmap_test.go | 31 - internal/pclnpost/binary.go | 53 +- internal/pclnpost/binary_test.go | 4 - internal/pclnpost/elf_fixture_test.go | 62 +- internal/pclnpost/external.go | 57 +- internal/pclnpost/external_test.go | 67 +- internal/pclnpost/logic_test.go | 12 +- internal/pclnpost/macho_fixture_test.go | 45 +- internal/pclnpost/pclnpost.go | 16 +- internal/pclnpost/write.go | 71 +- runtime/internal/clite/ffi/_wrap/libffi.c | 341 +++++ runtime/internal/clite/ffi/ffi_link.go | 3 + runtime/internal/ffi/call_llgo_explicit.go | 15 + runtime/internal/ffi/call_llgo_nest.go | 21 + runtime/internal/ffi/call_llgo_swiftself.go | 22 + runtime/internal/lib/reflect/makefunc.go | 51 +- runtime/internal/lib/reflect/value.go | 15 +- .../internal/lib/runtime/pclntab_external.go | 20 +- runtime/internal/lib/runtime/symtab.go | 172 +-- runtime/internal/runtime/alg.go | 32 +- ssa/abitype.go | 9 +- ssa/closure_abi.go | 132 ++ ssa/closure_env_test.go | 613 ++++++++ ssa/closure_wrap.go | 111 -- ssa/decl.go | 77 +- ssa/eh.go | 17 +- ssa/expr.go | 149 +- ssa/goroutine.go | 7 + ssa/goroutine_patch_test.go | 5 +- ssa/interface.go | 5 +- ssa/package.go | 39 +- ssa/ssa_test.go | 210 +-- ssa/target.go | 11 +- ssa/type.go | 1 + 126 files changed, 3194 insertions(+), 4805 deletions(-) delete mode 100644 cl/_testdata/print/out.ll create mode 100644 cl/_testgo/closureenv/expect.txt create mode 100644 cl/_testgo/closureenv/in.go create mode 100644 cl/_testgo/deferiface/expect.txt create mode 100644 cl/_testgo/deferiface/in.go delete mode 100644 cl/_testgo/tprecur/out.ll create mode 100644 cl/_testrt/reflectclosureenv/expect.txt create mode 100644 cl/_testrt/reflectclosureenv/in.go create mode 100644 runtime/internal/ffi/call_llgo_explicit.go create mode 100644 runtime/internal/ffi/call_llgo_nest.go create mode 100644 runtime/internal/ffi/call_llgo_swiftself.go create mode 100644 ssa/closure_abi.go create mode 100644 ssa/closure_env_test.go delete mode 100644 ssa/closure_wrap.go diff --git a/chore/litgen/rewrite.go b/chore/litgen/rewrite.go index 209a1a3d7f..37585a9a9c 100644 --- a/chore/litgen/rewrite.go +++ b/chore/litgen/rewrite.go @@ -67,6 +67,7 @@ var ( globalRefRE = regexp.MustCompile(`@"([^"]+)"|@([A-Za-z0-9$._-]+)`) checkLineRE = regexp.MustCompile(`^\s*//\s*CHECK(?:-[A-Z]+)?:`) debugMetaRE = regexp.MustCompile(`, ![A-Za-z0-9_.-]+ ![0-9]+`) + closureEnvRE = regexp.MustCompile(`(\s)(?:nest|swiftself)(\s)`) numericNameRE = regexp.MustCompile(`^\d+$`) ) @@ -439,9 +440,37 @@ func generalizeIRLine(line, modulePath string) string { func scrubIRLine(line string) string { line = debugMetaRE.ReplaceAllString(line, "") + line = generalizeClosureEnvAttrs(line) return strings.TrimRight(line, " \t") } +func generalizeClosureEnvAttrs(line string) string { + var b strings.Builder + start := 0 + inQuote := false + for i := 0; i < len(line); i++ { + if line[i] != '"' || isEscapedQuote(line, i) { + continue + } + if !inQuote { + b.WriteString(closureEnvRE.ReplaceAllString(line[start:i], `${1}{{(nest|swiftself)}}${2}`)) + b.WriteByte('"') + start = i + 1 + inQuote = true + continue + } + b.WriteString(line[start : i+1]) + start = i + 1 + inQuote = false + } + if inQuote { + b.WriteString(line[start:]) + } else { + b.WriteString(closureEnvRE.ReplaceAllString(line[start:], `${1}{{(nest|swiftself)}}${2}`)) + } + return b.String() +} + func generalizeModulePath(line, modulePath string) string { if modulePath == "" { return line @@ -499,10 +528,9 @@ func collectRefs(line string) []string { } func shouldSkipFunctionCheck(symbol string) bool { - base := strings.TrimPrefix(symbol, "__llgo_stub.") - return strings.HasSuffix(base, "/runtime/internal/runtime.memequal32") || - strings.HasSuffix(base, "/runtime/internal/runtime.memequalptr") || - strings.HasSuffix(base, "/runtime/internal/runtime.strequal") + return strings.HasSuffix(symbol, "/runtime/internal/runtime.memequal32") || + strings.HasSuffix(symbol, "/runtime/internal/runtime.memequalptr") || + strings.HasSuffix(symbol, "/runtime/internal/runtime.strequal") } func trimPkgPrefix(symbol, pkgPath string) (string, bool) { diff --git a/chore/litgen/rewrite_test.go b/chore/litgen/rewrite_test.go index 17eccd1a1f..296a6091a2 100644 --- a/chore/litgen/rewrite_test.go +++ b/chore/litgen/rewrite_test.go @@ -5,7 +5,7 @@ import ( "testing" ) -func TestRewriteSource_InsertsMainClosureAndStub(t *testing.T) { +func TestRewriteSource_InsertsMainAndClosure(t *testing.T) { const src = `// LITTEST package main @@ -25,11 +25,6 @@ _llgo_0: ret void } -define linkonce void @"__llgo_stub.example.com/p.main$1"(ptr %0) { -_llgo_0: - tail call void @"example.com/p.main$1"() - ret void -} ` got, err := rewriteSource(src, "in.go", "example.com/p", "example.com", ir) if err != nil { @@ -51,12 +46,6 @@ _llgo_0: if strings.Index(got, closureCheck) > strings.Index(got, closureStmt) { t.Fatalf("closure checks should appear before func literal:\n%s", got) } - if !strings.Contains(got, `// CHECK-LABEL: define linkonce void @"__llgo_stub.{{.*}}/p.main$1"(ptr %0){{.*}} {`) { - t.Fatalf("stub checks missing:\n%s", got) - } - if strings.Index(got, `// CHECK-LABEL: define linkonce void @"__llgo_stub.{{.*}}/p.main$1"(ptr %0){{.*}} {`) < strings.Index(got, "func main()") { - t.Fatalf("stub checks should be appended after source:\n%s", got) - } } func TestRewriteSource_AddsInitAndCheckEmptyAndSkipsHelpers(t *testing.T) { @@ -233,6 +222,35 @@ func TestGeneralizeDefineLine_WildcardsAttrsBeforeBrace(t *testing.T) { } } +func TestGeneralizeClosureEnvAttrs(t *testing.T) { + tests := []struct { + line string + want string + }{ + { + `define void @"example.com/nest.swiftself"(ptr swiftself %env) {`, + `define void @"example.com/nest.swiftself"(ptr {{(nest|swiftself)}} %env) {`, + }, + { + ` call void %fn(ptr nest %env, ptr %arg)`, + ` call void %fn(ptr {{(nest|swiftself)}} %env, ptr %arg)`, + }, + { + `@0 = private constant [14 x i8] c"nest swiftself"`, + `@0 = private constant [14 x i8] c"nest swiftself"`, + }, + { + `@nest = global ptr @swiftself`, + `@nest = global ptr @swiftself`, + }, + } + for _, test := range tests { + if got := generalizeClosureEnvAttrs(test.line); got != test.want { + t.Errorf("generalizeClosureEnvAttrs(%q) = %q, want %q", test.line, got, test.want) + } + } +} + func TestGeneralizeModulePath_ReplacesOnlyQuotedSegments(t *testing.T) { line := ` %0 = getelementptr inbounds %"go/example.Type", ptr @"go/example.fn"` got := generalizeModulePath(line, "go") diff --git a/chore/pclnpost/main.go b/chore/pclnpost/main.go index 22a7efe2c5..0a1a70156c 100644 --- a/chore/pclnpost/main.go +++ b/chore/pclnpost/main.go @@ -38,6 +38,6 @@ func main() { fmt.Fprintln(os.Stderr, "pclnpost:", err) os.Exit(1) } - fmt.Printf("%s: entry=%d stub=%d kept=%d inlineCopies=%d noSymbol=%d -> ftab=%d buckets=%d\n", - st.Format, st.EntryRecords, st.StubRecords, st.Kept, st.InlineCopies, st.NoSymbol, st.FtabEntries, st.Buckets) + fmt.Printf("%s: entry=%d kept=%d inlineCopies=%d noSymbol=%d -> ftab=%d buckets=%d\n", + st.Format, st.EntryRecords, st.Kept, st.InlineCopies, st.NoSymbol, st.FtabEntries, st.Buckets) } diff --git a/cl/_testdata/foo/foo.go b/cl/_testdata/foo/foo.go index 5b61d65807..a76da65cd9 100644 --- a/cl/_testdata/foo/foo.go +++ b/cl/_testdata/foo/foo.go @@ -106,9 +106,3 @@ func (g *Game) Load() { // CHECK-NEXT: _llgo_2: ; preds = %_llgo_1, %_llgo_0 // CHECK-NEXT: ret void // CHECK-NEXT: } - -// CHECK-LABEL: define linkonce i1 @"__llgo_stub.{{.*}}/runtime/internal/runtime.memequal64"(ptr %0, ptr %1, ptr %2){{.*}} { -// CHECK-NEXT: _llgo_0: -// CHECK-NEXT: %3 = tail call i1 @"{{.*}}/runtime/internal/runtime.memequal64"(ptr %1, ptr %2) -// CHECK-NEXT: ret i1 %3 -// CHECK-NEXT: } diff --git a/cl/_testdata/llgointrinsics/in.go b/cl/_testdata/llgointrinsics/in.go index e4befe675b..75971309d1 100644 --- a/cl/_testdata/llgointrinsics/in.go +++ b/cl/_testdata/llgointrinsics/in.go @@ -58,7 +58,7 @@ func UseCTrampoline() uintptr { // CHECK-NEXT: %0 = call ptr @"{{.*}}.AllocZ"(i64 8) // CHECK-NEXT: %1 = call ptr @"{{.*}}.AllocU"(i64 8) // CHECK: ret i64 ptrtoint (ptr @"{{.*}}.UseClosure$1" to i64) -// CHECK-LABEL: define void @"{{.*}}.UseClosure$1"(ptr %0){{.*}} { +// CHECK-LABEL: define void @"{{.*}}.UseClosure$1"(ptr {{(nest|swiftself)}} %0){{.*}} { // CHECK-NEXT: _llgo_0: // CHECK: %4 = add i64 %3, 1 // CHECK: ret void diff --git a/cl/_testdata/print/in.go b/cl/_testdata/print/in.go index b934f989bc..4d2f80ace1 100644 --- a/cl/_testdata/print/in.go +++ b/cl/_testdata/print/in.go @@ -1389,45 +1389,3 @@ func prinxor(n int64) { func stringStructOf(sp *string) *stringStruct { return (*stringStruct)(unsafe.Pointer(sp)) } - -// CHECK-LABEL: define linkonce i1 @"__llgo_stub.{{.*}}/runtime/internal/runtime.f32equal"(ptr %0, ptr %1, ptr %2){{.*}} { -// CHECK-NEXT: _llgo_0: -// CHECK-NEXT: %3 = tail call i1 @"{{.*}}/runtime/internal/runtime.f32equal"(ptr %1, ptr %2) -// CHECK-NEXT: ret i1 %3 -// CHECK-NEXT: } - -// CHECK-LABEL: define linkonce i1 @"__llgo_stub.{{.*}}/runtime/internal/runtime.f64equal"(ptr %0, ptr %1, ptr %2){{.*}} { -// CHECK-NEXT: _llgo_0: -// CHECK-NEXT: %3 = tail call i1 @"{{.*}}/runtime/internal/runtime.f64equal"(ptr %1, ptr %2) -// CHECK-NEXT: ret i1 %3 -// CHECK-NEXT: } - -// CHECK-LABEL: define linkonce i1 @"__llgo_stub.{{.*}}/runtime/internal/runtime.memequal8"(ptr %0, ptr %1, ptr %2){{.*}} { -// CHECK-NEXT: _llgo_0: -// CHECK-NEXT: %3 = tail call i1 @"{{.*}}/runtime/internal/runtime.memequal8"(ptr %1, ptr %2) -// CHECK-NEXT: ret i1 %3 -// CHECK-NEXT: } - -// CHECK-LABEL: define linkonce i1 @"__llgo_stub.{{.*}}/runtime/internal/runtime.memequal16"(ptr %0, ptr %1, ptr %2){{.*}} { -// CHECK-NEXT: _llgo_0: -// CHECK-NEXT: %3 = tail call i1 @"{{.*}}/runtime/internal/runtime.memequal16"(ptr %1, ptr %2) -// CHECK-NEXT: ret i1 %3 -// CHECK-NEXT: } - -// CHECK-LABEL: define linkonce i1 @"__llgo_stub.{{.*}}/runtime/internal/runtime.memequal64"(ptr %0, ptr %1, ptr %2){{.*}} { -// CHECK-NEXT: _llgo_0: -// CHECK-NEXT: %3 = tail call i1 @"{{.*}}/runtime/internal/runtime.memequal64"(ptr %1, ptr %2) -// CHECK-NEXT: ret i1 %3 -// CHECK-NEXT: } - -// CHECK-LABEL: define linkonce i1 @"__llgo_stub.{{.*}}/runtime/internal/runtime.c128equal"(ptr %0, ptr %1, ptr %2){{.*}} { -// CHECK-NEXT: _llgo_0: -// CHECK-NEXT: %3 = tail call i1 @"{{.*}}/runtime/internal/runtime.c128equal"(ptr %1, ptr %2) -// CHECK-NEXT: ret i1 %3 -// CHECK-NEXT: } - -// CHECK-LABEL: define linkonce i1 @"__llgo_stub.{{.*}}/runtime/internal/runtime.c64equal"(ptr %0, ptr %1, ptr %2){{.*}} { -// CHECK-NEXT: _llgo_0: -// CHECK-NEXT: %3 = tail call i1 @"{{.*}}/runtime/internal/runtime.c64equal"(ptr %1, ptr %2) -// CHECK-NEXT: ret i1 %3 -// CHECK-NEXT: } diff --git a/cl/_testdata/print/out.ll b/cl/_testdata/print/out.ll deleted file mode 100644 index 0e5a51eccd..0000000000 --- a/cl/_testdata/print/out.ll +++ /dev/null @@ -1,1258 +0,0 @@ -; ModuleID = 'github.com/goplus/llgo/cl/_testdata/print' -source_filename = "github.com/goplus/llgo/cl/_testdata/print" - -%"github.com/goplus/llgo/runtime/abi.Type" = type { i64, i64, i32, i8, i8, i8, i8, { ptr, ptr }, ptr, %"github.com/goplus/llgo/runtime/internal/runtime.String", ptr } -%"github.com/goplus/llgo/runtime/internal/runtime.String" = type { ptr, i64 } -%"github.com/goplus/llgo/runtime/abi.PtrType" = type { %"github.com/goplus/llgo/runtime/abi.Type", ptr } -%"github.com/goplus/llgo/runtime/internal/runtime.Slice" = type { ptr, i64, i64 } -%"github.com/goplus/llgo/cl/_testdata/print.stringStruct" = type { ptr, i64 } -%"github.com/goplus/llgo/cl/_testdata/print.slice" = type { ptr, i64, i64 } -%"github.com/goplus/llgo/runtime/internal/runtime.eface" = type { ptr, ptr } - -@"github.com/goplus/llgo/cl/_testdata/print.init$guard" = global i1 false, align 1 -@"github.com/goplus/llgo/cl/_testdata/print.minhexdigits" = global i64 0, align 8 -@0 = private unnamed_addr constant [3 x i8] c"%c\00", align 1 -@1 = private unnamed_addr constant [4 x i8] c"llgo", align 1 -@_llgo_float32 = weak_odr constant %"github.com/goplus/llgo/runtime/abi.Type" { i64 4, i64 0, i32 62173712, i8 4, i8 4, i8 4, i8 13, { ptr, ptr } { ptr @"__llgo_stub.github.com/goplus/llgo/runtime/internal/runtime.f32equal", ptr null }, ptr null, %"github.com/goplus/llgo/runtime/internal/runtime.String" { ptr @2, i64 7 }, ptr @"*_llgo_float32" }, align 8 -@2 = private unnamed_addr constant [7 x i8] c"float32", align 1 -@"*_llgo_float32" = weak_odr constant %"github.com/goplus/llgo/runtime/abi.PtrType" { %"github.com/goplus/llgo/runtime/abi.Type" { i64 8, i64 8, i32 -1426958587, i8 10, i8 8, i8 8, i8 54, { ptr, ptr } { ptr @"__llgo_stub.github.com/goplus/llgo/runtime/internal/runtime.memequalptr", ptr null }, ptr null, %"github.com/goplus/llgo/runtime/internal/runtime.String" { ptr @2, i64 7 }, ptr null }, ptr @_llgo_float32 }, align 8 -@_llgo_float64 = weak_odr constant %"github.com/goplus/llgo/runtime/abi.Type" { i64 8, i64 0, i32 -1233032631, i8 4, i8 8, i8 8, i8 14, { ptr, ptr } { ptr @"__llgo_stub.github.com/goplus/llgo/runtime/internal/runtime.f64equal", ptr null }, ptr null, %"github.com/goplus/llgo/runtime/internal/runtime.String" { ptr @3, i64 7 }, ptr @"*_llgo_float64" }, align 8 -@3 = private unnamed_addr constant [7 x i8] c"float64", align 1 -@"*_llgo_float64" = weak_odr constant %"github.com/goplus/llgo/runtime/abi.PtrType" { %"github.com/goplus/llgo/runtime/abi.Type" { i64 8, i64 8, i32 1664509894, i8 10, i8 8, i8 8, i8 54, { ptr, ptr } { ptr @"__llgo_stub.github.com/goplus/llgo/runtime/internal/runtime.memequalptr", ptr null }, ptr null, %"github.com/goplus/llgo/runtime/internal/runtime.String" { ptr @3, i64 7 }, ptr null }, ptr @_llgo_float64 }, align 8 -@4 = private unnamed_addr constant [10 x i8] c"check bool", align 1 -@_llgo_string = weak_odr constant %"github.com/goplus/llgo/runtime/abi.Type" { i64 16, i64 8, i32 1749264893, i8 4, i8 8, i8 8, i8 24, { ptr, ptr } { ptr @"__llgo_stub.github.com/goplus/llgo/runtime/internal/runtime.strequal", ptr null }, ptr null, %"github.com/goplus/llgo/runtime/internal/runtime.String" { ptr @5, i64 6 }, ptr @"*_llgo_string" }, align 8 -@5 = private unnamed_addr constant [6 x i8] c"string", align 1 -@"*_llgo_string" = weak_odr constant %"github.com/goplus/llgo/runtime/abi.PtrType" { %"github.com/goplus/llgo/runtime/abi.Type" { i64 8, i64 8, i32 -1323879264, i8 10, i8 8, i8 8, i8 54, { ptr, ptr } { ptr @"__llgo_stub.github.com/goplus/llgo/runtime/internal/runtime.memequalptr", ptr null }, ptr null, %"github.com/goplus/llgo/runtime/internal/runtime.String" { ptr @5, i64 6 }, ptr null }, ptr @_llgo_string }, align 8 -@_llgo_bool = weak_odr constant %"github.com/goplus/llgo/runtime/abi.Type" { i64 1, i64 0, i32 554183389, i8 12, i8 1, i8 1, i8 1, { ptr, ptr } { ptr @"__llgo_stub.github.com/goplus/llgo/runtime/internal/runtime.memequal8", ptr null }, ptr null, %"github.com/goplus/llgo/runtime/internal/runtime.String" { ptr @6, i64 4 }, ptr @"*_llgo_bool" }, align 8 -@6 = private unnamed_addr constant [4 x i8] c"bool", align 1 -@"*_llgo_bool" = weak_odr constant %"github.com/goplus/llgo/runtime/abi.PtrType" { %"github.com/goplus/llgo/runtime/abi.Type" { i64 8, i64 8, i32 -1896950390, i8 10, i8 8, i8 8, i8 54, { ptr, ptr } { ptr @"__llgo_stub.github.com/goplus/llgo/runtime/internal/runtime.memequalptr", ptr null }, ptr null, %"github.com/goplus/llgo/runtime/internal/runtime.String" { ptr @6, i64 4 }, ptr null }, ptr @_llgo_bool }, align 8 -@7 = private unnamed_addr constant [8 x i8] c"check &^", align 1 -@_llgo_int32 = weak_odr constant %"github.com/goplus/llgo/runtime/abi.Type" { i64 4, i64 0, i32 1448558410, i8 12, i8 4, i8 4, i8 5, { ptr, ptr } { ptr @"__llgo_stub.github.com/goplus/llgo/runtime/internal/runtime.memequal32", ptr null }, ptr null, %"github.com/goplus/llgo/runtime/internal/runtime.String" { ptr @8, i64 5 }, ptr @"*_llgo_int32" }, align 8 -@8 = private unnamed_addr constant [5 x i8] c"int32", align 1 -@"*_llgo_int32" = weak_odr constant %"github.com/goplus/llgo/runtime/abi.PtrType" { %"github.com/goplus/llgo/runtime/abi.Type" { i64 8, i64 8, i32 -38689692, i8 10, i8 8, i8 8, i8 54, { ptr, ptr } { ptr @"__llgo_stub.github.com/goplus/llgo/runtime/internal/runtime.memequalptr", ptr null }, ptr null, %"github.com/goplus/llgo/runtime/internal/runtime.String" { ptr @8, i64 5 }, ptr null }, ptr @_llgo_int32 }, align 8 -@_llgo_int8 = weak_odr constant %"github.com/goplus/llgo/runtime/abi.Type" { i64 1, i64 0, i32 1444672578, i8 12, i8 1, i8 1, i8 3, { ptr, ptr } { ptr @"__llgo_stub.github.com/goplus/llgo/runtime/internal/runtime.memequal8", ptr null }, ptr null, %"github.com/goplus/llgo/runtime/internal/runtime.String" { ptr @9, i64 4 }, ptr @"*_llgo_int8" }, align 8 -@9 = private unnamed_addr constant [4 x i8] c"int8", align 1 -@"*_llgo_int8" = weak_odr constant %"github.com/goplus/llgo/runtime/abi.PtrType" { %"github.com/goplus/llgo/runtime/abi.Type" { i64 8, i64 8, i32 -1399554408, i8 10, i8 8, i8 8, i8 54, { ptr, ptr } { ptr @"__llgo_stub.github.com/goplus/llgo/runtime/internal/runtime.memequalptr", ptr null }, ptr null, %"github.com/goplus/llgo/runtime/internal/runtime.String" { ptr @9, i64 4 }, ptr null }, ptr @_llgo_int8 }, align 8 -@_llgo_int16 = weak_odr constant %"github.com/goplus/llgo/runtime/abi.Type" { i64 2, i64 0, i32 1041867489, i8 12, i8 2, i8 2, i8 4, { ptr, ptr } { ptr @"__llgo_stub.github.com/goplus/llgo/runtime/internal/runtime.memequal16", ptr null }, ptr null, %"github.com/goplus/llgo/runtime/internal/runtime.String" { ptr @10, i64 5 }, ptr @"*_llgo_int16" }, align 8 -@10 = private unnamed_addr constant [5 x i8] c"int16", align 1 -@"*_llgo_int16" = weak_odr constant %"github.com/goplus/llgo/runtime/abi.PtrType" { %"github.com/goplus/llgo/runtime/abi.Type" { i64 8, i64 8, i32 575772759, i8 10, i8 8, i8 8, i8 54, { ptr, ptr } { ptr @"__llgo_stub.github.com/goplus/llgo/runtime/internal/runtime.memequalptr", ptr null }, ptr null, %"github.com/goplus/llgo/runtime/internal/runtime.String" { ptr @10, i64 5 }, ptr null }, ptr @_llgo_int16 }, align 8 -@_llgo_int64 = weak_odr constant %"github.com/goplus/llgo/runtime/abi.Type" { i64 8, i64 0, i32 394795202, i8 12, i8 8, i8 8, i8 6, { ptr, ptr } { ptr @"__llgo_stub.github.com/goplus/llgo/runtime/internal/runtime.memequal64", ptr null }, ptr null, %"github.com/goplus/llgo/runtime/internal/runtime.String" { ptr @11, i64 5 }, ptr @"*_llgo_int64" }, align 8 -@11 = private unnamed_addr constant [5 x i8] c"int64", align 1 -@"*_llgo_int64" = weak_odr constant %"github.com/goplus/llgo/runtime/abi.PtrType" { %"github.com/goplus/llgo/runtime/abi.Type" { i64 8, i64 8, i32 -1901231210, i8 10, i8 8, i8 8, i8 54, { ptr, ptr } { ptr @"__llgo_stub.github.com/goplus/llgo/runtime/internal/runtime.memequalptr", ptr null }, ptr null, %"github.com/goplus/llgo/runtime/internal/runtime.String" { ptr @11, i64 5 }, ptr null }, ptr @_llgo_int64 }, align 8 -@_llgo_int = weak_odr constant %"github.com/goplus/llgo/runtime/abi.Type" { i64 8, i64 0, i32 -25294021, i8 12, i8 8, i8 8, i8 2, { ptr, ptr } { ptr @"__llgo_stub.github.com/goplus/llgo/runtime/internal/runtime.memequal64", ptr null }, ptr null, %"github.com/goplus/llgo/runtime/internal/runtime.String" { ptr @12, i64 3 }, ptr @"*_llgo_int" }, align 8 -@12 = private unnamed_addr constant [3 x i8] c"int", align 1 -@"*_llgo_int" = weak_odr constant %"github.com/goplus/llgo/runtime/abi.PtrType" { %"github.com/goplus/llgo/runtime/abi.Type" { i64 8, i64 8, i32 -939606833, i8 10, i8 8, i8 8, i8 54, { ptr, ptr } { ptr @"__llgo_stub.github.com/goplus/llgo/runtime/internal/runtime.memequalptr", ptr null }, ptr null, %"github.com/goplus/llgo/runtime/internal/runtime.String" { ptr @12, i64 3 }, ptr null }, ptr @_llgo_int }, align 8 -@_llgo_uint8 = weak_odr constant %"github.com/goplus/llgo/runtime/abi.Type" { i64 1, i64 0, i32 269156761, i8 12, i8 1, i8 1, i8 8, { ptr, ptr } { ptr @"__llgo_stub.github.com/goplus/llgo/runtime/internal/runtime.memequal8", ptr null }, ptr null, %"github.com/goplus/llgo/runtime/internal/runtime.String" { ptr @13, i64 5 }, ptr @"*_llgo_uint8" }, align 8 -@13 = private unnamed_addr constant [5 x i8] c"uint8", align 1 -@"*_llgo_uint8" = weak_odr constant %"github.com/goplus/llgo/runtime/abi.PtrType" { %"github.com/goplus/llgo/runtime/abi.Type" { i64 8, i64 8, i32 1277858201, i8 10, i8 8, i8 8, i8 54, { ptr, ptr } { ptr @"__llgo_stub.github.com/goplus/llgo/runtime/internal/runtime.memequalptr", ptr null }, ptr null, %"github.com/goplus/llgo/runtime/internal/runtime.String" { ptr @13, i64 5 }, ptr null }, ptr @_llgo_uint8 }, align 8 -@_llgo_uint16 = weak_odr constant %"github.com/goplus/llgo/runtime/abi.Type" { i64 2, i64 0, i32 -75471123, i8 12, i8 2, i8 2, i8 9, { ptr, ptr } { ptr @"__llgo_stub.github.com/goplus/llgo/runtime/internal/runtime.memequal16", ptr null }, ptr null, %"github.com/goplus/llgo/runtime/internal/runtime.String" { ptr @14, i64 6 }, ptr @"*_llgo_uint16" }, align 8 -@14 = private unnamed_addr constant [6 x i8] c"uint16", align 1 -@"*_llgo_uint16" = weak_odr constant %"github.com/goplus/llgo/runtime/abi.PtrType" { %"github.com/goplus/llgo/runtime/abi.Type" { i64 8, i64 8, i32 530818523, i8 10, i8 8, i8 8, i8 54, { ptr, ptr } { ptr @"__llgo_stub.github.com/goplus/llgo/runtime/internal/runtime.memequalptr", ptr null }, ptr null, %"github.com/goplus/llgo/runtime/internal/runtime.String" { ptr @14, i64 6 }, ptr null }, ptr @_llgo_uint16 }, align 8 -@_llgo_uint32 = weak_odr constant %"github.com/goplus/llgo/runtime/abi.Type" { i64 4, i64 0, i32 -625909322, i8 12, i8 4, i8 4, i8 10, { ptr, ptr } { ptr @"__llgo_stub.github.com/goplus/llgo/runtime/internal/runtime.memequal32", ptr null }, ptr null, %"github.com/goplus/llgo/runtime/internal/runtime.String" { ptr @15, i64 6 }, ptr @"*_llgo_uint32" }, align 8 -@15 = private unnamed_addr constant [6 x i8] c"uint32", align 1 -@"*_llgo_uint32" = weak_odr constant %"github.com/goplus/llgo/runtime/abi.PtrType" { %"github.com/goplus/llgo/runtime/abi.Type" { i64 8, i64 8, i32 1605480511, i8 10, i8 8, i8 8, i8 54, { ptr, ptr } { ptr @"__llgo_stub.github.com/goplus/llgo/runtime/internal/runtime.memequalptr", ptr null }, ptr null, %"github.com/goplus/llgo/runtime/internal/runtime.String" { ptr @15, i64 6 }, ptr null }, ptr @_llgo_uint32 }, align 8 -@_llgo_uint64 = weak_odr constant %"github.com/goplus/llgo/runtime/abi.Type" { i64 8, i64 0, i32 -1994022077, i8 12, i8 8, i8 8, i8 11, { ptr, ptr } { ptr @"__llgo_stub.github.com/goplus/llgo/runtime/internal/runtime.memequal64", ptr null }, ptr null, %"github.com/goplus/llgo/runtime/internal/runtime.String" { ptr @16, i64 6 }, ptr @"*_llgo_uint64" }, align 8 -@16 = private unnamed_addr constant [6 x i8] c"uint64", align 1 -@"*_llgo_uint64" = weak_odr constant %"github.com/goplus/llgo/runtime/abi.PtrType" { %"github.com/goplus/llgo/runtime/abi.Type" { i64 8, i64 8, i32 89591114, i8 10, i8 8, i8 8, i8 54, { ptr, ptr } { ptr @"__llgo_stub.github.com/goplus/llgo/runtime/internal/runtime.memequalptr", ptr null }, ptr null, %"github.com/goplus/llgo/runtime/internal/runtime.String" { ptr @16, i64 6 }, ptr null }, ptr @_llgo_uint64 }, align 8 -@_llgo_uintptr = weak_odr constant %"github.com/goplus/llgo/runtime/abi.Type" { i64 8, i64 0, i32 1268343028, i8 12, i8 8, i8 8, i8 12, { ptr, ptr } { ptr @"__llgo_stub.github.com/goplus/llgo/runtime/internal/runtime.memequal64", ptr null }, ptr null, %"github.com/goplus/llgo/runtime/internal/runtime.String" { ptr @17, i64 7 }, ptr @"*_llgo_uintptr" }, align 8 -@17 = private unnamed_addr constant [7 x i8] c"uintptr", align 1 -@"*_llgo_uintptr" = weak_odr constant %"github.com/goplus/llgo/runtime/abi.PtrType" { %"github.com/goplus/llgo/runtime/abi.Type" { i64 8, i64 8, i32 -1684891952, i8 10, i8 8, i8 8, i8 54, { ptr, ptr } { ptr @"__llgo_stub.github.com/goplus/llgo/runtime/internal/runtime.memequalptr", ptr null }, ptr null, %"github.com/goplus/llgo/runtime/internal/runtime.String" { ptr @17, i64 7 }, ptr null }, ptr @_llgo_uintptr }, align 8 -@_llgo_complex128 = weak_odr constant %"github.com/goplus/llgo/runtime/abi.Type" { i64 16, i64 0, i32 -185553283, i8 4, i8 8, i8 8, i8 16, { ptr, ptr } { ptr @"__llgo_stub.github.com/goplus/llgo/runtime/internal/runtime.c128equal", ptr null }, ptr null, %"github.com/goplus/llgo/runtime/internal/runtime.String" { ptr @18, i64 10 }, ptr @"*_llgo_complex128" }, align 8 -@18 = private unnamed_addr constant [10 x i8] c"complex128", align 1 -@"*_llgo_complex128" = weak_odr constant %"github.com/goplus/llgo/runtime/abi.PtrType" { %"github.com/goplus/llgo/runtime/abi.Type" { i64 8, i64 8, i32 -210097625, i8 10, i8 8, i8 8, i8 54, { ptr, ptr } { ptr @"__llgo_stub.github.com/goplus/llgo/runtime/internal/runtime.memequalptr", ptr null }, ptr null, %"github.com/goplus/llgo/runtime/internal/runtime.String" { ptr @18, i64 10 }, ptr null }, ptr @_llgo_complex128 }, align 8 -@_llgo_uint = weak_odr constant %"github.com/goplus/llgo/runtime/abi.Type" { i64 8, i64 0, i32 172771804, i8 12, i8 8, i8 8, i8 7, { ptr, ptr } { ptr @"__llgo_stub.github.com/goplus/llgo/runtime/internal/runtime.memequal64", ptr null }, ptr null, %"github.com/goplus/llgo/runtime/internal/runtime.String" { ptr @19, i64 4 }, ptr @"*_llgo_uint" }, align 8 -@19 = private unnamed_addr constant [4 x i8] c"uint", align 1 -@"*_llgo_uint" = weak_odr constant %"github.com/goplus/llgo/runtime/abi.PtrType" { %"github.com/goplus/llgo/runtime/abi.Type" { i64 8, i64 8, i32 -1001256076, i8 10, i8 8, i8 8, i8 54, { ptr, ptr } { ptr @"__llgo_stub.github.com/goplus/llgo/runtime/internal/runtime.memequalptr", ptr null }, ptr null, %"github.com/goplus/llgo/runtime/internal/runtime.String" { ptr @19, i64 4 }, ptr null }, ptr @_llgo_uint }, align 8 -@_llgo_complex64 = weak_odr constant %"github.com/goplus/llgo/runtime/abi.Type" { i64 8, i64 0, i32 -1545857875, i8 4, i8 4, i8 4, i8 15, { ptr, ptr } { ptr @"__llgo_stub.github.com/goplus/llgo/runtime/internal/runtime.c64equal", ptr null }, ptr null, %"github.com/goplus/llgo/runtime/internal/runtime.String" { ptr @20, i64 9 }, ptr @"*_llgo_complex64" }, align 8 -@20 = private unnamed_addr constant [9 x i8] c"complex64", align 1 -@"*_llgo_complex64" = weak_odr constant %"github.com/goplus/llgo/runtime/abi.PtrType" { %"github.com/goplus/llgo/runtime/abi.Type" { i64 8, i64 8, i32 -1953092460, i8 10, i8 8, i8 8, i8 54, { ptr, ptr } { ptr @"__llgo_stub.github.com/goplus/llgo/runtime/internal/runtime.memequalptr", ptr null }, ptr null, %"github.com/goplus/llgo/runtime/internal/runtime.String" { ptr @20, i64 9 }, ptr null }, ptr @_llgo_complex64 }, align 8 -@21 = private unnamed_addr constant [1 x i8] c"(", align 1 -@22 = private unnamed_addr constant [2 x i8] c"i)", align 1 -@23 = private unnamed_addr constant [4 x i8] c"true", align 1 -@24 = private unnamed_addr constant [5 x i8] c"false", align 1 -@25 = private unnamed_addr constant [3 x i8] c"NaN", align 1 -@26 = private unnamed_addr constant [4 x i8] c"+Inf", align 1 -@27 = private unnamed_addr constant [4 x i8] c"-Inf", align 1 -@28 = private unnamed_addr constant [16 x i8] c"0123456789abcdef", align 1 -@29 = private unnamed_addr constant [1 x i8] c"-", align 1 -@30 = private unnamed_addr constant [1 x i8] c" ", align 1 -@31 = private unnamed_addr constant [1 x i8] c"\0A", align 1 - -define %"github.com/goplus/llgo/runtime/internal/runtime.Slice" @"github.com/goplus/llgo/cl/_testdata/print.bytes"(%"github.com/goplus/llgo/runtime/internal/runtime.String" %0) { -_llgo_0: - %1 = call ptr @"github.com/goplus/llgo/runtime/internal/runtime.AllocZ"(i64 16) - store %"github.com/goplus/llgo/runtime/internal/runtime.String" %0, ptr %1, align 8 - %2 = call ptr @"github.com/goplus/llgo/runtime/internal/runtime.AllocZ"(i64 24) - %3 = call ptr @"github.com/goplus/llgo/cl/_testdata/print.stringStructOf"(ptr %1) - %4 = getelementptr inbounds %"github.com/goplus/llgo/cl/_testdata/print.stringStruct", ptr %3, i32 0, i32 0 - %5 = load ptr, ptr %4, align 8 - %6 = getelementptr inbounds %"github.com/goplus/llgo/cl/_testdata/print.slice", ptr %2, i32 0, i32 0 - store ptr %5, ptr %6, align 8 - %7 = getelementptr inbounds %"github.com/goplus/llgo/cl/_testdata/print.stringStruct", ptr %3, i32 0, i32 1 - %8 = load i64, ptr %7, align 4 - %9 = getelementptr inbounds %"github.com/goplus/llgo/cl/_testdata/print.slice", ptr %2, i32 0, i32 1 - store i64 %8, ptr %9, align 4 - %10 = getelementptr inbounds %"github.com/goplus/llgo/cl/_testdata/print.stringStruct", ptr %3, i32 0, i32 1 - %11 = load i64, ptr %10, align 4 - %12 = getelementptr inbounds %"github.com/goplus/llgo/cl/_testdata/print.slice", ptr %2, i32 0, i32 2 - store i64 %11, ptr %12, align 4 - %13 = load %"github.com/goplus/llgo/runtime/internal/runtime.Slice", ptr %2, align 8 - ret %"github.com/goplus/llgo/runtime/internal/runtime.Slice" %13 -} - -define void @"github.com/goplus/llgo/cl/_testdata/print.gwrite"(%"github.com/goplus/llgo/runtime/internal/runtime.Slice" %0) { -_llgo_0: - %1 = extractvalue %"github.com/goplus/llgo/runtime/internal/runtime.Slice" %0, 1 - %2 = icmp eq i64 %1, 0 - br i1 %2, label %_llgo_1, label %_llgo_2 - -_llgo_1: ; preds = %_llgo_0 - ret void - -_llgo_2: ; preds = %_llgo_0 - %3 = extractvalue %"github.com/goplus/llgo/runtime/internal/runtime.Slice" %0, 1 - br label %_llgo_3 - -_llgo_3: ; preds = %_llgo_4, %_llgo_2 - %4 = phi i64 [ -1, %_llgo_2 ], [ %5, %_llgo_4 ] - %5 = add i64 %4, 1 - %6 = icmp slt i64 %5, %3 - br i1 %6, label %_llgo_4, label %_llgo_5 - -_llgo_4: ; preds = %_llgo_3 - %7 = extractvalue %"github.com/goplus/llgo/runtime/internal/runtime.Slice" %0, 0 - %8 = extractvalue %"github.com/goplus/llgo/runtime/internal/runtime.Slice" %0, 1 - %9 = icmp slt i64 %5, 0 - %10 = icmp uge i64 %5, %8 - %11 = or i1 %10, %9 - call void @"github.com/goplus/llgo/runtime/internal/runtime.AssertIndexRange"(i1 %11) - %12 = getelementptr inbounds i8, ptr %7, i64 %5 - %13 = load i8, ptr %12, align 1 - %14 = call i32 (ptr, ...) @printf(ptr @0, i8 %13) - br label %_llgo_3 - -_llgo_5: ; preds = %_llgo_3 - ret void -} - -define void @"github.com/goplus/llgo/cl/_testdata/print.init"() { -_llgo_0: - %0 = load i1, ptr @"github.com/goplus/llgo/cl/_testdata/print.init$guard", align 1 - br i1 %0, label %_llgo_2, label %_llgo_1 - -_llgo_1: ; preds = %_llgo_0 - store i1 true, ptr @"github.com/goplus/llgo/cl/_testdata/print.init$guard", align 1 - store i64 0, ptr @"github.com/goplus/llgo/cl/_testdata/print.minhexdigits", align 4 - br label %_llgo_2 - -_llgo_2: ; preds = %_llgo_1, %_llgo_0 - ret void -} - -define void @"github.com/goplus/llgo/cl/_testdata/print.main"() { -_llgo_0: - call void @"github.com/goplus/llgo/cl/_testdata/print.printstring"(%"github.com/goplus/llgo/runtime/internal/runtime.String" { ptr @1, i64 4 }) - call void @"github.com/goplus/llgo/cl/_testdata/print.printnl"() - call void @"github.com/goplus/llgo/cl/_testdata/print.printuint"(i64 1024) - call void @"github.com/goplus/llgo/cl/_testdata/print.printnl"() - call void @"github.com/goplus/llgo/cl/_testdata/print.printhex"(i64 305441743) - call void @"github.com/goplus/llgo/cl/_testdata/print.printnl"() - call void @"github.com/goplus/llgo/cl/_testdata/print.prinxor"(i64 1) - call void @"github.com/goplus/llgo/cl/_testdata/print.printnl"() - call void @"github.com/goplus/llgo/cl/_testdata/print.prinsub"(i64 100) - call void @"github.com/goplus/llgo/cl/_testdata/print.printnl"() - call void @"github.com/goplus/llgo/cl/_testdata/print.prinusub"(i64 -1) - call void @"github.com/goplus/llgo/cl/_testdata/print.printnl"() - call void @"github.com/goplus/llgo/cl/_testdata/print.prinfsub"(double 1.001000e+02) - call void @"github.com/goplus/llgo/cl/_testdata/print.printnl"() - %0 = call ptr @"github.com/goplus/llgo/runtime/internal/runtime.AllocU"(i64 4) - store float 1.000000e+09, ptr %0, align 4 - %1 = insertvalue %"github.com/goplus/llgo/runtime/internal/runtime.eface" { ptr @_llgo_float32, ptr undef }, ptr %0, 1 - call void @"github.com/goplus/llgo/cl/_testdata/print.printany"(%"github.com/goplus/llgo/runtime/internal/runtime.eface" %1) - call void @"github.com/goplus/llgo/cl/_testdata/print.printnl"() - %2 = call ptr @"github.com/goplus/llgo/runtime/internal/runtime.AllocU"(i64 8) - store double 2.000000e+09, ptr %2, align 8 - %3 = insertvalue %"github.com/goplus/llgo/runtime/internal/runtime.eface" { ptr @_llgo_float64, ptr undef }, ptr %2, 1 - call void @"github.com/goplus/llgo/cl/_testdata/print.printany"(%"github.com/goplus/llgo/runtime/internal/runtime.eface" %3) - call void @"github.com/goplus/llgo/cl/_testdata/print.printnl"() - br i1 true, label %_llgo_3, label %_llgo_2 - -_llgo_1: ; preds = %_llgo_3 - %4 = call ptr @"github.com/goplus/llgo/runtime/internal/runtime.AllocZ"(i64 32) - %5 = getelementptr inbounds %"github.com/goplus/llgo/runtime/internal/runtime.eface", ptr %4, i64 0 - %6 = call ptr @"github.com/goplus/llgo/runtime/internal/runtime.AllocU"(i64 16) - store %"github.com/goplus/llgo/runtime/internal/runtime.String" { ptr @4, i64 10 }, ptr %6, align 8 - %7 = insertvalue %"github.com/goplus/llgo/runtime/internal/runtime.eface" { ptr @_llgo_string, ptr undef }, ptr %6, 1 - store %"github.com/goplus/llgo/runtime/internal/runtime.eface" %7, ptr %5, align 8 - %8 = getelementptr inbounds %"github.com/goplus/llgo/runtime/internal/runtime.eface", ptr %4, i64 1 - %9 = call ptr @"github.com/goplus/llgo/runtime/internal/runtime.AllocU"(i64 1) - store i1 true, ptr %9, align 1 - %10 = insertvalue %"github.com/goplus/llgo/runtime/internal/runtime.eface" { ptr @_llgo_bool, ptr undef }, ptr %9, 1 - store %"github.com/goplus/llgo/runtime/internal/runtime.eface" %10, ptr %8, align 8 - %11 = insertvalue %"github.com/goplus/llgo/runtime/internal/runtime.Slice" undef, ptr %4, 0 - %12 = insertvalue %"github.com/goplus/llgo/runtime/internal/runtime.Slice" %11, i64 2, 1 - %13 = insertvalue %"github.com/goplus/llgo/runtime/internal/runtime.Slice" %12, i64 2, 2 - call void @"github.com/goplus/llgo/cl/_testdata/print.println"(%"github.com/goplus/llgo/runtime/internal/runtime.Slice" %13) - br label %_llgo_2 - -_llgo_2: ; preds = %_llgo_1, %_llgo_3, %_llgo_0 - %14 = call ptr @"github.com/goplus/llgo/runtime/internal/runtime.AllocZ"(i64 48) - %15 = getelementptr inbounds %"github.com/goplus/llgo/runtime/internal/runtime.eface", ptr %14, i64 0 - %16 = call ptr @"github.com/goplus/llgo/runtime/internal/runtime.AllocU"(i64 16) - store %"github.com/goplus/llgo/runtime/internal/runtime.String" { ptr @7, i64 8 }, ptr %16, align 8 - %17 = insertvalue %"github.com/goplus/llgo/runtime/internal/runtime.eface" { ptr @_llgo_string, ptr undef }, ptr %16, 1 - store %"github.com/goplus/llgo/runtime/internal/runtime.eface" %17, ptr %15, align 8 - %18 = getelementptr inbounds %"github.com/goplus/llgo/runtime/internal/runtime.eface", ptr %14, i64 1 - %19 = call ptr @"github.com/goplus/llgo/runtime/internal/runtime.AllocU"(i64 1) - store i1 true, ptr %19, align 1 - %20 = insertvalue %"github.com/goplus/llgo/runtime/internal/runtime.eface" { ptr @_llgo_bool, ptr undef }, ptr %19, 1 - store %"github.com/goplus/llgo/runtime/internal/runtime.eface" %20, ptr %18, align 8 - %21 = getelementptr inbounds %"github.com/goplus/llgo/runtime/internal/runtime.eface", ptr %14, i64 2 - %22 = call ptr @"github.com/goplus/llgo/runtime/internal/runtime.AllocU"(i64 1) - store i1 true, ptr %22, align 1 - %23 = insertvalue %"github.com/goplus/llgo/runtime/internal/runtime.eface" { ptr @_llgo_bool, ptr undef }, ptr %22, 1 - store %"github.com/goplus/llgo/runtime/internal/runtime.eface" %23, ptr %21, align 8 - %24 = insertvalue %"github.com/goplus/llgo/runtime/internal/runtime.Slice" undef, ptr %14, 0 - %25 = insertvalue %"github.com/goplus/llgo/runtime/internal/runtime.Slice" %24, i64 3, 1 - %26 = insertvalue %"github.com/goplus/llgo/runtime/internal/runtime.Slice" %25, i64 3, 2 - call void @"github.com/goplus/llgo/cl/_testdata/print.println"(%"github.com/goplus/llgo/runtime/internal/runtime.Slice" %26) - %27 = call ptr @"github.com/goplus/llgo/runtime/internal/runtime.AllocZ"(i64 256) - %28 = getelementptr inbounds %"github.com/goplus/llgo/runtime/internal/runtime.eface", ptr %27, i64 0 - %29 = call ptr @"github.com/goplus/llgo/runtime/internal/runtime.AllocU"(i64 1) - store i1 true, ptr %29, align 1 - %30 = insertvalue %"github.com/goplus/llgo/runtime/internal/runtime.eface" { ptr @_llgo_bool, ptr undef }, ptr %29, 1 - store %"github.com/goplus/llgo/runtime/internal/runtime.eface" %30, ptr %28, align 8 - %31 = getelementptr inbounds %"github.com/goplus/llgo/runtime/internal/runtime.eface", ptr %27, i64 1 - %32 = call ptr @"github.com/goplus/llgo/runtime/internal/runtime.AllocU"(i64 1) - store i1 false, ptr %32, align 1 - %33 = insertvalue %"github.com/goplus/llgo/runtime/internal/runtime.eface" { ptr @_llgo_bool, ptr undef }, ptr %32, 1 - store %"github.com/goplus/llgo/runtime/internal/runtime.eface" %33, ptr %31, align 8 - %34 = getelementptr inbounds %"github.com/goplus/llgo/runtime/internal/runtime.eface", ptr %27, i64 2 - %35 = call ptr @"github.com/goplus/llgo/runtime/internal/runtime.AllocU"(i64 4) - store i32 97, ptr %35, align 4 - %36 = insertvalue %"github.com/goplus/llgo/runtime/internal/runtime.eface" { ptr @_llgo_int32, ptr undef }, ptr %35, 1 - store %"github.com/goplus/llgo/runtime/internal/runtime.eface" %36, ptr %34, align 8 - %37 = getelementptr inbounds %"github.com/goplus/llgo/runtime/internal/runtime.eface", ptr %27, i64 3 - %38 = call ptr @"github.com/goplus/llgo/runtime/internal/runtime.AllocU"(i64 4) - store i32 65, ptr %38, align 4 - %39 = insertvalue %"github.com/goplus/llgo/runtime/internal/runtime.eface" { ptr @_llgo_int32, ptr undef }, ptr %38, 1 - store %"github.com/goplus/llgo/runtime/internal/runtime.eface" %39, ptr %37, align 8 - %40 = getelementptr inbounds %"github.com/goplus/llgo/runtime/internal/runtime.eface", ptr %27, i64 4 - %41 = call ptr @"github.com/goplus/llgo/runtime/internal/runtime.AllocU"(i64 4) - store i32 20013, ptr %41, align 4 - %42 = insertvalue %"github.com/goplus/llgo/runtime/internal/runtime.eface" { ptr @_llgo_int32, ptr undef }, ptr %41, 1 - store %"github.com/goplus/llgo/runtime/internal/runtime.eface" %42, ptr %40, align 8 - %43 = getelementptr inbounds %"github.com/goplus/llgo/runtime/internal/runtime.eface", ptr %27, i64 5 - %44 = call ptr @"github.com/goplus/llgo/runtime/internal/runtime.AllocU"(i64 1) - store i8 1, ptr %44, align 1 - %45 = insertvalue %"github.com/goplus/llgo/runtime/internal/runtime.eface" { ptr @_llgo_int8, ptr undef }, ptr %44, 1 - store %"github.com/goplus/llgo/runtime/internal/runtime.eface" %45, ptr %43, align 8 - %46 = getelementptr inbounds %"github.com/goplus/llgo/runtime/internal/runtime.eface", ptr %27, i64 6 - %47 = call ptr @"github.com/goplus/llgo/runtime/internal/runtime.AllocU"(i64 2) - store i16 2, ptr %47, align 2 - %48 = insertvalue %"github.com/goplus/llgo/runtime/internal/runtime.eface" { ptr @_llgo_int16, ptr undef }, ptr %47, 1 - store %"github.com/goplus/llgo/runtime/internal/runtime.eface" %48, ptr %46, align 8 - %49 = getelementptr inbounds %"github.com/goplus/llgo/runtime/internal/runtime.eface", ptr %27, i64 7 - %50 = call ptr @"github.com/goplus/llgo/runtime/internal/runtime.AllocU"(i64 4) - store i32 3, ptr %50, align 4 - %51 = insertvalue %"github.com/goplus/llgo/runtime/internal/runtime.eface" { ptr @_llgo_int32, ptr undef }, ptr %50, 1 - store %"github.com/goplus/llgo/runtime/internal/runtime.eface" %51, ptr %49, align 8 - %52 = getelementptr inbounds %"github.com/goplus/llgo/runtime/internal/runtime.eface", ptr %27, i64 8 - %53 = call ptr @"github.com/goplus/llgo/runtime/internal/runtime.AllocU"(i64 8) - store i64 4, ptr %53, align 4 - %54 = insertvalue %"github.com/goplus/llgo/runtime/internal/runtime.eface" { ptr @_llgo_int64, ptr undef }, ptr %53, 1 - store %"github.com/goplus/llgo/runtime/internal/runtime.eface" %54, ptr %52, align 8 - %55 = getelementptr inbounds %"github.com/goplus/llgo/runtime/internal/runtime.eface", ptr %27, i64 9 - %56 = call ptr @"github.com/goplus/llgo/runtime/internal/runtime.AllocU"(i64 8) - store i64 5, ptr %56, align 4 - %57 = insertvalue %"github.com/goplus/llgo/runtime/internal/runtime.eface" { ptr @_llgo_int, ptr undef }, ptr %56, 1 - store %"github.com/goplus/llgo/runtime/internal/runtime.eface" %57, ptr %55, align 8 - %58 = getelementptr inbounds %"github.com/goplus/llgo/runtime/internal/runtime.eface", ptr %27, i64 10 - %59 = call ptr @"github.com/goplus/llgo/runtime/internal/runtime.AllocU"(i64 1) - store i8 1, ptr %59, align 1 - %60 = insertvalue %"github.com/goplus/llgo/runtime/internal/runtime.eface" { ptr @_llgo_uint8, ptr undef }, ptr %59, 1 - store %"github.com/goplus/llgo/runtime/internal/runtime.eface" %60, ptr %58, align 8 - %61 = getelementptr inbounds %"github.com/goplus/llgo/runtime/internal/runtime.eface", ptr %27, i64 11 - %62 = call ptr @"github.com/goplus/llgo/runtime/internal/runtime.AllocU"(i64 2) - store i16 2, ptr %62, align 2 - %63 = insertvalue %"github.com/goplus/llgo/runtime/internal/runtime.eface" { ptr @_llgo_uint16, ptr undef }, ptr %62, 1 - store %"github.com/goplus/llgo/runtime/internal/runtime.eface" %63, ptr %61, align 8 - %64 = getelementptr inbounds %"github.com/goplus/llgo/runtime/internal/runtime.eface", ptr %27, i64 12 - %65 = call ptr @"github.com/goplus/llgo/runtime/internal/runtime.AllocU"(i64 4) - store i32 3, ptr %65, align 4 - %66 = insertvalue %"github.com/goplus/llgo/runtime/internal/runtime.eface" { ptr @_llgo_uint32, ptr undef }, ptr %65, 1 - store %"github.com/goplus/llgo/runtime/internal/runtime.eface" %66, ptr %64, align 8 - %67 = getelementptr inbounds %"github.com/goplus/llgo/runtime/internal/runtime.eface", ptr %27, i64 13 - %68 = call ptr @"github.com/goplus/llgo/runtime/internal/runtime.AllocU"(i64 8) - store i64 4, ptr %68, align 4 - %69 = insertvalue %"github.com/goplus/llgo/runtime/internal/runtime.eface" { ptr @_llgo_uint64, ptr undef }, ptr %68, 1 - store %"github.com/goplus/llgo/runtime/internal/runtime.eface" %69, ptr %67, align 8 - %70 = getelementptr inbounds %"github.com/goplus/llgo/runtime/internal/runtime.eface", ptr %27, i64 14 - %71 = call ptr @"github.com/goplus/llgo/runtime/internal/runtime.AllocU"(i64 8) - store i64 5, ptr %71, align 4 - %72 = insertvalue %"github.com/goplus/llgo/runtime/internal/runtime.eface" { ptr @_llgo_uintptr, ptr undef }, ptr %71, 1 - store %"github.com/goplus/llgo/runtime/internal/runtime.eface" %72, ptr %70, align 8 - %73 = getelementptr inbounds %"github.com/goplus/llgo/runtime/internal/runtime.eface", ptr %27, i64 15 - %74 = call ptr @"github.com/goplus/llgo/runtime/internal/runtime.AllocU"(i64 16) - store %"github.com/goplus/llgo/runtime/internal/runtime.String" { ptr @1, i64 4 }, ptr %74, align 8 - %75 = insertvalue %"github.com/goplus/llgo/runtime/internal/runtime.eface" { ptr @_llgo_string, ptr undef }, ptr %74, 1 - store %"github.com/goplus/llgo/runtime/internal/runtime.eface" %75, ptr %73, align 8 - %76 = insertvalue %"github.com/goplus/llgo/runtime/internal/runtime.Slice" undef, ptr %27, 0 - %77 = insertvalue %"github.com/goplus/llgo/runtime/internal/runtime.Slice" %76, i64 16, 1 - %78 = insertvalue %"github.com/goplus/llgo/runtime/internal/runtime.Slice" %77, i64 16, 2 - call void @"github.com/goplus/llgo/cl/_testdata/print.println"(%"github.com/goplus/llgo/runtime/internal/runtime.Slice" %78) - %79 = call ptr @"github.com/goplus/llgo/runtime/internal/runtime.AllocZ"(i64 16) - %80 = getelementptr inbounds %"github.com/goplus/llgo/runtime/internal/runtime.eface", ptr %79, i64 0 - %81 = call ptr @"github.com/goplus/llgo/runtime/internal/runtime.AllocU"(i64 16) - store { double, double } { double 1.000000e+00, double 2.000000e+00 }, ptr %81, align 8 - %82 = insertvalue %"github.com/goplus/llgo/runtime/internal/runtime.eface" { ptr @_llgo_complex128, ptr undef }, ptr %81, 1 - store %"github.com/goplus/llgo/runtime/internal/runtime.eface" %82, ptr %80, align 8 - %83 = insertvalue %"github.com/goplus/llgo/runtime/internal/runtime.Slice" undef, ptr %79, 0 - %84 = insertvalue %"github.com/goplus/llgo/runtime/internal/runtime.Slice" %83, i64 1, 1 - %85 = insertvalue %"github.com/goplus/llgo/runtime/internal/runtime.Slice" %84, i64 1, 2 - call void @"github.com/goplus/llgo/cl/_testdata/print.println"(%"github.com/goplus/llgo/runtime/internal/runtime.Slice" %85) - ret void - -_llgo_3: ; preds = %_llgo_0 - br i1 true, label %_llgo_1, label %_llgo_2 -} - -define void @"github.com/goplus/llgo/cl/_testdata/print.prinfsub"(double %0) { -_llgo_0: - %1 = fneg double %0 - call void @"github.com/goplus/llgo/cl/_testdata/print.printfloat"(double %1) - ret void -} - -define void @"github.com/goplus/llgo/cl/_testdata/print.prinsub"(i64 %0) { -_llgo_0: - %1 = sub i64 0, %0 - call void @"github.com/goplus/llgo/cl/_testdata/print.printint"(i64 %1) - ret void -} - -define void @"github.com/goplus/llgo/cl/_testdata/print.printany"(%"github.com/goplus/llgo/runtime/internal/runtime.eface" %0) { -_llgo_0: - %1 = extractvalue %"github.com/goplus/llgo/runtime/internal/runtime.eface" %0, 0 - %2 = icmp eq ptr %1, @_llgo_bool - br i1 %2, label %_llgo_35, label %_llgo_36 - -_llgo_1: ; preds = %_llgo_34, %_llgo_85, %_llgo_32, %_llgo_30, %_llgo_28, %_llgo_26, %_llgo_24, %_llgo_22, %_llgo_20, %_llgo_18, %_llgo_16, %_llgo_14, %_llgo_12, %_llgo_10, %_llgo_8, %_llgo_6, %_llgo_4, %_llgo_2 - ret void - -_llgo_2: ; preds = %_llgo_37 - call void @"github.com/goplus/llgo/cl/_testdata/print.printbool"(i1 %53) - br label %_llgo_1 - -_llgo_3: ; preds = %_llgo_37 - %3 = extractvalue %"github.com/goplus/llgo/runtime/internal/runtime.eface" %0, 0 - %4 = icmp eq ptr %3, @_llgo_int - br i1 %4, label %_llgo_38, label %_llgo_39 - -_llgo_4: ; preds = %_llgo_40 - call void @"github.com/goplus/llgo/cl/_testdata/print.printint"(i64 %60) - br label %_llgo_1 - -_llgo_5: ; preds = %_llgo_40 - %5 = extractvalue %"github.com/goplus/llgo/runtime/internal/runtime.eface" %0, 0 - %6 = icmp eq ptr %5, @_llgo_int8 - br i1 %6, label %_llgo_41, label %_llgo_42 - -_llgo_6: ; preds = %_llgo_43 - %7 = sext i8 %67 to i64 - call void @"github.com/goplus/llgo/cl/_testdata/print.printint"(i64 %7) - br label %_llgo_1 - -_llgo_7: ; preds = %_llgo_43 - %8 = extractvalue %"github.com/goplus/llgo/runtime/internal/runtime.eface" %0, 0 - %9 = icmp eq ptr %8, @_llgo_int16 - br i1 %9, label %_llgo_44, label %_llgo_45 - -_llgo_8: ; preds = %_llgo_46 - %10 = sext i16 %74 to i64 - call void @"github.com/goplus/llgo/cl/_testdata/print.printint"(i64 %10) - br label %_llgo_1 - -_llgo_9: ; preds = %_llgo_46 - %11 = extractvalue %"github.com/goplus/llgo/runtime/internal/runtime.eface" %0, 0 - %12 = icmp eq ptr %11, @_llgo_int32 - br i1 %12, label %_llgo_47, label %_llgo_48 - -_llgo_10: ; preds = %_llgo_49 - %13 = sext i32 %81 to i64 - call void @"github.com/goplus/llgo/cl/_testdata/print.printint"(i64 %13) - br label %_llgo_1 - -_llgo_11: ; preds = %_llgo_49 - %14 = extractvalue %"github.com/goplus/llgo/runtime/internal/runtime.eface" %0, 0 - %15 = icmp eq ptr %14, @_llgo_int64 - br i1 %15, label %_llgo_50, label %_llgo_51 - -_llgo_12: ; preds = %_llgo_52 - call void @"github.com/goplus/llgo/cl/_testdata/print.printint"(i64 %88) - br label %_llgo_1 - -_llgo_13: ; preds = %_llgo_52 - %16 = extractvalue %"github.com/goplus/llgo/runtime/internal/runtime.eface" %0, 0 - %17 = icmp eq ptr %16, @_llgo_uint - br i1 %17, label %_llgo_53, label %_llgo_54 - -_llgo_14: ; preds = %_llgo_55 - call void @"github.com/goplus/llgo/cl/_testdata/print.printuint"(i64 %95) - br label %_llgo_1 - -_llgo_15: ; preds = %_llgo_55 - %18 = extractvalue %"github.com/goplus/llgo/runtime/internal/runtime.eface" %0, 0 - %19 = icmp eq ptr %18, @_llgo_uint8 - br i1 %19, label %_llgo_56, label %_llgo_57 - -_llgo_16: ; preds = %_llgo_58 - %20 = zext i8 %102 to i64 - call void @"github.com/goplus/llgo/cl/_testdata/print.printuint"(i64 %20) - br label %_llgo_1 - -_llgo_17: ; preds = %_llgo_58 - %21 = extractvalue %"github.com/goplus/llgo/runtime/internal/runtime.eface" %0, 0 - %22 = icmp eq ptr %21, @_llgo_uint16 - br i1 %22, label %_llgo_59, label %_llgo_60 - -_llgo_18: ; preds = %_llgo_61 - %23 = zext i16 %109 to i64 - call void @"github.com/goplus/llgo/cl/_testdata/print.printuint"(i64 %23) - br label %_llgo_1 - -_llgo_19: ; preds = %_llgo_61 - %24 = extractvalue %"github.com/goplus/llgo/runtime/internal/runtime.eface" %0, 0 - %25 = icmp eq ptr %24, @_llgo_uint32 - br i1 %25, label %_llgo_62, label %_llgo_63 - -_llgo_20: ; preds = %_llgo_64 - %26 = zext i32 %116 to i64 - call void @"github.com/goplus/llgo/cl/_testdata/print.printuint"(i64 %26) - br label %_llgo_1 - -_llgo_21: ; preds = %_llgo_64 - %27 = extractvalue %"github.com/goplus/llgo/runtime/internal/runtime.eface" %0, 0 - %28 = icmp eq ptr %27, @_llgo_uint64 - br i1 %28, label %_llgo_65, label %_llgo_66 - -_llgo_22: ; preds = %_llgo_67 - call void @"github.com/goplus/llgo/cl/_testdata/print.printuint"(i64 %123) - br label %_llgo_1 - -_llgo_23: ; preds = %_llgo_67 - %29 = extractvalue %"github.com/goplus/llgo/runtime/internal/runtime.eface" %0, 0 - %30 = icmp eq ptr %29, @_llgo_uintptr - br i1 %30, label %_llgo_68, label %_llgo_69 - -_llgo_24: ; preds = %_llgo_70 - call void @"github.com/goplus/llgo/cl/_testdata/print.printuint"(i64 %130) - br label %_llgo_1 - -_llgo_25: ; preds = %_llgo_70 - %31 = extractvalue %"github.com/goplus/llgo/runtime/internal/runtime.eface" %0, 0 - %32 = icmp eq ptr %31, @_llgo_float32 - br i1 %32, label %_llgo_71, label %_llgo_72 - -_llgo_26: ; preds = %_llgo_73 - %33 = fpext float %137 to double - call void @"github.com/goplus/llgo/cl/_testdata/print.printfloat"(double %33) - br label %_llgo_1 - -_llgo_27: ; preds = %_llgo_73 - %34 = extractvalue %"github.com/goplus/llgo/runtime/internal/runtime.eface" %0, 0 - %35 = icmp eq ptr %34, @_llgo_float64 - br i1 %35, label %_llgo_74, label %_llgo_75 - -_llgo_28: ; preds = %_llgo_76 - call void @"github.com/goplus/llgo/cl/_testdata/print.printfloat"(double %144) - br label %_llgo_1 - -_llgo_29: ; preds = %_llgo_76 - %36 = extractvalue %"github.com/goplus/llgo/runtime/internal/runtime.eface" %0, 0 - %37 = icmp eq ptr %36, @_llgo_complex64 - br i1 %37, label %_llgo_77, label %_llgo_78 - -_llgo_30: ; preds = %_llgo_79 - call void @"github.com/goplus/llgo/cl/_testdata/print.printstring"(%"github.com/goplus/llgo/runtime/internal/runtime.String" { ptr @21, i64 1 }) - %38 = extractvalue { float, float } %151, 0 - %39 = fpext float %38 to double - call void @"github.com/goplus/llgo/cl/_testdata/print.printfloat"(double %39) - %40 = extractvalue { float, float } %151, 1 - %41 = fpext float %40 to double - call void @"github.com/goplus/llgo/cl/_testdata/print.printfloat"(double %41) - call void @"github.com/goplus/llgo/cl/_testdata/print.printstring"(%"github.com/goplus/llgo/runtime/internal/runtime.String" { ptr @22, i64 2 }) - br label %_llgo_1 - -_llgo_31: ; preds = %_llgo_79 - %42 = extractvalue %"github.com/goplus/llgo/runtime/internal/runtime.eface" %0, 0 - %43 = icmp eq ptr %42, @_llgo_complex128 - br i1 %43, label %_llgo_80, label %_llgo_81 - -_llgo_32: ; preds = %_llgo_82 - call void @"github.com/goplus/llgo/cl/_testdata/print.printstring"(%"github.com/goplus/llgo/runtime/internal/runtime.String" { ptr @21, i64 1 }) - %44 = extractvalue { double, double } %158, 0 - call void @"github.com/goplus/llgo/cl/_testdata/print.printfloat"(double %44) - %45 = extractvalue { double, double } %158, 1 - call void @"github.com/goplus/llgo/cl/_testdata/print.printfloat"(double %45) - call void @"github.com/goplus/llgo/cl/_testdata/print.printstring"(%"github.com/goplus/llgo/runtime/internal/runtime.String" { ptr @22, i64 2 }) - br label %_llgo_1 - -_llgo_33: ; preds = %_llgo_82 - %46 = extractvalue %"github.com/goplus/llgo/runtime/internal/runtime.eface" %0, 0 - %47 = icmp eq ptr %46, @_llgo_string - br i1 %47, label %_llgo_83, label %_llgo_84 - -_llgo_34: ; preds = %_llgo_85 - call void @"github.com/goplus/llgo/cl/_testdata/print.printstring"(%"github.com/goplus/llgo/runtime/internal/runtime.String" %165) - br label %_llgo_1 - -_llgo_35: ; preds = %_llgo_0 - %48 = extractvalue %"github.com/goplus/llgo/runtime/internal/runtime.eface" %0, 1 - %49 = load i1, ptr %48, align 1 - %50 = insertvalue { i1, i1 } undef, i1 %49, 0 - %51 = insertvalue { i1, i1 } %50, i1 true, 1 - br label %_llgo_37 - -_llgo_36: ; preds = %_llgo_0 - br label %_llgo_37 - -_llgo_37: ; preds = %_llgo_36, %_llgo_35 - %52 = phi { i1, i1 } [ %51, %_llgo_35 ], [ zeroinitializer, %_llgo_36 ] - %53 = extractvalue { i1, i1 } %52, 0 - %54 = extractvalue { i1, i1 } %52, 1 - br i1 %54, label %_llgo_2, label %_llgo_3 - -_llgo_38: ; preds = %_llgo_3 - %55 = extractvalue %"github.com/goplus/llgo/runtime/internal/runtime.eface" %0, 1 - %56 = load i64, ptr %55, align 4 - %57 = insertvalue { i64, i1 } undef, i64 %56, 0 - %58 = insertvalue { i64, i1 } %57, i1 true, 1 - br label %_llgo_40 - -_llgo_39: ; preds = %_llgo_3 - br label %_llgo_40 - -_llgo_40: ; preds = %_llgo_39, %_llgo_38 - %59 = phi { i64, i1 } [ %58, %_llgo_38 ], [ zeroinitializer, %_llgo_39 ] - %60 = extractvalue { i64, i1 } %59, 0 - %61 = extractvalue { i64, i1 } %59, 1 - br i1 %61, label %_llgo_4, label %_llgo_5 - -_llgo_41: ; preds = %_llgo_5 - %62 = extractvalue %"github.com/goplus/llgo/runtime/internal/runtime.eface" %0, 1 - %63 = load i8, ptr %62, align 1 - %64 = insertvalue { i8, i1 } undef, i8 %63, 0 - %65 = insertvalue { i8, i1 } %64, i1 true, 1 - br label %_llgo_43 - -_llgo_42: ; preds = %_llgo_5 - br label %_llgo_43 - -_llgo_43: ; preds = %_llgo_42, %_llgo_41 - %66 = phi { i8, i1 } [ %65, %_llgo_41 ], [ zeroinitializer, %_llgo_42 ] - %67 = extractvalue { i8, i1 } %66, 0 - %68 = extractvalue { i8, i1 } %66, 1 - br i1 %68, label %_llgo_6, label %_llgo_7 - -_llgo_44: ; preds = %_llgo_7 - %69 = extractvalue %"github.com/goplus/llgo/runtime/internal/runtime.eface" %0, 1 - %70 = load i16, ptr %69, align 2 - %71 = insertvalue { i16, i1 } undef, i16 %70, 0 - %72 = insertvalue { i16, i1 } %71, i1 true, 1 - br label %_llgo_46 - -_llgo_45: ; preds = %_llgo_7 - br label %_llgo_46 - -_llgo_46: ; preds = %_llgo_45, %_llgo_44 - %73 = phi { i16, i1 } [ %72, %_llgo_44 ], [ zeroinitializer, %_llgo_45 ] - %74 = extractvalue { i16, i1 } %73, 0 - %75 = extractvalue { i16, i1 } %73, 1 - br i1 %75, label %_llgo_8, label %_llgo_9 - -_llgo_47: ; preds = %_llgo_9 - %76 = extractvalue %"github.com/goplus/llgo/runtime/internal/runtime.eface" %0, 1 - %77 = load i32, ptr %76, align 4 - %78 = insertvalue { i32, i1 } undef, i32 %77, 0 - %79 = insertvalue { i32, i1 } %78, i1 true, 1 - br label %_llgo_49 - -_llgo_48: ; preds = %_llgo_9 - br label %_llgo_49 - -_llgo_49: ; preds = %_llgo_48, %_llgo_47 - %80 = phi { i32, i1 } [ %79, %_llgo_47 ], [ zeroinitializer, %_llgo_48 ] - %81 = extractvalue { i32, i1 } %80, 0 - %82 = extractvalue { i32, i1 } %80, 1 - br i1 %82, label %_llgo_10, label %_llgo_11 - -_llgo_50: ; preds = %_llgo_11 - %83 = extractvalue %"github.com/goplus/llgo/runtime/internal/runtime.eface" %0, 1 - %84 = load i64, ptr %83, align 4 - %85 = insertvalue { i64, i1 } undef, i64 %84, 0 - %86 = insertvalue { i64, i1 } %85, i1 true, 1 - br label %_llgo_52 - -_llgo_51: ; preds = %_llgo_11 - br label %_llgo_52 - -_llgo_52: ; preds = %_llgo_51, %_llgo_50 - %87 = phi { i64, i1 } [ %86, %_llgo_50 ], [ zeroinitializer, %_llgo_51 ] - %88 = extractvalue { i64, i1 } %87, 0 - %89 = extractvalue { i64, i1 } %87, 1 - br i1 %89, label %_llgo_12, label %_llgo_13 - -_llgo_53: ; preds = %_llgo_13 - %90 = extractvalue %"github.com/goplus/llgo/runtime/internal/runtime.eface" %0, 1 - %91 = load i64, ptr %90, align 4 - %92 = insertvalue { i64, i1 } undef, i64 %91, 0 - %93 = insertvalue { i64, i1 } %92, i1 true, 1 - br label %_llgo_55 - -_llgo_54: ; preds = %_llgo_13 - br label %_llgo_55 - -_llgo_55: ; preds = %_llgo_54, %_llgo_53 - %94 = phi { i64, i1 } [ %93, %_llgo_53 ], [ zeroinitializer, %_llgo_54 ] - %95 = extractvalue { i64, i1 } %94, 0 - %96 = extractvalue { i64, i1 } %94, 1 - br i1 %96, label %_llgo_14, label %_llgo_15 - -_llgo_56: ; preds = %_llgo_15 - %97 = extractvalue %"github.com/goplus/llgo/runtime/internal/runtime.eface" %0, 1 - %98 = load i8, ptr %97, align 1 - %99 = insertvalue { i8, i1 } undef, i8 %98, 0 - %100 = insertvalue { i8, i1 } %99, i1 true, 1 - br label %_llgo_58 - -_llgo_57: ; preds = %_llgo_15 - br label %_llgo_58 - -_llgo_58: ; preds = %_llgo_57, %_llgo_56 - %101 = phi { i8, i1 } [ %100, %_llgo_56 ], [ zeroinitializer, %_llgo_57 ] - %102 = extractvalue { i8, i1 } %101, 0 - %103 = extractvalue { i8, i1 } %101, 1 - br i1 %103, label %_llgo_16, label %_llgo_17 - -_llgo_59: ; preds = %_llgo_17 - %104 = extractvalue %"github.com/goplus/llgo/runtime/internal/runtime.eface" %0, 1 - %105 = load i16, ptr %104, align 2 - %106 = insertvalue { i16, i1 } undef, i16 %105, 0 - %107 = insertvalue { i16, i1 } %106, i1 true, 1 - br label %_llgo_61 - -_llgo_60: ; preds = %_llgo_17 - br label %_llgo_61 - -_llgo_61: ; preds = %_llgo_60, %_llgo_59 - %108 = phi { i16, i1 } [ %107, %_llgo_59 ], [ zeroinitializer, %_llgo_60 ] - %109 = extractvalue { i16, i1 } %108, 0 - %110 = extractvalue { i16, i1 } %108, 1 - br i1 %110, label %_llgo_18, label %_llgo_19 - -_llgo_62: ; preds = %_llgo_19 - %111 = extractvalue %"github.com/goplus/llgo/runtime/internal/runtime.eface" %0, 1 - %112 = load i32, ptr %111, align 4 - %113 = insertvalue { i32, i1 } undef, i32 %112, 0 - %114 = insertvalue { i32, i1 } %113, i1 true, 1 - br label %_llgo_64 - -_llgo_63: ; preds = %_llgo_19 - br label %_llgo_64 - -_llgo_64: ; preds = %_llgo_63, %_llgo_62 - %115 = phi { i32, i1 } [ %114, %_llgo_62 ], [ zeroinitializer, %_llgo_63 ] - %116 = extractvalue { i32, i1 } %115, 0 - %117 = extractvalue { i32, i1 } %115, 1 - br i1 %117, label %_llgo_20, label %_llgo_21 - -_llgo_65: ; preds = %_llgo_21 - %118 = extractvalue %"github.com/goplus/llgo/runtime/internal/runtime.eface" %0, 1 - %119 = load i64, ptr %118, align 4 - %120 = insertvalue { i64, i1 } undef, i64 %119, 0 - %121 = insertvalue { i64, i1 } %120, i1 true, 1 - br label %_llgo_67 - -_llgo_66: ; preds = %_llgo_21 - br label %_llgo_67 - -_llgo_67: ; preds = %_llgo_66, %_llgo_65 - %122 = phi { i64, i1 } [ %121, %_llgo_65 ], [ zeroinitializer, %_llgo_66 ] - %123 = extractvalue { i64, i1 } %122, 0 - %124 = extractvalue { i64, i1 } %122, 1 - br i1 %124, label %_llgo_22, label %_llgo_23 - -_llgo_68: ; preds = %_llgo_23 - %125 = extractvalue %"github.com/goplus/llgo/runtime/internal/runtime.eface" %0, 1 - %126 = load i64, ptr %125, align 4 - %127 = insertvalue { i64, i1 } undef, i64 %126, 0 - %128 = insertvalue { i64, i1 } %127, i1 true, 1 - br label %_llgo_70 - -_llgo_69: ; preds = %_llgo_23 - br label %_llgo_70 - -_llgo_70: ; preds = %_llgo_69, %_llgo_68 - %129 = phi { i64, i1 } [ %128, %_llgo_68 ], [ zeroinitializer, %_llgo_69 ] - %130 = extractvalue { i64, i1 } %129, 0 - %131 = extractvalue { i64, i1 } %129, 1 - br i1 %131, label %_llgo_24, label %_llgo_25 - -_llgo_71: ; preds = %_llgo_25 - %132 = extractvalue %"github.com/goplus/llgo/runtime/internal/runtime.eface" %0, 1 - %133 = load float, ptr %132, align 4 - %134 = insertvalue { float, i1 } undef, float %133, 0 - %135 = insertvalue { float, i1 } %134, i1 true, 1 - br label %_llgo_73 - -_llgo_72: ; preds = %_llgo_25 - br label %_llgo_73 - -_llgo_73: ; preds = %_llgo_72, %_llgo_71 - %136 = phi { float, i1 } [ %135, %_llgo_71 ], [ zeroinitializer, %_llgo_72 ] - %137 = extractvalue { float, i1 } %136, 0 - %138 = extractvalue { float, i1 } %136, 1 - br i1 %138, label %_llgo_26, label %_llgo_27 - -_llgo_74: ; preds = %_llgo_27 - %139 = extractvalue %"github.com/goplus/llgo/runtime/internal/runtime.eface" %0, 1 - %140 = load double, ptr %139, align 8 - %141 = insertvalue { double, i1 } undef, double %140, 0 - %142 = insertvalue { double, i1 } %141, i1 true, 1 - br label %_llgo_76 - -_llgo_75: ; preds = %_llgo_27 - br label %_llgo_76 - -_llgo_76: ; preds = %_llgo_75, %_llgo_74 - %143 = phi { double, i1 } [ %142, %_llgo_74 ], [ zeroinitializer, %_llgo_75 ] - %144 = extractvalue { double, i1 } %143, 0 - %145 = extractvalue { double, i1 } %143, 1 - br i1 %145, label %_llgo_28, label %_llgo_29 - -_llgo_77: ; preds = %_llgo_29 - %146 = extractvalue %"github.com/goplus/llgo/runtime/internal/runtime.eface" %0, 1 - %147 = load { float, float }, ptr %146, align 4 - %148 = insertvalue { { float, float }, i1 } undef, { float, float } %147, 0 - %149 = insertvalue { { float, float }, i1 } %148, i1 true, 1 - br label %_llgo_79 - -_llgo_78: ; preds = %_llgo_29 - br label %_llgo_79 - -_llgo_79: ; preds = %_llgo_78, %_llgo_77 - %150 = phi { { float, float }, i1 } [ %149, %_llgo_77 ], [ zeroinitializer, %_llgo_78 ] - %151 = extractvalue { { float, float }, i1 } %150, 0 - %152 = extractvalue { { float, float }, i1 } %150, 1 - br i1 %152, label %_llgo_30, label %_llgo_31 - -_llgo_80: ; preds = %_llgo_31 - %153 = extractvalue %"github.com/goplus/llgo/runtime/internal/runtime.eface" %0, 1 - %154 = load { double, double }, ptr %153, align 8 - %155 = insertvalue { { double, double }, i1 } undef, { double, double } %154, 0 - %156 = insertvalue { { double, double }, i1 } %155, i1 true, 1 - br label %_llgo_82 - -_llgo_81: ; preds = %_llgo_31 - br label %_llgo_82 - -_llgo_82: ; preds = %_llgo_81, %_llgo_80 - %157 = phi { { double, double }, i1 } [ %156, %_llgo_80 ], [ zeroinitializer, %_llgo_81 ] - %158 = extractvalue { { double, double }, i1 } %157, 0 - %159 = extractvalue { { double, double }, i1 } %157, 1 - br i1 %159, label %_llgo_32, label %_llgo_33 - -_llgo_83: ; preds = %_llgo_33 - %160 = extractvalue %"github.com/goplus/llgo/runtime/internal/runtime.eface" %0, 1 - %161 = load %"github.com/goplus/llgo/runtime/internal/runtime.String", ptr %160, align 8 - %162 = insertvalue { %"github.com/goplus/llgo/runtime/internal/runtime.String", i1 } undef, %"github.com/goplus/llgo/runtime/internal/runtime.String" %161, 0 - %163 = insertvalue { %"github.com/goplus/llgo/runtime/internal/runtime.String", i1 } %162, i1 true, 1 - br label %_llgo_85 - -_llgo_84: ; preds = %_llgo_33 - br label %_llgo_85 - -_llgo_85: ; preds = %_llgo_84, %_llgo_83 - %164 = phi { %"github.com/goplus/llgo/runtime/internal/runtime.String", i1 } [ %163, %_llgo_83 ], [ zeroinitializer, %_llgo_84 ] - %165 = extractvalue { %"github.com/goplus/llgo/runtime/internal/runtime.String", i1 } %164, 0 - %166 = extractvalue { %"github.com/goplus/llgo/runtime/internal/runtime.String", i1 } %164, 1 - br i1 %166, label %_llgo_34, label %_llgo_1 -} - -define void @"github.com/goplus/llgo/cl/_testdata/print.printbool"(i1 %0) { -_llgo_0: - br i1 %0, label %_llgo_1, label %_llgo_3 - -_llgo_1: ; preds = %_llgo_0 - call void @"github.com/goplus/llgo/cl/_testdata/print.printstring"(%"github.com/goplus/llgo/runtime/internal/runtime.String" { ptr @23, i64 4 }) - br label %_llgo_2 - -_llgo_2: ; preds = %_llgo_3, %_llgo_1 - ret void - -_llgo_3: ; preds = %_llgo_0 - call void @"github.com/goplus/llgo/cl/_testdata/print.printstring"(%"github.com/goplus/llgo/runtime/internal/runtime.String" { ptr @24, i64 5 }) - br label %_llgo_2 -} - -define void @"github.com/goplus/llgo/cl/_testdata/print.printfloat"(double %0) { -_llgo_0: - %1 = fcmp une double %0, %0 - br i1 %1, label %_llgo_1, label %_llgo_3 - -_llgo_1: ; preds = %_llgo_0 - call void @"github.com/goplus/llgo/cl/_testdata/print.printstring"(%"github.com/goplus/llgo/runtime/internal/runtime.String" { ptr @25, i64 3 }) - ret void - -_llgo_2: ; preds = %_llgo_7 - call void @"github.com/goplus/llgo/cl/_testdata/print.printstring"(%"github.com/goplus/llgo/runtime/internal/runtime.String" { ptr @26, i64 4 }) - ret void - -_llgo_3: ; preds = %_llgo_0 - %2 = fadd double %0, %0 - %3 = fcmp oeq double %2, %0 - br i1 %3, label %_llgo_6, label %_llgo_7 - -_llgo_4: ; preds = %_llgo_10 - call void @"github.com/goplus/llgo/cl/_testdata/print.printstring"(%"github.com/goplus/llgo/runtime/internal/runtime.String" { ptr @27, i64 4 }) - ret void - -_llgo_5: ; preds = %_llgo_7 - %4 = fadd double %0, %0 - %5 = fcmp oeq double %4, %0 - br i1 %5, label %_llgo_9, label %_llgo_10 - -_llgo_6: ; preds = %_llgo_3 - %6 = fcmp ogt double %0, 0.000000e+00 - br label %_llgo_7 - -_llgo_7: ; preds = %_llgo_6, %_llgo_3 - %7 = phi i1 [ false, %_llgo_3 ], [ %6, %_llgo_6 ] - br i1 %7, label %_llgo_2, label %_llgo_5 - -_llgo_8: ; preds = %_llgo_10 - %8 = call ptr @"github.com/goplus/llgo/runtime/internal/runtime.AllocZ"(i64 14) - %9 = getelementptr inbounds i8, ptr %8, i64 0 - store i8 43, ptr %9, align 1 - %10 = fcmp oeq double %0, 0.000000e+00 - br i1 %10, label %_llgo_11, label %_llgo_13 - -_llgo_9: ; preds = %_llgo_5 - %11 = fcmp olt double %0, 0.000000e+00 - br label %_llgo_10 - -_llgo_10: ; preds = %_llgo_9, %_llgo_5 - %12 = phi i1 [ false, %_llgo_5 ], [ %11, %_llgo_9 ] - br i1 %12, label %_llgo_4, label %_llgo_8 - -_llgo_11: ; preds = %_llgo_8 - %13 = fdiv double 1.000000e+00, %0 - %14 = fcmp olt double %13, 0.000000e+00 - br i1 %14, label %_llgo_14, label %_llgo_12 - -_llgo_12: ; preds = %_llgo_24, %_llgo_23, %_llgo_14, %_llgo_11 - %15 = phi double [ %0, %_llgo_11 ], [ %36, %_llgo_23 ], [ %0, %_llgo_14 ], [ %39, %_llgo_24 ] - %16 = phi i64 [ 0, %_llgo_11 ], [ %29, %_llgo_23 ], [ 0, %_llgo_14 ], [ %38, %_llgo_24 ] - br label %_llgo_25 - -_llgo_13: ; preds = %_llgo_8 - %17 = fcmp olt double %0, 0.000000e+00 - br i1 %17, label %_llgo_15, label %_llgo_17 - -_llgo_14: ; preds = %_llgo_11 - %18 = getelementptr inbounds i8, ptr %8, i64 0 - store i8 45, ptr %18, align 1 - br label %_llgo_12 - -_llgo_15: ; preds = %_llgo_13 - %19 = fneg double %0 - %20 = getelementptr inbounds i8, ptr %8, i64 0 - store i8 45, ptr %20, align 1 - br label %_llgo_17 - -_llgo_16: ; preds = %_llgo_17 - %21 = add i64 %24, 1 - %22 = fdiv double %23, 1.000000e+01 - br label %_llgo_17 - -_llgo_17: ; preds = %_llgo_16, %_llgo_15, %_llgo_13 - %23 = phi double [ %0, %_llgo_13 ], [ %22, %_llgo_16 ], [ %19, %_llgo_15 ] - %24 = phi i64 [ 0, %_llgo_13 ], [ %21, %_llgo_16 ], [ 0, %_llgo_15 ] - %25 = fcmp oge double %23, 1.000000e+01 - br i1 %25, label %_llgo_16, label %_llgo_20 - -_llgo_18: ; preds = %_llgo_20 - %26 = sub i64 %29, 1 - %27 = fmul double %28, 1.000000e+01 - br label %_llgo_20 - -_llgo_19: ; preds = %_llgo_20 - br label %_llgo_21 - -_llgo_20: ; preds = %_llgo_18, %_llgo_17 - %28 = phi double [ %23, %_llgo_17 ], [ %27, %_llgo_18 ] - %29 = phi i64 [ %24, %_llgo_17 ], [ %26, %_llgo_18 ] - %30 = fcmp olt double %28, 1.000000e+00 - br i1 %30, label %_llgo_18, label %_llgo_19 - -_llgo_21: ; preds = %_llgo_22, %_llgo_19 - %31 = phi double [ 5.000000e+00, %_llgo_19 ], [ %34, %_llgo_22 ] - %32 = phi i64 [ 0, %_llgo_19 ], [ %35, %_llgo_22 ] - %33 = icmp slt i64 %32, 7 - br i1 %33, label %_llgo_22, label %_llgo_23 - -_llgo_22: ; preds = %_llgo_21 - %34 = fdiv double %31, 1.000000e+01 - %35 = add i64 %32, 1 - br label %_llgo_21 - -_llgo_23: ; preds = %_llgo_21 - %36 = fadd double %28, %31 - %37 = fcmp oge double %36, 1.000000e+01 - br i1 %37, label %_llgo_24, label %_llgo_12 - -_llgo_24: ; preds = %_llgo_23 - %38 = add i64 %29, 1 - %39 = fdiv double %36, 1.000000e+01 - br label %_llgo_12 - -_llgo_25: ; preds = %_llgo_26, %_llgo_12 - %40 = phi double [ %15, %_llgo_12 ], [ %53, %_llgo_26 ] - %41 = phi i64 [ 0, %_llgo_12 ], [ %54, %_llgo_26 ] - %42 = icmp slt i64 %41, 7 - br i1 %42, label %_llgo_26, label %_llgo_27 - -_llgo_26: ; preds = %_llgo_25 - %43 = fptosi double %40 to i64 - %44 = add i64 %41, 2 - %45 = add i64 %43, 48 - %46 = trunc i64 %45 to i8 - %47 = icmp slt i64 %44, 0 - %48 = icmp uge i64 %44, 14 - %49 = or i1 %48, %47 - call void @"github.com/goplus/llgo/runtime/internal/runtime.AssertIndexRange"(i1 %49) - %50 = getelementptr inbounds i8, ptr %8, i64 %44 - store i8 %46, ptr %50, align 1 - %51 = sitofp i64 %43 to double - %52 = fsub double %40, %51 - %53 = fmul double %52, 1.000000e+01 - %54 = add i64 %41, 1 - br label %_llgo_25 - -_llgo_27: ; preds = %_llgo_25 - %55 = getelementptr inbounds i8, ptr %8, i64 2 - %56 = load i8, ptr %55, align 1 - %57 = getelementptr inbounds i8, ptr %8, i64 1 - store i8 %56, ptr %57, align 1 - %58 = getelementptr inbounds i8, ptr %8, i64 2 - store i8 46, ptr %58, align 1 - %59 = getelementptr inbounds i8, ptr %8, i64 9 - store i8 101, ptr %59, align 1 - %60 = getelementptr inbounds i8, ptr %8, i64 10 - store i8 43, ptr %60, align 1 - %61 = icmp slt i64 %16, 0 - br i1 %61, label %_llgo_28, label %_llgo_29 - -_llgo_28: ; preds = %_llgo_27 - %62 = sub i64 0, %16 - %63 = getelementptr inbounds i8, ptr %8, i64 10 - store i8 45, ptr %63, align 1 - br label %_llgo_29 - -_llgo_29: ; preds = %_llgo_28, %_llgo_27 - %64 = phi i64 [ %16, %_llgo_27 ], [ %62, %_llgo_28 ] - %65 = sdiv i64 %64, 100 - %66 = trunc i64 %65 to i8 - %67 = add i8 %66, 48 - %68 = getelementptr inbounds i8, ptr %8, i64 11 - store i8 %67, ptr %68, align 1 - %69 = sdiv i64 %64, 10 - %70 = trunc i64 %69 to i8 - %71 = urem i8 %70, 10 - %72 = add i8 %71, 48 - %73 = getelementptr inbounds i8, ptr %8, i64 12 - store i8 %72, ptr %73, align 1 - %74 = srem i64 %64, 10 - %75 = trunc i64 %74 to i8 - %76 = add i8 %75, 48 - %77 = getelementptr inbounds i8, ptr %8, i64 13 - store i8 %76, ptr %77, align 1 - %78 = insertvalue %"github.com/goplus/llgo/runtime/internal/runtime.Slice" undef, ptr %8, 0 - %79 = insertvalue %"github.com/goplus/llgo/runtime/internal/runtime.Slice" %78, i64 14, 1 - %80 = insertvalue %"github.com/goplus/llgo/runtime/internal/runtime.Slice" %79, i64 14, 2 - call void @"github.com/goplus/llgo/cl/_testdata/print.gwrite"(%"github.com/goplus/llgo/runtime/internal/runtime.Slice" %80) - ret void -} - -define void @"github.com/goplus/llgo/cl/_testdata/print.printhex"(i64 %0) { -_llgo_0: - %1 = call ptr @"github.com/goplus/llgo/runtime/internal/runtime.AllocZ"(i64 100) - br label %_llgo_3 - -_llgo_1: ; preds = %_llgo_3 - %2 = urem i64 %22, 16 - %3 = icmp uge i64 %2, 16 - call void @"github.com/goplus/llgo/runtime/internal/runtime.AssertIndexRange"(i1 %3) - %4 = getelementptr inbounds i8, ptr @28, i64 %2 - %5 = load i8, ptr %4, align 1 - %6 = icmp slt i64 %23, 0 - %7 = icmp uge i64 %23, 100 - %8 = or i1 %7, %6 - call void @"github.com/goplus/llgo/runtime/internal/runtime.AssertIndexRange"(i1 %8) - %9 = getelementptr inbounds i8, ptr %1, i64 %23 - store i8 %5, ptr %9, align 1 - %10 = icmp ult i64 %22, 16 - br i1 %10, label %_llgo_5, label %_llgo_4 - -_llgo_2: ; preds = %_llgo_5, %_llgo_3 - %11 = sub i64 %23, 1 - %12 = icmp slt i64 %11, 0 - %13 = icmp uge i64 %11, 100 - %14 = or i1 %13, %12 - call void @"github.com/goplus/llgo/runtime/internal/runtime.AssertIndexRange"(i1 %14) - %15 = getelementptr inbounds i8, ptr %1, i64 %11 - store i8 120, ptr %15, align 1 - %16 = sub i64 %11, 1 - %17 = icmp slt i64 %16, 0 - %18 = icmp uge i64 %16, 100 - %19 = or i1 %18, %17 - call void @"github.com/goplus/llgo/runtime/internal/runtime.AssertIndexRange"(i1 %19) - %20 = getelementptr inbounds i8, ptr %1, i64 %16 - store i8 48, ptr %20, align 1 - %21 = call %"github.com/goplus/llgo/runtime/internal/runtime.Slice" @"github.com/goplus/llgo/runtime/internal/runtime.NewSlice3"(ptr %1, i64 1, i64 100, i64 %16, i64 100, i64 100) - call void @"github.com/goplus/llgo/cl/_testdata/print.gwrite"(%"github.com/goplus/llgo/runtime/internal/runtime.Slice" %21) - ret void - -_llgo_3: ; preds = %_llgo_4, %_llgo_0 - %22 = phi i64 [ %0, %_llgo_0 ], [ %25, %_llgo_4 ] - %23 = phi i64 [ 99, %_llgo_0 ], [ %26, %_llgo_4 ] - %24 = icmp sgt i64 %23, 0 - br i1 %24, label %_llgo_1, label %_llgo_2 - -_llgo_4: ; preds = %_llgo_5, %_llgo_1 - %25 = udiv i64 %22, 16 - %26 = sub i64 %23, 1 - br label %_llgo_3 - -_llgo_5: ; preds = %_llgo_1 - %27 = sub i64 100, %23 - %28 = load i64, ptr @"github.com/goplus/llgo/cl/_testdata/print.minhexdigits", align 4 - %29 = icmp sge i64 %27, %28 - br i1 %29, label %_llgo_2, label %_llgo_4 -} - -define void @"github.com/goplus/llgo/cl/_testdata/print.printint"(i64 %0) { -_llgo_0: - %1 = icmp slt i64 %0, 0 - br i1 %1, label %_llgo_1, label %_llgo_2 - -_llgo_1: ; preds = %_llgo_0 - call void @"github.com/goplus/llgo/cl/_testdata/print.printstring"(%"github.com/goplus/llgo/runtime/internal/runtime.String" { ptr @29, i64 1 }) - %2 = sub i64 0, %0 - br label %_llgo_2 - -_llgo_2: ; preds = %_llgo_1, %_llgo_0 - %3 = phi i64 [ %0, %_llgo_0 ], [ %2, %_llgo_1 ] - call void @"github.com/goplus/llgo/cl/_testdata/print.printuint"(i64 %3) - ret void -} - -define void @"github.com/goplus/llgo/cl/_testdata/print.println"(%"github.com/goplus/llgo/runtime/internal/runtime.Slice" %0) { -_llgo_0: - %1 = extractvalue %"github.com/goplus/llgo/runtime/internal/runtime.Slice" %0, 1 - br label %_llgo_1 - -_llgo_1: ; preds = %_llgo_5, %_llgo_0 - %2 = phi i64 [ -1, %_llgo_0 ], [ %3, %_llgo_5 ] - %3 = add i64 %2, 1 - %4 = icmp slt i64 %3, %1 - br i1 %4, label %_llgo_2, label %_llgo_3 - -_llgo_2: ; preds = %_llgo_1 - %5 = extractvalue %"github.com/goplus/llgo/runtime/internal/runtime.Slice" %0, 0 - %6 = extractvalue %"github.com/goplus/llgo/runtime/internal/runtime.Slice" %0, 1 - %7 = icmp slt i64 %3, 0 - %8 = icmp uge i64 %3, %6 - %9 = or i1 %8, %7 - call void @"github.com/goplus/llgo/runtime/internal/runtime.AssertIndexRange"(i1 %9) - %10 = getelementptr inbounds %"github.com/goplus/llgo/runtime/internal/runtime.eface", ptr %5, i64 %3 - %11 = load %"github.com/goplus/llgo/runtime/internal/runtime.eface", ptr %10, align 8 - %12 = icmp ne i64 %3, 0 - br i1 %12, label %_llgo_4, label %_llgo_5 - -_llgo_3: ; preds = %_llgo_1 - call void @"github.com/goplus/llgo/cl/_testdata/print.printnl"() - ret void - -_llgo_4: ; preds = %_llgo_2 - call void @"github.com/goplus/llgo/cl/_testdata/print.printstring"(%"github.com/goplus/llgo/runtime/internal/runtime.String" { ptr @30, i64 1 }) - br label %_llgo_5 - -_llgo_5: ; preds = %_llgo_4, %_llgo_2 - call void @"github.com/goplus/llgo/cl/_testdata/print.printany"(%"github.com/goplus/llgo/runtime/internal/runtime.eface" %11) - br label %_llgo_1 -} - -define void @"github.com/goplus/llgo/cl/_testdata/print.printnl"() { -_llgo_0: - call void @"github.com/goplus/llgo/cl/_testdata/print.printstring"(%"github.com/goplus/llgo/runtime/internal/runtime.String" { ptr @31, i64 1 }) - ret void -} - -define void @"github.com/goplus/llgo/cl/_testdata/print.printsp"() { -_llgo_0: - call void @"github.com/goplus/llgo/cl/_testdata/print.printstring"(%"github.com/goplus/llgo/runtime/internal/runtime.String" { ptr @30, i64 1 }) - ret void -} - -define void @"github.com/goplus/llgo/cl/_testdata/print.printstring"(%"github.com/goplus/llgo/runtime/internal/runtime.String" %0) { -_llgo_0: - %1 = call %"github.com/goplus/llgo/runtime/internal/runtime.Slice" @"github.com/goplus/llgo/cl/_testdata/print.bytes"(%"github.com/goplus/llgo/runtime/internal/runtime.String" %0) - call void @"github.com/goplus/llgo/cl/_testdata/print.gwrite"(%"github.com/goplus/llgo/runtime/internal/runtime.Slice" %1) - ret void -} - -define void @"github.com/goplus/llgo/cl/_testdata/print.printuint"(i64 %0) { -_llgo_0: - %1 = call ptr @"github.com/goplus/llgo/runtime/internal/runtime.AllocZ"(i64 100) - br label %_llgo_3 - -_llgo_1: ; preds = %_llgo_3 - %2 = urem i64 %11, 10 - %3 = add i64 %2, 48 - %4 = trunc i64 %3 to i8 - %5 = icmp slt i64 %12, 0 - %6 = icmp uge i64 %12, 100 - %7 = or i1 %6, %5 - call void @"github.com/goplus/llgo/runtime/internal/runtime.AssertIndexRange"(i1 %7) - %8 = getelementptr inbounds i8, ptr %1, i64 %12 - store i8 %4, ptr %8, align 1 - %9 = icmp ult i64 %11, 10 - br i1 %9, label %_llgo_2, label %_llgo_4 - -_llgo_2: ; preds = %_llgo_1, %_llgo_3 - %10 = call %"github.com/goplus/llgo/runtime/internal/runtime.Slice" @"github.com/goplus/llgo/runtime/internal/runtime.NewSlice3"(ptr %1, i64 1, i64 100, i64 %12, i64 100, i64 100) - call void @"github.com/goplus/llgo/cl/_testdata/print.gwrite"(%"github.com/goplus/llgo/runtime/internal/runtime.Slice" %10) - ret void - -_llgo_3: ; preds = %_llgo_4, %_llgo_0 - %11 = phi i64 [ %0, %_llgo_0 ], [ %14, %_llgo_4 ] - %12 = phi i64 [ 99, %_llgo_0 ], [ %15, %_llgo_4 ] - %13 = icmp sgt i64 %12, 0 - br i1 %13, label %_llgo_1, label %_llgo_2 - -_llgo_4: ; preds = %_llgo_1 - %14 = udiv i64 %11, 10 - %15 = sub i64 %12, 1 - br label %_llgo_3 -} - -define void @"github.com/goplus/llgo/cl/_testdata/print.prinusub"(i64 %0) { -_llgo_0: - %1 = sub i64 0, %0 - call void @"github.com/goplus/llgo/cl/_testdata/print.printuint"(i64 %1) - ret void -} - -define void @"github.com/goplus/llgo/cl/_testdata/print.prinxor"(i64 %0) { -_llgo_0: - %1 = xor i64 %0, -1 - call void @"github.com/goplus/llgo/cl/_testdata/print.printint"(i64 %1) - ret void -} - -define ptr @"github.com/goplus/llgo/cl/_testdata/print.stringStructOf"(ptr %0) { -_llgo_0: - ret ptr %0 -} - -declare ptr @"github.com/goplus/llgo/runtime/internal/runtime.AllocZ"(i64) - -declare void @"github.com/goplus/llgo/runtime/internal/runtime.AssertIndexRange"(i1) - -declare i32 @printf(ptr, ...) - -declare i1 @"github.com/goplus/llgo/runtime/internal/runtime.f32equal"(ptr, ptr) - -define linkonce i1 @"__llgo_stub.github.com/goplus/llgo/runtime/internal/runtime.f32equal"(ptr %0, ptr %1, ptr %2) { -_llgo_0: - %3 = tail call i1 @"github.com/goplus/llgo/runtime/internal/runtime.f32equal"(ptr %1, ptr %2) - ret i1 %3 -} - -declare i1 @"github.com/goplus/llgo/runtime/internal/runtime.memequalptr"(ptr, ptr) - -define linkonce i1 @"__llgo_stub.github.com/goplus/llgo/runtime/internal/runtime.memequalptr"(ptr %0, ptr %1, ptr %2) { -_llgo_0: - %3 = tail call i1 @"github.com/goplus/llgo/runtime/internal/runtime.memequalptr"(ptr %1, ptr %2) - ret i1 %3 -} - -declare ptr @"github.com/goplus/llgo/runtime/internal/runtime.AllocU"(i64) - -declare i1 @"github.com/goplus/llgo/runtime/internal/runtime.f64equal"(ptr, ptr) - -define linkonce i1 @"__llgo_stub.github.com/goplus/llgo/runtime/internal/runtime.f64equal"(ptr %0, ptr %1, ptr %2) { -_llgo_0: - %3 = tail call i1 @"github.com/goplus/llgo/runtime/internal/runtime.f64equal"(ptr %1, ptr %2) - ret i1 %3 -} - -declare i1 @"github.com/goplus/llgo/runtime/internal/runtime.strequal"(ptr, ptr) - -define linkonce i1 @"__llgo_stub.github.com/goplus/llgo/runtime/internal/runtime.strequal"(ptr %0, ptr %1, ptr %2) { -_llgo_0: - %3 = tail call i1 @"github.com/goplus/llgo/runtime/internal/runtime.strequal"(ptr %1, ptr %2) - ret i1 %3 -} - -declare i1 @"github.com/goplus/llgo/runtime/internal/runtime.memequal8"(ptr, ptr) - -define linkonce i1 @"__llgo_stub.github.com/goplus/llgo/runtime/internal/runtime.memequal8"(ptr %0, ptr %1, ptr %2) { -_llgo_0: - %3 = tail call i1 @"github.com/goplus/llgo/runtime/internal/runtime.memequal8"(ptr %1, ptr %2) - ret i1 %3 -} - -declare i1 @"github.com/goplus/llgo/runtime/internal/runtime.memequal32"(ptr, ptr) - -define linkonce i1 @"__llgo_stub.github.com/goplus/llgo/runtime/internal/runtime.memequal32"(ptr %0, ptr %1, ptr %2) { -_llgo_0: - %3 = tail call i1 @"github.com/goplus/llgo/runtime/internal/runtime.memequal32"(ptr %1, ptr %2) - ret i1 %3 -} - -declare i1 @"github.com/goplus/llgo/runtime/internal/runtime.memequal16"(ptr, ptr) - -define linkonce i1 @"__llgo_stub.github.com/goplus/llgo/runtime/internal/runtime.memequal16"(ptr %0, ptr %1, ptr %2) { -_llgo_0: - %3 = tail call i1 @"github.com/goplus/llgo/runtime/internal/runtime.memequal16"(ptr %1, ptr %2) - ret i1 %3 -} - -declare i1 @"github.com/goplus/llgo/runtime/internal/runtime.memequal64"(ptr, ptr) - -define linkonce i1 @"__llgo_stub.github.com/goplus/llgo/runtime/internal/runtime.memequal64"(ptr %0, ptr %1, ptr %2) { -_llgo_0: - %3 = tail call i1 @"github.com/goplus/llgo/runtime/internal/runtime.memequal64"(ptr %1, ptr %2) - ret i1 %3 -} - -declare i1 @"github.com/goplus/llgo/runtime/internal/runtime.c128equal"(ptr, ptr) - -define linkonce i1 @"__llgo_stub.github.com/goplus/llgo/runtime/internal/runtime.c128equal"(ptr %0, ptr %1, ptr %2) { -_llgo_0: - %3 = tail call i1 @"github.com/goplus/llgo/runtime/internal/runtime.c128equal"(ptr %1, ptr %2) - ret i1 %3 -} - -declare i1 @"github.com/goplus/llgo/runtime/internal/runtime.c64equal"(ptr, ptr) - -define linkonce i1 @"__llgo_stub.github.com/goplus/llgo/runtime/internal/runtime.c64equal"(ptr %0, ptr %1, ptr %2) { -_llgo_0: - %3 = tail call i1 @"github.com/goplus/llgo/runtime/internal/runtime.c64equal"(ptr %1, ptr %2) - ret i1 %3 -} - -declare %"github.com/goplus/llgo/runtime/internal/runtime.Slice" @"github.com/goplus/llgo/runtime/internal/runtime.NewSlice3"(ptr, i64, i64, i64, i64, i64) diff --git a/cl/_testdata/vargs/in.go b/cl/_testdata/vargs/in.go index 804a8d9eef..8a9f6901ee 100644 --- a/cl/_testdata/vargs/in.go +++ b/cl/_testdata/vargs/in.go @@ -91,9 +91,3 @@ func test(a ...any) { // CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.PanicTypeAssert"(ptr %12, %"{{.*}}/runtime/internal/runtime.String" { ptr @0, i64 3 }, %"{{.*}}/runtime/internal/runtime.String" zeroinitializer) // CHECK-NEXT: unreachable // CHECK-NEXT: } - -// CHECK-LABEL: define linkonce i1 @"__llgo_stub.{{.*}}/runtime/internal/runtime.memequal64"(ptr %0, ptr %1, ptr %2){{.*}} { -// CHECK-NEXT: _llgo_0: -// CHECK-NEXT: %3 = tail call i1 @"{{.*}}/runtime/internal/runtime.memequal64"(ptr %1, ptr %2) -// CHECK-NEXT: ret i1 %3 -// CHECK-NEXT: } diff --git a/cl/_testgo/abimethod/in.go b/cl/_testgo/abimethod/in.go index fbd6f43e77..37d16f8c6d 100644 --- a/cl/_testgo/abimethod/in.go +++ b/cl/_testgo/abimethod/in.go @@ -913,78 +913,6 @@ type I2 interface { // CHECK-NEXT: ret i64 %4 // CHECK-NEXT: } -// CHECK-LABEL: define linkonce i1 @"__llgo_stub.{{.*}}/runtime/internal/runtime.memequal64"(ptr %0, ptr %1, ptr %2){{.*}} { -// CHECK-NEXT: _llgo_0: -// CHECK-NEXT: %3 = tail call i1 @"{{.*}}/runtime/internal/runtime.memequal64"(ptr %1, ptr %2) -// CHECK-NEXT: ret i1 %3 -// CHECK-NEXT: } - -// CHECK-LABEL: define linkonce i64 @__llgo_stub.main.T.Demo1(ptr %0, %main.T %1){{.*}} { -// CHECK-NEXT: _llgo_0: -// CHECK-NEXT: %2 = tail call i64 @main.T.Demo1(%main.T %1) -// CHECK-NEXT: ret i64 %2 -// CHECK-NEXT: } - -// CHECK-LABEL: define linkonce i64 @"__llgo_stub.main.(*T).Demo1"(ptr %0, ptr %1){{.*}} { -// CHECK-NEXT: _llgo_0: -// CHECK-NEXT: %2 = tail call i64 @"main.(*T).Demo1"(ptr %1) -// CHECK-NEXT: ret i64 %2 -// CHECK-NEXT: } - -// CHECK-LABEL: define linkonce i64 @"__llgo_stub.main.(*T).Demo2"(ptr %0, ptr %1){{.*}} { -// CHECK-NEXT: _llgo_0: -// CHECK-NEXT: %2 = tail call i64 @"main.(*T).Demo2"(ptr %1) -// CHECK-NEXT: ret i64 %2 -// CHECK-NEXT: } - -// CHECK-LABEL: define linkonce i64 @"__llgo_stub.main.(*T).demo3"(ptr %0, ptr %1){{.*}} { -// CHECK-NEXT: _llgo_0: -// CHECK-NEXT: %2 = tail call i64 @"main.(*T).demo3"(ptr %1) -// CHECK-NEXT: ret i64 %2 -// CHECK-NEXT: } - -// CHECK-LABEL: define linkonce i64 @"__llgo_stub.main.struct{m int; *main.T}.Demo1"(ptr %0, { i64, ptr } %1){{.*}} { -// CHECK-NEXT: _llgo_0: -// CHECK-NEXT: %2 = tail call i64 @"main.struct{m int; *main.T}.Demo1"({ i64, ptr } %1) -// CHECK-NEXT: ret i64 %2 -// CHECK-NEXT: } - -// CHECK-LABEL: define linkonce i64 @"__llgo_stub.main.struct{m int; *main.T}.Demo2"(ptr %0, { i64, ptr } %1){{.*}} { -// CHECK-NEXT: _llgo_0: -// CHECK-NEXT: %2 = tail call i64 @"main.struct{m int; *main.T}.Demo2"({ i64, ptr } %1) -// CHECK-NEXT: ret i64 %2 -// CHECK-NEXT: } - -// CHECK-LABEL: define linkonce i64 @"__llgo_stub.main.struct{m int; *main.T}.demo3"(ptr %0, { i64, ptr } %1){{.*}} { -// CHECK-NEXT: _llgo_0: -// CHECK-NEXT: %2 = tail call i64 @"main.struct{m int; *main.T}.demo3"({ i64, ptr } %1) -// CHECK-NEXT: ret i64 %2 -// CHECK-NEXT: } - -// CHECK-LABEL: define linkonce i64 @"__llgo_stub.main.*struct{m int; *main.T}.Demo1"(ptr %0, ptr %1){{.*}} { -// CHECK-NEXT: _llgo_0: -// CHECK-NEXT: %2 = tail call i64 @"main.*struct{m int; *main.T}.Demo1"(ptr %1) -// CHECK-NEXT: ret i64 %2 -// CHECK-NEXT: } - -// CHECK-LABEL: define linkonce i64 @"__llgo_stub.main.*struct{m int; *main.T}.Demo2"(ptr %0, ptr %1){{.*}} { -// CHECK-NEXT: _llgo_0: -// CHECK-NEXT: %2 = tail call i64 @"main.*struct{m int; *main.T}.Demo2"(ptr %1) -// CHECK-NEXT: ret i64 %2 -// CHECK-NEXT: } - -// CHECK-LABEL: define linkonce i64 @"__llgo_stub.main.*struct{m int; *main.T}.demo3"(ptr %0, ptr %1){{.*}} { -// CHECK-NEXT: _llgo_0: -// CHECK-NEXT: %2 = tail call i64 @"main.*struct{m int; *main.T}.demo3"(ptr %1) -// CHECK-NEXT: ret i64 %2 -// CHECK-NEXT: } - -// CHECK-LABEL: define linkonce i1 @"__llgo_stub.{{.*}}/runtime/internal/runtime.interequal"(ptr %0, ptr %1, ptr %2){{.*}} { -// CHECK-NEXT: _llgo_0: -// CHECK-NEXT: %3 = tail call i1 @"{{.*}}/runtime/internal/runtime.interequal"(ptr %1, ptr %2) -// CHECK-NEXT: ret i1 %3 -// CHECK-NEXT: } - // CHECK-LABEL: define i64 @"main.struct{m int; main.T}.Demo1"({ i64, %main.T } %0){{.*}} { // CHECK-NEXT: _llgo_0: // CHECK-NEXT: %1 = alloca { i64, %main.T }, align 8 @@ -1021,30 +949,6 @@ type I2 interface { // CHECK-NEXT: ret i64 %2 // CHECK-NEXT: } -// CHECK-LABEL: define linkonce i64 @"__llgo_stub.main.*struct{m int; main.T}.Demo1"(ptr %0, ptr %1){{.*}} { -// CHECK-NEXT: _llgo_0: -// CHECK-NEXT: %2 = tail call i64 @"main.*struct{m int; main.T}.Demo1"(ptr %1) -// CHECK-NEXT: ret i64 %2 -// CHECK-NEXT: } - -// CHECK-LABEL: define linkonce i64 @"__llgo_stub.main.*struct{m int; main.T}.Demo2"(ptr %0, ptr %1){{.*}} { -// CHECK-NEXT: _llgo_0: -// CHECK-NEXT: %2 = tail call i64 @"main.*struct{m int; main.T}.Demo2"(ptr %1) -// CHECK-NEXT: ret i64 %2 -// CHECK-NEXT: } - -// CHECK-LABEL: define linkonce i64 @"__llgo_stub.main.*struct{m int; main.T}.demo3"(ptr %0, ptr %1){{.*}} { -// CHECK-NEXT: _llgo_0: -// CHECK-NEXT: %2 = tail call i64 @"main.*struct{m int; main.T}.demo3"(ptr %1) -// CHECK-NEXT: ret i64 %2 -// CHECK-NEXT: } - -// CHECK-LABEL: define linkonce i64 @"__llgo_stub.main.struct{m int; main.T}.Demo1"(ptr %0, { i64, %main.T } %1){{.*}} { -// CHECK-NEXT: _llgo_0: -// CHECK-NEXT: %2 = tail call i64 @"main.struct{m int; main.T}.Demo1"({ i64, %main.T } %1) -// CHECK-NEXT: ret i64 %2 -// CHECK-NEXT: } - // CHECK-LABEL: define i64 @"main.*struct{m int; *bytes.Buffer}.Available"(ptr %0){{.*}} { // CHECK-NEXT: _llgo_0: // CHECK-NEXT: %1 = getelementptr inbounds { i64, ptr }, ptr %0, i32 0, i32 1 @@ -1658,498 +1562,6 @@ type I2 interface { // CHECK-NEXT: ret { i64, i1 } %9 // CHECK-NEXT: } -// CHECK-LABEL: define linkonce i1 @"__llgo_stub.{{.*}}/runtime/internal/runtime.memequal8"(ptr %0, ptr %1, ptr %2){{.*}} { -// CHECK-NEXT: _llgo_0: -// CHECK-NEXT: %3 = tail call i1 @"{{.*}}/runtime/internal/runtime.memequal8"(ptr %1, ptr %2) -// CHECK-NEXT: ret i1 %3 -// CHECK-NEXT: } - -// CHECK-LABEL: define linkonce i64 @"__llgo_stub.bytes.(*Buffer).Available"(ptr %0, ptr %1){{.*}} { -// CHECK-NEXT: _llgo_0: -// CHECK-NEXT: %2 = tail call i64 @"bytes.(*Buffer).Available"(ptr %1) -// CHECK-NEXT: ret i64 %2 -// CHECK-NEXT: } - -// CHECK-LABEL: define linkonce %"{{.*}}/runtime/internal/runtime.Slice" @"__llgo_stub.bytes.(*Buffer).AvailableBuffer"(ptr %0, ptr %1){{.*}} { -// CHECK-NEXT: _llgo_0: -// CHECK-NEXT: %2 = tail call %"{{.*}}/runtime/internal/runtime.Slice" @"bytes.(*Buffer).AvailableBuffer"(ptr %1) -// CHECK-NEXT: ret %"{{.*}}/runtime/internal/runtime.Slice" %2 -// CHECK-NEXT: } - -// CHECK-LABEL: define linkonce %"{{.*}}/runtime/internal/runtime.Slice" @"__llgo_stub.bytes.(*Buffer).Bytes"(ptr %0, ptr %1){{.*}} { -// CHECK-NEXT: _llgo_0: -// CHECK-NEXT: %2 = tail call %"{{.*}}/runtime/internal/runtime.Slice" @"bytes.(*Buffer).Bytes"(ptr %1) -// CHECK-NEXT: ret %"{{.*}}/runtime/internal/runtime.Slice" %2 -// CHECK-NEXT: } - -// CHECK-LABEL: define linkonce i64 @"__llgo_stub.bytes.(*Buffer).Cap"(ptr %0, ptr %1){{.*}} { -// CHECK-NEXT: _llgo_0: -// CHECK-NEXT: %2 = tail call i64 @"bytes.(*Buffer).Cap"(ptr %1) -// CHECK-NEXT: ret i64 %2 -// CHECK-NEXT: } - -// CHECK-LABEL: define linkonce void @"__llgo_stub.bytes.(*Buffer).Grow"(ptr %0, ptr %1, i64 %2){{.*}} { -// CHECK-NEXT: _llgo_0: -// CHECK-NEXT: tail call void @"bytes.(*Buffer).Grow"(ptr %1, i64 %2) -// CHECK-NEXT: ret void -// CHECK-NEXT: } - -// CHECK-LABEL: define linkonce i64 @"__llgo_stub.bytes.(*Buffer).Len"(ptr %0, ptr %1){{.*}} { -// CHECK-NEXT: _llgo_0: -// CHECK-NEXT: %2 = tail call i64 @"bytes.(*Buffer).Len"(ptr %1) -// CHECK-NEXT: ret i64 %2 -// CHECK-NEXT: } - -// CHECK-LABEL: define linkonce %"{{.*}}/runtime/internal/runtime.Slice" @"__llgo_stub.bytes.(*Buffer).Next"(ptr %0, ptr %1, i64 %2){{.*}} { -// CHECK-NEXT: _llgo_0: -// CHECK-NEXT: %3 = tail call %"{{.*}}/runtime/internal/runtime.Slice" @"bytes.(*Buffer).Next"(ptr %1, i64 %2) -// CHECK-NEXT: ret %"{{.*}}/runtime/internal/runtime.Slice" %3 -// CHECK-NEXT: } - -// CHECK-LABEL: define linkonce { i64, %"{{.*}}/runtime/internal/runtime.iface" } @"__llgo_stub.bytes.(*Buffer).Read"(ptr %0, ptr %1, %"{{.*}}/runtime/internal/runtime.Slice" %2){{.*}} { -// CHECK-NEXT: _llgo_0: -// CHECK-NEXT: %3 = tail call { i64, %"{{.*}}/runtime/internal/runtime.iface" } @"bytes.(*Buffer).Read"(ptr %1, %"{{.*}}/runtime/internal/runtime.Slice" %2) -// CHECK-NEXT: ret { i64, %"{{.*}}/runtime/internal/runtime.iface" } %3 -// CHECK-NEXT: } - -// CHECK-LABEL: define linkonce { i8, %"{{.*}}/runtime/internal/runtime.iface" } @"__llgo_stub.bytes.(*Buffer).ReadByte"(ptr %0, ptr %1){{.*}} { -// CHECK-NEXT: _llgo_0: -// CHECK-NEXT: %2 = tail call { i8, %"{{.*}}/runtime/internal/runtime.iface" } @"bytes.(*Buffer).ReadByte"(ptr %1) -// CHECK-NEXT: ret { i8, %"{{.*}}/runtime/internal/runtime.iface" } %2 -// CHECK-NEXT: } - -// CHECK-LABEL: define linkonce { %"{{.*}}/runtime/internal/runtime.Slice", %"{{.*}}/runtime/internal/runtime.iface" } @"__llgo_stub.bytes.(*Buffer).ReadBytes"(ptr %0, ptr %1, i8 %2){{.*}} { -// CHECK-NEXT: _llgo_0: -// CHECK-NEXT: %3 = tail call { %"{{.*}}/runtime/internal/runtime.Slice", %"{{.*}}/runtime/internal/runtime.iface" } @"bytes.(*Buffer).ReadBytes"(ptr %1, i8 %2) -// CHECK-NEXT: ret { %"{{.*}}/runtime/internal/runtime.Slice", %"{{.*}}/runtime/internal/runtime.iface" } %3 -// CHECK-NEXT: } - -// CHECK-LABEL: define linkonce { i64, %"{{.*}}/runtime/internal/runtime.iface" } @"__llgo_stub.bytes.(*Buffer).ReadFrom"(ptr %0, ptr %1, %"{{.*}}/runtime/internal/runtime.iface" %2){{.*}} { -// CHECK-NEXT: _llgo_0: -// CHECK-NEXT: %3 = tail call { i64, %"{{.*}}/runtime/internal/runtime.iface" } @"bytes.(*Buffer).ReadFrom"(ptr %1, %"{{.*}}/runtime/internal/runtime.iface" %2) -// CHECK-NEXT: ret { i64, %"{{.*}}/runtime/internal/runtime.iface" } %3 -// CHECK-NEXT: } - -// CHECK-LABEL: define linkonce { i32, i64, %"{{.*}}/runtime/internal/runtime.iface" } @"__llgo_stub.bytes.(*Buffer).ReadRune"(ptr %0, ptr %1){{.*}} { -// CHECK-NEXT: _llgo_0: -// CHECK-NEXT: %2 = tail call { i32, i64, %"{{.*}}/runtime/internal/runtime.iface" } @"bytes.(*Buffer).ReadRune"(ptr %1) -// CHECK-NEXT: ret { i32, i64, %"{{.*}}/runtime/internal/runtime.iface" } %2 -// CHECK-NEXT: } - -// CHECK-LABEL: define linkonce { %"{{.*}}/runtime/internal/runtime.String", %"{{.*}}/runtime/internal/runtime.iface" } @"__llgo_stub.bytes.(*Buffer).ReadString"(ptr %0, ptr %1, i8 %2){{.*}} { -// CHECK-NEXT: _llgo_0: -// CHECK-NEXT: %3 = tail call { %"{{.*}}/runtime/internal/runtime.String", %"{{.*}}/runtime/internal/runtime.iface" } @"bytes.(*Buffer).ReadString"(ptr %1, i8 %2) -// CHECK-NEXT: ret { %"{{.*}}/runtime/internal/runtime.String", %"{{.*}}/runtime/internal/runtime.iface" } %3 -// CHECK-NEXT: } - -// CHECK-LABEL: define linkonce void @"__llgo_stub.bytes.(*Buffer).Reset"(ptr %0, ptr %1){{.*}} { -// CHECK-NEXT: _llgo_0: -// CHECK-NEXT: tail call void @"bytes.(*Buffer).Reset"(ptr %1) -// CHECK-NEXT: ret void -// CHECK-NEXT: } - -// CHECK-LABEL: define linkonce %"{{.*}}/runtime/internal/runtime.String" @"__llgo_stub.bytes.(*Buffer).String"(ptr %0, ptr %1){{.*}} { -// CHECK-NEXT: _llgo_0: -// CHECK-NEXT: %2 = tail call %"{{.*}}/runtime/internal/runtime.String" @"bytes.(*Buffer).String"(ptr %1) -// CHECK-NEXT: ret %"{{.*}}/runtime/internal/runtime.String" %2 -// CHECK-NEXT: } - -// CHECK-LABEL: define linkonce void @"__llgo_stub.bytes.(*Buffer).Truncate"(ptr %0, ptr %1, i64 %2){{.*}} { -// CHECK-NEXT: _llgo_0: -// CHECK-NEXT: tail call void @"bytes.(*Buffer).Truncate"(ptr %1, i64 %2) -// CHECK-NEXT: ret void -// CHECK-NEXT: } - -// CHECK-LABEL: define linkonce %"{{.*}}/runtime/internal/runtime.iface" @"__llgo_stub.bytes.(*Buffer).UnreadByte"(ptr %0, ptr %1){{.*}} { -// CHECK-NEXT: _llgo_0: -// CHECK-NEXT: %2 = tail call %"{{.*}}/runtime/internal/runtime.iface" @"bytes.(*Buffer).UnreadByte"(ptr %1) -// CHECK-NEXT: ret %"{{.*}}/runtime/internal/runtime.iface" %2 -// CHECK-NEXT: } - -// CHECK-LABEL: define linkonce %"{{.*}}/runtime/internal/runtime.iface" @"__llgo_stub.bytes.(*Buffer).UnreadRune"(ptr %0, ptr %1){{.*}} { -// CHECK-NEXT: _llgo_0: -// CHECK-NEXT: %2 = tail call %"{{.*}}/runtime/internal/runtime.iface" @"bytes.(*Buffer).UnreadRune"(ptr %1) -// CHECK-NEXT: ret %"{{.*}}/runtime/internal/runtime.iface" %2 -// CHECK-NEXT: } - -// CHECK-LABEL: define linkonce { i64, %"{{.*}}/runtime/internal/runtime.iface" } @"__llgo_stub.bytes.(*Buffer).Write"(ptr %0, ptr %1, %"{{.*}}/runtime/internal/runtime.Slice" %2){{.*}} { -// CHECK-NEXT: _llgo_0: -// CHECK-NEXT: %3 = tail call { i64, %"{{.*}}/runtime/internal/runtime.iface" } @"bytes.(*Buffer).Write"(ptr %1, %"{{.*}}/runtime/internal/runtime.Slice" %2) -// CHECK-NEXT: ret { i64, %"{{.*}}/runtime/internal/runtime.iface" } %3 -// CHECK-NEXT: } - -// CHECK-LABEL: define linkonce %"{{.*}}/runtime/internal/runtime.iface" @"__llgo_stub.bytes.(*Buffer).WriteByte"(ptr %0, ptr %1, i8 %2){{.*}} { -// CHECK-NEXT: _llgo_0: -// CHECK-NEXT: %3 = tail call %"{{.*}}/runtime/internal/runtime.iface" @"bytes.(*Buffer).WriteByte"(ptr %1, i8 %2) -// CHECK-NEXT: ret %"{{.*}}/runtime/internal/runtime.iface" %3 -// CHECK-NEXT: } - -// CHECK-LABEL: define linkonce { i64, %"{{.*}}/runtime/internal/runtime.iface" } @"__llgo_stub.bytes.(*Buffer).WriteRune"(ptr %0, ptr %1, i32 %2){{.*}} { -// CHECK-NEXT: _llgo_0: -// CHECK-NEXT: %3 = tail call { i64, %"{{.*}}/runtime/internal/runtime.iface" } @"bytes.(*Buffer).WriteRune"(ptr %1, i32 %2) -// CHECK-NEXT: ret { i64, %"{{.*}}/runtime/internal/runtime.iface" } %3 -// CHECK-NEXT: } - -// CHECK-LABEL: define linkonce { i64, %"{{.*}}/runtime/internal/runtime.iface" } @"__llgo_stub.bytes.(*Buffer).WriteString"(ptr %0, ptr %1, %"{{.*}}/runtime/internal/runtime.String" %2){{.*}} { -// CHECK-NEXT: _llgo_0: -// CHECK-NEXT: %3 = tail call { i64, %"{{.*}}/runtime/internal/runtime.iface" } @"bytes.(*Buffer).WriteString"(ptr %1, %"{{.*}}/runtime/internal/runtime.String" %2) -// CHECK-NEXT: ret { i64, %"{{.*}}/runtime/internal/runtime.iface" } %3 -// CHECK-NEXT: } - -// CHECK-LABEL: define linkonce { i64, %"{{.*}}/runtime/internal/runtime.iface" } @"__llgo_stub.bytes.(*Buffer).WriteTo"(ptr %0, ptr %1, %"{{.*}}/runtime/internal/runtime.iface" %2){{.*}} { -// CHECK-NEXT: _llgo_0: -// CHECK-NEXT: %3 = tail call { i64, %"{{.*}}/runtime/internal/runtime.iface" } @"bytes.(*Buffer).WriteTo"(ptr %1, %"{{.*}}/runtime/internal/runtime.iface" %2) -// CHECK-NEXT: ret { i64, %"{{.*}}/runtime/internal/runtime.iface" } %3 -// CHECK-NEXT: } - -// CHECK-LABEL: define linkonce i1 @"__llgo_stub.bytes.(*Buffer).empty"(ptr %0, ptr %1){{.*}} { -// CHECK-NEXT: _llgo_0: -// CHECK-NEXT: %2 = tail call i1 @"bytes.(*Buffer).empty"(ptr %1) -// CHECK-NEXT: ret i1 %2 -// CHECK-NEXT: } - -// CHECK-LABEL: define linkonce i64 @"__llgo_stub.bytes.(*Buffer).grow"(ptr %0, ptr %1, i64 %2){{.*}} { -// CHECK-NEXT: _llgo_0: -// CHECK-NEXT: %3 = tail call i64 @"bytes.(*Buffer).grow"(ptr %1, i64 %2) -// CHECK-NEXT: ret i64 %3 -// CHECK-NEXT: } - -// CHECK-LABEL: define linkonce { %"{{.*}}/runtime/internal/runtime.Slice", %"{{.*}}/runtime/internal/runtime.iface" } @"__llgo_stub.bytes.(*Buffer).readSlice"(ptr %0, ptr %1, i8 %2){{.*}} { -// CHECK-NEXT: _llgo_0: -// CHECK-NEXT: %3 = tail call { %"{{.*}}/runtime/internal/runtime.Slice", %"{{.*}}/runtime/internal/runtime.iface" } @"bytes.(*Buffer).readSlice"(ptr %1, i8 %2) -// CHECK-NEXT: ret { %"{{.*}}/runtime/internal/runtime.Slice", %"{{.*}}/runtime/internal/runtime.iface" } %3 -// CHECK-NEXT: } - -// CHECK-LABEL: define linkonce { i64, i1 } @"__llgo_stub.bytes.(*Buffer).tryGrowByReslice"(ptr %0, ptr %1, i64 %2){{.*}} { -// CHECK-NEXT: _llgo_0: -// CHECK-NEXT: %3 = tail call { i64, i1 } @"bytes.(*Buffer).tryGrowByReslice"(ptr %1, i64 %2) -// CHECK-NEXT: ret { i64, i1 } %3 -// CHECK-NEXT: } - -// CHECK-LABEL: define linkonce i64 @"__llgo_stub.main.struct{m int; *bytes.Buffer}.Available"(ptr %0, { i64, ptr } %1){{.*}} { -// CHECK-NEXT: _llgo_0: -// CHECK-NEXT: %2 = tail call i64 @"main.struct{m int; *bytes.Buffer}.Available"({ i64, ptr } %1) -// CHECK-NEXT: ret i64 %2 -// CHECK-NEXT: } - -// CHECK-LABEL: define linkonce %"{{.*}}/runtime/internal/runtime.Slice" @"__llgo_stub.main.struct{m int; *bytes.Buffer}.AvailableBuffer"(ptr %0, { i64, ptr } %1){{.*}} { -// CHECK-NEXT: _llgo_0: -// CHECK-NEXT: %2 = tail call %"{{.*}}/runtime/internal/runtime.Slice" @"main.struct{m int; *bytes.Buffer}.AvailableBuffer"({ i64, ptr } %1) -// CHECK-NEXT: ret %"{{.*}}/runtime/internal/runtime.Slice" %2 -// CHECK-NEXT: } - -// CHECK-LABEL: define linkonce %"{{.*}}/runtime/internal/runtime.Slice" @"__llgo_stub.main.struct{m int; *bytes.Buffer}.Bytes"(ptr %0, { i64, ptr } %1){{.*}} { -// CHECK-NEXT: _llgo_0: -// CHECK-NEXT: %2 = tail call %"{{.*}}/runtime/internal/runtime.Slice" @"main.struct{m int; *bytes.Buffer}.Bytes"({ i64, ptr } %1) -// CHECK-NEXT: ret %"{{.*}}/runtime/internal/runtime.Slice" %2 -// CHECK-NEXT: } - -// CHECK-LABEL: define linkonce i64 @"__llgo_stub.main.struct{m int; *bytes.Buffer}.Cap"(ptr %0, { i64, ptr } %1){{.*}} { -// CHECK-NEXT: _llgo_0: -// CHECK-NEXT: %2 = tail call i64 @"main.struct{m int; *bytes.Buffer}.Cap"({ i64, ptr } %1) -// CHECK-NEXT: ret i64 %2 -// CHECK-NEXT: } - -// CHECK-LABEL: define linkonce void @"__llgo_stub.main.struct{m int; *bytes.Buffer}.Grow"(ptr %0, { i64, ptr } %1, i64 %2){{.*}} { -// CHECK-NEXT: _llgo_0: -// CHECK-NEXT: tail call void @"main.struct{m int; *bytes.Buffer}.Grow"({ i64, ptr } %1, i64 %2) -// CHECK-NEXT: ret void -// CHECK-NEXT: } - -// CHECK-LABEL: define linkonce i64 @"__llgo_stub.main.struct{m int; *bytes.Buffer}.Len"(ptr %0, { i64, ptr } %1){{.*}} { -// CHECK-NEXT: _llgo_0: -// CHECK-NEXT: %2 = tail call i64 @"main.struct{m int; *bytes.Buffer}.Len"({ i64, ptr } %1) -// CHECK-NEXT: ret i64 %2 -// CHECK-NEXT: } - -// CHECK-LABEL: define linkonce %"{{.*}}/runtime/internal/runtime.Slice" @"__llgo_stub.main.struct{m int; *bytes.Buffer}.Next"(ptr %0, { i64, ptr } %1, i64 %2){{.*}} { -// CHECK-NEXT: _llgo_0: -// CHECK-NEXT: %3 = tail call %"{{.*}}/runtime/internal/runtime.Slice" @"main.struct{m int; *bytes.Buffer}.Next"({ i64, ptr } %1, i64 %2) -// CHECK-NEXT: ret %"{{.*}}/runtime/internal/runtime.Slice" %3 -// CHECK-NEXT: } - -// CHECK-LABEL: define linkonce { i64, %"{{.*}}/runtime/internal/runtime.iface" } @"__llgo_stub.main.struct{m int; *bytes.Buffer}.Read"(ptr %0, { i64, ptr } %1, %"{{.*}}/runtime/internal/runtime.Slice" %2){{.*}} { -// CHECK-NEXT: _llgo_0: -// CHECK-NEXT: %3 = tail call { i64, %"{{.*}}/runtime/internal/runtime.iface" } @"main.struct{m int; *bytes.Buffer}.Read"({ i64, ptr } %1, %"{{.*}}/runtime/internal/runtime.Slice" %2) -// CHECK-NEXT: ret { i64, %"{{.*}}/runtime/internal/runtime.iface" } %3 -// CHECK-NEXT: } - -// CHECK-LABEL: define linkonce { i8, %"{{.*}}/runtime/internal/runtime.iface" } @"__llgo_stub.main.struct{m int; *bytes.Buffer}.ReadByte"(ptr %0, { i64, ptr } %1){{.*}} { -// CHECK-NEXT: _llgo_0: -// CHECK-NEXT: %2 = tail call { i8, %"{{.*}}/runtime/internal/runtime.iface" } @"main.struct{m int; *bytes.Buffer}.ReadByte"({ i64, ptr } %1) -// CHECK-NEXT: ret { i8, %"{{.*}}/runtime/internal/runtime.iface" } %2 -// CHECK-NEXT: } - -// CHECK-LABEL: define linkonce { %"{{.*}}/runtime/internal/runtime.Slice", %"{{.*}}/runtime/internal/runtime.iface" } @"__llgo_stub.main.struct{m int; *bytes.Buffer}.ReadBytes"(ptr %0, { i64, ptr } %1, i8 %2){{.*}} { -// CHECK-NEXT: _llgo_0: -// CHECK-NEXT: %3 = tail call { %"{{.*}}/runtime/internal/runtime.Slice", %"{{.*}}/runtime/internal/runtime.iface" } @"main.struct{m int; *bytes.Buffer}.ReadBytes"({ i64, ptr } %1, i8 %2) -// CHECK-NEXT: ret { %"{{.*}}/runtime/internal/runtime.Slice", %"{{.*}}/runtime/internal/runtime.iface" } %3 -// CHECK-NEXT: } - -// CHECK-LABEL: define linkonce { i64, %"{{.*}}/runtime/internal/runtime.iface" } @"__llgo_stub.main.struct{m int; *bytes.Buffer}.ReadFrom"(ptr %0, { i64, ptr } %1, %"{{.*}}/runtime/internal/runtime.iface" %2){{.*}} { -// CHECK-NEXT: _llgo_0: -// CHECK-NEXT: %3 = tail call { i64, %"{{.*}}/runtime/internal/runtime.iface" } @"main.struct{m int; *bytes.Buffer}.ReadFrom"({ i64, ptr } %1, %"{{.*}}/runtime/internal/runtime.iface" %2) -// CHECK-NEXT: ret { i64, %"{{.*}}/runtime/internal/runtime.iface" } %3 -// CHECK-NEXT: } - -// CHECK-LABEL: define linkonce { i32, i64, %"{{.*}}/runtime/internal/runtime.iface" } @"__llgo_stub.main.struct{m int; *bytes.Buffer}.ReadRune"(ptr %0, { i64, ptr } %1){{.*}} { -// CHECK-NEXT: _llgo_0: -// CHECK-NEXT: %2 = tail call { i32, i64, %"{{.*}}/runtime/internal/runtime.iface" } @"main.struct{m int; *bytes.Buffer}.ReadRune"({ i64, ptr } %1) -// CHECK-NEXT: ret { i32, i64, %"{{.*}}/runtime/internal/runtime.iface" } %2 -// CHECK-NEXT: } - -// CHECK-LABEL: define linkonce { %"{{.*}}/runtime/internal/runtime.String", %"{{.*}}/runtime/internal/runtime.iface" } @"__llgo_stub.main.struct{m int; *bytes.Buffer}.ReadString"(ptr %0, { i64, ptr } %1, i8 %2){{.*}} { -// CHECK-NEXT: _llgo_0: -// CHECK-NEXT: %3 = tail call { %"{{.*}}/runtime/internal/runtime.String", %"{{.*}}/runtime/internal/runtime.iface" } @"main.struct{m int; *bytes.Buffer}.ReadString"({ i64, ptr } %1, i8 %2) -// CHECK-NEXT: ret { %"{{.*}}/runtime/internal/runtime.String", %"{{.*}}/runtime/internal/runtime.iface" } %3 -// CHECK-NEXT: } - -// CHECK-LABEL: define linkonce void @"__llgo_stub.main.struct{m int; *bytes.Buffer}.Reset"(ptr %0, { i64, ptr } %1){{.*}} { -// CHECK-NEXT: _llgo_0: -// CHECK-NEXT: tail call void @"main.struct{m int; *bytes.Buffer}.Reset"({ i64, ptr } %1) -// CHECK-NEXT: ret void -// CHECK-NEXT: } - -// CHECK-LABEL: define linkonce %"{{.*}}/runtime/internal/runtime.String" @"__llgo_stub.main.struct{m int; *bytes.Buffer}.String"(ptr %0, { i64, ptr } %1){{.*}} { -// CHECK-NEXT: _llgo_0: -// CHECK-NEXT: %2 = tail call %"{{.*}}/runtime/internal/runtime.String" @"main.struct{m int; *bytes.Buffer}.String"({ i64, ptr } %1) -// CHECK-NEXT: ret %"{{.*}}/runtime/internal/runtime.String" %2 -// CHECK-NEXT: } - -// CHECK-LABEL: define linkonce void @"__llgo_stub.main.struct{m int; *bytes.Buffer}.Truncate"(ptr %0, { i64, ptr } %1, i64 %2){{.*}} { -// CHECK-NEXT: _llgo_0: -// CHECK-NEXT: tail call void @"main.struct{m int; *bytes.Buffer}.Truncate"({ i64, ptr } %1, i64 %2) -// CHECK-NEXT: ret void -// CHECK-NEXT: } - -// CHECK-LABEL: define linkonce %"{{.*}}/runtime/internal/runtime.iface" @"__llgo_stub.main.struct{m int; *bytes.Buffer}.UnreadByte"(ptr %0, { i64, ptr } %1){{.*}} { -// CHECK-NEXT: _llgo_0: -// CHECK-NEXT: %2 = tail call %"{{.*}}/runtime/internal/runtime.iface" @"main.struct{m int; *bytes.Buffer}.UnreadByte"({ i64, ptr } %1) -// CHECK-NEXT: ret %"{{.*}}/runtime/internal/runtime.iface" %2 -// CHECK-NEXT: } - -// CHECK-LABEL: define linkonce %"{{.*}}/runtime/internal/runtime.iface" @"__llgo_stub.main.struct{m int; *bytes.Buffer}.UnreadRune"(ptr %0, { i64, ptr } %1){{.*}} { -// CHECK-NEXT: _llgo_0: -// CHECK-NEXT: %2 = tail call %"{{.*}}/runtime/internal/runtime.iface" @"main.struct{m int; *bytes.Buffer}.UnreadRune"({ i64, ptr } %1) -// CHECK-NEXT: ret %"{{.*}}/runtime/internal/runtime.iface" %2 -// CHECK-NEXT: } - -// CHECK-LABEL: define linkonce { i64, %"{{.*}}/runtime/internal/runtime.iface" } @"__llgo_stub.main.struct{m int; *bytes.Buffer}.Write"(ptr %0, { i64, ptr } %1, %"{{.*}}/runtime/internal/runtime.Slice" %2){{.*}} { -// CHECK-NEXT: _llgo_0: -// CHECK-NEXT: %3 = tail call { i64, %"{{.*}}/runtime/internal/runtime.iface" } @"main.struct{m int; *bytes.Buffer}.Write"({ i64, ptr } %1, %"{{.*}}/runtime/internal/runtime.Slice" %2) -// CHECK-NEXT: ret { i64, %"{{.*}}/runtime/internal/runtime.iface" } %3 -// CHECK-NEXT: } - -// CHECK-LABEL: define linkonce %"{{.*}}/runtime/internal/runtime.iface" @"__llgo_stub.main.struct{m int; *bytes.Buffer}.WriteByte"(ptr %0, { i64, ptr } %1, i8 %2){{.*}} { -// CHECK-NEXT: _llgo_0: -// CHECK-NEXT: %3 = tail call %"{{.*}}/runtime/internal/runtime.iface" @"main.struct{m int; *bytes.Buffer}.WriteByte"({ i64, ptr } %1, i8 %2) -// CHECK-NEXT: ret %"{{.*}}/runtime/internal/runtime.iface" %3 -// CHECK-NEXT: } - -// CHECK-LABEL: define linkonce { i64, %"{{.*}}/runtime/internal/runtime.iface" } @"__llgo_stub.main.struct{m int; *bytes.Buffer}.WriteRune"(ptr %0, { i64, ptr } %1, i32 %2){{.*}} { -// CHECK-NEXT: _llgo_0: -// CHECK-NEXT: %3 = tail call { i64, %"{{.*}}/runtime/internal/runtime.iface" } @"main.struct{m int; *bytes.Buffer}.WriteRune"({ i64, ptr } %1, i32 %2) -// CHECK-NEXT: ret { i64, %"{{.*}}/runtime/internal/runtime.iface" } %3 -// CHECK-NEXT: } - -// CHECK-LABEL: define linkonce { i64, %"{{.*}}/runtime/internal/runtime.iface" } @"__llgo_stub.main.struct{m int; *bytes.Buffer}.WriteString"(ptr %0, { i64, ptr } %1, %"{{.*}}/runtime/internal/runtime.String" %2){{.*}} { -// CHECK-NEXT: _llgo_0: -// CHECK-NEXT: %3 = tail call { i64, %"{{.*}}/runtime/internal/runtime.iface" } @"main.struct{m int; *bytes.Buffer}.WriteString"({ i64, ptr } %1, %"{{.*}}/runtime/internal/runtime.String" %2) -// CHECK-NEXT: ret { i64, %"{{.*}}/runtime/internal/runtime.iface" } %3 -// CHECK-NEXT: } - -// CHECK-LABEL: define linkonce { i64, %"{{.*}}/runtime/internal/runtime.iface" } @"__llgo_stub.main.struct{m int; *bytes.Buffer}.WriteTo"(ptr %0, { i64, ptr } %1, %"{{.*}}/runtime/internal/runtime.iface" %2){{.*}} { -// CHECK-NEXT: _llgo_0: -// CHECK-NEXT: %3 = tail call { i64, %"{{.*}}/runtime/internal/runtime.iface" } @"main.struct{m int; *bytes.Buffer}.WriteTo"({ i64, ptr } %1, %"{{.*}}/runtime/internal/runtime.iface" %2) -// CHECK-NEXT: ret { i64, %"{{.*}}/runtime/internal/runtime.iface" } %3 -// CHECK-NEXT: } - -// CHECK-LABEL: define linkonce i1 @"__llgo_stub.main.struct{m int; *bytes.Buffer}.empty"(ptr %0, { i64, ptr } %1){{.*}} { -// CHECK-NEXT: _llgo_0: -// CHECK-NEXT: %2 = tail call i1 @"main.struct{m int; *bytes.Buffer}.empty"({ i64, ptr } %1) -// CHECK-NEXT: ret i1 %2 -// CHECK-NEXT: } - -// CHECK-LABEL: define linkonce i64 @"__llgo_stub.main.struct{m int; *bytes.Buffer}.grow"(ptr %0, { i64, ptr } %1, i64 %2){{.*}} { -// CHECK-NEXT: _llgo_0: -// CHECK-NEXT: %3 = tail call i64 @"main.struct{m int; *bytes.Buffer}.grow"({ i64, ptr } %1, i64 %2) -// CHECK-NEXT: ret i64 %3 -// CHECK-NEXT: } - -// CHECK-LABEL: define linkonce { %"{{.*}}/runtime/internal/runtime.Slice", %"{{.*}}/runtime/internal/runtime.iface" } @"__llgo_stub.main.struct{m int; *bytes.Buffer}.readSlice"(ptr %0, { i64, ptr } %1, i8 %2){{.*}} { -// CHECK-NEXT: _llgo_0: -// CHECK-NEXT: %3 = tail call { %"{{.*}}/runtime/internal/runtime.Slice", %"{{.*}}/runtime/internal/runtime.iface" } @"main.struct{m int; *bytes.Buffer}.readSlice"({ i64, ptr } %1, i8 %2) -// CHECK-NEXT: ret { %"{{.*}}/runtime/internal/runtime.Slice", %"{{.*}}/runtime/internal/runtime.iface" } %3 -// CHECK-NEXT: } - -// CHECK-LABEL: define linkonce { i64, i1 } @"__llgo_stub.main.struct{m int; *bytes.Buffer}.tryGrowByReslice"(ptr %0, { i64, ptr } %1, i64 %2){{.*}} { -// CHECK-NEXT: _llgo_0: -// CHECK-NEXT: %3 = tail call { i64, i1 } @"main.struct{m int; *bytes.Buffer}.tryGrowByReslice"({ i64, ptr } %1, i64 %2) -// CHECK-NEXT: ret { i64, i1 } %3 -// CHECK-NEXT: } - -// CHECK-LABEL: define linkonce i64 @"__llgo_stub.main.*struct{m int; *bytes.Buffer}.Available"(ptr %0, ptr %1){{.*}} { -// CHECK-NEXT: _llgo_0: -// CHECK-NEXT: %2 = tail call i64 @"main.*struct{m int; *bytes.Buffer}.Available"(ptr %1) -// CHECK-NEXT: ret i64 %2 -// CHECK-NEXT: } - -// CHECK-LABEL: define linkonce %"{{.*}}/runtime/internal/runtime.Slice" @"__llgo_stub.main.*struct{m int; *bytes.Buffer}.AvailableBuffer"(ptr %0, ptr %1){{.*}} { -// CHECK-NEXT: _llgo_0: -// CHECK-NEXT: %2 = tail call %"{{.*}}/runtime/internal/runtime.Slice" @"main.*struct{m int; *bytes.Buffer}.AvailableBuffer"(ptr %1) -// CHECK-NEXT: ret %"{{.*}}/runtime/internal/runtime.Slice" %2 -// CHECK-NEXT: } - -// CHECK-LABEL: define linkonce %"{{.*}}/runtime/internal/runtime.Slice" @"__llgo_stub.main.*struct{m int; *bytes.Buffer}.Bytes"(ptr %0, ptr %1){{.*}} { -// CHECK-NEXT: _llgo_0: -// CHECK-NEXT: %2 = tail call %"{{.*}}/runtime/internal/runtime.Slice" @"main.*struct{m int; *bytes.Buffer}.Bytes"(ptr %1) -// CHECK-NEXT: ret %"{{.*}}/runtime/internal/runtime.Slice" %2 -// CHECK-NEXT: } - -// CHECK-LABEL: define linkonce i64 @"__llgo_stub.main.*struct{m int; *bytes.Buffer}.Cap"(ptr %0, ptr %1){{.*}} { -// CHECK-NEXT: _llgo_0: -// CHECK-NEXT: %2 = tail call i64 @"main.*struct{m int; *bytes.Buffer}.Cap"(ptr %1) -// CHECK-NEXT: ret i64 %2 -// CHECK-NEXT: } - -// CHECK-LABEL: define linkonce void @"__llgo_stub.main.*struct{m int; *bytes.Buffer}.Grow"(ptr %0, ptr %1, i64 %2){{.*}} { -// CHECK-NEXT: _llgo_0: -// CHECK-NEXT: tail call void @"main.*struct{m int; *bytes.Buffer}.Grow"(ptr %1, i64 %2) -// CHECK-NEXT: ret void -// CHECK-NEXT: } - -// CHECK-LABEL: define linkonce i64 @"__llgo_stub.main.*struct{m int; *bytes.Buffer}.Len"(ptr %0, ptr %1){{.*}} { -// CHECK-NEXT: _llgo_0: -// CHECK-NEXT: %2 = tail call i64 @"main.*struct{m int; *bytes.Buffer}.Len"(ptr %1) -// CHECK-NEXT: ret i64 %2 -// CHECK-NEXT: } - -// CHECK-LABEL: define linkonce %"{{.*}}/runtime/internal/runtime.Slice" @"__llgo_stub.main.*struct{m int; *bytes.Buffer}.Next"(ptr %0, ptr %1, i64 %2){{.*}} { -// CHECK-NEXT: _llgo_0: -// CHECK-NEXT: %3 = tail call %"{{.*}}/runtime/internal/runtime.Slice" @"main.*struct{m int; *bytes.Buffer}.Next"(ptr %1, i64 %2) -// CHECK-NEXT: ret %"{{.*}}/runtime/internal/runtime.Slice" %3 -// CHECK-NEXT: } - -// CHECK-LABEL: define linkonce { i64, %"{{.*}}/runtime/internal/runtime.iface" } @"__llgo_stub.main.*struct{m int; *bytes.Buffer}.Read"(ptr %0, ptr %1, %"{{.*}}/runtime/internal/runtime.Slice" %2){{.*}} { -// CHECK-NEXT: _llgo_0: -// CHECK-NEXT: %3 = tail call { i64, %"{{.*}}/runtime/internal/runtime.iface" } @"main.*struct{m int; *bytes.Buffer}.Read"(ptr %1, %"{{.*}}/runtime/internal/runtime.Slice" %2) -// CHECK-NEXT: ret { i64, %"{{.*}}/runtime/internal/runtime.iface" } %3 -// CHECK-NEXT: } - -// CHECK-LABEL: define linkonce { i8, %"{{.*}}/runtime/internal/runtime.iface" } @"__llgo_stub.main.*struct{m int; *bytes.Buffer}.ReadByte"(ptr %0, ptr %1){{.*}} { -// CHECK-NEXT: _llgo_0: -// CHECK-NEXT: %2 = tail call { i8, %"{{.*}}/runtime/internal/runtime.iface" } @"main.*struct{m int; *bytes.Buffer}.ReadByte"(ptr %1) -// CHECK-NEXT: ret { i8, %"{{.*}}/runtime/internal/runtime.iface" } %2 -// CHECK-NEXT: } - -// CHECK-LABEL: define linkonce { %"{{.*}}/runtime/internal/runtime.Slice", %"{{.*}}/runtime/internal/runtime.iface" } @"__llgo_stub.main.*struct{m int; *bytes.Buffer}.ReadBytes"(ptr %0, ptr %1, i8 %2){{.*}} { -// CHECK-NEXT: _llgo_0: -// CHECK-NEXT: %3 = tail call { %"{{.*}}/runtime/internal/runtime.Slice", %"{{.*}}/runtime/internal/runtime.iface" } @"main.*struct{m int; *bytes.Buffer}.ReadBytes"(ptr %1, i8 %2) -// CHECK-NEXT: ret { %"{{.*}}/runtime/internal/runtime.Slice", %"{{.*}}/runtime/internal/runtime.iface" } %3 -// CHECK-NEXT: } - -// CHECK-LABEL: define linkonce { i64, %"{{.*}}/runtime/internal/runtime.iface" } @"__llgo_stub.main.*struct{m int; *bytes.Buffer}.ReadFrom"(ptr %0, ptr %1, %"{{.*}}/runtime/internal/runtime.iface" %2){{.*}} { -// CHECK-NEXT: _llgo_0: -// CHECK-NEXT: %3 = tail call { i64, %"{{.*}}/runtime/internal/runtime.iface" } @"main.*struct{m int; *bytes.Buffer}.ReadFrom"(ptr %1, %"{{.*}}/runtime/internal/runtime.iface" %2) -// CHECK-NEXT: ret { i64, %"{{.*}}/runtime/internal/runtime.iface" } %3 -// CHECK-NEXT: } - -// CHECK-LABEL: define linkonce { i32, i64, %"{{.*}}/runtime/internal/runtime.iface" } @"__llgo_stub.main.*struct{m int; *bytes.Buffer}.ReadRune"(ptr %0, ptr %1){{.*}} { -// CHECK-NEXT: _llgo_0: -// CHECK-NEXT: %2 = tail call { i32, i64, %"{{.*}}/runtime/internal/runtime.iface" } @"main.*struct{m int; *bytes.Buffer}.ReadRune"(ptr %1) -// CHECK-NEXT: ret { i32, i64, %"{{.*}}/runtime/internal/runtime.iface" } %2 -// CHECK-NEXT: } - -// CHECK-LABEL: define linkonce { %"{{.*}}/runtime/internal/runtime.String", %"{{.*}}/runtime/internal/runtime.iface" } @"__llgo_stub.main.*struct{m int; *bytes.Buffer}.ReadString"(ptr %0, ptr %1, i8 %2){{.*}} { -// CHECK-NEXT: _llgo_0: -// CHECK-NEXT: %3 = tail call { %"{{.*}}/runtime/internal/runtime.String", %"{{.*}}/runtime/internal/runtime.iface" } @"main.*struct{m int; *bytes.Buffer}.ReadString"(ptr %1, i8 %2) -// CHECK-NEXT: ret { %"{{.*}}/runtime/internal/runtime.String", %"{{.*}}/runtime/internal/runtime.iface" } %3 -// CHECK-NEXT: } - -// CHECK-LABEL: define linkonce void @"__llgo_stub.main.*struct{m int; *bytes.Buffer}.Reset"(ptr %0, ptr %1){{.*}} { -// CHECK-NEXT: _llgo_0: -// CHECK-NEXT: tail call void @"main.*struct{m int; *bytes.Buffer}.Reset"(ptr %1) -// CHECK-NEXT: ret void -// CHECK-NEXT: } - -// CHECK-LABEL: define linkonce %"{{.*}}/runtime/internal/runtime.String" @"__llgo_stub.main.*struct{m int; *bytes.Buffer}.String"(ptr %0, ptr %1){{.*}} { -// CHECK-NEXT: _llgo_0: -// CHECK-NEXT: %2 = tail call %"{{.*}}/runtime/internal/runtime.String" @"main.*struct{m int; *bytes.Buffer}.String"(ptr %1) -// CHECK-NEXT: ret %"{{.*}}/runtime/internal/runtime.String" %2 -// CHECK-NEXT: } - -// CHECK-LABEL: define linkonce void @"__llgo_stub.main.*struct{m int; *bytes.Buffer}.Truncate"(ptr %0, ptr %1, i64 %2){{.*}} { -// CHECK-NEXT: _llgo_0: -// CHECK-NEXT: tail call void @"main.*struct{m int; *bytes.Buffer}.Truncate"(ptr %1, i64 %2) -// CHECK-NEXT: ret void -// CHECK-NEXT: } - -// CHECK-LABEL: define linkonce %"{{.*}}/runtime/internal/runtime.iface" @"__llgo_stub.main.*struct{m int; *bytes.Buffer}.UnreadByte"(ptr %0, ptr %1){{.*}} { -// CHECK-NEXT: _llgo_0: -// CHECK-NEXT: %2 = tail call %"{{.*}}/runtime/internal/runtime.iface" @"main.*struct{m int; *bytes.Buffer}.UnreadByte"(ptr %1) -// CHECK-NEXT: ret %"{{.*}}/runtime/internal/runtime.iface" %2 -// CHECK-NEXT: } - -// CHECK-LABEL: define linkonce %"{{.*}}/runtime/internal/runtime.iface" @"__llgo_stub.main.*struct{m int; *bytes.Buffer}.UnreadRune"(ptr %0, ptr %1){{.*}} { -// CHECK-NEXT: _llgo_0: -// CHECK-NEXT: %2 = tail call %"{{.*}}/runtime/internal/runtime.iface" @"main.*struct{m int; *bytes.Buffer}.UnreadRune"(ptr %1) -// CHECK-NEXT: ret %"{{.*}}/runtime/internal/runtime.iface" %2 -// CHECK-NEXT: } - -// CHECK-LABEL: define linkonce { i64, %"{{.*}}/runtime/internal/runtime.iface" } @"__llgo_stub.main.*struct{m int; *bytes.Buffer}.Write"(ptr %0, ptr %1, %"{{.*}}/runtime/internal/runtime.Slice" %2){{.*}} { -// CHECK-NEXT: _llgo_0: -// CHECK-NEXT: %3 = tail call { i64, %"{{.*}}/runtime/internal/runtime.iface" } @"main.*struct{m int; *bytes.Buffer}.Write"(ptr %1, %"{{.*}}/runtime/internal/runtime.Slice" %2) -// CHECK-NEXT: ret { i64, %"{{.*}}/runtime/internal/runtime.iface" } %3 -// CHECK-NEXT: } - -// CHECK-LABEL: define linkonce %"{{.*}}/runtime/internal/runtime.iface" @"__llgo_stub.main.*struct{m int; *bytes.Buffer}.WriteByte"(ptr %0, ptr %1, i8 %2){{.*}} { -// CHECK-NEXT: _llgo_0: -// CHECK-NEXT: %3 = tail call %"{{.*}}/runtime/internal/runtime.iface" @"main.*struct{m int; *bytes.Buffer}.WriteByte"(ptr %1, i8 %2) -// CHECK-NEXT: ret %"{{.*}}/runtime/internal/runtime.iface" %3 -// CHECK-NEXT: } - -// CHECK-LABEL: define linkonce { i64, %"{{.*}}/runtime/internal/runtime.iface" } @"__llgo_stub.main.*struct{m int; *bytes.Buffer}.WriteRune"(ptr %0, ptr %1, i32 %2){{.*}} { -// CHECK-NEXT: _llgo_0: -// CHECK-NEXT: %3 = tail call { i64, %"{{.*}}/runtime/internal/runtime.iface" } @"main.*struct{m int; *bytes.Buffer}.WriteRune"(ptr %1, i32 %2) -// CHECK-NEXT: ret { i64, %"{{.*}}/runtime/internal/runtime.iface" } %3 -// CHECK-NEXT: } - -// CHECK-LABEL: define linkonce { i64, %"{{.*}}/runtime/internal/runtime.iface" } @"__llgo_stub.main.*struct{m int; *bytes.Buffer}.WriteString"(ptr %0, ptr %1, %"{{.*}}/runtime/internal/runtime.String" %2){{.*}} { -// CHECK-NEXT: _llgo_0: -// CHECK-NEXT: %3 = tail call { i64, %"{{.*}}/runtime/internal/runtime.iface" } @"main.*struct{m int; *bytes.Buffer}.WriteString"(ptr %1, %"{{.*}}/runtime/internal/runtime.String" %2) -// CHECK-NEXT: ret { i64, %"{{.*}}/runtime/internal/runtime.iface" } %3 -// CHECK-NEXT: } - -// CHECK-LABEL: define linkonce { i64, %"{{.*}}/runtime/internal/runtime.iface" } @"__llgo_stub.main.*struct{m int; *bytes.Buffer}.WriteTo"(ptr %0, ptr %1, %"{{.*}}/runtime/internal/runtime.iface" %2){{.*}} { -// CHECK-NEXT: _llgo_0: -// CHECK-NEXT: %3 = tail call { i64, %"{{.*}}/runtime/internal/runtime.iface" } @"main.*struct{m int; *bytes.Buffer}.WriteTo"(ptr %1, %"{{.*}}/runtime/internal/runtime.iface" %2) -// CHECK-NEXT: ret { i64, %"{{.*}}/runtime/internal/runtime.iface" } %3 -// CHECK-NEXT: } - -// CHECK-LABEL: define linkonce i1 @"__llgo_stub.main.*struct{m int; *bytes.Buffer}.empty"(ptr %0, ptr %1){{.*}} { -// CHECK-NEXT: _llgo_0: -// CHECK-NEXT: %2 = tail call i1 @"main.*struct{m int; *bytes.Buffer}.empty"(ptr %1) -// CHECK-NEXT: ret i1 %2 -// CHECK-NEXT: } - -// CHECK-LABEL: define linkonce i64 @"__llgo_stub.main.*struct{m int; *bytes.Buffer}.grow"(ptr %0, ptr %1, i64 %2){{.*}} { -// CHECK-NEXT: _llgo_0: -// CHECK-NEXT: %3 = tail call i64 @"main.*struct{m int; *bytes.Buffer}.grow"(ptr %1, i64 %2) -// CHECK-NEXT: ret i64 %3 -// CHECK-NEXT: } - -// CHECK-LABEL: define linkonce { %"{{.*}}/runtime/internal/runtime.Slice", %"{{.*}}/runtime/internal/runtime.iface" } @"__llgo_stub.main.*struct{m int; *bytes.Buffer}.readSlice"(ptr %0, ptr %1, i8 %2){{.*}} { -// CHECK-NEXT: _llgo_0: -// CHECK-NEXT: %3 = tail call { %"{{.*}}/runtime/internal/runtime.Slice", %"{{.*}}/runtime/internal/runtime.iface" } @"main.*struct{m int; *bytes.Buffer}.readSlice"(ptr %1, i8 %2) -// CHECK-NEXT: ret { %"{{.*}}/runtime/internal/runtime.Slice", %"{{.*}}/runtime/internal/runtime.iface" } %3 -// CHECK-NEXT: } - -// CHECK-LABEL: define linkonce { i64, i1 } @"__llgo_stub.main.*struct{m int; *bytes.Buffer}.tryGrowByReslice"(ptr %0, ptr %1, i64 %2){{.*}} { -// CHECK-NEXT: _llgo_0: -// CHECK-NEXT: %3 = tail call { i64, i1 } @"main.*struct{m int; *bytes.Buffer}.tryGrowByReslice"(ptr %1, i64 %2) -// CHECK-NEXT: ret { i64, i1 } %3 -// CHECK-NEXT: } - // CHECK-LABEL: define linkonce ptr @"main.(*Pointer[any]).Load"(ptr %0){{.*}} { // CHECK-NEXT: _llgo_0: // CHECK-NEXT: %1 = icmp eq ptr %0, null @@ -2167,21 +1579,3 @@ type I2 interface { // CHECK-NEXT: store atomic ptr %1, ptr %3 seq_cst, align 8 // CHECK-NEXT: ret void // CHECK-NEXT: } - -// CHECK-LABEL: define linkonce i1 @"__llgo_stub.{{.*}}/runtime/internal/runtime.nilinterequal"(ptr %0, ptr %1, ptr %2){{.*}} { -// CHECK-NEXT: _llgo_0: -// CHECK-NEXT: %3 = tail call i1 @"{{.*}}/runtime/internal/runtime.nilinterequal"(ptr %1, ptr %2) -// CHECK-NEXT: ret i1 %3 -// CHECK-NEXT: } - -// CHECK-LABEL: define linkonce ptr @"__llgo_stub.main.(*Pointer[any]).Load"(ptr %0, ptr %1){{.*}} { -// CHECK-NEXT: _llgo_0: -// CHECK-NEXT: %2 = tail call ptr @"main.(*Pointer[any]).Load"(ptr %1) -// CHECK-NEXT: ret ptr %2 -// CHECK-NEXT: } - -// CHECK-LABEL: define linkonce void @"__llgo_stub.main.(*Pointer[any]).Store"(ptr %0, ptr %1, ptr %2){{.*}} { -// CHECK-NEXT: _llgo_0: -// CHECK-NEXT: tail call void @"main.(*Pointer[any]).Store"(ptr %1, ptr %2) -// CHECK-NEXT: ret void -// CHECK-NEXT: } diff --git a/cl/_testgo/cgobasic/cgobasic.go b/cl/_testgo/cgobasic/cgobasic.go index 8017d92376..d7fef6b914 100644 --- a/cl/_testgo/cgobasic/cgobasic.go +++ b/cl/_testgo/cgobasic/cgobasic.go @@ -139,7 +139,7 @@ func main() { C.free(cbytes) } -// CHECK-LABEL: define ptr @"main.main$1"(ptr %0){{.*}} { +// CHECK-LABEL: define ptr @"main.main$1"(ptr {{(nest|swiftself)}} %0){{.*}} { // CHECK-NEXT: _llgo_0: // CHECK-NEXT: %1 = load { ptr }, ptr %0, align 8 // CHECK-NEXT: %2 = extractvalue { ptr } %1, 0 @@ -151,7 +151,7 @@ func main() { // CHECK-NEXT: ret ptr %6 // CHECK-NEXT: } -// CHECK-LABEL: define %"{{.*}}/runtime/internal/runtime.Slice" @"main.main$2"(ptr %0){{.*}} { +// CHECK-LABEL: define %"{{.*}}/runtime/internal/runtime.Slice" @"main.main$2"(ptr {{(nest|swiftself)}} %0){{.*}} { // CHECK-NEXT: _llgo_0: // CHECK-NEXT: %1 = load { ptr }, ptr %0, align 8 // CHECK-NEXT: %2 = extractvalue { ptr } %1, 0 @@ -161,7 +161,7 @@ func main() { // CHECK-NEXT: ret %"{{.*}}/runtime/internal/runtime.Slice" %5 // CHECK-NEXT: } -// CHECK-LABEL: define void @"main.main$3"(ptr %0){{.*}} { +// CHECK-LABEL: define void @"main.main$3"(ptr {{(nest|swiftself)}} %0){{.*}} { // CHECK-NEXT: _llgo_0: // CHECK-NEXT: %1 = load { ptr }, ptr %0, align 8 // CHECK-NEXT: %2 = extractvalue { ptr } %1, 0 @@ -171,7 +171,7 @@ func main() { // CHECK-NEXT: ret void // CHECK-NEXT: } -// CHECK-LABEL: define void @"main.main$4"(ptr %0){{.*}} { +// CHECK-LABEL: define void @"main.main$4"(ptr {{(nest|swiftself)}} %0){{.*}} { // CHECK-NEXT: _llgo_0: // CHECK-NEXT: %1 = load { ptr }, ptr %0, align 8 // CHECK-NEXT: %2 = extractvalue { ptr } %1, 0 diff --git a/cl/_testgo/cgodefer/cgodefer.go b/cl/_testgo/cgodefer/cgodefer.go index 8d9bca1306..5ce8dd6bfe 100644 --- a/cl/_testgo/cgodefer/cgodefer.go +++ b/cl/_testgo/cgodefer/cgodefer.go @@ -26,7 +26,8 @@ import "C" // CHECK-NEXT: %4 = insertvalue { ptr, ptr } { ptr @"main.main$1", ptr undef }, ptr %2, 1 // CHECK-NEXT: %5 = extractvalue { ptr, ptr } %4, 1 // CHECK-NEXT: %6 = extractvalue { ptr, ptr } %4, 0 -// CHECK-NEXT: %7 = call { ptr, ptr } %6(ptr %5) +// CHECK-NEXT: %__llgo_funcval_code = call ptr asm "", "=r,0"(ptr %6) +// CHECK-NEXT: %7 = call { ptr, ptr } %__llgo_funcval_code(ptr {{(nest|swiftself)}} %5) // CHECK-NEXT: %8 = call ptr @"{{.*}}/runtime/internal/runtime.GetThreadDefer"() // CHECK-NEXT: %9 = alloca i8, i64 {{.*}}, align 1 // CHECK-NEXT: %10 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 48) @@ -92,7 +93,8 @@ import "C" // CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.FreeDeferNode"(ptr %30) // CHECK-NEXT: %34 = extractvalue { ptr, ptr } %33, 1 // CHECK-NEXT: %35 = extractvalue { ptr, ptr } %33, 0 -// CHECK-NEXT: call void %35(ptr %34) +// CHECK-NEXT: %__llgo_funcval_code1 = call ptr asm "", "=r,0"(ptr %35) +// CHECK-NEXT: call void %__llgo_funcval_code1(ptr {{(nest|swiftself)}} %34) // CHECK-NEXT: br label %_llgo_8 // CHECK-EMPTY: // CHECK-NEXT: _llgo_8: ; preds = %_llgo_7, %_llgo_2 @@ -103,7 +105,7 @@ import "C" // CHECK-NEXT: indirectbr ptr %38, [label %_llgo_3, label %_llgo_6] // CHECK-NEXT: } func main() { - // CHECK-LABEL: define { ptr, ptr } @"main.main$1"(ptr %0){{.*}} { + // CHECK-LABEL: define { ptr, ptr } @"main.main$1"(ptr {{(nest|swiftself)}} %0){{.*}} { // CHECK-NEXT: _llgo_0: // CHECK-NEXT: %1 = call ptr @"{{.*}}/runtime/internal/runtime.AllocZ"(i64 8) // CHECK-NEXT: %2 = load { ptr }, ptr %0, align 8 @@ -117,7 +119,7 @@ func main() { // CHECK-NEXT: ret { ptr, ptr } %7 // CHECK-NEXT: } p := C.malloc(1024) - // CHECK-LABEL: define void @"main.main$1$1"(ptr %0){{.*}} { + // CHECK-LABEL: define void @"main.main$1$1"(ptr {{(nest|swiftself)}} %0){{.*}} { // CHECK-NEXT: _llgo_0: // CHECK-NEXT: %1 = load { ptr }, ptr %0, align 8 // CHECK-NEXT: %2 = extractvalue { ptr } %1, 0 diff --git a/cl/_testgo/closure/in.go b/cl/_testgo/closure/in.go index eabccf6e81..ad7eabba2e 100644 --- a/cl/_testgo/closure/in.go +++ b/cl/_testgo/closure/in.go @@ -9,8 +9,9 @@ func main() { // CHECK: store %"{{.*}}String" { ptr @0, i64 3 }, ptr %0, align 8 // CHECK: call ptr @"{{.*}}AllocU"(i64 8) // CHECK: { ptr @"main.main$2", ptr undef } - // CHECK: call void @"__llgo_stub.main.main$1"(ptr null, i64 100) - // CHECK: call void %7(ptr %6, i64 200) + // CHECK: call void @"main.main$1"(i64 100) + // CHECK: %__llgo_funcval_code = call ptr asm "", "=r,0"(ptr %7) + // CHECK: call void %__llgo_funcval_code(ptr {{(nest|swiftself)}} %6, i64 200) // CHECK: ret void var env string = "env" var v1 T = func(i int) { @@ -24,7 +25,7 @@ func main() { println("func", i) } var v2 T = func(i int) { - // CHECK-LABEL: define void @"main.main$2"(ptr %0, i64 %1){{.*}} { + // CHECK-LABEL: define void @"main.main$2"(ptr {{(nest|swiftself)}} %0, i64 %1){{.*}} { // CHECK-NEXT: _llgo_0: // CHECK-NEXT: %2 = load { ptr }, ptr %0, align 8 // CHECK-NEXT: %3 = extractvalue { ptr } %2, 0 diff --git a/cl/_testgo/closure2/in.go b/cl/_testgo/closure2/in.go index a32d628efd..0e19371aa7 100644 --- a/cl/_testgo/closure2/in.go +++ b/cl/_testgo/closure2/in.go @@ -7,12 +7,14 @@ func main() { // CHECK: store i64 1, ptr %0, align 8 // CHECK: call ptr @"{{.*}}AllocU"(i64 8) // CHECK: { ptr @"main.main$1", ptr undef } - // CHECK: call { ptr, ptr } %5(ptr %4, i64 1) - // CHECK: call void %8(ptr %7, i64 2) + // CHECK: %__llgo_funcval_code = call ptr asm "", "=r,0"(ptr %5) + // CHECK: call { ptr, ptr } %__llgo_funcval_code(ptr {{(nest|swiftself)}} %4, i64 1) + // CHECK: %__llgo_funcval_code1 = call ptr asm "", "=r,0"(ptr %8) + // CHECK: call void %__llgo_funcval_code1(ptr {{(nest|swiftself)}} %7, i64 2) // CHECK: ret void x := 1 f := func(i int) func(int) { - // CHECK-LABEL: define { ptr, ptr } @"main.main$1"(ptr %0, i64 %1){{.*}} { + // CHECK-LABEL: define { ptr, ptr } @"main.main$1"(ptr {{(nest|swiftself)}} %0, i64 %1){{.*}} { // CHECK-NEXT: _llgo_0: // CHECK-NEXT: %2 = load { ptr }, ptr %0, align 8 // CHECK-NEXT: %3 = extractvalue { ptr } %2, 0 @@ -22,7 +24,7 @@ func main() { // CHECK-NEXT: %6 = insertvalue { ptr, ptr } { ptr @"main.main$1$1", ptr undef }, ptr %4, 1 // CHECK-NEXT: ret { ptr, ptr } %6 return func(i int) { - // CHECK-LABEL: define void @"main.main$1$1"(ptr %0, i64 %1){{.*}} { + // CHECK-LABEL: define void @"main.main$1$1"(ptr {{(nest|swiftself)}} %0, i64 %1){{.*}} { // CHECK-NEXT: _llgo_0: // CHECK-NEXT: %2 = load { ptr }, ptr %0, align 8 // CHECK-NEXT: %3 = extractvalue { ptr } %2, 0 diff --git a/cl/_testgo/closureall/in.go b/cl/_testgo/closureall/in.go index 185b4f7854..5d7e0ed0d9 100644 --- a/cl/_testgo/closureall/in.go +++ b/cl/_testgo/closureall/in.go @@ -21,6 +21,11 @@ type CCallback func(c.Int) c.Int type Fn func(int) int +//go:noinline +func callCInt(fn func(c.Int) c.Int, x c.Int) c.Int { + return fn(x) +} + type S struct { v int } @@ -81,8 +86,7 @@ func main() { cs := cSqrt _ = cs(4) - ca := cAbs - _ = ca(-3) + _ = callCInt(cAbs, -3) cb := CCallback(func(x c.Int) c.Int { return x + 1 }) _ = callCallback(cb, 7) @@ -105,6 +109,15 @@ func makeWithFree(base int) Fn { // CHECK-NEXT: ret i64 %4 // CHECK-NEXT: } +// CHECK-LABEL: define i32 @main.callCInt({ ptr, ptr } %0, i32 %1){{.*}} { +// CHECK-NEXT: _llgo_0: +// CHECK-NEXT: %2 = extractvalue { ptr, ptr } %0, 1 +// CHECK-NEXT: %3 = extractvalue { ptr, ptr } %0, 0 +// CHECK-NEXT: %__llgo_funcval_code = call ptr asm "", "=r,0"(ptr %3) +// CHECK-NEXT: %4 = call i32 %__llgo_funcval_code(ptr {{(nest|swiftself)}} %2, i32 %1) +// CHECK-NEXT: ret i32 %4 +// CHECK-NEXT: } + // CHECK-LABEL: define i32 @main.callCallback(ptr %0, i32 %1){{.*}} { // CHECK-NEXT: _llgo_0: // CHECK-NEXT: %2 = call i32 %0(i32 %1) @@ -136,10 +149,12 @@ func makeWithFree(base int) Fn { // CHECK-NEXT: %1 = call %main.Fn @main.makeWithFree(i64 3) // CHECK-NEXT: %2 = extractvalue %main.Fn %0, 1 // CHECK-NEXT: %3 = extractvalue %main.Fn %0, 0 -// CHECK-NEXT: %4 = call i64 %3(ptr %2, i64 1) +// CHECK-NEXT: %__llgo_funcval_code = call ptr asm "", "=r,0"(ptr %3) +// CHECK-NEXT: %4 = call i64 %__llgo_funcval_code(ptr {{(nest|swiftself)}} %2, i64 1) // CHECK-NEXT: %5 = extractvalue %main.Fn %1, 1 // CHECK-NEXT: %6 = extractvalue %main.Fn %1, 0 -// CHECK-NEXT: %7 = call i64 %6(ptr %5, i64 2) +// CHECK-NEXT: %__llgo_funcval_code1 = call ptr asm "", "=r,0"(ptr %6) +// CHECK-NEXT: %7 = call i64 %__llgo_funcval_code1(ptr {{(nest|swiftself)}} %5, i64 2) // CHECK-NEXT: %8 = call i64 @main.globalAdd(i64 1, i64 2) // CHECK-NEXT: %9 = call ptr @"{{.*}}/runtime/internal/runtime.AllocZ"(i64 8) // CHECK-NEXT: %10 = getelementptr inbounds %main.S, ptr %9, i32 0, i32 0 @@ -150,7 +165,8 @@ func makeWithFree(base int) Fn { // CHECK-NEXT: %13 = insertvalue { ptr, ptr } { ptr @"main.(*S).Add$bound", ptr undef }, ptr %11, 1 // CHECK-NEXT: %14 = extractvalue { ptr, ptr } %13, 1 // CHECK-NEXT: %15 = extractvalue { ptr, ptr } %13, 0 -// CHECK-NEXT: %16 = call i64 %15(ptr %14, i64 7) +// CHECK-NEXT: %__llgo_funcval_code2 = call ptr asm "", "=r,0"(ptr %15) +// CHECK-NEXT: %16 = call i64 %__llgo_funcval_code2(ptr {{(nest|swiftself)}} %14, i64 7) // CHECK-NEXT: %17 = call i64 @"main.(*S).Add$thunk"(ptr %9, i64 8) // CHECK-NEXT: %18 = call ptr @"{{.*}}/runtime/internal/runtime.NewItab"(ptr @"_llgo_iface${{[-A-Za-z0-9_]+}}", ptr @"*_llgo_main.S") // CHECK-NEXT: %19 = insertvalue %"{{.*}}/runtime/internal/runtime.iface" undef, ptr %18, 0 @@ -166,9 +182,10 @@ func makeWithFree(base int) Fn { // CHECK-NEXT: %25 = insertvalue { ptr, ptr } { ptr @"main.interface{Add(int) int}.Add$bound", ptr undef }, ptr %23, 1 // CHECK-NEXT: %26 = extractvalue { ptr, ptr } %25, 1 // CHECK-NEXT: %27 = extractvalue { ptr, ptr } %25, 0 -// CHECK-NEXT: %28 = call i64 %27(ptr %26, i64 9) -// CHECK-NEXT: %29 = call double {{.*}}sqrt{{.*}}(double 4.000000e+00) -// CHECK-NEXT: %30 = call i32 @abs(i32 -3) +// CHECK-NEXT: %__llgo_funcval_code3 = call ptr asm "", "=r,0"(ptr %27) +// CHECK-NEXT: %28 = call i64 %__llgo_funcval_code3(ptr {{(nest|swiftself)}} %26, i64 9) +// CHECK-NEXT: %29 = call double @sqrt(double 4.000000e+00) +// CHECK-NEXT: %30 = call i32 @main.callCInt({ ptr, ptr } { ptr @abs, ptr null }, i32 -3) // CHECK-NEXT: %31 = call i32 @main.callCallback(ptr @"main.main$1", i32 7) // CHECK-NEXT: ret void // CHECK-EMPTY: @@ -185,7 +202,7 @@ func makeWithFree(base int) Fn { // CHECK-LABEL: define %main.Fn @main.makeNoFree(){{.*}} { // CHECK-NEXT: _llgo_0: -// CHECK-NEXT: ret %main.Fn { ptr @"__llgo_stub.main.makeNoFree$1", ptr null } +// CHECK-NEXT: ret %main.Fn { ptr @"main.makeNoFree$1", ptr null } // CHECK-NEXT: } // CHECK-LABEL: define i64 @"main.makeNoFree$1"(i64 %0){{.*}} { @@ -208,7 +225,7 @@ func makeWithFree(base int) Fn { // CHECK-NEXT: ret %main.Fn %6 // CHECK-NEXT: } -// CHECK-LABEL: define i64 @"main.makeWithFree$1"(ptr %0, i64 %1){{.*}} { +// CHECK-LABEL: define i64 @"main.makeWithFree$1"(ptr {{(nest|swiftself)}} %0, i64 %1){{.*}} { // CHECK-NEXT: _llgo_0: // CHECK-NEXT: %2 = load { ptr }, ptr %0, align 8 // CHECK-NEXT: %3 = extractvalue { ptr } %2, 0 @@ -217,7 +234,7 @@ func makeWithFree(base int) Fn { // CHECK-NEXT: ret i64 %5 // CHECK-NEXT: } -// CHECK-LABEL: define i64 @"main.(*S).Add$bound"(ptr %0, i64 %1){{.*}} { +// CHECK-LABEL: define i64 @"main.(*S).Add$bound"(ptr {{(nest|swiftself)}} %0, i64 %1){{.*}} { // CHECK-NEXT: _llgo_0: // CHECK-NEXT: %2 = load { ptr }, ptr %0, align 8 // CHECK-NEXT: %3 = extractvalue { ptr } %2, 0 @@ -231,37 +248,7 @@ func makeWithFree(base int) Fn { // CHECK-NEXT: ret i64 %2 // CHECK-NEXT: } -// CHECK-LABEL: define linkonce i1 @"__llgo_stub.{{.*}}/runtime/internal/runtime.memequal64"(ptr %0, ptr %1, ptr %2){{.*}} { -// CHECK-NEXT: _llgo_0: -// CHECK-NEXT: %3 = tail call i1 @"{{.*}}/runtime/internal/runtime.memequal64"(ptr %1, ptr %2) -// CHECK-NEXT: ret i1 %3 -// CHECK-NEXT: } - -// CHECK-LABEL: define linkonce i64 @__llgo_stub.main.S.Inc(ptr %0, %main.S %1, i64 %2){{.*}} { -// CHECK-NEXT: _llgo_0: -// CHECK-NEXT: %3 = tail call i64 @main.S.Inc(%main.S %1, i64 %2) -// CHECK-NEXT: ret i64 %3 -// CHECK-NEXT: } - -// CHECK-LABEL: define linkonce i64 @"__llgo_stub.main.(*S).Add"(ptr %0, ptr %1, i64 %2){{.*}} { -// CHECK-NEXT: _llgo_0: -// CHECK-NEXT: %3 = tail call i64 @"main.(*S).Add"(ptr %1, i64 %2) -// CHECK-NEXT: ret i64 %3 -// CHECK-NEXT: } - -// CHECK-LABEL: define linkonce i64 @"__llgo_stub.main.(*S).Inc"(ptr %0, ptr %1, i64 %2){{.*}} { -// CHECK-NEXT: _llgo_0: -// CHECK-NEXT: %3 = tail call i64 @"main.(*S).Inc"(ptr %1, i64 %2) -// CHECK-NEXT: ret i64 %3 -// CHECK-NEXT: } - -// CHECK-LABEL: define linkonce i1 @"__llgo_stub.{{.*}}/runtime/internal/runtime.interequal"(ptr %0, ptr %1, ptr %2){{.*}} { -// CHECK-NEXT: _llgo_0: -// CHECK-NEXT: %3 = tail call i1 @"{{.*}}/runtime/internal/runtime.interequal"(ptr %1, ptr %2) -// CHECK-NEXT: ret i1 %3 -// CHECK-NEXT: } - -// CHECK-LABEL: define i64 @"main.interface{Add(int) int}.Add$bound"(ptr %0, i64 %1){{.*}} { +// CHECK-LABEL: define i64 @"main.interface{Add(int) int}.Add$bound"(ptr {{(nest|swiftself)}} %0, i64 %1){{.*}} { // CHECK-NEXT: _llgo_0: // CHECK-NEXT: %2 = load { %"{{.*}}/runtime/internal/runtime.iface" }, ptr %0, align 8 // CHECK-NEXT: %3 = extractvalue { %"{{.*}}/runtime/internal/runtime.iface" } %2, 0 @@ -276,9 +263,3 @@ func makeWithFree(base int) Fn { // CHECK-NEXT: %12 = call i64 %11(ptr %10, i64 %1) // CHECK-NEXT: ret i64 %12 // CHECK-NEXT: } - -// CHECK-LABEL: define linkonce i64 @"__llgo_stub.main.makeNoFree$1"(ptr %0, i64 %1){{.*}} { -// CHECK-NEXT: _llgo_0: -// CHECK-NEXT: %2 = tail call i64 @"main.makeNoFree$1"(i64 %1) -// CHECK-NEXT: ret i64 %2 -// CHECK-NEXT: } diff --git a/cl/_testgo/closureenv/expect.txt b/cl/_testgo/closureenv/expect.txt new file mode 100644 index 0000000000..9766475a41 --- /dev/null +++ b/cl/_testgo/closureenv/expect.txt @@ -0,0 +1 @@ +ok diff --git a/cl/_testgo/closureenv/in.go b/cl/_testgo/closureenv/in.go new file mode 100644 index 0000000000..b83578930d --- /dev/null +++ b/cl/_testgo/closureenv/in.go @@ -0,0 +1,255 @@ +// LITTEST +package main + +// CHECK: {{^}}@0 = private unnamed_addr constant [18 x i8] c"zero-sized capture", align 1{{$}} +// CHECK: {{^}}@2 = private unnamed_addr constant [26 x i8] c"zero-sized capture address", align 1{{$}} +// CHECK: {{^}}@3 = private unnamed_addr constant [26 x i8] c"zero-sized pointer capture", align 1{{$}} +// CHECK: {{^}}@6 = private unnamed_addr constant [5 x i8] c"IsNil", align 1{{$}} +// CHECK: {{^}}@10 = private unnamed_addr constant [23 x i8] c"interface{IsNil() bool}", align 1{{$}} +// CHECK: {{^}}@11 = private unnamed_addr constant [25 x i8] c"nil receiver method value", align 1{{$}} +// CHECK: {{^}}@12 = private unnamed_addr constant [2 x i8] c"ok", align 1{{$}} +// CHECK: {{^}}@13 = private unnamed_addr constant [32 x i8] c"typed-nil interface method value", align 1{{$}} + +type nilReceiver struct{} + +func (p *nilReceiver) IsNil() bool { + return p == nil +} + +func zeroSizedCapture() func() int { + captured := struct{}{} + return func() int { + if captured != (struct{}{}) { + return 0 + } + return 42 + } +} + +func zeroSizedAddressCapture() (func() *struct{}, *struct{}) { + captured := struct{}{} + return func() *struct{} { return &captured }, &captured +} + +func zeroSizedPointerCapture(pointer *struct{}) func() bool { + return func() bool { return pointer == nil } +} + +func main() { + if zeroSizedCapture()() != 42 { + panic("zero-sized capture") + } + addressClosure, address := zeroSizedAddressCapture() + if addressClosure() != address { + panic("zero-sized capture address") + } + if !zeroSizedPointerCapture(nil)() { + panic("zero-sized pointer capture") + } + + var receiver *nilReceiver + method := receiver.IsNil + if !method() { + panic("nil receiver method value") + } + + var typedNil interface{ IsNil() bool } = receiver + interfaceMethod := typedNil.IsNil + if !interfaceMethod() { + panic("typed-nil interface method value") + } + println("ok") +} + +// CHECK-LABEL: define void @main.init(){{.*}} { +// CHECK-NEXT: _llgo_0: +// CHECK-NEXT: %0 = load i1, ptr @"main.init$guard", align 1 +// CHECK-NEXT: br i1 %0, label %_llgo_2, label %_llgo_1 +// CHECK-EMPTY: +// CHECK-NEXT: _llgo_1: ; preds = %_llgo_0 +// CHECK-NEXT: store i1 true, ptr @"main.init$guard", align 1 +// CHECK-NEXT: br label %_llgo_2 +// CHECK-EMPTY: +// CHECK-NEXT: _llgo_2: ; preds = %_llgo_1, %_llgo_0 +// CHECK-NEXT: ret void +// CHECK-NEXT: } + +// CHECK-LABEL: define void @main.main(){{.*}} { +// CHECK-NEXT: _llgo_0: +// CHECK-NEXT: %0 = call { ptr, ptr } @main.zeroSizedCapture() +// CHECK-NEXT: %1 = extractvalue { ptr, ptr } %0, 1 +// CHECK-NEXT: %2 = extractvalue { ptr, ptr } %0, 0 +// CHECK-NEXT: %__llgo_funcval_code = call ptr asm "", "=r,0"(ptr %2) +// CHECK-NEXT: %3 = call i64 %__llgo_funcval_code(ptr {{(nest|swiftself)}} %1) +// CHECK-NEXT: %4 = icmp ne i64 %3, 42 +// CHECK-NEXT: br i1 %4, label %_llgo_1, label %_llgo_2 +// CHECK-EMPTY: +// CHECK-NEXT: _llgo_1: ; preds = %_llgo_0 +// CHECK-NEXT: %5 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 16) +// CHECK-NEXT: store %"{{.*}}/runtime/internal/runtime.String" { ptr @0, i64 18 }, ptr %5, align 8 +// CHECK-NEXT: %6 = insertvalue %"{{.*}}/runtime/internal/runtime.eface" { ptr @_llgo_string, ptr undef }, ptr %5, 1 +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.Panic"(%"{{.*}}/runtime/internal/runtime.eface" %6) +// CHECK-NEXT: unreachable +// CHECK-EMPTY: +// CHECK-NEXT: _llgo_2: ; preds = %_llgo_0 +// CHECK-NEXT: %7 = call { { ptr, ptr }, ptr } @main.zeroSizedAddressCapture() +// CHECK-NEXT: %8 = extractvalue { { ptr, ptr }, ptr } %7, 0 +// CHECK-NEXT: %9 = extractvalue { { ptr, ptr }, ptr } %7, 1 +// CHECK-NEXT: %10 = extractvalue { ptr, ptr } %8, 1 +// CHECK-NEXT: %11 = extractvalue { ptr, ptr } %8, 0 +// CHECK-NEXT: %__llgo_funcval_code1 = call ptr asm "", "=r,0"(ptr %11) +// CHECK-NEXT: %12 = call ptr %__llgo_funcval_code1(ptr {{(nest|swiftself)}} %10) +// CHECK-NEXT: %13 = icmp ne ptr %12, %9 +// CHECK-NEXT: br i1 %13, label %_llgo_3, label %_llgo_4 +// CHECK-EMPTY: +// CHECK-NEXT: _llgo_3: ; preds = %_llgo_2 +// CHECK-NEXT: %14 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 16) +// CHECK-NEXT: store %"{{.*}}/runtime/internal/runtime.String" { ptr @2, i64 26 }, ptr %14, align 8 +// CHECK-NEXT: %15 = insertvalue %"{{.*}}/runtime/internal/runtime.eface" { ptr @_llgo_string, ptr undef }, ptr %14, 1 +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.Panic"(%"{{.*}}/runtime/internal/runtime.eface" %15) +// CHECK-NEXT: unreachable +// CHECK-EMPTY: +// CHECK-NEXT: _llgo_4: ; preds = %_llgo_2 +// CHECK-NEXT: %16 = call { ptr, ptr } @main.zeroSizedPointerCapture(ptr null) +// CHECK-NEXT: %17 = extractvalue { ptr, ptr } %16, 1 +// CHECK-NEXT: %18 = extractvalue { ptr, ptr } %16, 0 +// CHECK-NEXT: %__llgo_funcval_code2 = call ptr asm "", "=r,0"(ptr %18) +// CHECK-NEXT: %19 = call i1 %__llgo_funcval_code2(ptr {{(nest|swiftself)}} %17) +// CHECK-NEXT: br i1 %19, label %_llgo_6, label %_llgo_5 +// CHECK-EMPTY: +// CHECK-NEXT: _llgo_5: ; preds = %_llgo_4 +// CHECK-NEXT: %20 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 16) +// CHECK-NEXT: store %"{{.*}}/runtime/internal/runtime.String" { ptr @3, i64 26 }, ptr %20, align 8 +// CHECK-NEXT: %21 = insertvalue %"{{.*}}/runtime/internal/runtime.eface" { ptr @_llgo_string, ptr undef }, ptr %20, 1 +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.Panic"(%"{{.*}}/runtime/internal/runtime.eface" %21) +// CHECK-NEXT: unreachable +// CHECK-EMPTY: +// CHECK-NEXT: _llgo_6: ; preds = %_llgo_4 +// CHECK-NEXT: %22 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 8) +// CHECK-NEXT: %23 = getelementptr inbounds { ptr }, ptr %22, i32 0, i32 0 +// CHECK-NEXT: store ptr null, ptr %23, align 8 +// CHECK-NEXT: %24 = insertvalue { ptr, ptr } { ptr @"main.(*nilReceiver).IsNil$bound", ptr undef }, ptr %22, 1 +// CHECK-NEXT: %25 = extractvalue { ptr, ptr } %24, 1 +// CHECK-NEXT: %26 = extractvalue { ptr, ptr } %24, 0 +// CHECK-NEXT: %__llgo_funcval_code3 = call ptr asm "", "=r,0"(ptr %26) +// CHECK-NEXT: %27 = call i1 %__llgo_funcval_code3(ptr {{(nest|swiftself)}} %25) +// CHECK-NEXT: br i1 %27, label %_llgo_8, label %_llgo_7 +// CHECK-EMPTY: +// CHECK-NEXT: _llgo_7: ; preds = %_llgo_6 +// CHECK-NEXT: %28 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 16) +// CHECK-NEXT: store %"{{.*}}/runtime/internal/runtime.String" { ptr @11, i64 25 }, ptr %28, align 8 +// CHECK-NEXT: %29 = insertvalue %"{{.*}}/runtime/internal/runtime.eface" { ptr @_llgo_string, ptr undef }, ptr %28, 1 +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.Panic"(%"{{.*}}/runtime/internal/runtime.eface" %29) +// CHECK-NEXT: unreachable +// CHECK-EMPTY: +// CHECK-NEXT: _llgo_8: ; preds = %_llgo_6 +// CHECK-NEXT: %30 = call ptr @"{{.*}}/runtime/internal/runtime.NewItab"(ptr @"_llgo_iface$36psrSzSiKQuwmDQNUwPgWt23w6DHhlw0KM1_Hu7IbY", ptr @"*_llgo_main.nilReceiver") +// CHECK-NEXT: %31 = insertvalue %"{{.*}}/runtime/internal/runtime.iface" undef, ptr %30, 0 +// CHECK-NEXT: %32 = insertvalue %"{{.*}}/runtime/internal/runtime.iface" %31, ptr null, 1 +// CHECK-NEXT: %33 = call ptr @"{{.*}}/runtime/internal/runtime.IfaceType"(%"{{.*}}/runtime/internal/runtime.iface" %32) +// CHECK-NEXT: %34 = icmp ne ptr %33, null +// CHECK-NEXT: br i1 %34, label %_llgo_11, label %_llgo_12 +// CHECK-EMPTY: +// CHECK-NEXT: _llgo_9: ; preds = %_llgo_11 +// CHECK-NEXT: %35 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 16) +// CHECK-NEXT: store %"{{.*}}/runtime/internal/runtime.String" { ptr @13, i64 32 }, ptr %35, align 8 +// CHECK-NEXT: %36 = insertvalue %"{{.*}}/runtime/internal/runtime.eface" { ptr @_llgo_string, ptr undef }, ptr %35, 1 +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.Panic"(%"{{.*}}/runtime/internal/runtime.eface" %36) +// CHECK-NEXT: unreachable +// CHECK-EMPTY: +// CHECK-NEXT: _llgo_10: ; preds = %_llgo_11 +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.PrintString"(%"{{.*}}/runtime/internal/runtime.String" { ptr @12, i64 2 }) +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.PrintByte"(i8 10) +// CHECK-NEXT: ret void +// CHECK-EMPTY: +// CHECK-NEXT: _llgo_11: ; preds = %_llgo_8 +// CHECK-NEXT: %37 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 16) +// CHECK-NEXT: %38 = getelementptr inbounds { %"{{.*}}/runtime/internal/runtime.iface" }, ptr %37, i32 0, i32 0 +// CHECK-NEXT: store %"{{.*}}/runtime/internal/runtime.iface" %32, ptr %38, align 8 +// CHECK-NEXT: %39 = insertvalue { ptr, ptr } { ptr @"main.interface{IsNil() bool}.IsNil$bound", ptr undef }, ptr %37, 1 +// CHECK-NEXT: %40 = extractvalue { ptr, ptr } %39, 1 +// CHECK-NEXT: %41 = extractvalue { ptr, ptr } %39, 0 +// CHECK-NEXT: %__llgo_funcval_code4 = call ptr asm "", "=r,0"(ptr %41) +// CHECK-NEXT: %42 = call i1 %__llgo_funcval_code4(ptr {{(nest|swiftself)}} %40) +// CHECK-NEXT: br i1 %42, label %_llgo_10, label %_llgo_9 +// CHECK-EMPTY: +// CHECK-NEXT: _llgo_12: ; preds = %_llgo_8 +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.PanicTypeAssert"(ptr %33, %"{{.*}}/runtime/internal/runtime.String" { ptr @10, i64 23 }, %"{{.*}}/runtime/internal/runtime.String" { ptr @6, i64 5 }) +// CHECK-NEXT: unreachable +// CHECK-NEXT: } + +// CHECK-LABEL: define i1 @"main.(*nilReceiver).IsNil"(ptr %0){{.*}} { +// CHECK-NEXT: _llgo_0: +// CHECK-NEXT: %1 = icmp eq ptr %0, null +// CHECK-NEXT: ret i1 %1 +// CHECK-NEXT: } + +// CHECK-LABEL: define { { ptr, ptr }, ptr } @main.zeroSizedAddressCapture(){{.*}} { +// CHECK-NEXT: _llgo_0: +// CHECK-NEXT: ret { { ptr, ptr }, ptr } { { ptr, ptr } { ptr @"main.zeroSizedAddressCapture$1", ptr null }, ptr @"__llgo.moduleZeroSizedAlloc$" } +// CHECK-NEXT: } + +// CHECK-LABEL: define ptr @"main.zeroSizedAddressCapture$1"(){{.*}} { +// CHECK-NEXT: _llgo_0: +// CHECK-NEXT: ret ptr @"__llgo.moduleZeroSizedAlloc$" +// CHECK-NEXT: } + +// CHECK-LABEL: define { ptr, ptr } @main.zeroSizedCapture(){{.*}} { +// CHECK-NEXT: _llgo_0: +// CHECK-NEXT: ret { ptr, ptr } { ptr @"main.zeroSizedCapture$1", ptr null } +// CHECK-NEXT: } + +// CHECK-LABEL: define i64 @"main.zeroSizedCapture$1"(){{.*}} { +// CHECK-NEXT: _llgo_0: +// CHECK-NEXT: br i1 false, label %_llgo_1, label %_llgo_2 +// CHECK-EMPTY: +// CHECK-NEXT: _llgo_1: ; preds = %_llgo_0 +// CHECK-NEXT: ret i64 0 +// CHECK-EMPTY: +// CHECK-NEXT: _llgo_2: ; preds = %_llgo_0 +// CHECK-NEXT: ret i64 42 +// CHECK-NEXT: } + +// CHECK-LABEL: define { ptr, ptr } @main.zeroSizedPointerCapture(ptr %0){{.*}} { +// CHECK-NEXT: _llgo_0: +// CHECK-NEXT: %1 = call ptr @"{{.*}}/runtime/internal/runtime.AllocZ"(i64 8) +// CHECK-NEXT: store ptr %0, ptr %1, align 8 +// CHECK-NEXT: %2 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 8) +// CHECK-NEXT: %3 = getelementptr inbounds { ptr }, ptr %2, i32 0, i32 0 +// CHECK-NEXT: store ptr %1, ptr %3, align 8 +// CHECK-NEXT: %4 = insertvalue { ptr, ptr } { ptr @"main.zeroSizedPointerCapture$1", ptr undef }, ptr %2, 1 +// CHECK-NEXT: ret { ptr, ptr } %4 +// CHECK-NEXT: } + +// CHECK-LABEL: define i1 @"main.zeroSizedPointerCapture$1"(ptr {{(nest|swiftself)}} %0){{.*}} { +// CHECK-NEXT: _llgo_0: +// CHECK-NEXT: %1 = load { ptr }, ptr %0, align 8 +// CHECK-NEXT: %2 = extractvalue { ptr } %1, 0 +// CHECK-NEXT: %3 = load ptr, ptr %2, align 8 +// CHECK-NEXT: %4 = icmp eq ptr %3, null +// CHECK-NEXT: ret i1 %4 +// CHECK-NEXT: } + +// CHECK-LABEL: define i1 @"main.(*nilReceiver).IsNil$bound"(ptr {{(nest|swiftself)}} %0){{.*}} { +// CHECK-NEXT: _llgo_0: +// CHECK-NEXT: %1 = load { ptr }, ptr %0, align 8 +// CHECK-NEXT: %2 = extractvalue { ptr } %1, 0 +// CHECK-NEXT: %3 = call i1 @"main.(*nilReceiver).IsNil"(ptr %2) +// CHECK-NEXT: ret i1 %3 +// CHECK-NEXT: } + +// CHECK-LABEL: define i1 @"main.interface{IsNil() bool}.IsNil$bound"(ptr {{(nest|swiftself)}} %0){{.*}} { +// CHECK-NEXT: _llgo_0: +// CHECK-NEXT: %1 = load { %"{{.*}}/runtime/internal/runtime.iface" }, ptr %0, align 8 +// CHECK-NEXT: %2 = extractvalue { %"{{.*}}/runtime/internal/runtime.iface" } %1, 0 +// CHECK-NEXT: %3 = call ptr @"{{.*}}/runtime/internal/runtime.IfacePtrData"(%"{{.*}}/runtime/internal/runtime.iface" %2) +// CHECK-NEXT: %4 = extractvalue %"{{.*}}/runtime/internal/runtime.iface" %2, 0 +// CHECK-NEXT: %5 = getelementptr ptr, ptr %4, i64 3 +// CHECK-NEXT: %6 = load ptr, ptr %5, align 8 +// CHECK-NEXT: %7 = insertvalue { ptr, ptr } undef, ptr %6, 0 +// CHECK-NEXT: %8 = insertvalue { ptr, ptr } %7, ptr %3, 1 +// CHECK-NEXT: %9 = extractvalue { ptr, ptr } %8, 1 +// CHECK-NEXT: %10 = extractvalue { ptr, ptr } %8, 0 +// CHECK-NEXT: %11 = call i1 %10(ptr %9) +// CHECK-NEXT: ret i1 %11 +// CHECK-NEXT: } diff --git a/cl/_testgo/cursor/in.go b/cl/_testgo/cursor/in.go index d0a2fc24bf..3fa82f1704 100644 --- a/cl/_testgo/cursor/in.go +++ b/cl/_testgo/cursor/in.go @@ -66,7 +66,8 @@ func (c Cursor) Node() ast.Node { // CHECK-NEXT: %20 = insertvalue { ptr, ptr } { ptr @"main.Cursor.FindNode$1", ptr undef }, ptr %15, 1 // CHECK-NEXT: %21 = extractvalue %"iter.Seq[main.Cursor]" %13, 1 // CHECK-NEXT: %22 = extractvalue %"iter.Seq[main.Cursor]" %13, 0 -// CHECK-NEXT: call void %22(ptr %21, { ptr, ptr } %20) +// CHECK-NEXT: %__llgo_funcval_code = call ptr asm "", "=r,0"(ptr %22) +// CHECK-NEXT: call void %__llgo_funcval_code(ptr {{(nest|swiftself)}} %21, { ptr, ptr } %20) // CHECK-NEXT: %23 = load i64, ptr %14, align 8 // CHECK-NEXT: %24 = icmp eq i64 %23, -1 // CHECK-NEXT: br i1 %24, label %_llgo_4, label %_llgo_5 @@ -497,7 +498,7 @@ const ( nValueSpec ) -// CHECK-LABEL: define i1 @"main.Cursor.FindNode$1"(ptr %0, %main.Cursor %1){{.*}} { +// CHECK-LABEL: define i1 @"main.Cursor.FindNode$1"(ptr {{(nest|swiftself)}} %0, %main.Cursor %1){{.*}} { // CHECK-NEXT: _llgo_0: // CHECK-NEXT: %2 = load { ptr, ptr, ptr, ptr }, ptr %0, align 8 // CHECK-NEXT: %3 = extractvalue { ptr, ptr, ptr, ptr } %2, 0 @@ -596,7 +597,7 @@ const ( // CHECK-NEXT: ret %"iter.Seq[main.Cursor]" %10 // CHECK-NEXT: } -// CHECK-LABEL: define void @"main.Cursor.Preorder$1"(ptr %0, { ptr, ptr } %1){{.*}} { +// CHECK-LABEL: define void @"main.Cursor.Preorder$1"(ptr {{(nest|swiftself)}} %0, { ptr, ptr } %1){{.*}} { // CHECK-NEXT: _llgo_0: // CHECK-NEXT: %2 = load { ptr, ptr }, ptr %0, align 8 // CHECK-NEXT: %3 = extractvalue { ptr, ptr } %2, 0 @@ -683,7 +684,8 @@ const ( // CHECK-NEXT: %56 = load %main.Cursor, ptr %50, align 8 // CHECK-NEXT: %57 = extractvalue { ptr, ptr } %1, 1 // CHECK-NEXT: %58 = extractvalue { ptr, ptr } %1, 0 -// CHECK-NEXT: %59 = call i1 %58(ptr %57, %main.Cursor %56) +// CHECK-NEXT: %__llgo_funcval_code = call ptr asm "", "=r,0"(ptr %58) +// CHECK-NEXT: %59 = call i1 %__llgo_funcval_code(ptr {{(nest|swiftself)}} %57, %main.Cursor %56) // CHECK-NEXT: br i1 %59, label %_llgo_6, label %_llgo_3 // CHECK-EMPTY: // CHECK-NEXT: _llgo_8: ; preds = %_llgo_6 @@ -2157,27 +2159,3 @@ const ( // CHECK-NEXT: %456 = extractvalue { ptr, i1 } %454, 1 // CHECK-NEXT: br i1 %456, label %_llgo_113, label %_llgo_114 // CHECK-NEXT: } - -// CHECK-LABEL: define linkonce i1 @"__llgo_stub.{{.*}}/runtime/internal/runtime.memequal64"(ptr %0, ptr %1, ptr %2){{.*}} { -// CHECK-NEXT: _llgo_0: -// CHECK-NEXT: %3 = tail call i1 @"{{.*}}/runtime/internal/runtime.memequal64"(ptr %1, ptr %2) -// CHECK-NEXT: ret i1 %3 -// CHECK-NEXT: } - -// CHECK-LABEL: define linkonce i1 @"__llgo_stub.{{.*}}/runtime/internal/runtime.memequal8"(ptr %0, ptr %1, ptr %2){{.*}} { -// CHECK-NEXT: _llgo_0: -// CHECK-NEXT: %3 = tail call i1 @"{{.*}}/runtime/internal/runtime.memequal8"(ptr %1, ptr %2) -// CHECK-NEXT: ret i1 %3 -// CHECK-NEXT: } - -// CHECK-LABEL: define linkonce i1 @"__llgo_stub.{{.*}}/runtime/internal/runtime.nilinterequal"(ptr %0, ptr %1, ptr %2){{.*}} { -// CHECK-NEXT: _llgo_0: -// CHECK-NEXT: %3 = tail call i1 @"{{.*}}/runtime/internal/runtime.nilinterequal"(ptr %1, ptr %2) -// CHECK-NEXT: ret i1 %3 -// CHECK-NEXT: } - -// CHECK-LABEL: define linkonce i1 @"__llgo_stub.{{.*}}/runtime/internal/runtime.interequal"(ptr %0, ptr %1, ptr %2){{.*}} { -// CHECK-NEXT: _llgo_0: -// CHECK-NEXT: %3 = tail call i1 @"{{.*}}/runtime/internal/runtime.interequal"(ptr %1, ptr %2) -// CHECK-NEXT: ret i1 %3 -// CHECK-NEXT: } diff --git a/cl/_testgo/deferiface/expect.txt b/cl/_testgo/deferiface/expect.txt new file mode 100644 index 0000000000..a7924147e5 --- /dev/null +++ b/cl/_testgo/deferiface/expect.txt @@ -0,0 +1,2 @@ +body +reset 42 diff --git a/cl/_testgo/deferiface/in.go b/cl/_testgo/deferiface/in.go new file mode 100644 index 0000000000..bcee22b9ae --- /dev/null +++ b/cl/_testgo/deferiface/in.go @@ -0,0 +1,148 @@ +// LITTEST +package main + +// CHECK: {{^}}@0 = private unnamed_addr constant [5 x i8] c"reset", align 1{{$}} +// CHECK: {{^}}@8 = private unnamed_addr constant [4 x i8] c"body", align 1{{$}} + +type resetter interface { + Reset() +} + +type item struct { + value int +} + +func (p *item) Reset() { + println("reset", p.value) +} + +func run(v resetter) { + defer v.Reset() + println("body") +} + +func main() { + run(&item{42}) +} + +// CHECK-LABEL: define void @main.init(){{.*}} { +// CHECK-NEXT: _llgo_0: +// CHECK-NEXT: %0 = load i1, ptr @"main.init$guard", align 1 +// CHECK-NEXT: br i1 %0, label %_llgo_2, label %_llgo_1 +// CHECK-EMPTY: +// CHECK-NEXT: _llgo_1: ; preds = %_llgo_0 +// CHECK-NEXT: store i1 true, ptr @"main.init$guard", align 1 +// CHECK-NEXT: br label %_llgo_2 +// CHECK-EMPTY: +// CHECK-NEXT: _llgo_2: ; preds = %_llgo_1, %_llgo_0 +// CHECK-NEXT: ret void +// CHECK-NEXT: } + +// CHECK-LABEL: define void @"main.(*item).Reset"(ptr %0){{.*}} { +// CHECK-NEXT: _llgo_0: +// CHECK-NEXT: %1 = getelementptr inbounds %main.item, ptr %0, i32 0, i32 0 +// CHECK-NEXT: %2 = load i64, ptr %1, align 8 +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.PrintString"(%"{{.*}}/runtime/internal/runtime.String" { ptr @0, i64 5 }) +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.PrintByte"(i8 32) +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.PrintInt"(i64 %2) +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.PrintByte"(i8 10) +// CHECK-NEXT: ret void +// CHECK-NEXT: } + +// CHECK-LABEL: define void @main.main(){{.*}} { +// CHECK-NEXT: _llgo_0: +// CHECK-NEXT: %0 = call ptr @"{{.*}}/runtime/internal/runtime.AllocZ"(i64 8) +// CHECK-NEXT: %1 = getelementptr inbounds %main.item, ptr %0, i32 0, i32 0 +// CHECK-NEXT: store i64 42, ptr %1, align 8 +// CHECK-NEXT: %2 = call ptr @"{{.*}}/runtime/internal/runtime.NewItab"(ptr @"_llgo_iface$yjH5fOWhYIH6Pv7ce-kmK-CVKIWOLvKPVzRvjwBotEM", ptr @"*_llgo_main.item") +// CHECK-NEXT: %3 = insertvalue %"{{.*}}/runtime/internal/runtime.iface" undef, ptr %2, 0 +// CHECK-NEXT: %4 = insertvalue %"{{.*}}/runtime/internal/runtime.iface" %3, ptr %0, 1 +// CHECK-NEXT: call void @main.run(%"{{.*}}/runtime/internal/runtime.iface" %4) +// CHECK-NEXT: ret void +// CHECK-NEXT: } + +// CHECK-LABEL: define void @main.run(%"{{.*}}/runtime/internal/runtime.iface" %0){{.*}} { +// CHECK-NEXT: _llgo_0: +// CHECK-NEXT: %1 = call ptr @"{{.*}}/runtime/internal/runtime.IfacePtrData"(%"{{.*}}/runtime/internal/runtime.iface" %0) +// CHECK-NEXT: %2 = extractvalue %"{{.*}}/runtime/internal/runtime.iface" %0, 0 +// CHECK-NEXT: %3 = getelementptr ptr, ptr %2, i64 3 +// CHECK-NEXT: %4 = load ptr, ptr %3, align 8 +// CHECK-NEXT: %5 = insertvalue { ptr, ptr } undef, ptr %4, 0 +// CHECK-NEXT: %6 = insertvalue { ptr, ptr } %5, ptr %1, 1 +// CHECK-NEXT: %7 = call ptr @"{{.*}}/runtime/internal/runtime.GetThreadDefer"() +// CHECK-NEXT: %8 = alloca i8, i64 {{.*}}, align 1 +// CHECK-NEXT: %9 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 48) +// CHECK-NEXT: %10 = getelementptr inbounds %"{{.*}}/runtime/internal/runtime.Defer", ptr %9, i32 0, i32 0 +// CHECK-NEXT: store ptr %8, ptr %10, align 8 +// CHECK-NEXT: %11 = getelementptr inbounds %"{{.*}}/runtime/internal/runtime.Defer", ptr %9, i32 0, i32 1 +// CHECK-NEXT: store i64 0, ptr %11, align 8 +// CHECK-NEXT: %12 = getelementptr inbounds %"{{.*}}/runtime/internal/runtime.Defer", ptr %9, i32 0, i32 2 +// CHECK-NEXT: store ptr %7, ptr %12, align 8 +// CHECK-NEXT: %13 = getelementptr inbounds %"{{.*}}/runtime/internal/runtime.Defer", ptr %9, i32 0, i32 3 +// CHECK-NEXT: store ptr blockaddress(@main.run, %_llgo_2), ptr %13, align 8 +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.SetThreadDefer"(ptr %9) +// CHECK-NEXT: %14 = getelementptr inbounds %"{{.*}}/runtime/internal/runtime.Defer", ptr %9, i32 0, i32 1 +// CHECK-NEXT: %15 = getelementptr inbounds %"{{.*}}/runtime/internal/runtime.Defer", ptr %9, i32 0, i32 3 +// CHECK-NEXT: %16 = getelementptr inbounds %"{{.*}}/runtime/internal/runtime.Defer", ptr %9, i32 0, i32 4 +// CHECK-NEXT: %17 = getelementptr inbounds %"{{.*}}/runtime/internal/runtime.Defer", ptr %9, i32 0, i32 5 +// CHECK-NEXT: store ptr null, ptr %17, align 8 +// CHECK-NEXT: %18 = call i32 @{{.*}}sigsetjmp(ptr %8, i32 0) +// CHECK-NEXT: %19 = icmp eq i32 %18, 0 +// CHECK-NEXT: br i1 %19, label %_llgo_4, label %_llgo_5 +// CHECK-EMPTY: +// CHECK-NEXT: _llgo_1: ; preds = %_llgo_3 +// CHECK-NEXT: ret void +// CHECK-EMPTY: +// CHECK-NEXT: _llgo_2: ; preds = %_llgo_5, %_llgo_4 +// CHECK-NEXT: store ptr blockaddress(@main.run, %_llgo_3), ptr %15, align 8 +// CHECK-NEXT: %20 = load i64, ptr %14, align 8 +// CHECK-NEXT: %21 = load ptr, ptr %17, align 8 +// CHECK-NEXT: %22 = icmp ne ptr %21, null +// CHECK-NEXT: br i1 %22, label %_llgo_7, label %_llgo_8 +// CHECK-EMPTY: +// CHECK-NEXT: _llgo_3: ; preds = %_llgo_5, %_llgo_8 +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.Rethrow"(ptr %7) +// CHECK-NEXT: br label %_llgo_1 +// CHECK-EMPTY: +// CHECK-NEXT: _llgo_4: ; preds = %_llgo_0 +// CHECK-NEXT: %23 = load ptr, ptr %17, align 8 +// CHECK-NEXT: %24 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 32) +// CHECK-NEXT: %25 = getelementptr inbounds { ptr, i64, { ptr, ptr } }, ptr %24, i32 0, i32 0 +// CHECK-NEXT: store ptr %23, ptr %25, align 8 +// CHECK-NEXT: %26 = getelementptr inbounds { ptr, i64, { ptr, ptr } }, ptr %24, i32 0, i32 1 +// CHECK-NEXT: store i64 0, ptr %26, align 8 +// CHECK-NEXT: %27 = getelementptr inbounds { ptr, i64, { ptr, ptr } }, ptr %24, i32 0, i32 2 +// CHECK-NEXT: store { ptr, ptr } %6, ptr %27, align 8 +// CHECK-NEXT: store ptr %24, ptr %17, align 8 +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.PrintString"(%"{{.*}}/runtime/internal/runtime.String" { ptr @8, i64 4 }) +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.PrintByte"(i8 10) +// CHECK-NEXT: store ptr blockaddress(@main.run, %_llgo_6), ptr %16, align 8 +// CHECK-NEXT: br label %_llgo_2 +// CHECK-EMPTY: +// CHECK-NEXT: _llgo_5: ; preds = %_llgo_0 +// CHECK-NEXT: store ptr blockaddress(@main.run, %_llgo_3), ptr %16, align 8 +// CHECK-NEXT: %28 = load ptr, ptr %15, align 8 +// CHECK-NEXT: indirectbr ptr %28, [label %_llgo_3, label %_llgo_2] +// CHECK-EMPTY: +// CHECK-NEXT: _llgo_6: ; preds = %_llgo_8 +// CHECK-NEXT: ret void +// CHECK-EMPTY: +// CHECK-NEXT: _llgo_7: ; preds = %_llgo_2 +// CHECK-NEXT: %29 = load ptr, ptr %17, align 8 +// CHECK-NEXT: %30 = load { ptr, i64, { ptr, ptr } }, ptr %29, align 8 +// CHECK-NEXT: %31 = extractvalue { ptr, i64, { ptr, ptr } } %30, 0 +// CHECK-NEXT: store ptr %31, ptr %17, align 8 +// CHECK-NEXT: %32 = extractvalue { ptr, i64, { ptr, ptr } } %30, 2 +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.FreeDeferNode"(ptr %29) +// CHECK-NEXT: %33 = extractvalue { ptr, ptr } %32, 1 +// CHECK-NEXT: %34 = extractvalue { ptr, ptr } %32, 0 +// CHECK-NEXT: call void %34(ptr %33) +// CHECK-NEXT: br label %_llgo_8 +// CHECK-EMPTY: +// CHECK-NEXT: _llgo_8: ; preds = %_llgo_7, %_llgo_2 +// CHECK-NEXT: %35 = load %"{{.*}}/runtime/internal/runtime.Defer", ptr %9, align 8 +// CHECK-NEXT: %36 = extractvalue %"{{.*}}/runtime/internal/runtime.Defer" %35, 2 +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.SetThreadDefer"(ptr %36) +// CHECK-NEXT: %37 = load ptr, ptr %16, align 8 +// CHECK-NEXT: indirectbr ptr %37, [label %_llgo_3, label %_llgo_6] +// CHECK-NEXT: } diff --git a/cl/_testgo/equal/in.go b/cl/_testgo/equal/in.go index 0a2347e2c4..b1b657132e 100644 --- a/cl/_testgo/equal/in.go +++ b/cl/_testgo/equal/in.go @@ -77,7 +77,7 @@ func init() { // CHECK-NEXT: } var n int fn3 := func() { println(n) } - // CHECK-LABEL: define void @"main.init#1$2"(ptr %0){{.*}} { + // CHECK-LABEL: define void @"main.init#1$2"(ptr {{(nest|swiftself)}} %0){{.*}} { // CHECK-NEXT: _llgo_0: // CHECK-NEXT: %1 = load { ptr }, ptr %0, align 8 // CHECK-NEXT: %2 = extractvalue { ptr } %1, 0 diff --git a/cl/_testgo/genericembediface/in.go b/cl/_testgo/genericembediface/in.go index 3ac1e4ccef..be2c2122ee 100644 --- a/cl/_testgo/genericembediface/in.go +++ b/cl/_testgo/genericembediface/in.go @@ -133,12 +133,6 @@ func main() { // CHECK-NEXT: ret %"{{.*}}/runtime/internal/runtime.String" %3 // CHECK-NEXT: } -// CHECK-LABEL: define linkonce i1 @"__llgo_stub.{{.*}}/runtime/internal/runtime.interequal"(ptr %0, ptr %1, ptr %2){{.*}} { -// CHECK-NEXT: _llgo_0: -// CHECK-NEXT: %3 = tail call i1 @"{{.*}}/runtime/internal/runtime.interequal"(ptr %1, ptr %2) -// CHECK-NEXT: ret i1 %3 -// CHECK-NEXT: } - // CHECK-LABEL: define linkonce %"{{.*}}/runtime/internal/runtime.String" @"{{.*}}/cl/_testgo/genericembediface/streamlib.(*GenericServerStream[main.Request,main.Response]).Context"(ptr %0){{.*}} { // CHECK-NEXT: _llgo_0: // CHECK-NEXT: %1 = getelementptr inbounds %"{{.*}}/cl/_testgo/genericembediface/streamlib.GenericServerStream[main.Request,main.Response]", ptr %0, i32 0, i32 0 @@ -173,45 +167,3 @@ func main() { // CHECK-NEXT: %12 = call %"{{.*}}/runtime/internal/runtime.String" %11(ptr %10) // CHECK-NEXT: ret %"{{.*}}/runtime/internal/runtime.String" %12 // CHECK-NEXT: } - -// CHECK-LABEL: define linkonce %"{{.*}}/runtime/internal/runtime.String" @"__llgo_stub.{{.*}}/cl/_testgo/genericembediface/streamlib.GenericServerStream[main.Request,main.Response].Context"(ptr %0, %"{{.*}}/cl/_testgo/genericembediface/streamlib.GenericServerStream[main.Request,main.Response]" %1){{.*}} { -// CHECK-NEXT: _llgo_0: -// CHECK-NEXT: %2 = tail call %"{{.*}}/runtime/internal/runtime.String" @"{{.*}}/cl/_testgo/genericembediface/streamlib.GenericServerStream[main.Request,main.Response].Context"(%"{{.*}}/cl/_testgo/genericembediface/streamlib.GenericServerStream[main.Request,main.Response]" %1) -// CHECK-NEXT: ret %"{{.*}}/runtime/internal/runtime.String" %2 -// CHECK-NEXT: } - -// CHECK-LABEL: define linkonce %"{{.*}}/runtime/internal/runtime.String" @"__llgo_stub.{{.*}}/cl/_testgo/genericembediface/streamlib.(*GenericServerStream[main.Request,main.Response]).Context"(ptr %0, ptr %1){{.*}} { -// CHECK-NEXT: _llgo_0: -// CHECK-NEXT: %2 = tail call %"{{.*}}/runtime/internal/runtime.String" @"{{.*}}/cl/_testgo/genericembediface/streamlib.(*GenericServerStream[main.Request,main.Response]).Context"(ptr %1) -// CHECK-NEXT: ret %"{{.*}}/runtime/internal/runtime.String" %2 -// CHECK-NEXT: } - -// CHECK-LABEL: define linkonce i1 @"__llgo_stub.{{.*}}/runtime/internal/runtime.memequal0"(ptr %0, ptr %1, ptr %2){{.*}} { -// CHECK-NEXT: _llgo_0: -// CHECK-NEXT: %3 = tail call i1 @"{{.*}}/runtime/internal/runtime.memequal0"(ptr %1, ptr %2) -// CHECK-NEXT: ret i1 %3 -// CHECK-NEXT: } - -// CHECK-LABEL: define linkonce %"{{.*}}/runtime/internal/runtime.iface" @"__llgo_stub.main.(*server).ServerReflectionInfo"(ptr %0, ptr %1, %"{{.*}}/runtime/internal/runtime.iface" %2){{.*}} { -// CHECK-NEXT: _llgo_0: -// CHECK-NEXT: %3 = tail call %"{{.*}}/runtime/internal/runtime.iface" @"main.(*server).ServerReflectionInfo"(ptr %1, %"{{.*}}/runtime/internal/runtime.iface" %2) -// CHECK-NEXT: ret %"{{.*}}/runtime/internal/runtime.iface" %3 -// CHECK-NEXT: } - -// CHECK-LABEL: define linkonce %"{{.*}}/runtime/internal/runtime.iface" @__llgo_stub.main.server.ServerReflectionInfo(ptr %0, %main.server %1, %"{{.*}}/runtime/internal/runtime.iface" %2){{.*}} { -// CHECK-NEXT: _llgo_0: -// CHECK-NEXT: %3 = tail call %"{{.*}}/runtime/internal/runtime.iface" @main.server.ServerReflectionInfo(%main.server %1, %"{{.*}}/runtime/internal/runtime.iface" %2) -// CHECK-NEXT: ret %"{{.*}}/runtime/internal/runtime.iface" %3 -// CHECK-NEXT: } - -// CHECK-LABEL: define linkonce %"{{.*}}/runtime/internal/runtime.String" @"__llgo_stub.main.(*stream).Context"(ptr %0, ptr %1){{.*}} { -// CHECK-NEXT: _llgo_0: -// CHECK-NEXT: %2 = tail call %"{{.*}}/runtime/internal/runtime.String" @"main.(*stream).Context"(ptr %1) -// CHECK-NEXT: ret %"{{.*}}/runtime/internal/runtime.String" %2 -// CHECK-NEXT: } - -// CHECK-LABEL: define linkonce %"{{.*}}/runtime/internal/runtime.String" @__llgo_stub.main.stream.Context(ptr %0, %main.stream %1){{.*}} { -// CHECK-NEXT: _llgo_0: -// CHECK-NEXT: %2 = tail call %"{{.*}}/runtime/internal/runtime.String" @main.stream.Context(%main.stream %1) -// CHECK-NEXT: ret %"{{.*}}/runtime/internal/runtime.String" %2 -// CHECK-NEXT: } diff --git a/cl/_testgo/genericiter/in.go b/cl/_testgo/genericiter/in.go index 14ea1f8284..7a3e4d9f7d 100644 --- a/cl/_testgo/genericiter/in.go +++ b/cl/_testgo/genericiter/in.go @@ -62,7 +62,7 @@ func (t *Tree) Ascend(iterator Iterator) { func main() { var got int tree := (*Tree)(new(TreeG[int])) - // CHECK-LABEL: define i1 @"main.main$1"(ptr %0, i64 %1){{.*}} { + // CHECK-LABEL: define i1 @"main.main$1"(ptr {{(nest|swiftself)}} %0, i64 %1){{.*}} { // CHECK-NEXT: _llgo_0: // CHECK-NEXT: %2 = add i64 %1, 1 // CHECK-NEXT: %3 = load { ptr }, ptr %0, align 8 @@ -85,6 +85,7 @@ func main() { // CHECK-NEXT: _llgo_0: // CHECK-NEXT: %2 = extractvalue %"main.IteratorG[int]" %1, 1 // CHECK-NEXT: %3 = extractvalue %"main.IteratorG[int]" %1, 0 -// CHECK-NEXT: %4 = call i1 %3(ptr %2, i64 0) +// CHECK-NEXT: %__llgo_funcval_code = call ptr asm "", "=r,0"(ptr %3) +// CHECK-NEXT: %4 = call i1 %__llgo_funcval_code(ptr {{(nest|swiftself)}} %2, i64 0) // CHECK-NEXT: ret void // CHECK-NEXT: } diff --git a/cl/_testgo/goroutine/in.go b/cl/_testgo/goroutine/in.go index 112e3c2906..0521c06343 100644 --- a/cl/_testgo/goroutine/in.go +++ b/cl/_testgo/goroutine/in.go @@ -16,7 +16,7 @@ func main() { // CHECK: call void @"{{.*}}NewProc"(ptr @"main._llgo_routine$2", ptr {{%[0-9]+}}, i64 0) // CHECK: call void @"{{.*}}PrintString"(%"{{.*}}String" { ptr @2, i64 1 }) // CHECK: ret void - // CHECK-LABEL: define void @"main.main$1"(ptr %0, %"{{.*}}String" %1){{.*}} { + // CHECK-LABEL: define void @"main.main$1"(ptr {{(nest|swiftself)}} %0, %"{{.*}}String" %1){{.*}} { // CHECK-NEXT: _llgo_0: // CHECK-NEXT: call void @"{{.*}}PrintString"(%"{{.*}}String" %1) // CHECK-NEXT: call void @"{{.*}}PrintByte"(i8 10) @@ -49,5 +49,6 @@ func main() { // CHECK-NEXT: call void @"{{.*}}FreeRoot"(ptr %0) // CHECK-NEXT: %4 = extractvalue { ptr, ptr } %2, 1 // CHECK-NEXT: %5 = extractvalue { ptr, ptr } %2, 0 -// CHECK-NEXT: call void %5(ptr %4, %"{{.*}}String" %3) +// CHECK-NEXT: %__llgo_funcval_code = call ptr asm "", "=r,0"(ptr %5) +// CHECK-NEXT: call void %__llgo_funcval_code(ptr {{(nest|swiftself)}} %4, %"{{.*}}String" %3) // CHECK-NEXT: ret ptr null diff --git a/cl/_testgo/ifaceconv/in.go b/cl/_testgo/ifaceconv/in.go index 2f1a83cd2b..b7b9ce6160 100644 --- a/cl/_testgo/ifaceconv/in.go +++ b/cl/_testgo/ifaceconv/in.go @@ -464,57 +464,3 @@ func main() { // CHECK-NEXT: %125 = extractvalue { %"{{.*}}/runtime/internal/runtime.iface", i1 } %123, 1 // CHECK-NEXT: br i1 %125, label %_llgo_18, label %_llgo_17 // CHECK-NEXT: } - -// CHECK-LABEL: define linkonce i1 @"__llgo_stub.{{.*}}/runtime/internal/runtime.nilinterequal"(ptr %0, ptr %1, ptr %2){{.*}} { -// CHECK-NEXT: _llgo_0: -// CHECK-NEXT: %3 = tail call i1 @"{{.*}}/runtime/internal/runtime.nilinterequal"(ptr %1, ptr %2) -// CHECK-NEXT: ret i1 %3 -// CHECK-NEXT: } - -// CHECK-LABEL: define linkonce i1 @"__llgo_stub.{{.*}}/runtime/internal/runtime.interequal"(ptr %0, ptr %1, ptr %2){{.*}} { -// CHECK-NEXT: _llgo_0: -// CHECK-NEXT: %3 = tail call i1 @"{{.*}}/runtime/internal/runtime.interequal"(ptr %1, ptr %2) -// CHECK-NEXT: ret i1 %3 -// CHECK-NEXT: } - -// CHECK-LABEL: define linkonce i1 @"__llgo_stub.{{.*}}/runtime/internal/runtime.memequal0"(ptr %0, ptr %1, ptr %2){{.*}} { -// CHECK-NEXT: _llgo_0: -// CHECK-NEXT: %3 = tail call i1 @"{{.*}}/runtime/internal/runtime.memequal0"(ptr %1, ptr %2) -// CHECK-NEXT: ret i1 %3 -// CHECK-NEXT: } - -// CHECK-LABEL: define linkonce void @"__llgo_stub.main.(*C1).f"(ptr %0, ptr %1){{.*}} { -// CHECK-NEXT: _llgo_0: -// CHECK-NEXT: tail call void @"main.(*C1).f"(ptr %1) -// CHECK-NEXT: ret void -// CHECK-NEXT: } - -// CHECK-LABEL: define linkonce void @__llgo_stub.main.C1.f(ptr %0, %main.C1 %1){{.*}} { -// CHECK-NEXT: _llgo_0: -// CHECK-NEXT: tail call void @main.C1.f(%main.C1 %1) -// CHECK-NEXT: ret void -// CHECK-NEXT: } - -// CHECK-LABEL: define linkonce void @"__llgo_stub.main.(*C2).f"(ptr %0, ptr %1){{.*}} { -// CHECK-NEXT: _llgo_0: -// CHECK-NEXT: tail call void @"main.(*C2).f"(ptr %1) -// CHECK-NEXT: ret void -// CHECK-NEXT: } - -// CHECK-LABEL: define linkonce void @"__llgo_stub.main.(*C2).g"(ptr %0, ptr %1){{.*}} { -// CHECK-NEXT: _llgo_0: -// CHECK-NEXT: tail call void @"main.(*C2).g"(ptr %1) -// CHECK-NEXT: ret void -// CHECK-NEXT: } - -// CHECK-LABEL: define linkonce void @__llgo_stub.main.C2.f(ptr %0, %main.C2 %1){{.*}} { -// CHECK-NEXT: _llgo_0: -// CHECK-NEXT: tail call void @main.C2.f(%main.C2 %1) -// CHECK-NEXT: ret void -// CHECK-NEXT: } - -// CHECK-LABEL: define linkonce void @__llgo_stub.main.C2.g(ptr %0, %main.C2 %1){{.*}} { -// CHECK-NEXT: _llgo_0: -// CHECK-NEXT: tail call void @main.C2.g(%main.C2 %1) -// CHECK-NEXT: ret void -// CHECK-NEXT: } diff --git a/cl/_testgo/ifaceprom/in.go b/cl/_testgo/ifaceprom/in.go index b75d561191..3dd49d6e04 100644 --- a/cl/_testgo/ifaceprom/in.go +++ b/cl/_testgo/ifaceprom/in.go @@ -347,7 +347,8 @@ func main() { // CHECK-NEXT: %90 = insertvalue { ptr, ptr } { ptr @"main.I.one$bound", ptr undef }, ptr %88, 1 // CHECK-NEXT: %91 = extractvalue { ptr, ptr } %90, 1 // CHECK-NEXT: %92 = extractvalue { ptr, ptr } %90, 0 -// CHECK-NEXT: %93 = call i64 %92(ptr %91) +// CHECK-NEXT: %__llgo_funcval_code = call ptr asm "", "=r,0"(ptr %92) +// CHECK-NEXT: %93 = call i64 %__llgo_funcval_code(ptr {{(nest|swiftself)}} %91) // CHECK-NEXT: %94 = icmp ne i64 %93, 1 // CHECK-NEXT: br i1 %94, label %_llgo_5, label %_llgo_6 // CHECK-EMPTY: @@ -362,7 +363,8 @@ func main() { // CHECK-NEXT: %97 = insertvalue { ptr, ptr } { ptr @"main.I.one$bound", ptr undef }, ptr %95, 1 // CHECK-NEXT: %98 = extractvalue { ptr, ptr } %97, 1 // CHECK-NEXT: %99 = extractvalue { ptr, ptr } %97, 0 -// CHECK-NEXT: %100 = call i64 %99(ptr %98) +// CHECK-NEXT: %__llgo_funcval_code1 = call ptr asm "", "=r,0"(ptr %99) +// CHECK-NEXT: %100 = call i64 %__llgo_funcval_code1(ptr {{(nest|swiftself)}} %98) // CHECK-NEXT: %101 = icmp ne i64 %100, 1 // CHECK-NEXT: br i1 %101, label %_llgo_7, label %_llgo_8 // CHECK-EMPTY: @@ -377,7 +379,8 @@ func main() { // CHECK-NEXT: %104 = insertvalue { ptr, ptr } { ptr @"main.I.two$bound", ptr undef }, ptr %102, 1 // CHECK-NEXT: %105 = extractvalue { ptr, ptr } %104, 1 // CHECK-NEXT: %106 = extractvalue { ptr, ptr } %104, 0 -// CHECK-NEXT: %107 = call %"{{.*}}/runtime/internal/runtime.String" %106(ptr %105) +// CHECK-NEXT: %__llgo_funcval_code2 = call ptr asm "", "=r,0"(ptr %106) +// CHECK-NEXT: %107 = call %"{{.*}}/runtime/internal/runtime.String" %__llgo_funcval_code2(ptr {{(nest|swiftself)}} %105) // CHECK-NEXT: %108 = call i1 @"{{.*}}/runtime/internal/runtime.StringEqual"(%"{{.*}}/runtime/internal/runtime.String" %107, %"{{.*}}/runtime/internal/runtime.String" { ptr @0, i64 3 }) // CHECK-NEXT: %109 = xor i1 %108, true // CHECK-NEXT: br i1 %109, label %_llgo_13, label %_llgo_14 @@ -393,7 +396,8 @@ func main() { // CHECK-NEXT: %112 = insertvalue { ptr, ptr } { ptr @"main.I.two$bound", ptr undef }, ptr %110, 1 // CHECK-NEXT: %113 = extractvalue { ptr, ptr } %112, 1 // CHECK-NEXT: %114 = extractvalue { ptr, ptr } %112, 0 -// CHECK-NEXT: %115 = call %"{{.*}}/runtime/internal/runtime.String" %114(ptr %113) +// CHECK-NEXT: %__llgo_funcval_code3 = call ptr asm "", "=r,0"(ptr %114) +// CHECK-NEXT: %115 = call %"{{.*}}/runtime/internal/runtime.String" %__llgo_funcval_code3(ptr {{(nest|swiftself)}} %113) // CHECK-NEXT: %116 = call i1 @"{{.*}}/runtime/internal/runtime.StringEqual"(%"{{.*}}/runtime/internal/runtime.String" %115, %"{{.*}}/runtime/internal/runtime.String" { ptr @0, i64 3 }) // CHECK-NEXT: %117 = xor i1 %116, true // CHECK-NEXT: br i1 %117, label %_llgo_15, label %_llgo_16 @@ -403,49 +407,7 @@ func main() { // CHECK-NEXT: unreachable // CHECK-NEXT: } -// CHECK-LABEL: define linkonce i1 @"__llgo_stub.{{.*}}/runtime/internal/runtime.memequal0"(ptr %0, ptr %1, ptr %2){{.*}} { -// CHECK-NEXT: _llgo_0: -// CHECK-NEXT: %3 = tail call i1 @"{{.*}}/runtime/internal/runtime.memequal0"(ptr %1, ptr %2) -// CHECK-NEXT: ret i1 %3 -// CHECK-NEXT: } - -// CHECK-LABEL: define linkonce i64 @"__llgo_stub.main.(*impl).one"(ptr %0, ptr %1){{.*}} { -// CHECK-NEXT: _llgo_0: -// CHECK-NEXT: %2 = tail call i64 @"main.(*impl).one"(ptr %1) -// CHECK-NEXT: ret i64 %2 -// CHECK-NEXT: } - -// CHECK-LABEL: define linkonce i1 @"__llgo_stub.{{.*}}/runtime/internal/runtime.memequal64"(ptr %0, ptr %1, ptr %2){{.*}} { -// CHECK-NEXT: _llgo_0: -// CHECK-NEXT: %3 = tail call i1 @"{{.*}}/runtime/internal/runtime.memequal64"(ptr %1, ptr %2) -// CHECK-NEXT: ret i1 %3 -// CHECK-NEXT: } - -// CHECK-LABEL: define linkonce %"{{.*}}/runtime/internal/runtime.String" @"__llgo_stub.main.(*impl).two"(ptr %0, ptr %1){{.*}} { -// CHECK-NEXT: _llgo_0: -// CHECK-NEXT: %2 = tail call %"{{.*}}/runtime/internal/runtime.String" @"main.(*impl).two"(ptr %1) -// CHECK-NEXT: ret %"{{.*}}/runtime/internal/runtime.String" %2 -// CHECK-NEXT: } - -// CHECK-LABEL: define linkonce i64 @__llgo_stub.main.impl.one(ptr %0, %main.impl %1){{.*}} { -// CHECK-NEXT: _llgo_0: -// CHECK-NEXT: %2 = tail call i64 @main.impl.one(%main.impl %1) -// CHECK-NEXT: ret i64 %2 -// CHECK-NEXT: } - -// CHECK-LABEL: define linkonce %"{{.*}}/runtime/internal/runtime.String" @__llgo_stub.main.impl.two(ptr %0, %main.impl %1){{.*}} { -// CHECK-NEXT: _llgo_0: -// CHECK-NEXT: %2 = tail call %"{{.*}}/runtime/internal/runtime.String" @main.impl.two(%main.impl %1) -// CHECK-NEXT: ret %"{{.*}}/runtime/internal/runtime.String" %2 -// CHECK-NEXT: } - -// CHECK-LABEL: define linkonce i1 @"__llgo_stub.{{.*}}/runtime/internal/runtime.interequal"(ptr %0, ptr %1, ptr %2){{.*}} { -// CHECK-NEXT: _llgo_0: -// CHECK-NEXT: %3 = tail call i1 @"{{.*}}/runtime/internal/runtime.interequal"(ptr %1, ptr %2) -// CHECK-NEXT: ret i1 %3 -// CHECK-NEXT: } - -// CHECK-LABEL: define i64 @"main.I.one$bound"(ptr %0){{.*}} { +// CHECK-LABEL: define i64 @"main.I.one$bound"(ptr {{(nest|swiftself)}} %0){{.*}} { // CHECK-NEXT: _llgo_0: // CHECK-NEXT: %1 = load { %"{{.*}}/runtime/internal/runtime.iface" }, ptr %0, align 8 // CHECK-NEXT: %2 = extractvalue { %"{{.*}}/runtime/internal/runtime.iface" } %1, 0 @@ -461,7 +423,7 @@ func main() { // CHECK-NEXT: ret i64 %11 // CHECK-NEXT: } -// CHECK-LABEL: define %"{{.*}}/runtime/internal/runtime.String" @"main.I.two$bound"(ptr %0){{.*}} { +// CHECK-LABEL: define %"{{.*}}/runtime/internal/runtime.String" @"main.I.two$bound"(ptr {{(nest|swiftself)}} %0){{.*}} { // CHECK-NEXT: _llgo_0: // CHECK-NEXT: %1 = load { %"{{.*}}/runtime/internal/runtime.iface" }, ptr %0, align 8 // CHECK-NEXT: %2 = extractvalue { %"{{.*}}/runtime/internal/runtime.iface" } %1, 0 diff --git a/cl/_testgo/invoke/in.go b/cl/_testgo/invoke/in.go index e48e4ea7f5..22cbccef4e 100644 --- a/cl/_testgo/invoke/in.go +++ b/cl/_testgo/invoke/in.go @@ -270,7 +270,8 @@ type M interface { // CHECK-NEXT: _llgo_0: // CHECK-NEXT: %1 = extractvalue %main.T6 %0, 1 // CHECK-NEXT: %2 = extractvalue %main.T6 %0, 0 -// CHECK-NEXT: %3 = call i64 %2(ptr %1) +// CHECK-NEXT: %__llgo_funcval_code = call ptr asm "", "=r,0"(ptr %2) +// CHECK-NEXT: %3 = call i64 %__llgo_funcval_code(ptr {{(nest|swiftself)}} %1) // CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.PrintString"(%"{{.*}}/runtime/internal/runtime.String" { ptr @12, i64 7 }) // CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.PrintByte"(i8 32) // CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.PrintInt"(i64 %3) @@ -334,7 +335,7 @@ type M interface { // CHECK-NEXT: %8 = getelementptr inbounds %main.T5, ptr %7, i32 0, i32 0 // CHECK-NEXT: store i64 300, ptr %8, align 8 // CHECK-NEXT: %9 = call ptr @"{{.*}}/runtime/internal/runtime.AllocZ"(i64 16) -// CHECK-NEXT: store %main.T6 { ptr @"__llgo_stub.main.main$1", ptr null }, ptr %9, align 8 +// CHECK-NEXT: store %main.T6 { ptr @"main.main$1", ptr null }, ptr %9, align 8 // CHECK-NEXT: %10 = load %main.T, ptr %0, align 8 // CHECK-NEXT: %11 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 16) // CHECK-NEXT: store %main.T %10, ptr %11, align 8 @@ -474,123 +475,3 @@ type M interface { // CHECK-NEXT: _llgo_0: // CHECK-NEXT: ret i64 400 // CHECK-NEXT: } - -// CHECK-LABEL: define linkonce i64 @"__llgo_stub.main.main$1"(ptr %0){{.*}} { -// CHECK-NEXT: _llgo_0: -// CHECK-NEXT: %1 = tail call i64 @"main.main$1"() -// CHECK-NEXT: ret i64 %1 -// CHECK-NEXT: } - -// CHECK-LABEL: define linkonce i64 @"__llgo_stub.main.(*T).Invoke"(ptr %0, ptr %1){{.*}} { -// CHECK-NEXT: _llgo_0: -// CHECK-NEXT: %2 = tail call i64 @"main.(*T).Invoke"(ptr %1) -// CHECK-NEXT: ret i64 %2 -// CHECK-NEXT: } - -// CHECK-LABEL: define linkonce i1 @"__llgo_stub.{{.*}}/runtime/internal/runtime.memequal64"(ptr %0, ptr %1, ptr %2){{.*}} { -// CHECK-NEXT: _llgo_0: -// CHECK-NEXT: %3 = tail call i1 @"{{.*}}/runtime/internal/runtime.memequal64"(ptr %1, ptr %2) -// CHECK-NEXT: ret i1 %3 -// CHECK-NEXT: } - -// CHECK-LABEL: define linkonce void @"__llgo_stub.main.(*T).Method"(ptr %0, ptr %1){{.*}} { -// CHECK-NEXT: _llgo_0: -// CHECK-NEXT: tail call void @"main.(*T).Method"(ptr %1) -// CHECK-NEXT: ret void -// CHECK-NEXT: } - -// CHECK-LABEL: define linkonce i64 @__llgo_stub.main.T.Invoke(ptr %0, %main.T %1){{.*}} { -// CHECK-NEXT: _llgo_0: -// CHECK-NEXT: %2 = tail call i64 @main.T.Invoke(%main.T %1) -// CHECK-NEXT: ret i64 %2 -// CHECK-NEXT: } - -// CHECK-LABEL: define linkonce i1 @"__llgo_stub.{{.*}}/runtime/internal/runtime.interequal"(ptr %0, ptr %1, ptr %2){{.*}} { -// CHECK-NEXT: _llgo_0: -// CHECK-NEXT: %3 = tail call i1 @"{{.*}}/runtime/internal/runtime.interequal"(ptr %1, ptr %2) -// CHECK-NEXT: ret i1 %3 -// CHECK-NEXT: } - -// CHECK-LABEL: define linkonce i64 @"__llgo_stub.main.(*T1).Invoke"(ptr %0, ptr %1){{.*}} { -// CHECK-NEXT: _llgo_0: -// CHECK-NEXT: %2 = tail call i64 @"main.(*T1).Invoke"(ptr %1) -// CHECK-NEXT: ret i64 %2 -// CHECK-NEXT: } - -// CHECK-LABEL: define linkonce i64 @__llgo_stub.main.T1.Invoke(ptr %0, i64 %1){{.*}} { -// CHECK-NEXT: _llgo_0: -// CHECK-NEXT: %2 = tail call i64 @main.T1.Invoke(i64 %1) -// CHECK-NEXT: ret i64 %2 -// CHECK-NEXT: } - -// CHECK-LABEL: define linkonce i1 @"__llgo_stub.{{.*}}/runtime/internal/runtime.f64equal"(ptr %0, ptr %1, ptr %2){{.*}} { -// CHECK-NEXT: _llgo_0: -// CHECK-NEXT: %3 = tail call i1 @"{{.*}}/runtime/internal/runtime.f64equal"(ptr %1, ptr %2) -// CHECK-NEXT: ret i1 %3 -// CHECK-NEXT: } - -// CHECK-LABEL: define linkonce i64 @"__llgo_stub.main.(*T2).Invoke"(ptr %0, ptr %1){{.*}} { -// CHECK-NEXT: _llgo_0: -// CHECK-NEXT: %2 = tail call i64 @"main.(*T2).Invoke"(ptr %1) -// CHECK-NEXT: ret i64 %2 -// CHECK-NEXT: } - -// CHECK-LABEL: define linkonce i64 @__llgo_stub.main.T2.Invoke(ptr %0, double %1){{.*}} { -// CHECK-NEXT: _llgo_0: -// CHECK-NEXT: %2 = tail call i64 @main.T2.Invoke(double %1) -// CHECK-NEXT: ret i64 %2 -// CHECK-NEXT: } - -// CHECK-LABEL: define linkonce i1 @"__llgo_stub.{{.*}}/runtime/internal/runtime.memequal8"(ptr %0, ptr %1, ptr %2){{.*}} { -// CHECK-NEXT: _llgo_0: -// CHECK-NEXT: %3 = tail call i1 @"{{.*}}/runtime/internal/runtime.memequal8"(ptr %1, ptr %2) -// CHECK-NEXT: ret i1 %3 -// CHECK-NEXT: } - -// CHECK-LABEL: define linkonce i64 @"__llgo_stub.main.(*T3).Invoke"(ptr %0, ptr %1){{.*}} { -// CHECK-NEXT: _llgo_0: -// CHECK-NEXT: %2 = tail call i64 @"main.(*T3).Invoke"(ptr %1) -// CHECK-NEXT: ret i64 %2 -// CHECK-NEXT: } - -// CHECK-LABEL: define linkonce i64 @"__llgo_stub.main.(*T4).Invoke"(ptr %0, ptr %1){{.*}} { -// CHECK-NEXT: _llgo_0: -// CHECK-NEXT: %2 = tail call i64 @"main.(*T4).Invoke"(ptr %1) -// CHECK-NEXT: ret i64 %2 -// CHECK-NEXT: } - -// CHECK-LABEL: define linkonce i64 @__llgo_stub.main.T4.Invoke(ptr %0, [1 x i64] %1){{.*}} { -// CHECK-NEXT: _llgo_0: -// CHECK-NEXT: %2 = tail call i64 @main.T4.Invoke([1 x i64] %1) -// CHECK-NEXT: ret i64 %2 -// CHECK-NEXT: } - -// CHECK-LABEL: define linkonce i64 @"__llgo_stub.main.(*T5).Invoke"(ptr %0, ptr %1){{.*}} { -// CHECK-NEXT: _llgo_0: -// CHECK-NEXT: %2 = tail call i64 @"main.(*T5).Invoke"(ptr %1) -// CHECK-NEXT: ret i64 %2 -// CHECK-NEXT: } - -// CHECK-LABEL: define linkonce i64 @__llgo_stub.main.T5.Invoke(ptr %0, %main.T5 %1){{.*}} { -// CHECK-NEXT: _llgo_0: -// CHECK-NEXT: %2 = tail call i64 @main.T5.Invoke(%main.T5 %1) -// CHECK-NEXT: ret i64 %2 -// CHECK-NEXT: } - -// CHECK-LABEL: define linkonce i64 @"__llgo_stub.main.(*T6).Invoke"(ptr %0, ptr %1){{.*}} { -// CHECK-NEXT: _llgo_0: -// CHECK-NEXT: %2 = tail call i64 @"main.(*T6).Invoke"(ptr %1) -// CHECK-NEXT: ret i64 %2 -// CHECK-NEXT: } - -// CHECK-LABEL: define linkonce i64 @__llgo_stub.main.T6.Invoke(ptr %0, %main.T6 %1){{.*}} { -// CHECK-NEXT: _llgo_0: -// CHECK-NEXT: %2 = tail call i64 @main.T6.Invoke(%main.T6 %1) -// CHECK-NEXT: ret i64 %2 -// CHECK-NEXT: } - -// CHECK-LABEL: define linkonce i1 @"__llgo_stub.{{.*}}/runtime/internal/runtime.nilinterequal"(ptr %0, ptr %1, ptr %2){{.*}} { -// CHECK-NEXT: _llgo_0: -// CHECK-NEXT: %3 = tail call i1 @"{{.*}}/runtime/internal/runtime.nilinterequal"(ptr %1, ptr %2) -// CHECK-NEXT: ret i1 %3 -// CHECK-NEXT: } diff --git a/cl/_testgo/reader/in.go b/cl/_testgo/reader/in.go index bf9d1c0934..2fd463b8a6 100644 --- a/cl/_testgo/reader/in.go +++ b/cl/_testgo/reader/in.go @@ -1132,147 +1132,3 @@ func main() { // CHECK-NEXT: %39 = call i1 @"{{.*}}/runtime/internal/runtime.EfaceEqual"(%"{{.*}}/runtime/internal/runtime.eface" %35, %"{{.*}}/runtime/internal/runtime.eface" %38) // CHECK-NEXT: br i1 %39, label %_llgo_5, label %_llgo_6 // CHECK-NEXT: } - -// CHECK-LABEL: define linkonce i1 @"__llgo_stub.{{.*}}/runtime/internal/runtime.interequal"(ptr %0, ptr %1, ptr %2){{.*}} { -// CHECK-NEXT: _llgo_0: -// CHECK-NEXT: %3 = tail call i1 @"{{.*}}/runtime/internal/runtime.interequal"(ptr %1, ptr %2) -// CHECK-NEXT: ret i1 %3 -// CHECK-NEXT: } - -// CHECK-LABEL: define linkonce i1 @"__llgo_stub.{{.*}}/runtime/internal/runtime.memequal8"(ptr %0, ptr %1, ptr %2){{.*}} { -// CHECK-NEXT: _llgo_0: -// CHECK-NEXT: %3 = tail call i1 @"{{.*}}/runtime/internal/runtime.memequal8"(ptr %1, ptr %2) -// CHECK-NEXT: ret i1 %3 -// CHECK-NEXT: } - -// CHECK-LABEL: define linkonce i1 @"__llgo_stub.{{.*}}/runtime/internal/runtime.memequal64"(ptr %0, ptr %1, ptr %2){{.*}} { -// CHECK-NEXT: _llgo_0: -// CHECK-NEXT: %3 = tail call i1 @"{{.*}}/runtime/internal/runtime.memequal64"(ptr %1, ptr %2) -// CHECK-NEXT: ret i1 %3 -// CHECK-NEXT: } - -// CHECK-LABEL: define linkonce %"{{.*}}/runtime/internal/runtime.iface" @"__llgo_stub.main.(*nopCloserWriterTo).Close"(ptr %0, ptr %1){{.*}} { -// CHECK-NEXT: _llgo_0: -// CHECK-NEXT: %2 = tail call %"{{.*}}/runtime/internal/runtime.iface" @"main.(*nopCloserWriterTo).Close"(ptr %1) -// CHECK-NEXT: ret %"{{.*}}/runtime/internal/runtime.iface" %2 -// CHECK-NEXT: } - -// CHECK-LABEL: define linkonce { i64, %"{{.*}}/runtime/internal/runtime.iface" } @"__llgo_stub.main.(*nopCloserWriterTo).Read"(ptr %0, ptr %1, %"{{.*}}/runtime/internal/runtime.Slice" %2){{.*}} { -// CHECK-NEXT: _llgo_0: -// CHECK-NEXT: %3 = tail call { i64, %"{{.*}}/runtime/internal/runtime.iface" } @"main.(*nopCloserWriterTo).Read"(ptr %1, %"{{.*}}/runtime/internal/runtime.Slice" %2) -// CHECK-NEXT: ret { i64, %"{{.*}}/runtime/internal/runtime.iface" } %3 -// CHECK-NEXT: } - -// CHECK-LABEL: define linkonce { i64, %"{{.*}}/runtime/internal/runtime.iface" } @"__llgo_stub.main.(*nopCloserWriterTo).WriteTo"(ptr %0, ptr %1, %"{{.*}}/runtime/internal/runtime.iface" %2){{.*}} { -// CHECK-NEXT: _llgo_0: -// CHECK-NEXT: %3 = tail call { i64, %"{{.*}}/runtime/internal/runtime.iface" } @"main.(*nopCloserWriterTo).WriteTo"(ptr %1, %"{{.*}}/runtime/internal/runtime.iface" %2) -// CHECK-NEXT: ret { i64, %"{{.*}}/runtime/internal/runtime.iface" } %3 -// CHECK-NEXT: } - -// CHECK-LABEL: define linkonce %"{{.*}}/runtime/internal/runtime.iface" @__llgo_stub.main.nopCloserWriterTo.Close(ptr %0, %main.nopCloserWriterTo %1){{.*}} { -// CHECK-NEXT: _llgo_0: -// CHECK-NEXT: %2 = tail call %"{{.*}}/runtime/internal/runtime.iface" @main.nopCloserWriterTo.Close(%main.nopCloserWriterTo %1) -// CHECK-NEXT: ret %"{{.*}}/runtime/internal/runtime.iface" %2 -// CHECK-NEXT: } - -// CHECK-LABEL: define linkonce { i64, %"{{.*}}/runtime/internal/runtime.iface" } @__llgo_stub.main.nopCloserWriterTo.Read(ptr %0, %main.nopCloserWriterTo %1, %"{{.*}}/runtime/internal/runtime.Slice" %2){{.*}} { -// CHECK-NEXT: _llgo_0: -// CHECK-NEXT: %3 = tail call { i64, %"{{.*}}/runtime/internal/runtime.iface" } @main.nopCloserWriterTo.Read(%main.nopCloserWriterTo %1, %"{{.*}}/runtime/internal/runtime.Slice" %2) -// CHECK-NEXT: ret { i64, %"{{.*}}/runtime/internal/runtime.iface" } %3 -// CHECK-NEXT: } - -// CHECK-LABEL: define linkonce { i64, %"{{.*}}/runtime/internal/runtime.iface" } @__llgo_stub.main.nopCloserWriterTo.WriteTo(ptr %0, %main.nopCloserWriterTo %1, %"{{.*}}/runtime/internal/runtime.iface" %2){{.*}} { -// CHECK-NEXT: _llgo_0: -// CHECK-NEXT: %3 = tail call { i64, %"{{.*}}/runtime/internal/runtime.iface" } @main.nopCloserWriterTo.WriteTo(%main.nopCloserWriterTo %1, %"{{.*}}/runtime/internal/runtime.iface" %2) -// CHECK-NEXT: ret { i64, %"{{.*}}/runtime/internal/runtime.iface" } %3 -// CHECK-NEXT: } - -// CHECK-LABEL: define linkonce %"{{.*}}/runtime/internal/runtime.iface" @"__llgo_stub.main.(*nopCloser).Close"(ptr %0, ptr %1){{.*}} { -// CHECK-NEXT: _llgo_0: -// CHECK-NEXT: %2 = tail call %"{{.*}}/runtime/internal/runtime.iface" @"main.(*nopCloser).Close"(ptr %1) -// CHECK-NEXT: ret %"{{.*}}/runtime/internal/runtime.iface" %2 -// CHECK-NEXT: } - -// CHECK-LABEL: define linkonce { i64, %"{{.*}}/runtime/internal/runtime.iface" } @"__llgo_stub.main.(*nopCloser).Read"(ptr %0, ptr %1, %"{{.*}}/runtime/internal/runtime.Slice" %2){{.*}} { -// CHECK-NEXT: _llgo_0: -// CHECK-NEXT: %3 = tail call { i64, %"{{.*}}/runtime/internal/runtime.iface" } @"main.(*nopCloser).Read"(ptr %1, %"{{.*}}/runtime/internal/runtime.Slice" %2) -// CHECK-NEXT: ret { i64, %"{{.*}}/runtime/internal/runtime.iface" } %3 -// CHECK-NEXT: } - -// CHECK-LABEL: define linkonce %"{{.*}}/runtime/internal/runtime.iface" @__llgo_stub.main.nopCloser.Close(ptr %0, %main.nopCloser %1){{.*}} { -// CHECK-NEXT: _llgo_0: -// CHECK-NEXT: %2 = tail call %"{{.*}}/runtime/internal/runtime.iface" @main.nopCloser.Close(%main.nopCloser %1) -// CHECK-NEXT: ret %"{{.*}}/runtime/internal/runtime.iface" %2 -// CHECK-NEXT: } - -// CHECK-LABEL: define linkonce { i64, %"{{.*}}/runtime/internal/runtime.iface" } @__llgo_stub.main.nopCloser.Read(ptr %0, %main.nopCloser %1, %"{{.*}}/runtime/internal/runtime.Slice" %2){{.*}} { -// CHECK-NEXT: _llgo_0: -// CHECK-NEXT: %3 = tail call { i64, %"{{.*}}/runtime/internal/runtime.iface" } @main.nopCloser.Read(%main.nopCloser %1, %"{{.*}}/runtime/internal/runtime.Slice" %2) -// CHECK-NEXT: ret { i64, %"{{.*}}/runtime/internal/runtime.iface" } %3 -// CHECK-NEXT: } - -// CHECK-LABEL: define linkonce i64 @"__llgo_stub.main.(*stringReader).Len"(ptr %0, ptr %1){{.*}} { -// CHECK-NEXT: _llgo_0: -// CHECK-NEXT: %2 = tail call i64 @"main.(*stringReader).Len"(ptr %1) -// CHECK-NEXT: ret i64 %2 -// CHECK-NEXT: } - -// CHECK-LABEL: define linkonce { i64, %"{{.*}}/runtime/internal/runtime.iface" } @"__llgo_stub.main.(*stringReader).Read"(ptr %0, ptr %1, %"{{.*}}/runtime/internal/runtime.Slice" %2){{.*}} { -// CHECK-NEXT: _llgo_0: -// CHECK-NEXT: %3 = tail call { i64, %"{{.*}}/runtime/internal/runtime.iface" } @"main.(*stringReader).Read"(ptr %1, %"{{.*}}/runtime/internal/runtime.Slice" %2) -// CHECK-NEXT: ret { i64, %"{{.*}}/runtime/internal/runtime.iface" } %3 -// CHECK-NEXT: } - -// CHECK-LABEL: define linkonce { i64, %"{{.*}}/runtime/internal/runtime.iface" } @"__llgo_stub.main.(*stringReader).ReadAt"(ptr %0, ptr %1, %"{{.*}}/runtime/internal/runtime.Slice" %2, i64 %3){{.*}} { -// CHECK-NEXT: _llgo_0: -// CHECK-NEXT: %4 = tail call { i64, %"{{.*}}/runtime/internal/runtime.iface" } @"main.(*stringReader).ReadAt"(ptr %1, %"{{.*}}/runtime/internal/runtime.Slice" %2, i64 %3) -// CHECK-NEXT: ret { i64, %"{{.*}}/runtime/internal/runtime.iface" } %4 -// CHECK-NEXT: } - -// CHECK-LABEL: define linkonce { i8, %"{{.*}}/runtime/internal/runtime.iface" } @"__llgo_stub.main.(*stringReader).ReadByte"(ptr %0, ptr %1){{.*}} { -// CHECK-NEXT: _llgo_0: -// CHECK-NEXT: %2 = tail call { i8, %"{{.*}}/runtime/internal/runtime.iface" } @"main.(*stringReader).ReadByte"(ptr %1) -// CHECK-NEXT: ret { i8, %"{{.*}}/runtime/internal/runtime.iface" } %2 -// CHECK-NEXT: } - -// CHECK-LABEL: define linkonce { i32, i64, %"{{.*}}/runtime/internal/runtime.iface" } @"__llgo_stub.main.(*stringReader).ReadRune"(ptr %0, ptr %1){{.*}} { -// CHECK-NEXT: _llgo_0: -// CHECK-NEXT: %2 = tail call { i32, i64, %"{{.*}}/runtime/internal/runtime.iface" } @"main.(*stringReader).ReadRune"(ptr %1) -// CHECK-NEXT: ret { i32, i64, %"{{.*}}/runtime/internal/runtime.iface" } %2 -// CHECK-NEXT: } - -// CHECK-LABEL: define linkonce { i64, %"{{.*}}/runtime/internal/runtime.iface" } @"__llgo_stub.main.(*stringReader).Seek"(ptr %0, ptr %1, i64 %2, i64 %3){{.*}} { -// CHECK-NEXT: _llgo_0: -// CHECK-NEXT: %4 = tail call { i64, %"{{.*}}/runtime/internal/runtime.iface" } @"main.(*stringReader).Seek"(ptr %1, i64 %2, i64 %3) -// CHECK-NEXT: ret { i64, %"{{.*}}/runtime/internal/runtime.iface" } %4 -// CHECK-NEXT: } - -// CHECK-LABEL: define linkonce i64 @"__llgo_stub.main.(*stringReader).Size"(ptr %0, ptr %1){{.*}} { -// CHECK-NEXT: _llgo_0: -// CHECK-NEXT: %2 = tail call i64 @"main.(*stringReader).Size"(ptr %1) -// CHECK-NEXT: ret i64 %2 -// CHECK-NEXT: } - -// CHECK-LABEL: define linkonce %"{{.*}}/runtime/internal/runtime.iface" @"__llgo_stub.main.(*stringReader).UnreadByte"(ptr %0, ptr %1){{.*}} { -// CHECK-NEXT: _llgo_0: -// CHECK-NEXT: %2 = tail call %"{{.*}}/runtime/internal/runtime.iface" @"main.(*stringReader).UnreadByte"(ptr %1) -// CHECK-NEXT: ret %"{{.*}}/runtime/internal/runtime.iface" %2 -// CHECK-NEXT: } - -// CHECK-LABEL: define linkonce %"{{.*}}/runtime/internal/runtime.iface" @"__llgo_stub.main.(*stringReader).UnreadRune"(ptr %0, ptr %1){{.*}} { -// CHECK-NEXT: _llgo_0: -// CHECK-NEXT: %2 = tail call %"{{.*}}/runtime/internal/runtime.iface" @"main.(*stringReader).UnreadRune"(ptr %1) -// CHECK-NEXT: ret %"{{.*}}/runtime/internal/runtime.iface" %2 -// CHECK-NEXT: } - -// CHECK-LABEL: define linkonce { i64, %"{{.*}}/runtime/internal/runtime.iface" } @"__llgo_stub.main.(*stringReader).WriteTo"(ptr %0, ptr %1, %"{{.*}}/runtime/internal/runtime.iface" %2){{.*}} { -// CHECK-NEXT: _llgo_0: -// CHECK-NEXT: %3 = tail call { i64, %"{{.*}}/runtime/internal/runtime.iface" } @"main.(*stringReader).WriteTo"(ptr %1, %"{{.*}}/runtime/internal/runtime.iface" %2) -// CHECK-NEXT: ret { i64, %"{{.*}}/runtime/internal/runtime.iface" } %3 -// CHECK-NEXT: } - -// CHECK-LABEL: define linkonce %"{{.*}}/runtime/internal/runtime.String" @"__llgo_stub.main.(*errorString).Error"(ptr %0, ptr %1){{.*}} { -// CHECK-NEXT: _llgo_0: -// CHECK-NEXT: %2 = tail call %"{{.*}}/runtime/internal/runtime.String" @"main.(*errorString).Error"(ptr %1) -// CHECK-NEXT: ret %"{{.*}}/runtime/internal/runtime.String" %2 -// CHECK-NEXT: } diff --git a/cl/_testgo/reflect/in.go b/cl/_testgo/reflect/in.go index ea6dd78c61..8110cc7a0f 100644 --- a/cl/_testgo/reflect/in.go +++ b/cl/_testgo/reflect/in.go @@ -168,7 +168,8 @@ type T struct { // CHECK-NEXT: _llgo_2: ; preds = %_llgo_5 // CHECK-NEXT: %39 = extractvalue { ptr, ptr } %47, 1 // CHECK-NEXT: %40 = extractvalue { ptr, ptr } %47, 0 -// CHECK-NEXT: %41 = call i64 %40(ptr %39, i64 100) +// CHECK-NEXT: %__llgo_funcval_code = call ptr asm "", "=r,0"(ptr %40) +// CHECK-NEXT: %41 = call i64 %__llgo_funcval_code(ptr {{(nest|swiftself)}} %39, i64 100) // CHECK-NEXT: ret void // CHECK-EMPTY: // CHECK-NEXT: _llgo_3: ; preds = %_llgo_0 @@ -188,7 +189,7 @@ type T struct { // CHECK-NEXT: br i1 %48, label %_llgo_2, label %_llgo_1 // CHECK-NEXT: } -// CHECK-LABEL: define i64 @"main.callClosure$1"(ptr %0, i64 %1){{.*}} { +// CHECK-LABEL: define i64 @"main.callClosure$1"(ptr {{(nest|swiftself)}} %0, i64 %1){{.*}} { // CHECK-NEXT: _llgo_0: // CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.PrintString"(%"{{.*}}/runtime/internal/runtime.String" { ptr @9, i64 12 }) // CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.PrintByte"(i8 10) @@ -203,7 +204,7 @@ type T struct { // CHECK-LABEL: define void @main.callFunc(){{.*}} { // CHECK-NEXT: _llgo_0: // CHECK-NEXT: %0 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 16) -// CHECK-NEXT: store { ptr, ptr } { ptr @"__llgo_stub.main.callFunc$1", ptr null }, ptr %0, align 8 +// CHECK-NEXT: store { ptr, ptr } { ptr @"main.callFunc$1", ptr null }, ptr %0, align 8 // CHECK-NEXT: %1 = insertvalue %"{{.*}}/runtime/internal/runtime.eface" { ptr @"_llgo_closure${{[-A-Za-z0-9_]+}}", ptr undef }, ptr %0, 1 // CHECK-NEXT: %2 = call %reflect.Value @reflect.ValueOf(%"{{.*}}/runtime/internal/runtime.eface" %1) // CHECK-NEXT: %3 = call i64 @reflect.Value.Kind(%reflect.Value %2) @@ -259,7 +260,8 @@ type T struct { // CHECK-NEXT: _llgo_2: ; preds = %_llgo_5 // CHECK-NEXT: %35 = extractvalue { ptr, ptr } %43, 1 // CHECK-NEXT: %36 = extractvalue { ptr, ptr } %43, 0 -// CHECK-NEXT: %37 = call i64 %36(ptr %35, i64 100) +// CHECK-NEXT: %__llgo_funcval_code = call ptr asm "", "=r,0"(ptr %36) +// CHECK-NEXT: %37 = call i64 %__llgo_funcval_code(ptr {{(nest|swiftself)}} %35, i64 100) // CHECK-NEXT: ret void // CHECK-EMPTY: // CHECK-NEXT: _llgo_3: ; preds = %_llgo_0 @@ -386,7 +388,8 @@ func callMethod() { // CHECK-NEXT: _llgo_2: ; preds = %_llgo_5 // CHECK-NEXT: %43 = extractvalue { ptr, ptr } %69, 1 // CHECK-NEXT: %44 = extractvalue { ptr, ptr } %69, 0 -// CHECK-NEXT: %45 = call i64 %44(ptr %43, i64 1) +// CHECK-NEXT: %__llgo_funcval_code = call ptr asm "", "=r,0"(ptr %44) +// CHECK-NEXT: %45 = call i64 %__llgo_funcval_code(ptr {{(nest|swiftself)}} %43, i64 1) // CHECK-NEXT: %46 = call %"{{.*}}/runtime/internal/runtime.eface" @reflect.Value.Interface(%reflect.Value %10) // CHECK-NEXT: %47 = call %reflect.Value @reflect.ValueOf(%"{{.*}}/runtime/internal/runtime.eface" %46) // CHECK-NEXT: %48 = call ptr @"{{.*}}/runtime/internal/runtime.AllocZ"(i64 24) @@ -490,7 +493,8 @@ func callMethod() { // CHECK-NEXT: _llgo_2: ; preds = %_llgo_5 // CHECK-NEXT: %37 = extractvalue { ptr, ptr } %63, 1 // CHECK-NEXT: %38 = extractvalue { ptr, ptr } %63, 0 -// CHECK-NEXT: %39 = call i64 %38(ptr %37, i64 1) +// CHECK-NEXT: %__llgo_funcval_code = call ptr asm "", "=r,0"(ptr %38) +// CHECK-NEXT: %39 = call i64 %__llgo_funcval_code(ptr {{(nest|swiftself)}} %37, i64 1) // CHECK-NEXT: %40 = call %"{{.*}}/runtime/internal/runtime.eface" @reflect.Value.Interface(%reflect.Value %4) // CHECK-NEXT: %41 = call %reflect.Value @reflect.ValueOf(%"{{.*}}/runtime/internal/runtime.eface" %40) // CHECK-NEXT: %42 = call ptr @"{{.*}}/runtime/internal/runtime.AllocZ"(i64 24) @@ -536,7 +540,7 @@ func callMethod() { // CHECK-LABEL: define void @main.callSlice(){{.*}} { // CHECK-NEXT: _llgo_0: // CHECK-NEXT: %0 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 16) -// CHECK-NEXT: store { ptr, ptr } { ptr @__llgo_stub.main.demo, ptr null }, ptr %0, align 8 +// CHECK-NEXT: store { ptr, ptr } { ptr @main.demo, ptr null }, ptr %0, align 8 // CHECK-NEXT: %1 = insertvalue %"{{.*}}/runtime/internal/runtime.eface" { ptr @"_llgo_closure${{[-A-Za-z0-9_]+}}", ptr undef }, ptr %0, 1 // CHECK-NEXT: %2 = call %reflect.Value @reflect.ValueOf(%"{{.*}}/runtime/internal/runtime.eface" %1) // CHECK-NEXT: %3 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 8) @@ -1145,45 +1149,3 @@ func mapDemo2() { } } } - -// CHECK-LABEL: define linkonce i1 @"__llgo_stub.{{.*}}/runtime/internal/runtime.memequal64"(ptr %0, ptr %1, ptr %2){{.*}} { -// CHECK-NEXT: _llgo_0: -// CHECK-NEXT: %3 = tail call i1 @"{{.*}}/runtime/internal/runtime.memequal64"(ptr %1, ptr %2) -// CHECK-NEXT: ret i1 %3 -// CHECK-NEXT: } - -// CHECK-LABEL: define linkonce i64 @"__llgo_stub.main.callFunc$1"(ptr %0, i64 %1){{.*}} { -// CHECK-NEXT: _llgo_0: -// CHECK-NEXT: %2 = tail call i64 @"main.callFunc$1"(i64 %1) -// CHECK-NEXT: ret i64 %2 -// CHECK-NEXT: } - -// CHECK-LABEL: define linkonce i64 @"__llgo_stub.main.(*T).Add"(ptr %0, ptr %1, i64 %2){{.*}} { -// CHECK-NEXT: _llgo_0: -// CHECK-NEXT: %3 = tail call i64 @"main.(*T).Add"(ptr %1, i64 %2) -// CHECK-NEXT: ret i64 %3 -// CHECK-NEXT: } - -// CHECK-LABEL: define linkonce i1 @"__llgo_stub.{{.*}}/runtime/internal/runtime.interequal"(ptr %0, ptr %1, ptr %2){{.*}} { -// CHECK-NEXT: _llgo_0: -// CHECK-NEXT: %3 = tail call i1 @"{{.*}}/runtime/internal/runtime.interequal"(ptr %1, ptr %2) -// CHECK-NEXT: ret i1 %3 -// CHECK-NEXT: } - -// CHECK-LABEL: define linkonce { i64, i64 } @__llgo_stub.main.demo(ptr %0, i64 %1, i64 %2, i64 %3, i64 %4, i64 %5, i64 %6, i64 %7, i64 %8, i64 %9, %"{{.*}}/runtime/internal/runtime.Slice" %10){{.*}} { -// CHECK-NEXT: _llgo_0: -// CHECK-NEXT: %11 = tail call { i64, i64 } @main.demo(i64 %1, i64 %2, i64 %3, i64 %4, i64 %5, i64 %6, i64 %7, i64 %8, i64 %9, %"{{.*}}/runtime/internal/runtime.Slice" %10) -// CHECK-NEXT: ret { i64, i64 } %11 -// CHECK-NEXT: } - -// CHECK-LABEL: define linkonce i1 @"__llgo_stub.{{.*}}/runtime/internal/runtime.nilinterequal"(ptr %0, ptr %1, ptr %2){{.*}} { -// CHECK-NEXT: _llgo_0: -// CHECK-NEXT: %3 = tail call i1 @"{{.*}}/runtime/internal/runtime.nilinterequal"(ptr %1, ptr %2) -// CHECK-NEXT: ret i1 %3 -// CHECK-NEXT: } - -// CHECK-LABEL: define linkonce i1 @"__llgo_stub.{{.*}}/runtime/internal/runtime.memequal8"(ptr %0, ptr %1, ptr %2){{.*}} { -// CHECK-NEXT: _llgo_0: -// CHECK-NEXT: %3 = tail call i1 @"{{.*}}/runtime/internal/runtime.memequal8"(ptr %1, ptr %2) -// CHECK-NEXT: ret i1 %3 -// CHECK-NEXT: } diff --git a/cl/_testgo/reflectfn/in.go b/cl/_testgo/reflectfn/in.go index d61921ad6c..e535767eea 100644 --- a/cl/_testgo/reflectfn/in.go +++ b/cl/_testgo/reflectfn/in.go @@ -37,7 +37,7 @@ func demo() { // CHECK-NEXT: %12 = call ptr @"{{.*}}/runtime/internal/runtime.AllocZ"(i64 16) // CHECK-NEXT: %13 = getelementptr inbounds %"{{.*}}/runtime/internal/runtime.eface", ptr %12, i64 0 // CHECK-NEXT: %14 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 16) -// CHECK-NEXT: store { ptr, ptr } { ptr @__llgo_stub.main.demo, ptr null }, ptr %14, align 8 +// CHECK-NEXT: store { ptr, ptr } { ptr @main.demo, ptr null }, ptr %14, align 8 // CHECK-NEXT: %15 = insertvalue %"{{.*}}/runtime/internal/runtime.eface" { ptr @"_llgo_closure${{[-A-Za-z0-9_]+}}", ptr undef }, ptr %14, 1 // CHECK-NEXT: store %"{{.*}}/runtime/internal/runtime.eface" %15, ptr %13, align 8 // CHECK-NEXT: %16 = insertvalue %"{{.*}}/runtime/internal/runtime.Slice" undef, ptr %12, 0 @@ -47,7 +47,7 @@ func demo() { // CHECK-NEXT: %20 = call ptr @"{{.*}}/runtime/internal/runtime.AllocZ"(i64 16) // CHECK-NEXT: %21 = getelementptr inbounds %"{{.*}}/runtime/internal/runtime.eface", ptr %20, i64 0 // CHECK-NEXT: %22 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 16) -// CHECK-NEXT: store { ptr, ptr } { ptr @__llgo_stub.main.demo, ptr null }, ptr %22, align 8 +// CHECK-NEXT: store { ptr, ptr } { ptr @main.demo, ptr null }, ptr %22, align 8 // CHECK-NEXT: %23 = insertvalue %"{{.*}}/runtime/internal/runtime.eface" { ptr @"_llgo_closure${{[-A-Za-z0-9_]+}}", ptr undef }, ptr %22, 1 // CHECK-NEXT: store %"{{.*}}/runtime/internal/runtime.eface" %23, ptr %21, align 8 // CHECK-NEXT: %24 = insertvalue %"{{.*}}/runtime/internal/runtime.Slice" undef, ptr %20, 0 @@ -68,7 +68,7 @@ func demo() { // CHECK-NEXT: %37 = insertvalue %"{{.*}}/runtime/internal/runtime.Slice" %36, i64 1, 2 // CHECK-NEXT: %38 = call { i64, %"{{.*}}/runtime/internal/runtime.iface" } @fmt.Println(%"{{.*}}/runtime/internal/runtime.Slice" %37) // CHECK-NEXT: %39 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 16) -// CHECK-NEXT: store { ptr, ptr } { ptr @__llgo_stub.main.demo, ptr null }, ptr %39, align 8 +// CHECK-NEXT: store { ptr, ptr } { ptr @main.demo, ptr null }, ptr %39, align 8 // CHECK-NEXT: %40 = insertvalue %"{{.*}}/runtime/internal/runtime.eface" { ptr @"_llgo_closure${{[-A-Za-z0-9_]+}}", ptr undef }, ptr %39, 1 // CHECK-NEXT: %41 = call %reflect.Value @reflect.ValueOf(%"{{.*}}/runtime/internal/runtime.eface" %40) // CHECK-NEXT: %42 = call ptr @reflect.Value.UnsafePointer(%reflect.Value %41) @@ -81,7 +81,7 @@ func demo() { // CHECK-NEXT: %48 = insertvalue %"{{.*}}/runtime/internal/runtime.Slice" %47, i64 1, 2 // CHECK-NEXT: %49 = call { i64, %"{{.*}}/runtime/internal/runtime.iface" } @fmt.Println(%"{{.*}}/runtime/internal/runtime.Slice" %48) // CHECK-NEXT: %50 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 16) -// CHECK-NEXT: store { ptr, ptr } { ptr @__llgo_stub.main.demo, ptr null }, ptr %50, align 8 +// CHECK-NEXT: store { ptr, ptr } { ptr @main.demo, ptr null }, ptr %50, align 8 // CHECK-NEXT: %51 = insertvalue %"{{.*}}/runtime/internal/runtime.eface" { ptr @"_llgo_closure${{[-A-Za-z0-9_]+}}", ptr undef }, ptr %50, 1 // CHECK-NEXT: %52 = call %reflect.Value @reflect.ValueOf(%"{{.*}}/runtime/internal/runtime.eface" %51) // CHECK-NEXT: %53 = call ptr @reflect.Value.UnsafePointer(%reflect.Value %52) diff --git a/cl/_testgo/reflectmk/in.go b/cl/_testgo/reflectmk/in.go index 0e82f3c1db..46d854fbe2 100644 --- a/cl/_testgo/reflectmk/in.go +++ b/cl/_testgo/reflectmk/in.go @@ -621,9 +621,3 @@ func methodByName(name string) { // CHECK-NEXT: _llgo_2: ; preds = %_llgo_0 // CHECK-NEXT: ret void // CHECK-NEXT: } - -// CHECK-LABEL: define linkonce i1 @"__llgo_stub.{{.*}}/runtime/internal/runtime.memequal64"(ptr %0, ptr %1, ptr %2){{.*}} { -// CHECK-NEXT: _llgo_0: -// CHECK-NEXT: %3 = tail call i1 @"{{.*}}/runtime/internal/runtime.memequal64"(ptr %1, ptr %2) -// CHECK-NEXT: ret i1 %3 -// CHECK-NEXT: } diff --git a/cl/_testgo/reflectmkfn/in.go b/cl/_testgo/reflectmkfn/in.go index 5eb20a2d62..60d5c06c0e 100644 --- a/cl/_testgo/reflectmkfn/in.go +++ b/cl/_testgo/reflectmkfn/in.go @@ -11,7 +11,8 @@ import ( // CHECK: call %reflect.Value @reflect.MakeFunc( // CHECK: call %"g{{.*}}/runtime/internal/runtime.eface" @reflect.Value.Interface( // CHECK: call i1 @"g{{.*}}/runtime/internal/runtime.MatchesClosure"( -// CHECK: call %"g{{.*}}/runtime/internal/runtime.String" %{{.*}}(ptr %{{.*}}, %"g{{.*}}/runtime/internal/runtime.String" { ptr @{{.*}}, i64 3 }, i64 2) +// CHECK: call ptr asm "", "=r,0"(ptr %{{.*}}) +// CHECK-NEXT: call %"g{{.*}}/runtime/internal/runtime.String" %{{.*}}(ptr {{(nest|swiftself)}} %{{.*}}, %"g{{.*}}/runtime/internal/runtime.String" { ptr @{{.*}}, i64 3 }, i64 2) // CHECK: call i1 @"g{{.*}}/runtime/internal/runtime.StringEqual"( func main() { typ := reflect.FuncOf([]reflect.Type{reflect.TypeOf(""), reflect.TypeOf(0)}, []reflect.Type{reflect.TypeOf("")}, false) diff --git a/cl/_testgo/selects/in.go b/cl/_testgo/selects/in.go index 2f90335132..a271116251 100644 --- a/cl/_testgo/selects/in.go +++ b/cl/_testgo/selects/in.go @@ -149,7 +149,7 @@ func main() { // CHECK-NEXT: unreachable // CHECK-NEXT: } -// CHECK-LABEL: define void @"main.main$1"(ptr %0){{.*}} { +// CHECK-LABEL: define void @"main.main$1"(ptr {{(nest|swiftself)}} %0){{.*}} { // CHECK-NEXT: _llgo_0: // CHECK-NEXT: %1 = load { ptr, ptr, ptr }, ptr %0, align 8 // CHECK-NEXT: %2 = extractvalue { ptr, ptr, ptr } %1, 0 @@ -235,6 +235,7 @@ func main() { // CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.FreeRoot"(ptr %0) // CHECK-NEXT: %3 = extractvalue { ptr, ptr } %2, 1 // CHECK-NEXT: %4 = extractvalue { ptr, ptr } %2, 0 -// CHECK-NEXT: call void %4(ptr %3) +// CHECK-NEXT: %__llgo_funcval_code = call ptr asm "", "=r,0"(ptr %4) +// CHECK-NEXT: call void %__llgo_funcval_code(ptr {{(nest|swiftself)}} %3) // CHECK-NEXT: ret ptr null // CHECK-NEXT: } diff --git a/cl/_testgo/tpinst/main.go b/cl/_testgo/tpinst/main.go index fdd41ff1f2..5dc3772151 100644 --- a/cl/_testgo/tpinst/main.go +++ b/cl/_testgo/tpinst/main.go @@ -168,30 +168,6 @@ func (pt *M[T]) value() T { // CHECK-NEXT: ret i64 %2 // CHECK-NEXT: } -// CHECK-LABEL: define linkonce i1 @"__llgo_stub.{{.*}}/runtime/internal/runtime.memequal64"(ptr %0, ptr %1, ptr %2){{.*}} { -// CHECK-NEXT: _llgo_0: -// CHECK-NEXT: %3 = tail call i1 @"{{.*}}/runtime/internal/runtime.memequal64"(ptr %1, ptr %2) -// CHECK-NEXT: ret i1 %3 -// CHECK-NEXT: } - -// CHECK-LABEL: define linkonce i64 @"__llgo_stub.main.(*M[int]).Value"(ptr %0, ptr %1){{.*}} { -// CHECK-NEXT: _llgo_0: -// CHECK-NEXT: %2 = tail call i64 @"main.(*M[int]).Value"(ptr %1) -// CHECK-NEXT: ret i64 %2 -// CHECK-NEXT: } - -// CHECK-LABEL: define linkonce i64 @"__llgo_stub.main.(*M[int]).value"(ptr %0, ptr %1){{.*}} { -// CHECK-NEXT: _llgo_0: -// CHECK-NEXT: %2 = tail call i64 @"main.(*M[int]).value"(ptr %1) -// CHECK-NEXT: ret i64 %2 -// CHECK-NEXT: } - -// CHECK-LABEL: define linkonce i1 @"__llgo_stub.{{.*}}/runtime/internal/runtime.interequal"(ptr %0, ptr %1, ptr %2){{.*}} { -// CHECK-NEXT: _llgo_0: -// CHECK-NEXT: %3 = tail call i1 @"{{.*}}/runtime/internal/runtime.interequal"(ptr %1, ptr %2) -// CHECK-NEXT: ret i1 %3 -// CHECK-NEXT: } - // CHECK-LABEL: define linkonce double @"main.(*M[float64]).Value"(ptr %0){{.*}} { // CHECK-NEXT: _llgo_0: // CHECK-NEXT: %1 = getelementptr inbounds %"main.M[float64]", ptr %0, i32 0, i32 0 @@ -205,21 +181,3 @@ func (pt *M[T]) value() T { // CHECK-NEXT: %2 = load double, ptr %1, align 8 // CHECK-NEXT: ret double %2 // CHECK-NEXT: } - -// CHECK-LABEL: define linkonce i1 @"__llgo_stub.{{.*}}/runtime/internal/runtime.f64equal"(ptr %0, ptr %1, ptr %2){{.*}} { -// CHECK-NEXT: _llgo_0: -// CHECK-NEXT: %3 = tail call i1 @"{{.*}}/runtime/internal/runtime.f64equal"(ptr %1, ptr %2) -// CHECK-NEXT: ret i1 %3 -// CHECK-NEXT: } - -// CHECK-LABEL: define linkonce double @"__llgo_stub.main.(*M[float64]).Value"(ptr %0, ptr %1){{.*}} { -// CHECK-NEXT: _llgo_0: -// CHECK-NEXT: %2 = tail call double @"main.(*M[float64]).Value"(ptr %1) -// CHECK-NEXT: ret double %2 -// CHECK-NEXT: } - -// CHECK-LABEL: define linkonce double @"__llgo_stub.main.(*M[float64]).value"(ptr %0, ptr %1){{.*}} { -// CHECK-NEXT: _llgo_0: -// CHECK-NEXT: %2 = tail call double @"main.(*M[float64]).value"(ptr %1) -// CHECK-NEXT: ret double %2 -// CHECK-NEXT: } diff --git a/cl/_testgo/tpnamed/in.go b/cl/_testgo/tpnamed/in.go index 856ab7ea4c..ca5a244a08 100644 --- a/cl/_testgo/tpnamed/in.go +++ b/cl/_testgo/tpnamed/in.go @@ -8,14 +8,14 @@ type IO[T any] func() Future[T] // CHECK-LABEL: define %"main.IO[error]" @main.WriteFile(%"{{.*}}/runtime/internal/runtime.String" %0){{.*}} { // CHECK-NEXT: _llgo_0: -// CHECK-NEXT: ret %"main.IO[error]" { ptr @"__llgo_stub.main.WriteFile$1", ptr null } +// CHECK-NEXT: ret %"main.IO[error]" { ptr @"main.WriteFile$1", ptr null } // CHECK-NEXT: } func WriteFile(fileName string) IO[error] { // CHECK-LABEL: define %"main.Future[error]" @"main.WriteFile$1"(){{.*}} { // CHECK-NEXT: _llgo_0: - // CHECK-NEXT: ret %"main.Future[error]" { ptr @"__llgo_stub.main.WriteFile$1$1", ptr null } + // CHECK-NEXT: ret %"main.Future[error]" { ptr @"main.WriteFile$1$1", ptr null } // CHECK-NEXT: } return func() Future[error] { @@ -46,7 +46,7 @@ func WriteFile(fileName string) IO[error] { // CHECK-LABEL: define void @main.main(){{.*}} { // CHECK-NEXT: _llgo_0: -// CHECK-NEXT: %0 = call [0 x i8] @"main.RunIO{{\[\[0\]byte\]}}"(%"main.IO{{\[\[0\]byte\]}}" { ptr @"__llgo_stub.main.main$1", ptr null }) +// CHECK-NEXT: %0 = call [0 x i8] @"main.RunIO{{\[\[0\]byte\]}}"(%"main.IO{{\[\[0\]byte\]}}" { ptr @"main.main$1", ptr null }) // CHECK-NEXT: ret void // CHECK-NEXT: } @@ -54,7 +54,7 @@ func main() { // CHECK-LABEL: define %"main.Future{{\[\[0\]byte\]}}" @"main.main$1"() // CHECK-NEXT: _llgo_0: - // CHECK-NEXT: ret %"main.Future{{\[\[0\]byte\]}}" { ptr @"__llgo_stub.main.main$1$1", ptr null } + // CHECK-NEXT: ret %"main.Future{{\[\[0\]byte\]}}" { ptr @"main.main$1$1", ptr null } // CHECK-NEXT: } RunIO[Void](func() Future[Void] { @@ -74,39 +74,17 @@ func RunIO[T any](call IO[T]) T { return call()() } -// CHECK-LABEL: define linkonce %"main.Future[error]" @"__llgo_stub.main.WriteFile$1"(ptr %0){{.*}} { -// CHECK-NEXT: _llgo_0: -// CHECK-NEXT: %1 = tail call %"main.Future[error]" @"main.WriteFile$1"() -// CHECK-NEXT: ret %"main.Future[error]" %1 -// CHECK-NEXT: } - -// CHECK-LABEL: define linkonce %"{{.*}}/runtime/internal/runtime.iface" @"__llgo_stub.main.WriteFile$1$1"(ptr %0){{.*}} { -// CHECK-NEXT: _llgo_0: -// CHECK-NEXT: %1 = tail call %"{{.*}}/runtime/internal/runtime.iface" @"main.WriteFile$1$1"() -// CHECK-NEXT: ret %"{{.*}}/runtime/internal/runtime.iface" %1 -// CHECK-NEXT: } - -// CHECK-LABEL: define linkonce %"main.Future{{\[\[0\]byte\]}}" @"__llgo_stub.main.main$1"(ptr %0){{.*}} { -// CHECK-NEXT: _llgo_0: -// CHECK-NEXT: %1 = tail call %"main.Future{{\[\[0\]byte\]}}" @"main.main$1"() -// CHECK-NEXT: ret %"main.Future{{\[\[0\]byte\]}}" %1 -// CHECK-NEXT: } - // CHECK-LABEL: define linkonce [0 x i8] @"main.RunIO{{\[\[0\]byte\]}}"(%"main.IO{{\[\[0\]byte\]}}" %0){{.*}} { // CHECK-NEXT: _llgo_0: // CHECK-NEXT: %1 = extractvalue %"main.IO{{\[\[0\]byte\]}}" %0, 1 // CHECK-NEXT: %2 = extractvalue %"main.IO{{\[\[0\]byte\]}}" %0, 0 -// CHECK-NEXT: %3 = call %"main.Future{{\[\[0\]byte\]}}" %2(ptr %1) +// CHECK-NEXT: %__llgo_funcval_code = call ptr asm "", "=r,0"(ptr %2) +// CHECK-NEXT: %3 = call %"main.Future{{\[\[0\]byte\]}}" %__llgo_funcval_code(ptr {{(nest|swiftself)}} %1) // CHECK-NEXT: %4 = extractvalue %"main.Future{{\[\[0\]byte\]}}" %3, 1 // CHECK-NEXT: %5 = extractvalue %"main.Future{{\[\[0\]byte\]}}" %3, 0 // CHECK-NEXT: %6 = icmp eq ptr %5, null // CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.AssertNilDeref"(i1 %6) -// CHECK-NEXT: %7 = call [0 x i8] %5(ptr %4) +// CHECK-NEXT: %__llgo_funcval_code1 = call ptr asm "", "=r,0"(ptr %5) +// CHECK-NEXT: %7 = call [0 x i8] %__llgo_funcval_code1(ptr {{(nest|swiftself)}} %4) // CHECK-NEXT: ret [0 x i8] %7 // CHECK-NEXT: } - -// CHECK-LABEL: define linkonce [0 x i8] @"__llgo_stub.main.main$1$1"(ptr %0){{.*}} { -// CHECK-NEXT: _llgo_0: -// CHECK-NEXT: %1 = tail call [0 x i8] @"main.main$1$1"() -// CHECK-NEXT: ret [0 x i8] %1 -// CHECK-NEXT: } diff --git a/cl/_testgo/tprecur/out.ll b/cl/_testgo/tprecur/out.ll deleted file mode 100644 index 655ecdee11..0000000000 --- a/cl/_testgo/tprecur/out.ll +++ /dev/null @@ -1,147 +0,0 @@ -; ModuleID = 'github.com/goplus/llgo/cl/_testgo/tprecur' -source_filename = "github.com/goplus/llgo/cl/_testgo/tprecur" - -%"github.com/goplus/llgo/runtime/abi.Type" = type { i64, i64, i32, i8, i8, i8, i8, { ptr, ptr }, ptr, %"github.com/goplus/llgo/runtime/internal/runtime.String", ptr } -%"github.com/goplus/llgo/runtime/internal/runtime.String" = type { ptr, i64 } -%"github.com/goplus/llgo/runtime/abi.PtrType" = type { %"github.com/goplus/llgo/runtime/abi.Type", ptr } -%"github.com/goplus/llgo/runtime/internal/runtime.eface" = type { ptr, ptr } -%"github.com/goplus/llgo/runtime/internal/runtime.Slice" = type { ptr, i64, i64 } - -@"github.com/goplus/llgo/cl/_testgo/tprecur.init$guard" = global i1 false, align 1 -@0 = private unnamed_addr constant [5 x i8] c"error", align 1 -@_llgo_string = weak_odr constant %"github.com/goplus/llgo/runtime/abi.Type" { i64 16, i64 8, i32 1749264893, i8 4, i8 8, i8 8, i8 24, { ptr, ptr } { ptr @"__llgo_stub.github.com/goplus/llgo/runtime/internal/runtime.strequal", ptr null }, ptr null, %"github.com/goplus/llgo/runtime/internal/runtime.String" { ptr @1, i64 6 }, ptr @"*_llgo_string" }, align 8 -@1 = private unnamed_addr constant [6 x i8] c"string", align 1 -@"*_llgo_string" = weak_odr constant %"github.com/goplus/llgo/runtime/abi.PtrType" { %"github.com/goplus/llgo/runtime/abi.Type" { i64 8, i64 8, i32 -1323879264, i8 10, i8 8, i8 8, i8 54, { ptr, ptr } { ptr @"__llgo_stub.github.com/goplus/llgo/runtime/internal/runtime.memequalptr", ptr null }, ptr null, %"github.com/goplus/llgo/runtime/internal/runtime.String" { ptr @1, i64 6 }, ptr null }, ptr @_llgo_string }, align 8 - -define void @"github.com/goplus/llgo/cl/_testgo/tprecur.init"() { -_llgo_0: - %0 = load i1, ptr @"github.com/goplus/llgo/cl/_testgo/tprecur.init$guard", align 1 - br i1 %0, label %_llgo_2, label %_llgo_1 - -_llgo_1: ; preds = %_llgo_0 - store i1 true, ptr @"github.com/goplus/llgo/cl/_testgo/tprecur.init$guard", align 1 - br label %_llgo_2 - -_llgo_2: ; preds = %_llgo_1, %_llgo_0 - ret void -} - -define void @"github.com/goplus/llgo/cl/_testgo/tprecur.main"() { -_llgo_0: - call void @"github.com/goplus/llgo/cl/_testgo/tprecur.recursive"() - ret void -} - -define void @"github.com/goplus/llgo/cl/_testgo/tprecur.recursive"() { -_llgo_0: - %0 = call i64 @"github.com/goplus/llgo/cl/_testgo/tprecur.recur1[github.com/goplus/llgo/cl/_testgo/tprecur.T.1.0]"(i64 5) - %1 = icmp ne i64 %0, 110 - br i1 %1, label %_llgo_1, label %_llgo_2 - -_llgo_1: ; preds = %_llgo_0 - %2 = call ptr @"github.com/goplus/llgo/runtime/internal/runtime.AllocU"(i64 16) - store %"github.com/goplus/llgo/runtime/internal/runtime.String" { ptr @0, i64 5 }, ptr %2, align 8 - %3 = insertvalue %"github.com/goplus/llgo/runtime/internal/runtime.eface" { ptr @_llgo_string, ptr undef }, ptr %2, 1 - call void @"github.com/goplus/llgo/runtime/internal/runtime.Panic"(%"github.com/goplus/llgo/runtime/internal/runtime.eface" %3) - unreachable - -_llgo_2: ; preds = %_llgo_0 - ret void -} - -define linkonce i64 @"github.com/goplus/llgo/cl/_testgo/tprecur.recur1[github.com/goplus/llgo/cl/_testgo/tprecur.T.1.0]"(i64 %0) { -_llgo_0: - %1 = icmp eq i64 %0, 0 - br i1 %1, label %_llgo_1, label %_llgo_3 - -_llgo_1: ; preds = %_llgo_3, %_llgo_0 - ret i64 1 - -_llgo_2: ; preds = %_llgo_3 - %2 = sub i64 %0, 1 - %3 = call i64 @"github.com/goplus/llgo/cl/_testgo/tprecur.recur2[github.com/goplus/llgo/cl/_testgo/tprecur.T.1.0]"(i64 %2) - %4 = mul i64 %0, %3 - ret i64 %4 - -_llgo_3: ; preds = %_llgo_0 - %5 = icmp eq i64 %0, 1 - br i1 %5, label %_llgo_1, label %_llgo_2 -} - -declare i1 @"github.com/goplus/llgo/runtime/internal/runtime.strequal"(ptr, ptr) - -define linkonce i1 @"__llgo_stub.github.com/goplus/llgo/runtime/internal/runtime.strequal"(ptr %0, ptr %1, ptr %2) { -_llgo_0: - %3 = tail call i1 @"github.com/goplus/llgo/runtime/internal/runtime.strequal"(ptr %1, ptr %2) - ret i1 %3 -} - -declare i1 @"github.com/goplus/llgo/runtime/internal/runtime.memequalptr"(ptr, ptr) - -define linkonce i1 @"__llgo_stub.github.com/goplus/llgo/runtime/internal/runtime.memequalptr"(ptr %0, ptr %1, ptr %2) { -_llgo_0: - %3 = tail call i1 @"github.com/goplus/llgo/runtime/internal/runtime.memequalptr"(ptr %1, ptr %2) - ret i1 %3 -} - -declare ptr @"github.com/goplus/llgo/runtime/internal/runtime.AllocU"(i64) - -declare void @"github.com/goplus/llgo/runtime/internal/runtime.Panic"(%"github.com/goplus/llgo/runtime/internal/runtime.eface") - -define linkonce i64 @"github.com/goplus/llgo/cl/_testgo/tprecur.recur2[github.com/goplus/llgo/cl/_testgo/tprecur.T.1.0]"(i64 %0) { -_llgo_0: - %1 = call %"github.com/goplus/llgo/runtime/internal/runtime.Slice" @"github.com/goplus/llgo/runtime/internal/runtime.MakeSlice"(i64 %0, i64 %0, i64 8) - %2 = extractvalue %"github.com/goplus/llgo/runtime/internal/runtime.Slice" %1, 1 - br label %_llgo_1 - -_llgo_1: ; preds = %_llgo_2, %_llgo_0 - %3 = phi i64 [ -1, %_llgo_0 ], [ %4, %_llgo_2 ] - %4 = add i64 %3, 1 - %5 = icmp slt i64 %4, %2 - br i1 %5, label %_llgo_2, label %_llgo_3 - -_llgo_2: ; preds = %_llgo_1 - %6 = add i64 %4, 1 - %7 = extractvalue %"github.com/goplus/llgo/runtime/internal/runtime.Slice" %1, 0 - %8 = extractvalue %"github.com/goplus/llgo/runtime/internal/runtime.Slice" %1, 1 - %9 = icmp slt i64 %4, 0 - %10 = icmp uge i64 %4, %8 - %11 = or i1 %10, %9 - call void @"github.com/goplus/llgo/runtime/internal/runtime.AssertIndexRange"(i1 %11) - %12 = getelementptr inbounds i64, ptr %7, i64 %4 - store i64 %6, ptr %12, align 4 - br label %_llgo_1 - -_llgo_3: ; preds = %_llgo_1 - %13 = extractvalue %"github.com/goplus/llgo/runtime/internal/runtime.Slice" %1, 1 - br label %_llgo_4 - -_llgo_4: ; preds = %_llgo_5, %_llgo_3 - %14 = phi i64 [ 0, %_llgo_3 ], [ %25, %_llgo_5 ] - %15 = phi i64 [ -1, %_llgo_3 ], [ %16, %_llgo_5 ] - %16 = add i64 %15, 1 - %17 = icmp slt i64 %16, %13 - br i1 %17, label %_llgo_5, label %_llgo_6 - -_llgo_5: ; preds = %_llgo_4 - %18 = extractvalue %"github.com/goplus/llgo/runtime/internal/runtime.Slice" %1, 0 - %19 = extractvalue %"github.com/goplus/llgo/runtime/internal/runtime.Slice" %1, 1 - %20 = icmp slt i64 %16, 0 - %21 = icmp uge i64 %16, %19 - %22 = or i1 %21, %20 - call void @"github.com/goplus/llgo/runtime/internal/runtime.AssertIndexRange"(i1 %22) - %23 = getelementptr inbounds i64, ptr %18, i64 %16 - %24 = load i64, ptr %23, align 4 - %25 = add i64 %14, %24 - br label %_llgo_4 - -_llgo_6: ; preds = %_llgo_4 - %26 = sub i64 %0, 1 - %27 = call i64 @"github.com/goplus/llgo/cl/_testgo/tprecur.recur1[github.com/goplus/llgo/cl/_testgo/tprecur.T.1.0]"(i64 %26) - %28 = add i64 %14, %27 - ret i64 %28 -} - -declare %"github.com/goplus/llgo/runtime/internal/runtime.Slice" @"github.com/goplus/llgo/runtime/internal/runtime.MakeSlice"(i64, i64, i64) - -declare void @"github.com/goplus/llgo/runtime/internal/runtime.AssertIndexRange"(i1) diff --git a/cl/_testgo/tprecurfn/in.go b/cl/_testgo/tprecurfn/in.go index de9928916d..c8e20a4707 100644 --- a/cl/_testgo/tprecurfn/in.go +++ b/cl/_testgo/tprecurfn/in.go @@ -12,7 +12,7 @@ func main() { // CHECK-NEXT: %1 = getelementptr inbounds %"main.My[int]", ptr %0, i32 0, i32 1 // CHECK-NEXT: %2 = call ptr @"{{.*}}/runtime/internal/runtime.AllocZ"(i64 24) // CHECK-NEXT: %3 = getelementptr inbounds %"main.My[int]", ptr %2, i32 0, i32 0 - // CHECK-NEXT: store { ptr, ptr } { ptr @"__llgo_stub.main.main$1", ptr null }, ptr %3, align 8 + // CHECK-NEXT: store { ptr, ptr } { ptr @"main.main$1", ptr null }, ptr %3, align 8 // CHECK-NEXT: store ptr %2, ptr %1, align 8 // CHECK-NEXT: %4 = getelementptr inbounds %"main.My[int]", ptr %0, i32 0, i32 1 // CHECK-NEXT: %5 = load ptr, ptr %4, align 8 @@ -20,7 +20,8 @@ func main() { // CHECK-NEXT: %7 = load { ptr, ptr }, ptr %6, align 8 // CHECK-NEXT: %8 = extractvalue { ptr, ptr } %7, 1 // CHECK-NEXT: %9 = extractvalue { ptr, ptr } %7, 0 - // CHECK-NEXT: call void %9(ptr %8, i64 100) + // CHECK-NEXT: %__llgo_funcval_code = call ptr asm "", "=r,0"(ptr %9) + // CHECK-NEXT: call void %__llgo_funcval_code(ptr {{(nest|swiftself)}} %8, i64 100) // CHECK-NEXT: ret void // CHECK-NEXT:} m := &My[int]{next: &My[int]{fn: func(n int) { println(n) }}} diff --git a/cl/_testgo/typerecur/in.go b/cl/_testgo/typerecur/in.go index 247cb793df..cd7492b2f9 100644 --- a/cl/_testgo/typerecur/in.go +++ b/cl/_testgo/typerecur/in.go @@ -20,7 +20,7 @@ type counter struct { // CHECK: call void @"{{.*}}PrintInt"(i64 %6) // CHECK: icmp sge i64 %8, %10 // CHECK: ret %main.stateFn zeroinitializer -// CHECK: ret %main.stateFn { ptr @__llgo_stub.main.countState, ptr null } +// CHECK: ret %main.stateFn { ptr @main.countState, ptr null } func countState(c *counter) stateFn { c.value++ println("count:", c.value) @@ -35,8 +35,9 @@ func countState(c *counter) stateFn { func main() { // CHECK: call ptr @"{{.*}}AllocZ"(i64 32) // CHECK: store i64 5, ptr %1, align 8 - // CHECK: store %main.stateFn { ptr @__llgo_stub.main.countState, ptr null }, ptr %2, align 8 - // CHECK: call %main.stateFn %6(ptr %5, ptr %0) + // CHECK: store %main.stateFn { ptr @main.countState, ptr null }, ptr %2, align 8 + // CHECK: %__llgo_funcval_code = call ptr asm "", "=r,0"(ptr %6) + // CHECK: call %main.stateFn %__llgo_funcval_code(ptr {{(nest|swiftself)}} %5, ptr %0) // CHECK: store %main.stateFn %7, ptr %8, align 8 // CHECK: icmp ne ptr %11, null // CHECK: br i1 %12, label %_llgo_1, label %_llgo_2 diff --git a/cl/_testlibgo/strings/in.go b/cl/_testlibgo/strings/in.go index 9c1d390e32..f7239b2229 100644 --- a/cl/_testlibgo/strings/in.go +++ b/cl/_testlibgo/strings/in.go @@ -28,10 +28,10 @@ func main() { // CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.PrintByte"(i8 32) // CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.PrintString"(%"{{.*}}/runtime/internal/runtime.String" %6) // CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.PrintByte"(i8 10) - // CHECK-NEXT: %7 = call i64 @strings.IndexFunc(%"{{.*}}/runtime/internal/runtime.String" { ptr @5, i64 13 }, { ptr, ptr } { ptr @"__llgo_stub.main.main$1", ptr null }) + // CHECK-NEXT: %7 = call i64 @strings.IndexFunc(%"{{.*}}/runtime/internal/runtime.String" { ptr @5, i64 13 }, { ptr, ptr } { ptr @"main.main$1", ptr null }) // CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.PrintInt"(i64 %7) // CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.PrintByte"(i8 10) - // CHECK-NEXT: %8 = call i64 @strings.IndexFunc(%"{{.*}}/runtime/internal/runtime.String" { ptr @6, i64 12 }, { ptr, ptr } { ptr @"__llgo_stub.main.main$1", ptr null }) + // CHECK-NEXT: %8 = call i64 @strings.IndexFunc(%"{{.*}}/runtime/internal/runtime.String" { ptr @6, i64 12 }, { ptr, ptr } { ptr @"main.main$1", ptr null }) // CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.PrintInt"(i64 %8) // CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.PrintByte"(i8 10) // CHECK-NEXT: ret void diff --git a/cl/_testmeta/ifaceuse_basic/meta-expect.txt b/cl/_testmeta/ifaceuse_basic/meta-expect.txt index bb9606227c..cff8a1caf1 100644 --- a/cl/_testmeta/ifaceuse_basic/meta-expect.txt +++ b/cl/_testmeta/ifaceuse_basic/meta-expect.txt @@ -6,15 +6,11 @@ _llgo_main.T: [OrdinaryEdges] *_llgo_main.T: - __llgo_stub.github.com/goplus/llgo/runtime/internal/runtime.memequalptr _llgo_main.T -__llgo_stub.github.com/goplus/llgo/runtime/internal/runtime.memequal0: - github.com/goplus/llgo/runtime/internal/runtime.memequal0 -__llgo_stub.github.com/goplus/llgo/runtime/internal/runtime.memequalptr: github.com/goplus/llgo/runtime/internal/runtime.memequalptr _llgo_main.T: *_llgo_main.T - __llgo_stub.github.com/goplus/llgo/runtime/internal/runtime.memequal0 + github.com/goplus/llgo/runtime/internal/runtime.memequal0 main.init: main.init$guard main.main: diff --git a/cl/_testmeta/interface_anyonmous/meta-expect.txt b/cl/_testmeta/interface_anyonmous/meta-expect.txt index f8e21b08ca..eeeee403f9 100644 --- a/cl/_testmeta/interface_anyonmous/meta-expect.txt +++ b/cl/_testmeta/interface_anyonmous/meta-expect.txt @@ -12,39 +12,25 @@ _llgo_main.T: [OrdinaryEdges] *_llgo_func$2_iS07vIlF2_rZqWB5eU0IvP_9HviM4MYZNkXZDvbac: - __llgo_stub.github.com/goplus/llgo/runtime/internal/runtime.memequalptr _llgo_func$2_iS07vIlF2_rZqWB5eU0IvP_9HviM4MYZNkXZDvbac + github.com/goplus/llgo/runtime/internal/runtime.memequalptr *_llgo_iface$f14WsslTA1u5wwC83jLU0HU2u2mmAWxBVE38vPBbRAo: - __llgo_stub.github.com/goplus/llgo/runtime/internal/runtime.memequalptr _llgo_iface$f14WsslTA1u5wwC83jLU0HU2u2mmAWxBVE38vPBbRAo + github.com/goplus/llgo/runtime/internal/runtime.memequalptr *_llgo_main.T: - __llgo_stub.github.com/goplus/llgo/runtime/internal/runtime.memequalptr _llgo_main.T -__llgo_stub.github.com/goplus/llgo/runtime/internal/runtime.interequal: - github.com/goplus/llgo/runtime/internal/runtime.interequal -__llgo_stub.github.com/goplus/llgo/runtime/internal/runtime.memequal0: - github.com/goplus/llgo/runtime/internal/runtime.memequal0 -__llgo_stub.github.com/goplus/llgo/runtime/internal/runtime.memequalptr: github.com/goplus/llgo/runtime/internal/runtime.memequalptr -__llgo_stub.main.(*T).M: - main.(*T).M -__llgo_stub.main.(*T).N: - main.(*T).N -__llgo_stub.main.T.M: - main.T.M -__llgo_stub.main.T.N: - main.T.N _llgo_func$2_iS07vIlF2_rZqWB5eU0IvP_9HviM4MYZNkXZDvbac: *_llgo_func$2_iS07vIlF2_rZqWB5eU0IvP_9HviM4MYZNkXZDvbac _llgo_iface$f14WsslTA1u5wwC83jLU0HU2u2mmAWxBVE38vPBbRAo: *_llgo_iface$f14WsslTA1u5wwC83jLU0HU2u2mmAWxBVE38vPBbRAo - __llgo_stub.github.com/goplus/llgo/runtime/internal/runtime.interequal _llgo_iface$f14WsslTA1u5wwC83jLU0HU2u2mmAWxBVE38vPBbRAo$imethods + github.com/goplus/llgo/runtime/internal/runtime.interequal _llgo_iface$f14WsslTA1u5wwC83jLU0HU2u2mmAWxBVE38vPBbRAo$imethods: _llgo_func$2_iS07vIlF2_rZqWB5eU0IvP_9HviM4MYZNkXZDvbac _llgo_main.T: *_llgo_main.T - __llgo_stub.github.com/goplus/llgo/runtime/internal/runtime.memequal0 + github.com/goplus/llgo/runtime/internal/runtime.memequal0 main.(*T).M: github.com/goplus/llgo/runtime/internal/runtime.AssertNilDeref github.com/goplus/llgo/runtime/internal/runtime.PanicWrapNilPointer @@ -75,11 +61,11 @@ main.use: [MethodInfo] *_llgo_main.T: - 0 M _llgo_func$2_iS07vIlF2_rZqWB5eU0IvP_9HviM4MYZNkXZDvbac main.(*T).M __llgo_stub.main.(*T).M - 1 N _llgo_func$2_iS07vIlF2_rZqWB5eU0IvP_9HviM4MYZNkXZDvbac main.(*T).N __llgo_stub.main.(*T).N + 0 M _llgo_func$2_iS07vIlF2_rZqWB5eU0IvP_9HviM4MYZNkXZDvbac main.(*T).M main.(*T).M + 1 N _llgo_func$2_iS07vIlF2_rZqWB5eU0IvP_9HviM4MYZNkXZDvbac main.(*T).N main.(*T).N _llgo_main.T: - 0 M _llgo_func$2_iS07vIlF2_rZqWB5eU0IvP_9HviM4MYZNkXZDvbac main.(*T).M __llgo_stub.main.T.M - 1 N _llgo_func$2_iS07vIlF2_rZqWB5eU0IvP_9HviM4MYZNkXZDvbac main.(*T).N __llgo_stub.main.T.N + 0 M _llgo_func$2_iS07vIlF2_rZqWB5eU0IvP_9HviM4MYZNkXZDvbac main.(*T).M main.T.M + 1 N _llgo_func$2_iS07vIlF2_rZqWB5eU0IvP_9HviM4MYZNkXZDvbac main.(*T).N main.T.N [InterfaceInfo] _llgo_iface$f14WsslTA1u5wwC83jLU0HU2u2mmAWxBVE38vPBbRAo: diff --git a/cl/_testmeta/interface_exported_var/meta-expect.txt b/cl/_testmeta/interface_exported_var/meta-expect.txt index cc381a3fce..6343b52498 100644 --- a/cl/_testmeta/interface_exported_var/meta-expect.txt +++ b/cl/_testmeta/interface_exported_var/meta-expect.txt @@ -93,124 +93,64 @@ _llgo_uint8: [OrdinaryEdges] *[]_llgo_uint8: []_llgo_uint8 - __llgo_stub.github.com/goplus/llgo/runtime/internal/runtime.memequalptr + github.com/goplus/llgo/runtime/internal/runtime.memequalptr *_llgo_encoding/binary.littleEndian: - __llgo_stub.github.com/goplus/llgo/runtime/internal/runtime.memequalptr _llgo_encoding/binary.littleEndian + github.com/goplus/llgo/runtime/internal/runtime.memequalptr *_llgo_func$HQem8FNvPqrEVQ_c0XssBDFXIDOnET_Ex7o3PlV9bSs: - __llgo_stub.github.com/goplus/llgo/runtime/internal/runtime.memequalptr _llgo_func$HQem8FNvPqrEVQ_c0XssBDFXIDOnET_Ex7o3PlV9bSs + github.com/goplus/llgo/runtime/internal/runtime.memequalptr *_llgo_func$ICfGJV9Kp4o-2SMi1iuyC9xBBX1c5utHD63uVbyrfEc: - __llgo_stub.github.com/goplus/llgo/runtime/internal/runtime.memequalptr _llgo_func$ICfGJV9Kp4o-2SMi1iuyC9xBBX1c5utHD63uVbyrfEc + github.com/goplus/llgo/runtime/internal/runtime.memequalptr *_llgo_func$JXgl4jz35cOkksEkyj-ImVTqIDNL16JrZ25HHa-Yekw: - __llgo_stub.github.com/goplus/llgo/runtime/internal/runtime.memequalptr _llgo_func$JXgl4jz35cOkksEkyj-ImVTqIDNL16JrZ25HHa-Yekw + github.com/goplus/llgo/runtime/internal/runtime.memequalptr *_llgo_func$YjgNCugJxKXYLk39KOJyRyLtvcHU1d7KRz4inhHdVgg: - __llgo_stub.github.com/goplus/llgo/runtime/internal/runtime.memequalptr _llgo_func$YjgNCugJxKXYLk39KOJyRyLtvcHU1d7KRz4inhHdVgg + github.com/goplus/llgo/runtime/internal/runtime.memequalptr *_llgo_func$_JswjMs_mFNKWtFb56TJlZa479nBYWhoAxYBwUTwOyc: - __llgo_stub.github.com/goplus/llgo/runtime/internal/runtime.memequalptr _llgo_func$_JswjMs_mFNKWtFb56TJlZa479nBYWhoAxYBwUTwOyc + github.com/goplus/llgo/runtime/internal/runtime.memequalptr *_llgo_func$hV5ojfmZDe6MffI0ylemgDF5GZlZiYaJbQvka2A0Gus: - __llgo_stub.github.com/goplus/llgo/runtime/internal/runtime.memequalptr _llgo_func$hV5ojfmZDe6MffI0ylemgDF5GZlZiYaJbQvka2A0Gus + github.com/goplus/llgo/runtime/internal/runtime.memequalptr *_llgo_func$ibbVVENlZHDgol7ROnCbrRmXPuO818NXcpl5dfFoKhU: - __llgo_stub.github.com/goplus/llgo/runtime/internal/runtime.memequalptr _llgo_func$ibbVVENlZHDgol7ROnCbrRmXPuO818NXcpl5dfFoKhU + github.com/goplus/llgo/runtime/internal/runtime.memequalptr *_llgo_func$mBhSCdZCFK2IHVQVA73dFmon0gMcig2Q387khsbzmm8: - __llgo_stub.github.com/goplus/llgo/runtime/internal/runtime.memequalptr _llgo_func$mBhSCdZCFK2IHVQVA73dFmon0gMcig2Q387khsbzmm8 + github.com/goplus/llgo/runtime/internal/runtime.memequalptr *_llgo_func$mjkdaEUHPtpOYlUrWGfnskhhvdyc7k9Fk-vwWj3VftE: - __llgo_stub.github.com/goplus/llgo/runtime/internal/runtime.memequalptr _llgo_func$mjkdaEUHPtpOYlUrWGfnskhhvdyc7k9Fk-vwWj3VftE + github.com/goplus/llgo/runtime/internal/runtime.memequalptr *_llgo_func$zNDVRsWTIpUPKouNUS805RGX--IV9qVK8B31IZbg5to: - __llgo_stub.github.com/goplus/llgo/runtime/internal/runtime.memequalptr _llgo_func$zNDVRsWTIpUPKouNUS805RGX--IV9qVK8B31IZbg5to + github.com/goplus/llgo/runtime/internal/runtime.memequalptr *_llgo_iface$J1wM-rGcIPemx5jloXBmH7pUzUCSqpgNkOdb0QIFTxw: - __llgo_stub.github.com/goplus/llgo/runtime/internal/runtime.memequalptr _llgo_iface$J1wM-rGcIPemx5jloXBmH7pUzUCSqpgNkOdb0QIFTxw + github.com/goplus/llgo/runtime/internal/runtime.memequalptr *_llgo_string: - __llgo_stub.github.com/goplus/llgo/runtime/internal/runtime.memequalptr _llgo_string + github.com/goplus/llgo/runtime/internal/runtime.memequalptr *_llgo_uint16: - __llgo_stub.github.com/goplus/llgo/runtime/internal/runtime.memequalptr _llgo_uint16 + github.com/goplus/llgo/runtime/internal/runtime.memequalptr *_llgo_uint32: - __llgo_stub.github.com/goplus/llgo/runtime/internal/runtime.memequalptr _llgo_uint32 + github.com/goplus/llgo/runtime/internal/runtime.memequalptr *_llgo_uint64: - __llgo_stub.github.com/goplus/llgo/runtime/internal/runtime.memequalptr _llgo_uint64 + github.com/goplus/llgo/runtime/internal/runtime.memequalptr *_llgo_uint8: - __llgo_stub.github.com/goplus/llgo/runtime/internal/runtime.memequalptr _llgo_uint8 + github.com/goplus/llgo/runtime/internal/runtime.memequalptr []_llgo_uint8: *[]_llgo_uint8 _llgo_uint8 -__llgo_stub.encoding/binary.(*littleEndian).AppendUint16: - encoding/binary.(*littleEndian).AppendUint16 -__llgo_stub.encoding/binary.(*littleEndian).AppendUint32: - encoding/binary.(*littleEndian).AppendUint32 -__llgo_stub.encoding/binary.(*littleEndian).AppendUint64: - encoding/binary.(*littleEndian).AppendUint64 -__llgo_stub.encoding/binary.(*littleEndian).GoString: - encoding/binary.(*littleEndian).GoString -__llgo_stub.encoding/binary.(*littleEndian).PutUint16: - encoding/binary.(*littleEndian).PutUint16 -__llgo_stub.encoding/binary.(*littleEndian).PutUint32: - encoding/binary.(*littleEndian).PutUint32 -__llgo_stub.encoding/binary.(*littleEndian).PutUint64: - encoding/binary.(*littleEndian).PutUint64 -__llgo_stub.encoding/binary.(*littleEndian).String: - encoding/binary.(*littleEndian).String -__llgo_stub.encoding/binary.(*littleEndian).Uint16: - encoding/binary.(*littleEndian).Uint16 -__llgo_stub.encoding/binary.(*littleEndian).Uint32: - encoding/binary.(*littleEndian).Uint32 -__llgo_stub.encoding/binary.(*littleEndian).Uint64: - encoding/binary.(*littleEndian).Uint64 -__llgo_stub.encoding/binary.littleEndian.AppendUint16: - encoding/binary.littleEndian.AppendUint16 -__llgo_stub.encoding/binary.littleEndian.AppendUint32: - encoding/binary.littleEndian.AppendUint32 -__llgo_stub.encoding/binary.littleEndian.AppendUint64: - encoding/binary.littleEndian.AppendUint64 -__llgo_stub.encoding/binary.littleEndian.GoString: - encoding/binary.littleEndian.GoString -__llgo_stub.encoding/binary.littleEndian.PutUint16: - encoding/binary.littleEndian.PutUint16 -__llgo_stub.encoding/binary.littleEndian.PutUint32: - encoding/binary.littleEndian.PutUint32 -__llgo_stub.encoding/binary.littleEndian.PutUint64: - encoding/binary.littleEndian.PutUint64 -__llgo_stub.encoding/binary.littleEndian.String: - encoding/binary.littleEndian.String -__llgo_stub.encoding/binary.littleEndian.Uint16: - encoding/binary.littleEndian.Uint16 -__llgo_stub.encoding/binary.littleEndian.Uint32: - encoding/binary.littleEndian.Uint32 -__llgo_stub.encoding/binary.littleEndian.Uint64: - encoding/binary.littleEndian.Uint64 -__llgo_stub.github.com/goplus/llgo/runtime/internal/runtime.interequal: - github.com/goplus/llgo/runtime/internal/runtime.interequal -__llgo_stub.github.com/goplus/llgo/runtime/internal/runtime.memequal0: - github.com/goplus/llgo/runtime/internal/runtime.memequal0 -__llgo_stub.github.com/goplus/llgo/runtime/internal/runtime.memequal16: - github.com/goplus/llgo/runtime/internal/runtime.memequal16 -__llgo_stub.github.com/goplus/llgo/runtime/internal/runtime.memequal32: - github.com/goplus/llgo/runtime/internal/runtime.memequal32 -__llgo_stub.github.com/goplus/llgo/runtime/internal/runtime.memequal64: - github.com/goplus/llgo/runtime/internal/runtime.memequal64 -__llgo_stub.github.com/goplus/llgo/runtime/internal/runtime.memequal8: - github.com/goplus/llgo/runtime/internal/runtime.memequal8 -__llgo_stub.github.com/goplus/llgo/runtime/internal/runtime.memequalptr: - github.com/goplus/llgo/runtime/internal/runtime.memequalptr -__llgo_stub.github.com/goplus/llgo/runtime/internal/runtime.strequal: - github.com/goplus/llgo/runtime/internal/runtime.strequal _llgo_encoding/binary.littleEndian: *_llgo_encoding/binary.littleEndian - __llgo_stub.github.com/goplus/llgo/runtime/internal/runtime.memequal0 + github.com/goplus/llgo/runtime/internal/runtime.memequal0 _llgo_func$HQem8FNvPqrEVQ_c0XssBDFXIDOnET_Ex7o3PlV9bSs: *_llgo_func$HQem8FNvPqrEVQ_c0XssBDFXIDOnET_Ex7o3PlV9bSs _llgo_func$HQem8FNvPqrEVQ_c0XssBDFXIDOnET_Ex7o3PlV9bSs$in @@ -287,8 +227,8 @@ _llgo_func$zNDVRsWTIpUPKouNUS805RGX--IV9qVK8B31IZbg5to$out: _llgo_string _llgo_iface$J1wM-rGcIPemx5jloXBmH7pUzUCSqpgNkOdb0QIFTxw: *_llgo_iface$J1wM-rGcIPemx5jloXBmH7pUzUCSqpgNkOdb0QIFTxw - __llgo_stub.github.com/goplus/llgo/runtime/internal/runtime.interequal _llgo_iface$J1wM-rGcIPemx5jloXBmH7pUzUCSqpgNkOdb0QIFTxw$imethods + github.com/goplus/llgo/runtime/internal/runtime.interequal _llgo_iface$J1wM-rGcIPemx5jloXBmH7pUzUCSqpgNkOdb0QIFTxw$imethods: _llgo_func$ICfGJV9Kp4o-2SMi1iuyC9xBBX1c5utHD63uVbyrfEc _llgo_func$YjgNCugJxKXYLk39KOJyRyLtvcHU1d7KRz4inhHdVgg @@ -299,19 +239,19 @@ _llgo_iface$J1wM-rGcIPemx5jloXBmH7pUzUCSqpgNkOdb0QIFTxw$imethods: _llgo_func$zNDVRsWTIpUPKouNUS805RGX--IV9qVK8B31IZbg5to _llgo_string: *_llgo_string - __llgo_stub.github.com/goplus/llgo/runtime/internal/runtime.strequal + github.com/goplus/llgo/runtime/internal/runtime.strequal _llgo_uint16: *_llgo_uint16 - __llgo_stub.github.com/goplus/llgo/runtime/internal/runtime.memequal16 + github.com/goplus/llgo/runtime/internal/runtime.memequal16 _llgo_uint32: *_llgo_uint32 - __llgo_stub.github.com/goplus/llgo/runtime/internal/runtime.memequal32 + github.com/goplus/llgo/runtime/internal/runtime.memequal32 _llgo_uint64: *_llgo_uint64 - __llgo_stub.github.com/goplus/llgo/runtime/internal/runtime.memequal64 + github.com/goplus/llgo/runtime/internal/runtime.memequal64 _llgo_uint8: *_llgo_uint8 - __llgo_stub.github.com/goplus/llgo/runtime/internal/runtime.memequal8 + github.com/goplus/llgo/runtime/internal/runtime.memequal8 main.init: encoding/binary.init main.init$guard @@ -335,29 +275,29 @@ main.main: [MethodInfo] *_llgo_encoding/binary.littleEndian: - 0 AppendUint16 _llgo_func$JXgl4jz35cOkksEkyj-ImVTqIDNL16JrZ25HHa-Yekw encoding/binary.(*littleEndian).AppendUint16 __llgo_stub.encoding/binary.(*littleEndian).AppendUint16 - 1 AppendUint32 _llgo_func$_JswjMs_mFNKWtFb56TJlZa479nBYWhoAxYBwUTwOyc encoding/binary.(*littleEndian).AppendUint32 __llgo_stub.encoding/binary.(*littleEndian).AppendUint32 - 2 AppendUint64 _llgo_func$HQem8FNvPqrEVQ_c0XssBDFXIDOnET_Ex7o3PlV9bSs encoding/binary.(*littleEndian).AppendUint64 __llgo_stub.encoding/binary.(*littleEndian).AppendUint64 - 3 GoString _llgo_func$zNDVRsWTIpUPKouNUS805RGX--IV9qVK8B31IZbg5to encoding/binary.(*littleEndian).GoString __llgo_stub.encoding/binary.(*littleEndian).GoString - 4 PutUint16 _llgo_func$ibbVVENlZHDgol7ROnCbrRmXPuO818NXcpl5dfFoKhU encoding/binary.(*littleEndian).PutUint16 __llgo_stub.encoding/binary.(*littleEndian).PutUint16 - 5 PutUint32 _llgo_func$YjgNCugJxKXYLk39KOJyRyLtvcHU1d7KRz4inhHdVgg encoding/binary.(*littleEndian).PutUint32 __llgo_stub.encoding/binary.(*littleEndian).PutUint32 - 6 PutUint64 _llgo_func$mBhSCdZCFK2IHVQVA73dFmon0gMcig2Q387khsbzmm8 encoding/binary.(*littleEndian).PutUint64 __llgo_stub.encoding/binary.(*littleEndian).PutUint64 - 7 String _llgo_func$zNDVRsWTIpUPKouNUS805RGX--IV9qVK8B31IZbg5to encoding/binary.(*littleEndian).String __llgo_stub.encoding/binary.(*littleEndian).String - 8 Uint16 _llgo_func$hV5ojfmZDe6MffI0ylemgDF5GZlZiYaJbQvka2A0Gus encoding/binary.(*littleEndian).Uint16 __llgo_stub.encoding/binary.(*littleEndian).Uint16 - 9 Uint32 _llgo_func$ICfGJV9Kp4o-2SMi1iuyC9xBBX1c5utHD63uVbyrfEc encoding/binary.(*littleEndian).Uint32 __llgo_stub.encoding/binary.(*littleEndian).Uint32 - 10 Uint64 _llgo_func$mjkdaEUHPtpOYlUrWGfnskhhvdyc7k9Fk-vwWj3VftE encoding/binary.(*littleEndian).Uint64 __llgo_stub.encoding/binary.(*littleEndian).Uint64 + 0 AppendUint16 _llgo_func$JXgl4jz35cOkksEkyj-ImVTqIDNL16JrZ25HHa-Yekw encoding/binary.(*littleEndian).AppendUint16 encoding/binary.(*littleEndian).AppendUint16 + 1 AppendUint32 _llgo_func$_JswjMs_mFNKWtFb56TJlZa479nBYWhoAxYBwUTwOyc encoding/binary.(*littleEndian).AppendUint32 encoding/binary.(*littleEndian).AppendUint32 + 2 AppendUint64 _llgo_func$HQem8FNvPqrEVQ_c0XssBDFXIDOnET_Ex7o3PlV9bSs encoding/binary.(*littleEndian).AppendUint64 encoding/binary.(*littleEndian).AppendUint64 + 3 GoString _llgo_func$zNDVRsWTIpUPKouNUS805RGX--IV9qVK8B31IZbg5to encoding/binary.(*littleEndian).GoString encoding/binary.(*littleEndian).GoString + 4 PutUint16 _llgo_func$ibbVVENlZHDgol7ROnCbrRmXPuO818NXcpl5dfFoKhU encoding/binary.(*littleEndian).PutUint16 encoding/binary.(*littleEndian).PutUint16 + 5 PutUint32 _llgo_func$YjgNCugJxKXYLk39KOJyRyLtvcHU1d7KRz4inhHdVgg encoding/binary.(*littleEndian).PutUint32 encoding/binary.(*littleEndian).PutUint32 + 6 PutUint64 _llgo_func$mBhSCdZCFK2IHVQVA73dFmon0gMcig2Q387khsbzmm8 encoding/binary.(*littleEndian).PutUint64 encoding/binary.(*littleEndian).PutUint64 + 7 String _llgo_func$zNDVRsWTIpUPKouNUS805RGX--IV9qVK8B31IZbg5to encoding/binary.(*littleEndian).String encoding/binary.(*littleEndian).String + 8 Uint16 _llgo_func$hV5ojfmZDe6MffI0ylemgDF5GZlZiYaJbQvka2A0Gus encoding/binary.(*littleEndian).Uint16 encoding/binary.(*littleEndian).Uint16 + 9 Uint32 _llgo_func$ICfGJV9Kp4o-2SMi1iuyC9xBBX1c5utHD63uVbyrfEc encoding/binary.(*littleEndian).Uint32 encoding/binary.(*littleEndian).Uint32 + 10 Uint64 _llgo_func$mjkdaEUHPtpOYlUrWGfnskhhvdyc7k9Fk-vwWj3VftE encoding/binary.(*littleEndian).Uint64 encoding/binary.(*littleEndian).Uint64 _llgo_encoding/binary.littleEndian: - 0 AppendUint16 _llgo_func$JXgl4jz35cOkksEkyj-ImVTqIDNL16JrZ25HHa-Yekw encoding/binary.(*littleEndian).AppendUint16 __llgo_stub.encoding/binary.littleEndian.AppendUint16 - 1 AppendUint32 _llgo_func$_JswjMs_mFNKWtFb56TJlZa479nBYWhoAxYBwUTwOyc encoding/binary.(*littleEndian).AppendUint32 __llgo_stub.encoding/binary.littleEndian.AppendUint32 - 2 AppendUint64 _llgo_func$HQem8FNvPqrEVQ_c0XssBDFXIDOnET_Ex7o3PlV9bSs encoding/binary.(*littleEndian).AppendUint64 __llgo_stub.encoding/binary.littleEndian.AppendUint64 - 3 GoString _llgo_func$zNDVRsWTIpUPKouNUS805RGX--IV9qVK8B31IZbg5to encoding/binary.(*littleEndian).GoString __llgo_stub.encoding/binary.littleEndian.GoString - 4 PutUint16 _llgo_func$ibbVVENlZHDgol7ROnCbrRmXPuO818NXcpl5dfFoKhU encoding/binary.(*littleEndian).PutUint16 __llgo_stub.encoding/binary.littleEndian.PutUint16 - 5 PutUint32 _llgo_func$YjgNCugJxKXYLk39KOJyRyLtvcHU1d7KRz4inhHdVgg encoding/binary.(*littleEndian).PutUint32 __llgo_stub.encoding/binary.littleEndian.PutUint32 - 6 PutUint64 _llgo_func$mBhSCdZCFK2IHVQVA73dFmon0gMcig2Q387khsbzmm8 encoding/binary.(*littleEndian).PutUint64 __llgo_stub.encoding/binary.littleEndian.PutUint64 - 7 String _llgo_func$zNDVRsWTIpUPKouNUS805RGX--IV9qVK8B31IZbg5to encoding/binary.(*littleEndian).String __llgo_stub.encoding/binary.littleEndian.String - 8 Uint16 _llgo_func$hV5ojfmZDe6MffI0ylemgDF5GZlZiYaJbQvka2A0Gus encoding/binary.(*littleEndian).Uint16 __llgo_stub.encoding/binary.littleEndian.Uint16 - 9 Uint32 _llgo_func$ICfGJV9Kp4o-2SMi1iuyC9xBBX1c5utHD63uVbyrfEc encoding/binary.(*littleEndian).Uint32 __llgo_stub.encoding/binary.littleEndian.Uint32 - 10 Uint64 _llgo_func$mjkdaEUHPtpOYlUrWGfnskhhvdyc7k9Fk-vwWj3VftE encoding/binary.(*littleEndian).Uint64 __llgo_stub.encoding/binary.littleEndian.Uint64 + 0 AppendUint16 _llgo_func$JXgl4jz35cOkksEkyj-ImVTqIDNL16JrZ25HHa-Yekw encoding/binary.(*littleEndian).AppendUint16 encoding/binary.littleEndian.AppendUint16 + 1 AppendUint32 _llgo_func$_JswjMs_mFNKWtFb56TJlZa479nBYWhoAxYBwUTwOyc encoding/binary.(*littleEndian).AppendUint32 encoding/binary.littleEndian.AppendUint32 + 2 AppendUint64 _llgo_func$HQem8FNvPqrEVQ_c0XssBDFXIDOnET_Ex7o3PlV9bSs encoding/binary.(*littleEndian).AppendUint64 encoding/binary.littleEndian.AppendUint64 + 3 GoString _llgo_func$zNDVRsWTIpUPKouNUS805RGX--IV9qVK8B31IZbg5to encoding/binary.(*littleEndian).GoString encoding/binary.littleEndian.GoString + 4 PutUint16 _llgo_func$ibbVVENlZHDgol7ROnCbrRmXPuO818NXcpl5dfFoKhU encoding/binary.(*littleEndian).PutUint16 encoding/binary.littleEndian.PutUint16 + 5 PutUint32 _llgo_func$YjgNCugJxKXYLk39KOJyRyLtvcHU1d7KRz4inhHdVgg encoding/binary.(*littleEndian).PutUint32 encoding/binary.littleEndian.PutUint32 + 6 PutUint64 _llgo_func$mBhSCdZCFK2IHVQVA73dFmon0gMcig2Q387khsbzmm8 encoding/binary.(*littleEndian).PutUint64 encoding/binary.littleEndian.PutUint64 + 7 String _llgo_func$zNDVRsWTIpUPKouNUS805RGX--IV9qVK8B31IZbg5to encoding/binary.(*littleEndian).String encoding/binary.littleEndian.String + 8 Uint16 _llgo_func$hV5ojfmZDe6MffI0ylemgDF5GZlZiYaJbQvka2A0Gus encoding/binary.(*littleEndian).Uint16 encoding/binary.littleEndian.Uint16 + 9 Uint32 _llgo_func$ICfGJV9Kp4o-2SMi1iuyC9xBBX1c5utHD63uVbyrfEc encoding/binary.(*littleEndian).Uint32 encoding/binary.littleEndian.Uint32 + 10 Uint64 _llgo_func$mjkdaEUHPtpOYlUrWGfnskhhvdyc7k9Fk-vwWj3VftE encoding/binary.(*littleEndian).Uint64 encoding/binary.littleEndian.Uint64 [InterfaceInfo] _llgo_iface$J1wM-rGcIPemx5jloXBmH7pUzUCSqpgNkOdb0QIFTxw: diff --git a/cl/_testmeta/interface_generic/meta-expect.txt b/cl/_testmeta/interface_generic/meta-expect.txt index 31a14b57ce..5303bdf9f6 100644 --- a/cl/_testmeta/interface_generic/meta-expect.txt +++ b/cl/_testmeta/interface_generic/meta-expect.txt @@ -18,25 +18,17 @@ _llgo_main.Box[int]: [OrdinaryEdges] *_llgo_func$ETeB8WwW04JEq0ztcm-XPTJtuYvtpkjIsAc0-2NT9zA: - __llgo_stub.github.com/goplus/llgo/runtime/internal/runtime.memequalptr _llgo_func$ETeB8WwW04JEq0ztcm-XPTJtuYvtpkjIsAc0-2NT9zA + github.com/goplus/llgo/runtime/internal/runtime.memequalptr *_llgo_iface$Jvxc0PCI_drlfK7S5npMGdZkQLeRkQ_x2e2CifPE6w8: - __llgo_stub.github.com/goplus/llgo/runtime/internal/runtime.memequalptr _llgo_iface$Jvxc0PCI_drlfK7S5npMGdZkQLeRkQ_x2e2CifPE6w8 + github.com/goplus/llgo/runtime/internal/runtime.memequalptr *_llgo_int: - __llgo_stub.github.com/goplus/llgo/runtime/internal/runtime.memequalptr _llgo_int + github.com/goplus/llgo/runtime/internal/runtime.memequalptr *_llgo_main.Box[int]: - __llgo_stub.github.com/goplus/llgo/runtime/internal/runtime.memequalptr _llgo_main.Box[int] -__llgo_stub.github.com/goplus/llgo/runtime/internal/runtime.interequal: - github.com/goplus/llgo/runtime/internal/runtime.interequal -__llgo_stub.github.com/goplus/llgo/runtime/internal/runtime.memequal64: - github.com/goplus/llgo/runtime/internal/runtime.memequal64 -__llgo_stub.github.com/goplus/llgo/runtime/internal/runtime.memequalptr: github.com/goplus/llgo/runtime/internal/runtime.memequalptr -__llgo_stub.main.(*Box[int]).Value: - main.(*Box[int]).Value _llgo_func$ETeB8WwW04JEq0ztcm-XPTJtuYvtpkjIsAc0-2NT9zA: *_llgo_func$ETeB8WwW04JEq0ztcm-XPTJtuYvtpkjIsAc0-2NT9zA _llgo_func$ETeB8WwW04JEq0ztcm-XPTJtuYvtpkjIsAc0-2NT9zA$out @@ -44,13 +36,13 @@ _llgo_func$ETeB8WwW04JEq0ztcm-XPTJtuYvtpkjIsAc0-2NT9zA$out: _llgo_int _llgo_iface$Jvxc0PCI_drlfK7S5npMGdZkQLeRkQ_x2e2CifPE6w8: *_llgo_iface$Jvxc0PCI_drlfK7S5npMGdZkQLeRkQ_x2e2CifPE6w8 - __llgo_stub.github.com/goplus/llgo/runtime/internal/runtime.interequal _llgo_iface$Jvxc0PCI_drlfK7S5npMGdZkQLeRkQ_x2e2CifPE6w8$imethods + github.com/goplus/llgo/runtime/internal/runtime.interequal _llgo_iface$Jvxc0PCI_drlfK7S5npMGdZkQLeRkQ_x2e2CifPE6w8$imethods: _llgo_func$ETeB8WwW04JEq0ztcm-XPTJtuYvtpkjIsAc0-2NT9zA _llgo_int: *_llgo_int - __llgo_stub.github.com/goplus/llgo/runtime/internal/runtime.memequal64 + github.com/goplus/llgo/runtime/internal/runtime.memequal64 _llgo_main.Box[int]: *_llgo_main.Box[int] github.com/goplus/llgo/cl/_testmeta/interface_generic.struct$lOhriNu2BrWBR2Mh8k-KggMYlAw0Wx-2ftE2_gNyubg$fields @@ -78,7 +70,7 @@ main.useInt: [MethodInfo] *_llgo_main.Box[int]: - 0 Value _llgo_func$ETeB8WwW04JEq0ztcm-XPTJtuYvtpkjIsAc0-2NT9zA main.(*Box[int]).Value __llgo_stub.main.(*Box[int]).Value + 0 Value _llgo_func$ETeB8WwW04JEq0ztcm-XPTJtuYvtpkjIsAc0-2NT9zA main.(*Box[int]).Value main.(*Box[int]).Value [InterfaceInfo] _llgo_iface$Jvxc0PCI_drlfK7S5npMGdZkQLeRkQ_x2e2CifPE6w8: diff --git a/cl/_testmeta/interface_generic_crosspkg/meta-expect.txt b/cl/_testmeta/interface_generic_crosspkg/meta-expect.txt index 98c89794a5..37605e8c23 100644 --- a/cl/_testmeta/interface_generic_crosspkg/meta-expect.txt +++ b/cl/_testmeta/interface_generic_crosspkg/meta-expect.txt @@ -32,42 +32,26 @@ _llgo_string: [OrdinaryEdges] *_llgo_func$ETeB8WwW04JEq0ztcm-XPTJtuYvtpkjIsAc0-2NT9zA: - __llgo_stub.github.com/goplus/llgo/runtime/internal/runtime.memequalptr _llgo_func$ETeB8WwW04JEq0ztcm-XPTJtuYvtpkjIsAc0-2NT9zA + github.com/goplus/llgo/runtime/internal/runtime.memequalptr *_llgo_func$zNDVRsWTIpUPKouNUS805RGX--IV9qVK8B31IZbg5to: - __llgo_stub.github.com/goplus/llgo/runtime/internal/runtime.memequalptr _llgo_func$zNDVRsWTIpUPKouNUS805RGX--IV9qVK8B31IZbg5to + github.com/goplus/llgo/runtime/internal/runtime.memequalptr *_llgo_github.com/goplus/llgo/cl/_testmeta/interface_generic_crosspkg/model.Box[int]: - __llgo_stub.github.com/goplus/llgo/runtime/internal/runtime.memequalptr _llgo_github.com/goplus/llgo/cl/_testmeta/interface_generic_crosspkg/model.Box[int] + github.com/goplus/llgo/runtime/internal/runtime.memequalptr *_llgo_github.com/goplus/llgo/cl/_testmeta/interface_generic_crosspkg/model.Box[string]: - __llgo_stub.github.com/goplus/llgo/runtime/internal/runtime.memequalptr _llgo_github.com/goplus/llgo/cl/_testmeta/interface_generic_crosspkg/model.Box[string] + github.com/goplus/llgo/runtime/internal/runtime.memequalptr *_llgo_iface$Jvxc0PCI_drlfK7S5npMGdZkQLeRkQ_x2e2CifPE6w8: - __llgo_stub.github.com/goplus/llgo/runtime/internal/runtime.memequalptr _llgo_iface$Jvxc0PCI_drlfK7S5npMGdZkQLeRkQ_x2e2CifPE6w8 + github.com/goplus/llgo/runtime/internal/runtime.memequalptr *_llgo_int: - __llgo_stub.github.com/goplus/llgo/runtime/internal/runtime.memequalptr _llgo_int + github.com/goplus/llgo/runtime/internal/runtime.memequalptr *_llgo_string: - __llgo_stub.github.com/goplus/llgo/runtime/internal/runtime.memequalptr _llgo_string -__llgo_stub.github.com/goplus/llgo/cl/_testmeta/interface_generic_crosspkg/model.(*Box[int]).Drop: - github.com/goplus/llgo/cl/_testmeta/interface_generic_crosspkg/model.(*Box[int]).Drop -__llgo_stub.github.com/goplus/llgo/cl/_testmeta/interface_generic_crosspkg/model.(*Box[int]).Value: - github.com/goplus/llgo/cl/_testmeta/interface_generic_crosspkg/model.(*Box[int]).Value -__llgo_stub.github.com/goplus/llgo/cl/_testmeta/interface_generic_crosspkg/model.(*Box[string]).Drop: - github.com/goplus/llgo/cl/_testmeta/interface_generic_crosspkg/model.(*Box[string]).Drop -__llgo_stub.github.com/goplus/llgo/cl/_testmeta/interface_generic_crosspkg/model.(*Box[string]).Value: - github.com/goplus/llgo/cl/_testmeta/interface_generic_crosspkg/model.(*Box[string]).Value -__llgo_stub.github.com/goplus/llgo/runtime/internal/runtime.interequal: - github.com/goplus/llgo/runtime/internal/runtime.interequal -__llgo_stub.github.com/goplus/llgo/runtime/internal/runtime.memequal64: - github.com/goplus/llgo/runtime/internal/runtime.memequal64 -__llgo_stub.github.com/goplus/llgo/runtime/internal/runtime.memequalptr: github.com/goplus/llgo/runtime/internal/runtime.memequalptr -__llgo_stub.github.com/goplus/llgo/runtime/internal/runtime.strequal: - github.com/goplus/llgo/runtime/internal/runtime.strequal _llgo_func$ETeB8WwW04JEq0ztcm-XPTJtuYvtpkjIsAc0-2NT9zA: *_llgo_func$ETeB8WwW04JEq0ztcm-XPTJtuYvtpkjIsAc0-2NT9zA _llgo_func$ETeB8WwW04JEq0ztcm-XPTJtuYvtpkjIsAc0-2NT9zA$out @@ -88,16 +72,16 @@ _llgo_github.com/goplus/llgo/cl/_testmeta/interface_generic_crosspkg/model.Box[s github.com/goplus/llgo/runtime/internal/runtime.structequal _llgo_iface$Jvxc0PCI_drlfK7S5npMGdZkQLeRkQ_x2e2CifPE6w8: *_llgo_iface$Jvxc0PCI_drlfK7S5npMGdZkQLeRkQ_x2e2CifPE6w8 - __llgo_stub.github.com/goplus/llgo/runtime/internal/runtime.interequal _llgo_iface$Jvxc0PCI_drlfK7S5npMGdZkQLeRkQ_x2e2CifPE6w8$imethods + github.com/goplus/llgo/runtime/internal/runtime.interequal _llgo_iface$Jvxc0PCI_drlfK7S5npMGdZkQLeRkQ_x2e2CifPE6w8$imethods: _llgo_func$ETeB8WwW04JEq0ztcm-XPTJtuYvtpkjIsAc0-2NT9zA _llgo_int: *_llgo_int - __llgo_stub.github.com/goplus/llgo/runtime/internal/runtime.memequal64 + github.com/goplus/llgo/runtime/internal/runtime.memequal64 _llgo_string: *_llgo_string - __llgo_stub.github.com/goplus/llgo/runtime/internal/runtime.strequal + github.com/goplus/llgo/runtime/internal/runtime.strequal github.com/goplus/llgo/cl/_testmeta/interface_generic_crosspkg/model.(*Box[int]).Drop: _llgo_string github.com/goplus/llgo/runtime/internal/runtime.AllocU @@ -138,9 +122,9 @@ main.main: [MethodInfo] *_llgo_github.com/goplus/llgo/cl/_testmeta/interface_generic_crosspkg/model.Box[int]: - 0 Drop _llgo_func$ETeB8WwW04JEq0ztcm-XPTJtuYvtpkjIsAc0-2NT9zA github.com/goplus/llgo/cl/_testmeta/interface_generic_crosspkg/model.(*Box[int]).Drop __llgo_stub.github.com/goplus/llgo/cl/_testmeta/interface_generic_crosspkg/model.(*Box[int]).Drop - 1 Value _llgo_func$ETeB8WwW04JEq0ztcm-XPTJtuYvtpkjIsAc0-2NT9zA github.com/goplus/llgo/cl/_testmeta/interface_generic_crosspkg/model.(*Box[int]).Value __llgo_stub.github.com/goplus/llgo/cl/_testmeta/interface_generic_crosspkg/model.(*Box[int]).Value + 0 Drop _llgo_func$ETeB8WwW04JEq0ztcm-XPTJtuYvtpkjIsAc0-2NT9zA github.com/goplus/llgo/cl/_testmeta/interface_generic_crosspkg/model.(*Box[int]).Drop github.com/goplus/llgo/cl/_testmeta/interface_generic_crosspkg/model.(*Box[int]).Drop + 1 Value _llgo_func$ETeB8WwW04JEq0ztcm-XPTJtuYvtpkjIsAc0-2NT9zA github.com/goplus/llgo/cl/_testmeta/interface_generic_crosspkg/model.(*Box[int]).Value github.com/goplus/llgo/cl/_testmeta/interface_generic_crosspkg/model.(*Box[int]).Value *_llgo_github.com/goplus/llgo/cl/_testmeta/interface_generic_crosspkg/model.Box[string]: - 0 Drop _llgo_func$zNDVRsWTIpUPKouNUS805RGX--IV9qVK8B31IZbg5to github.com/goplus/llgo/cl/_testmeta/interface_generic_crosspkg/model.(*Box[string]).Drop __llgo_stub.github.com/goplus/llgo/cl/_testmeta/interface_generic_crosspkg/model.(*Box[string]).Drop - 1 Value _llgo_func$zNDVRsWTIpUPKouNUS805RGX--IV9qVK8B31IZbg5to github.com/goplus/llgo/cl/_testmeta/interface_generic_crosspkg/model.(*Box[string]).Value __llgo_stub.github.com/goplus/llgo/cl/_testmeta/interface_generic_crosspkg/model.(*Box[string]).Value + 0 Drop _llgo_func$zNDVRsWTIpUPKouNUS805RGX--IV9qVK8B31IZbg5to github.com/goplus/llgo/cl/_testmeta/interface_generic_crosspkg/model.(*Box[string]).Drop github.com/goplus/llgo/cl/_testmeta/interface_generic_crosspkg/model.(*Box[string]).Drop + 1 Value _llgo_func$zNDVRsWTIpUPKouNUS805RGX--IV9qVK8B31IZbg5to github.com/goplus/llgo/cl/_testmeta/interface_generic_crosspkg/model.(*Box[string]).Value github.com/goplus/llgo/cl/_testmeta/interface_generic_crosspkg/model.(*Box[string]).Value diff --git a/cl/_testmeta/interface_imported/meta-expect.txt b/cl/_testmeta/interface_imported/meta-expect.txt index 9c6bbe94ec..0d06c70bfc 100644 --- a/cl/_testmeta/interface_imported/meta-expect.txt +++ b/cl/_testmeta/interface_imported/meta-expect.txt @@ -45,61 +45,41 @@ _llgo_uint8: [OrdinaryEdges] *[]_llgo_uint8: []_llgo_uint8 - __llgo_stub.github.com/goplus/llgo/runtime/internal/runtime.memequalptr + github.com/goplus/llgo/runtime/internal/runtime.memequalptr *_llgo_error: - __llgo_stub.github.com/goplus/llgo/runtime/internal/runtime.memequalptr _llgo_error + github.com/goplus/llgo/runtime/internal/runtime.memequalptr *_llgo_func$8rsrSd_r3UHd_2DiYTyaOKR7BYkei4zw5ysG35KF38w: - __llgo_stub.github.com/goplus/llgo/runtime/internal/runtime.memequalptr _llgo_func$8rsrSd_r3UHd_2DiYTyaOKR7BYkei4zw5ysG35KF38w + github.com/goplus/llgo/runtime/internal/runtime.memequalptr *_llgo_func$G2hch9Iy9DrhKKsg70PbL54bK-XSl-1IUUORN17J2Dk: - __llgo_stub.github.com/goplus/llgo/runtime/internal/runtime.memequalptr _llgo_func$G2hch9Iy9DrhKKsg70PbL54bK-XSl-1IUUORN17J2Dk + github.com/goplus/llgo/runtime/internal/runtime.memequalptr *_llgo_func$zNDVRsWTIpUPKouNUS805RGX--IV9qVK8B31IZbg5to: - __llgo_stub.github.com/goplus/llgo/runtime/internal/runtime.memequalptr _llgo_func$zNDVRsWTIpUPKouNUS805RGX--IV9qVK8B31IZbg5to + github.com/goplus/llgo/runtime/internal/runtime.memequalptr *_llgo_github.com/goplus/llgo/cl/_testmeta/interface_imported/api.Source: - __llgo_stub.github.com/goplus/llgo/runtime/internal/runtime.memequalptr _llgo_github.com/goplus/llgo/cl/_testmeta/interface_imported/api.Source + github.com/goplus/llgo/runtime/internal/runtime.memequalptr *_llgo_iface$uycIKA3bbxRhudEjW1hHKWKdLqHQsCVy8NdW1bkQmNw: - __llgo_stub.github.com/goplus/llgo/runtime/internal/runtime.memequalptr _llgo_iface$uycIKA3bbxRhudEjW1hHKWKdLqHQsCVy8NdW1bkQmNw + github.com/goplus/llgo/runtime/internal/runtime.memequalptr *_llgo_int: - __llgo_stub.github.com/goplus/llgo/runtime/internal/runtime.memequalptr _llgo_int + github.com/goplus/llgo/runtime/internal/runtime.memequalptr *_llgo_string: - __llgo_stub.github.com/goplus/llgo/runtime/internal/runtime.memequalptr _llgo_string + github.com/goplus/llgo/runtime/internal/runtime.memequalptr *_llgo_uint8: - __llgo_stub.github.com/goplus/llgo/runtime/internal/runtime.memequalptr _llgo_uint8 + github.com/goplus/llgo/runtime/internal/runtime.memequalptr []_llgo_uint8: *[]_llgo_uint8 _llgo_uint8 -__llgo_stub.github.com/goplus/llgo/cl/_testmeta/interface_imported/api.(*Source).Close: - github.com/goplus/llgo/cl/_testmeta/interface_imported/api.(*Source).Close -__llgo_stub.github.com/goplus/llgo/cl/_testmeta/interface_imported/api.(*Source).Read: - github.com/goplus/llgo/cl/_testmeta/interface_imported/api.(*Source).Read -__llgo_stub.github.com/goplus/llgo/cl/_testmeta/interface_imported/api.Source.Close: - github.com/goplus/llgo/cl/_testmeta/interface_imported/api.Source.Close -__llgo_stub.github.com/goplus/llgo/cl/_testmeta/interface_imported/api.Source.Read: - github.com/goplus/llgo/cl/_testmeta/interface_imported/api.Source.Read -__llgo_stub.github.com/goplus/llgo/runtime/internal/runtime.interequal: - github.com/goplus/llgo/runtime/internal/runtime.interequal -__llgo_stub.github.com/goplus/llgo/runtime/internal/runtime.memequal0: - github.com/goplus/llgo/runtime/internal/runtime.memequal0 -__llgo_stub.github.com/goplus/llgo/runtime/internal/runtime.memequal64: - github.com/goplus/llgo/runtime/internal/runtime.memequal64 -__llgo_stub.github.com/goplus/llgo/runtime/internal/runtime.memequal8: - github.com/goplus/llgo/runtime/internal/runtime.memequal8 -__llgo_stub.github.com/goplus/llgo/runtime/internal/runtime.memequalptr: - github.com/goplus/llgo/runtime/internal/runtime.memequalptr -__llgo_stub.github.com/goplus/llgo/runtime/internal/runtime.strequal: - github.com/goplus/llgo/runtime/internal/runtime.strequal _llgo_error: *_llgo_error - __llgo_stub.github.com/goplus/llgo/runtime/internal/runtime.interequal _llgo_iface$Fh8eUJ-Gw4e6TYuajcFIOSCuqSPKAt5nS4ow7xeGXEU$imethods + github.com/goplus/llgo/runtime/internal/runtime.interequal _llgo_func$8rsrSd_r3UHd_2DiYTyaOKR7BYkei4zw5ysG35KF38w: *_llgo_func$8rsrSd_r3UHd_2DiYTyaOKR7BYkei4zw5ysG35KF38w _llgo_func$8rsrSd_r3UHd_2DiYTyaOKR7BYkei4zw5ysG35KF38w$out @@ -121,24 +101,24 @@ _llgo_func$zNDVRsWTIpUPKouNUS805RGX--IV9qVK8B31IZbg5to$out: _llgo_string _llgo_github.com/goplus/llgo/cl/_testmeta/interface_imported/api.Source: *_llgo_github.com/goplus/llgo/cl/_testmeta/interface_imported/api.Source - __llgo_stub.github.com/goplus/llgo/runtime/internal/runtime.memequal0 + github.com/goplus/llgo/runtime/internal/runtime.memequal0 _llgo_iface$Fh8eUJ-Gw4e6TYuajcFIOSCuqSPKAt5nS4ow7xeGXEU$imethods: _llgo_func$zNDVRsWTIpUPKouNUS805RGX--IV9qVK8B31IZbg5to _llgo_iface$uycIKA3bbxRhudEjW1hHKWKdLqHQsCVy8NdW1bkQmNw: *_llgo_iface$uycIKA3bbxRhudEjW1hHKWKdLqHQsCVy8NdW1bkQmNw - __llgo_stub.github.com/goplus/llgo/runtime/internal/runtime.interequal _llgo_iface$uycIKA3bbxRhudEjW1hHKWKdLqHQsCVy8NdW1bkQmNw$imethods + github.com/goplus/llgo/runtime/internal/runtime.interequal _llgo_iface$uycIKA3bbxRhudEjW1hHKWKdLqHQsCVy8NdW1bkQmNw$imethods: _llgo_func$G2hch9Iy9DrhKKsg70PbL54bK-XSl-1IUUORN17J2Dk _llgo_int: *_llgo_int - __llgo_stub.github.com/goplus/llgo/runtime/internal/runtime.memequal64 + github.com/goplus/llgo/runtime/internal/runtime.memequal64 _llgo_string: *_llgo_string - __llgo_stub.github.com/goplus/llgo/runtime/internal/runtime.strequal + github.com/goplus/llgo/runtime/internal/runtime.strequal _llgo_uint8: *_llgo_uint8 - __llgo_stub.github.com/goplus/llgo/runtime/internal/runtime.memequal8 + github.com/goplus/llgo/runtime/internal/runtime.memequal8 main.init: github.com/goplus/llgo/cl/_testmeta/interface_imported/api.init main.init$guard @@ -161,11 +141,11 @@ main.use: [MethodInfo] *_llgo_github.com/goplus/llgo/cl/_testmeta/interface_imported/api.Source: - 0 Close _llgo_func$8rsrSd_r3UHd_2DiYTyaOKR7BYkei4zw5ysG35KF38w github.com/goplus/llgo/cl/_testmeta/interface_imported/api.(*Source).Close __llgo_stub.github.com/goplus/llgo/cl/_testmeta/interface_imported/api.(*Source).Close - 1 Read _llgo_func$G2hch9Iy9DrhKKsg70PbL54bK-XSl-1IUUORN17J2Dk github.com/goplus/llgo/cl/_testmeta/interface_imported/api.(*Source).Read __llgo_stub.github.com/goplus/llgo/cl/_testmeta/interface_imported/api.(*Source).Read + 0 Close _llgo_func$8rsrSd_r3UHd_2DiYTyaOKR7BYkei4zw5ysG35KF38w github.com/goplus/llgo/cl/_testmeta/interface_imported/api.(*Source).Close github.com/goplus/llgo/cl/_testmeta/interface_imported/api.(*Source).Close + 1 Read _llgo_func$G2hch9Iy9DrhKKsg70PbL54bK-XSl-1IUUORN17J2Dk github.com/goplus/llgo/cl/_testmeta/interface_imported/api.(*Source).Read github.com/goplus/llgo/cl/_testmeta/interface_imported/api.(*Source).Read _llgo_github.com/goplus/llgo/cl/_testmeta/interface_imported/api.Source: - 0 Close _llgo_func$8rsrSd_r3UHd_2DiYTyaOKR7BYkei4zw5ysG35KF38w github.com/goplus/llgo/cl/_testmeta/interface_imported/api.(*Source).Close __llgo_stub.github.com/goplus/llgo/cl/_testmeta/interface_imported/api.Source.Close - 1 Read _llgo_func$G2hch9Iy9DrhKKsg70PbL54bK-XSl-1IUUORN17J2Dk github.com/goplus/llgo/cl/_testmeta/interface_imported/api.(*Source).Read __llgo_stub.github.com/goplus/llgo/cl/_testmeta/interface_imported/api.Source.Read + 0 Close _llgo_func$8rsrSd_r3UHd_2DiYTyaOKR7BYkei4zw5ysG35KF38w github.com/goplus/llgo/cl/_testmeta/interface_imported/api.(*Source).Close github.com/goplus/llgo/cl/_testmeta/interface_imported/api.Source.Close + 1 Read _llgo_func$G2hch9Iy9DrhKKsg70PbL54bK-XSl-1IUUORN17J2Dk github.com/goplus/llgo/cl/_testmeta/interface_imported/api.(*Source).Read github.com/goplus/llgo/cl/_testmeta/interface_imported/api.Source.Read [InterfaceInfo] _llgo_iface$uycIKA3bbxRhudEjW1hHKWKdLqHQsCVy8NdW1bkQmNw: diff --git a/cl/_testmeta/interface_named/meta-expect.txt b/cl/_testmeta/interface_named/meta-expect.txt index 156ce8ac43..1eca6ed529 100644 --- a/cl/_testmeta/interface_named/meta-expect.txt +++ b/cl/_testmeta/interface_named/meta-expect.txt @@ -12,35 +12,25 @@ _llgo_main.T: [OrdinaryEdges] *_llgo_func$2_iS07vIlF2_rZqWB5eU0IvP_9HviM4MYZNkXZDvbac: - __llgo_stub.github.com/goplus/llgo/runtime/internal/runtime.memequalptr _llgo_func$2_iS07vIlF2_rZqWB5eU0IvP_9HviM4MYZNkXZDvbac + github.com/goplus/llgo/runtime/internal/runtime.memequalptr *_llgo_iface$anEWstLioBmxcO9rxTXClbAzDIEQLw2tApwq0mcSt88: - __llgo_stub.github.com/goplus/llgo/runtime/internal/runtime.memequalptr _llgo_iface$anEWstLioBmxcO9rxTXClbAzDIEQLw2tApwq0mcSt88 + github.com/goplus/llgo/runtime/internal/runtime.memequalptr *_llgo_main.T: - __llgo_stub.github.com/goplus/llgo/runtime/internal/runtime.memequalptr _llgo_main.T -__llgo_stub.github.com/goplus/llgo/runtime/internal/runtime.interequal: - github.com/goplus/llgo/runtime/internal/runtime.interequal -__llgo_stub.github.com/goplus/llgo/runtime/internal/runtime.memequal0: - github.com/goplus/llgo/runtime/internal/runtime.memequal0 -__llgo_stub.github.com/goplus/llgo/runtime/internal/runtime.memequalptr: github.com/goplus/llgo/runtime/internal/runtime.memequalptr -__llgo_stub.main.(*T).M: - main.(*T).M -__llgo_stub.main.T.M: - main.T.M _llgo_func$2_iS07vIlF2_rZqWB5eU0IvP_9HviM4MYZNkXZDvbac: *_llgo_func$2_iS07vIlF2_rZqWB5eU0IvP_9HviM4MYZNkXZDvbac _llgo_iface$anEWstLioBmxcO9rxTXClbAzDIEQLw2tApwq0mcSt88: *_llgo_iface$anEWstLioBmxcO9rxTXClbAzDIEQLw2tApwq0mcSt88 - __llgo_stub.github.com/goplus/llgo/runtime/internal/runtime.interequal _llgo_iface$anEWstLioBmxcO9rxTXClbAzDIEQLw2tApwq0mcSt88$imethods + github.com/goplus/llgo/runtime/internal/runtime.interequal _llgo_iface$anEWstLioBmxcO9rxTXClbAzDIEQLw2tApwq0mcSt88$imethods: _llgo_func$2_iS07vIlF2_rZqWB5eU0IvP_9HviM4MYZNkXZDvbac _llgo_main.T: *_llgo_main.T - __llgo_stub.github.com/goplus/llgo/runtime/internal/runtime.memequal0 + github.com/goplus/llgo/runtime/internal/runtime.memequal0 main.(*T).M: github.com/goplus/llgo/runtime/internal/runtime.AssertNilDeref github.com/goplus/llgo/runtime/internal/runtime.PanicWrapNilPointer @@ -66,9 +56,9 @@ main.use: [MethodInfo] *_llgo_main.T: - 0 M _llgo_func$2_iS07vIlF2_rZqWB5eU0IvP_9HviM4MYZNkXZDvbac main.(*T).M __llgo_stub.main.(*T).M + 0 M _llgo_func$2_iS07vIlF2_rZqWB5eU0IvP_9HviM4MYZNkXZDvbac main.(*T).M main.(*T).M _llgo_main.T: - 0 M _llgo_func$2_iS07vIlF2_rZqWB5eU0IvP_9HviM4MYZNkXZDvbac main.(*T).M __llgo_stub.main.T.M + 0 M _llgo_func$2_iS07vIlF2_rZqWB5eU0IvP_9HviM4MYZNkXZDvbac main.(*T).M main.T.M [InterfaceInfo] _llgo_iface$anEWstLioBmxcO9rxTXClbAzDIEQLw2tApwq0mcSt88: diff --git a/cl/_testmeta/interface_unexported/meta-expect.txt b/cl/_testmeta/interface_unexported/meta-expect.txt index 343c0c4c81..ccdf02bfb2 100644 --- a/cl/_testmeta/interface_unexported/meta-expect.txt +++ b/cl/_testmeta/interface_unexported/meta-expect.txt @@ -12,33 +12,23 @@ _llgo_main.T: [OrdinaryEdges] *_llgo_func$2_iS07vIlF2_rZqWB5eU0IvP_9HviM4MYZNkXZDvbac: - __llgo_stub.github.com/goplus/llgo/runtime/internal/runtime.memequalptr _llgo_func$2_iS07vIlF2_rZqWB5eU0IvP_9HviM4MYZNkXZDvbac + github.com/goplus/llgo/runtime/internal/runtime.memequalptr *_llgo_main.T: - __llgo_stub.github.com/goplus/llgo/runtime/internal/runtime.memequalptr _llgo_main.T + github.com/goplus/llgo/runtime/internal/runtime.memequalptr *github.com/goplus/llgo/cl/_testmeta/interface_unexported.iface$SE5y-KS93u1u9p1qAf9LRB1hncS44rJIq27_JZbIQVo: - __llgo_stub.github.com/goplus/llgo/runtime/internal/runtime.memequalptr github.com/goplus/llgo/cl/_testmeta/interface_unexported.iface$SE5y-KS93u1u9p1qAf9LRB1hncS44rJIq27_JZbIQVo -__llgo_stub.github.com/goplus/llgo/runtime/internal/runtime.interequal: - github.com/goplus/llgo/runtime/internal/runtime.interequal -__llgo_stub.github.com/goplus/llgo/runtime/internal/runtime.memequal0: - github.com/goplus/llgo/runtime/internal/runtime.memequal0 -__llgo_stub.github.com/goplus/llgo/runtime/internal/runtime.memequalptr: github.com/goplus/llgo/runtime/internal/runtime.memequalptr -__llgo_stub.main.(*T).m: - main.(*T).m -__llgo_stub.main.T.m: - main.T.m _llgo_func$2_iS07vIlF2_rZqWB5eU0IvP_9HviM4MYZNkXZDvbac: *_llgo_func$2_iS07vIlF2_rZqWB5eU0IvP_9HviM4MYZNkXZDvbac _llgo_main.T: *_llgo_main.T - __llgo_stub.github.com/goplus/llgo/runtime/internal/runtime.memequal0 + github.com/goplus/llgo/runtime/internal/runtime.memequal0 github.com/goplus/llgo/cl/_testmeta/interface_unexported.iface$SE5y-KS93u1u9p1qAf9LRB1hncS44rJIq27_JZbIQVo: *github.com/goplus/llgo/cl/_testmeta/interface_unexported.iface$SE5y-KS93u1u9p1qAf9LRB1hncS44rJIq27_JZbIQVo - __llgo_stub.github.com/goplus/llgo/runtime/internal/runtime.interequal github.com/goplus/llgo/cl/_testmeta/interface_unexported.iface$SE5y-KS93u1u9p1qAf9LRB1hncS44rJIq27_JZbIQVo$imethods + github.com/goplus/llgo/runtime/internal/runtime.interequal github.com/goplus/llgo/cl/_testmeta/interface_unexported.iface$SE5y-KS93u1u9p1qAf9LRB1hncS44rJIq27_JZbIQVo$imethods: _llgo_func$2_iS07vIlF2_rZqWB5eU0IvP_9HviM4MYZNkXZDvbac main.(*T).m: @@ -66,9 +56,9 @@ main.use: [MethodInfo] *_llgo_main.T: - 0 main.m _llgo_func$2_iS07vIlF2_rZqWB5eU0IvP_9HviM4MYZNkXZDvbac main.(*T).m __llgo_stub.main.(*T).m + 0 main.m _llgo_func$2_iS07vIlF2_rZqWB5eU0IvP_9HviM4MYZNkXZDvbac main.(*T).m main.(*T).m _llgo_main.T: - 0 main.m _llgo_func$2_iS07vIlF2_rZqWB5eU0IvP_9HviM4MYZNkXZDvbac main.(*T).m __llgo_stub.main.T.m + 0 main.m _llgo_func$2_iS07vIlF2_rZqWB5eU0IvP_9HviM4MYZNkXZDvbac main.(*T).m main.T.m [InterfaceInfo] github.com/goplus/llgo/cl/_testmeta/interface_unexported.iface$SE5y-KS93u1u9p1qAf9LRB1hncS44rJIq27_JZbIQVo: diff --git a/cl/_testmeta/methodinfo_imported/meta-expect.txt b/cl/_testmeta/methodinfo_imported/meta-expect.txt index 85035b0228..3776000c2d 100644 --- a/cl/_testmeta/methodinfo_imported/meta-expect.txt +++ b/cl/_testmeta/methodinfo_imported/meta-expect.txt @@ -177,190 +177,122 @@ _llgo_uint8: [OrdinaryEdges] *[]_llgo_uint8: []_llgo_uint8 - __llgo_stub.github.com/goplus/llgo/runtime/internal/runtime.memequalptr + github.com/goplus/llgo/runtime/internal/runtime.memequalptr *_llgo_bool: - __llgo_stub.github.com/goplus/llgo/runtime/internal/runtime.memequalptr _llgo_bool + github.com/goplus/llgo/runtime/internal/runtime.memequalptr *_llgo_bytes.Buffer: - __llgo_stub.github.com/goplus/llgo/runtime/internal/runtime.memequalptr _llgo_bytes.Buffer + github.com/goplus/llgo/runtime/internal/runtime.memequalptr *_llgo_bytes.readOp: - __llgo_stub.github.com/goplus/llgo/runtime/internal/runtime.memequalptr _llgo_bytes.readOp + github.com/goplus/llgo/runtime/internal/runtime.memequalptr *_llgo_error: - __llgo_stub.github.com/goplus/llgo/runtime/internal/runtime.memequalptr _llgo_error + github.com/goplus/llgo/runtime/internal/runtime.memequalptr *_llgo_func$2_iS07vIlF2_rZqWB5eU0IvP_9HviM4MYZNkXZDvbac: - __llgo_stub.github.com/goplus/llgo/runtime/internal/runtime.memequalptr _llgo_func$2_iS07vIlF2_rZqWB5eU0IvP_9HviM4MYZNkXZDvbac + github.com/goplus/llgo/runtime/internal/runtime.memequalptr *_llgo_func$8rsrSd_r3UHd_2DiYTyaOKR7BYkei4zw5ysG35KF38w: - __llgo_stub.github.com/goplus/llgo/runtime/internal/runtime.memequalptr _llgo_func$8rsrSd_r3UHd_2DiYTyaOKR7BYkei4zw5ysG35KF38w + github.com/goplus/llgo/runtime/internal/runtime.memequalptr *_llgo_func$ETeB8WwW04JEq0ztcm-XPTJtuYvtpkjIsAc0-2NT9zA: - __llgo_stub.github.com/goplus/llgo/runtime/internal/runtime.memequalptr _llgo_func$ETeB8WwW04JEq0ztcm-XPTJtuYvtpkjIsAc0-2NT9zA + github.com/goplus/llgo/runtime/internal/runtime.memequalptr *_llgo_func$G2hch9Iy9DrhKKsg70PbL54bK-XSl-1IUUORN17J2Dk: - __llgo_stub.github.com/goplus/llgo/runtime/internal/runtime.memequalptr _llgo_func$G2hch9Iy9DrhKKsg70PbL54bK-XSl-1IUUORN17J2Dk + github.com/goplus/llgo/runtime/internal/runtime.memequalptr *_llgo_func$TBlCn7YTQdraI1HMiBWmkrqIGG-8UgD1UVyJy62Z_0o: - __llgo_stub.github.com/goplus/llgo/runtime/internal/runtime.memequalptr _llgo_func$TBlCn7YTQdraI1HMiBWmkrqIGG-8UgD1UVyJy62Z_0o + github.com/goplus/llgo/runtime/internal/runtime.memequalptr *_llgo_func$VZ-8VPNF1RaLICwxc1Ghn7BbgyFX3v762OCdx127EkA: - __llgo_stub.github.com/goplus/llgo/runtime/internal/runtime.memequalptr _llgo_func$VZ-8VPNF1RaLICwxc1Ghn7BbgyFX3v762OCdx127EkA + github.com/goplus/llgo/runtime/internal/runtime.memequalptr *_llgo_func$YHeRw3AOvQtzv982-ZO3Yn8vh3Fx89RM3VvI8E4iKVk: - __llgo_stub.github.com/goplus/llgo/runtime/internal/runtime.memequalptr _llgo_func$YHeRw3AOvQtzv982-ZO3Yn8vh3Fx89RM3VvI8E4iKVk + github.com/goplus/llgo/runtime/internal/runtime.memequalptr *_llgo_func$Z_-7GWzB37LCYRTQLsSYmEihg_hqBK8o_GbT88pqnPY: - __llgo_stub.github.com/goplus/llgo/runtime/internal/runtime.memequalptr _llgo_func$Z_-7GWzB37LCYRTQLsSYmEihg_hqBK8o_GbT88pqnPY + github.com/goplus/llgo/runtime/internal/runtime.memequalptr *_llgo_func$aJkaU3jhXr0Q2QraTe2_TTdupeMMW2MD66UwBxynRM0: - __llgo_stub.github.com/goplus/llgo/runtime/internal/runtime.memequalptr _llgo_func$aJkaU3jhXr0Q2QraTe2_TTdupeMMW2MD66UwBxynRM0 + github.com/goplus/llgo/runtime/internal/runtime.memequalptr *_llgo_func$c8Vvy7bpifdsF4PDKWnpU2KNuhLPRr7XBIDM-4p45sQ: - __llgo_stub.github.com/goplus/llgo/runtime/internal/runtime.memequalptr _llgo_func$c8Vvy7bpifdsF4PDKWnpU2KNuhLPRr7XBIDM-4p45sQ + github.com/goplus/llgo/runtime/internal/runtime.memequalptr *_llgo_func$d4kMA_oCkLwnd1j8nVlv1hwRarEVuCIrDCpnHhDz9UY: - __llgo_stub.github.com/goplus/llgo/runtime/internal/runtime.memequalptr _llgo_func$d4kMA_oCkLwnd1j8nVlv1hwRarEVuCIrDCpnHhDz9UY + github.com/goplus/llgo/runtime/internal/runtime.memequalptr *_llgo_func$ekGNsrYBSzltfAjxbl6T8H6Yq8j16wzqS3nDj2xxGMU: - __llgo_stub.github.com/goplus/llgo/runtime/internal/runtime.memequalptr _llgo_func$ekGNsrYBSzltfAjxbl6T8H6Yq8j16wzqS3nDj2xxGMU + github.com/goplus/llgo/runtime/internal/runtime.memequalptr *_llgo_func$lukqSsfDYBoIp_R8GMojGkZnrYDqaq2iHn8RkCjW7iQ: - __llgo_stub.github.com/goplus/llgo/runtime/internal/runtime.memequalptr _llgo_func$lukqSsfDYBoIp_R8GMojGkZnrYDqaq2iHn8RkCjW7iQ + github.com/goplus/llgo/runtime/internal/runtime.memequalptr *_llgo_func$q-bw-_pPYBCXnr1TXIF8sOD4fVVzzIlpHqD-A13AB4Y: - __llgo_stub.github.com/goplus/llgo/runtime/internal/runtime.memequalptr _llgo_func$q-bw-_pPYBCXnr1TXIF8sOD4fVVzzIlpHqD-A13AB4Y + github.com/goplus/llgo/runtime/internal/runtime.memequalptr *_llgo_func$qVJ5SH6qhXP_h0AM41vpBGzQEMp-fQIfvwQEJy5NI8M: - __llgo_stub.github.com/goplus/llgo/runtime/internal/runtime.memequalptr _llgo_func$qVJ5SH6qhXP_h0AM41vpBGzQEMp-fQIfvwQEJy5NI8M + github.com/goplus/llgo/runtime/internal/runtime.memequalptr *_llgo_func$thH5FBpdXzJNnCpSfiLU5ItTntFU6LWp0RJhDm2XJjw: - __llgo_stub.github.com/goplus/llgo/runtime/internal/runtime.memequalptr _llgo_func$thH5FBpdXzJNnCpSfiLU5ItTntFU6LWp0RJhDm2XJjw + github.com/goplus/llgo/runtime/internal/runtime.memequalptr *_llgo_func$uVmBDI0DMcrui3Q9y-g_hbtVN8JckQ18V2wmO5_G7A8: - __llgo_stub.github.com/goplus/llgo/runtime/internal/runtime.memequalptr _llgo_func$uVmBDI0DMcrui3Q9y-g_hbtVN8JckQ18V2wmO5_G7A8 + github.com/goplus/llgo/runtime/internal/runtime.memequalptr *_llgo_func$uf8yw1UkUdbDuCneSpNKIq_NThWIEVE7f1IYfJGz_bw: - __llgo_stub.github.com/goplus/llgo/runtime/internal/runtime.memequalptr _llgo_func$uf8yw1UkUdbDuCneSpNKIq_NThWIEVE7f1IYfJGz_bw + github.com/goplus/llgo/runtime/internal/runtime.memequalptr *_llgo_func$vSv85k0UY6JWccAc3T-lvdCx9J-4GM-oZC9zGLrxW1M: - __llgo_stub.github.com/goplus/llgo/runtime/internal/runtime.memequalptr _llgo_func$vSv85k0UY6JWccAc3T-lvdCx9J-4GM-oZC9zGLrxW1M + github.com/goplus/llgo/runtime/internal/runtime.memequalptr *_llgo_func$w4tN9iibS_UimF5vLUWoKP0uAk2tJZF26VqETo_8LVg: - __llgo_stub.github.com/goplus/llgo/runtime/internal/runtime.memequalptr _llgo_func$w4tN9iibS_UimF5vLUWoKP0uAk2tJZF26VqETo_8LVg + github.com/goplus/llgo/runtime/internal/runtime.memequalptr *_llgo_func$zNDVRsWTIpUPKouNUS805RGX--IV9qVK8B31IZbg5to: - __llgo_stub.github.com/goplus/llgo/runtime/internal/runtime.memequalptr _llgo_func$zNDVRsWTIpUPKouNUS805RGX--IV9qVK8B31IZbg5to + github.com/goplus/llgo/runtime/internal/runtime.memequalptr *_llgo_iface$uycIKA3bbxRhudEjW1hHKWKdLqHQsCVy8NdW1bkQmNw: - __llgo_stub.github.com/goplus/llgo/runtime/internal/runtime.memequalptr _llgo_iface$uycIKA3bbxRhudEjW1hHKWKdLqHQsCVy8NdW1bkQmNw + github.com/goplus/llgo/runtime/internal/runtime.memequalptr *_llgo_int: - __llgo_stub.github.com/goplus/llgo/runtime/internal/runtime.memequalptr _llgo_int + github.com/goplus/llgo/runtime/internal/runtime.memequalptr *_llgo_int32: - __llgo_stub.github.com/goplus/llgo/runtime/internal/runtime.memequalptr _llgo_int32 + github.com/goplus/llgo/runtime/internal/runtime.memequalptr *_llgo_int64: - __llgo_stub.github.com/goplus/llgo/runtime/internal/runtime.memequalptr _llgo_int64 + github.com/goplus/llgo/runtime/internal/runtime.memequalptr *_llgo_io.Reader: - __llgo_stub.github.com/goplus/llgo/runtime/internal/runtime.memequalptr _llgo_io.Reader + github.com/goplus/llgo/runtime/internal/runtime.memequalptr *_llgo_io.Writer: - __llgo_stub.github.com/goplus/llgo/runtime/internal/runtime.memequalptr _llgo_io.Writer + github.com/goplus/llgo/runtime/internal/runtime.memequalptr *_llgo_string: - __llgo_stub.github.com/goplus/llgo/runtime/internal/runtime.memequalptr _llgo_string + github.com/goplus/llgo/runtime/internal/runtime.memequalptr *_llgo_uint8: - __llgo_stub.github.com/goplus/llgo/runtime/internal/runtime.memequalptr _llgo_uint8 + github.com/goplus/llgo/runtime/internal/runtime.memequalptr []_llgo_uint8: *[]_llgo_uint8 _llgo_uint8 -__llgo_stub.bytes.(*Buffer).Available: - bytes.(*Buffer).Available -__llgo_stub.bytes.(*Buffer).AvailableBuffer: - bytes.(*Buffer).AvailableBuffer -__llgo_stub.bytes.(*Buffer).Bytes: - bytes.(*Buffer).Bytes -__llgo_stub.bytes.(*Buffer).Cap: - bytes.(*Buffer).Cap -__llgo_stub.bytes.(*Buffer).Grow: - bytes.(*Buffer).Grow -__llgo_stub.bytes.(*Buffer).Len: - bytes.(*Buffer).Len -__llgo_stub.bytes.(*Buffer).Next: - bytes.(*Buffer).Next -__llgo_stub.bytes.(*Buffer).Peek: - bytes.(*Buffer).Peek -__llgo_stub.bytes.(*Buffer).Read: - bytes.(*Buffer).Read -__llgo_stub.bytes.(*Buffer).ReadByte: - bytes.(*Buffer).ReadByte -__llgo_stub.bytes.(*Buffer).ReadBytes: - bytes.(*Buffer).ReadBytes -__llgo_stub.bytes.(*Buffer).ReadFrom: - bytes.(*Buffer).ReadFrom -__llgo_stub.bytes.(*Buffer).ReadRune: - bytes.(*Buffer).ReadRune -__llgo_stub.bytes.(*Buffer).ReadString: - bytes.(*Buffer).ReadString -__llgo_stub.bytes.(*Buffer).Reset: - bytes.(*Buffer).Reset -__llgo_stub.bytes.(*Buffer).String: - bytes.(*Buffer).String -__llgo_stub.bytes.(*Buffer).Truncate: - bytes.(*Buffer).Truncate -__llgo_stub.bytes.(*Buffer).UnreadByte: - bytes.(*Buffer).UnreadByte -__llgo_stub.bytes.(*Buffer).UnreadRune: - bytes.(*Buffer).UnreadRune -__llgo_stub.bytes.(*Buffer).Write: - bytes.(*Buffer).Write -__llgo_stub.bytes.(*Buffer).WriteByte: - bytes.(*Buffer).WriteByte -__llgo_stub.bytes.(*Buffer).WriteRune: - bytes.(*Buffer).WriteRune -__llgo_stub.bytes.(*Buffer).WriteString: - bytes.(*Buffer).WriteString -__llgo_stub.bytes.(*Buffer).WriteTo: - bytes.(*Buffer).WriteTo -__llgo_stub.bytes.(*Buffer).empty: - bytes.(*Buffer).empty -__llgo_stub.bytes.(*Buffer).grow: - bytes.(*Buffer).grow -__llgo_stub.bytes.(*Buffer).readSlice: - bytes.(*Buffer).readSlice -__llgo_stub.bytes.(*Buffer).tryGrowByReslice: - bytes.(*Buffer).tryGrowByReslice -__llgo_stub.github.com/goplus/llgo/runtime/internal/runtime.interequal: - github.com/goplus/llgo/runtime/internal/runtime.interequal -__llgo_stub.github.com/goplus/llgo/runtime/internal/runtime.memequal32: - github.com/goplus/llgo/runtime/internal/runtime.memequal32 -__llgo_stub.github.com/goplus/llgo/runtime/internal/runtime.memequal64: - github.com/goplus/llgo/runtime/internal/runtime.memequal64 -__llgo_stub.github.com/goplus/llgo/runtime/internal/runtime.memequal8: - github.com/goplus/llgo/runtime/internal/runtime.memequal8 -__llgo_stub.github.com/goplus/llgo/runtime/internal/runtime.memequalptr: - github.com/goplus/llgo/runtime/internal/runtime.memequalptr -__llgo_stub.github.com/goplus/llgo/runtime/internal/runtime.strequal: - github.com/goplus/llgo/runtime/internal/runtime.strequal _llgo_bool: *_llgo_bool - __llgo_stub.github.com/goplus/llgo/runtime/internal/runtime.memequal8 + github.com/goplus/llgo/runtime/internal/runtime.memequal8 _llgo_bytes.Buffer: *_llgo_bytes.Buffer bytes.struct$8M6lRFZ7Fk2XCr2laNI9Y7uQtk2A8VDBrezMuq2Fkuo$fields _llgo_bytes.readOp: *_llgo_bytes.readOp - __llgo_stub.github.com/goplus/llgo/runtime/internal/runtime.memequal8 + github.com/goplus/llgo/runtime/internal/runtime.memequal8 _llgo_error: *_llgo_error - __llgo_stub.github.com/goplus/llgo/runtime/internal/runtime.interequal _llgo_iface$Fh8eUJ-Gw4e6TYuajcFIOSCuqSPKAt5nS4ow7xeGXEU$imethods + github.com/goplus/llgo/runtime/internal/runtime.interequal _llgo_func$2_iS07vIlF2_rZqWB5eU0IvP_9HviM4MYZNkXZDvbac: *_llgo_func$2_iS07vIlF2_rZqWB5eU0IvP_9HviM4MYZNkXZDvbac _llgo_func$8rsrSd_r3UHd_2DiYTyaOKR7BYkei4zw5ysG35KF38w: @@ -517,33 +449,33 @@ _llgo_iface$kr1iSWwMezh0B9LdQN0MhEZUNZvBlHPhlst95jAyxE0$imethods: _llgo_func$G2hch9Iy9DrhKKsg70PbL54bK-XSl-1IUUORN17J2Dk _llgo_iface$uycIKA3bbxRhudEjW1hHKWKdLqHQsCVy8NdW1bkQmNw: *_llgo_iface$uycIKA3bbxRhudEjW1hHKWKdLqHQsCVy8NdW1bkQmNw - __llgo_stub.github.com/goplus/llgo/runtime/internal/runtime.interequal _llgo_iface$uycIKA3bbxRhudEjW1hHKWKdLqHQsCVy8NdW1bkQmNw$imethods + github.com/goplus/llgo/runtime/internal/runtime.interequal _llgo_iface$uycIKA3bbxRhudEjW1hHKWKdLqHQsCVy8NdW1bkQmNw$imethods: _llgo_func$G2hch9Iy9DrhKKsg70PbL54bK-XSl-1IUUORN17J2Dk _llgo_int: *_llgo_int - __llgo_stub.github.com/goplus/llgo/runtime/internal/runtime.memequal64 + github.com/goplus/llgo/runtime/internal/runtime.memequal64 _llgo_int32: *_llgo_int32 - __llgo_stub.github.com/goplus/llgo/runtime/internal/runtime.memequal32 + github.com/goplus/llgo/runtime/internal/runtime.memequal32 _llgo_int64: *_llgo_int64 - __llgo_stub.github.com/goplus/llgo/runtime/internal/runtime.memequal64 + github.com/goplus/llgo/runtime/internal/runtime.memequal64 _llgo_io.Reader: *_llgo_io.Reader - __llgo_stub.github.com/goplus/llgo/runtime/internal/runtime.interequal _llgo_iface$uycIKA3bbxRhudEjW1hHKWKdLqHQsCVy8NdW1bkQmNw$imethods + github.com/goplus/llgo/runtime/internal/runtime.interequal _llgo_io.Writer: *_llgo_io.Writer - __llgo_stub.github.com/goplus/llgo/runtime/internal/runtime.interequal _llgo_iface$kr1iSWwMezh0B9LdQN0MhEZUNZvBlHPhlst95jAyxE0$imethods + github.com/goplus/llgo/runtime/internal/runtime.interequal _llgo_string: *_llgo_string - __llgo_stub.github.com/goplus/llgo/runtime/internal/runtime.strequal + github.com/goplus/llgo/runtime/internal/runtime.strequal _llgo_uint8: *_llgo_uint8 - __llgo_stub.github.com/goplus/llgo/runtime/internal/runtime.memequal8 + github.com/goplus/llgo/runtime/internal/runtime.memequal8 bytes.struct$8M6lRFZ7Fk2XCr2laNI9Y7uQtk2A8VDBrezMuq2Fkuo$fields: []_llgo_uint8 _llgo_bytes.readOp @@ -569,34 +501,34 @@ main.main: [MethodInfo] *_llgo_bytes.Buffer: - 0 Available _llgo_func$ETeB8WwW04JEq0ztcm-XPTJtuYvtpkjIsAc0-2NT9zA bytes.(*Buffer).Available __llgo_stub.bytes.(*Buffer).Available - 1 AvailableBuffer _llgo_func$Z_-7GWzB37LCYRTQLsSYmEihg_hqBK8o_GbT88pqnPY bytes.(*Buffer).AvailableBuffer __llgo_stub.bytes.(*Buffer).AvailableBuffer - 2 Bytes _llgo_func$Z_-7GWzB37LCYRTQLsSYmEihg_hqBK8o_GbT88pqnPY bytes.(*Buffer).Bytes __llgo_stub.bytes.(*Buffer).Bytes - 3 Cap _llgo_func$ETeB8WwW04JEq0ztcm-XPTJtuYvtpkjIsAc0-2NT9zA bytes.(*Buffer).Cap __llgo_stub.bytes.(*Buffer).Cap - 4 Grow _llgo_func$VZ-8VPNF1RaLICwxc1Ghn7BbgyFX3v762OCdx127EkA bytes.(*Buffer).Grow __llgo_stub.bytes.(*Buffer).Grow - 5 Len _llgo_func$ETeB8WwW04JEq0ztcm-XPTJtuYvtpkjIsAc0-2NT9zA bytes.(*Buffer).Len __llgo_stub.bytes.(*Buffer).Len - 6 Next _llgo_func$d4kMA_oCkLwnd1j8nVlv1hwRarEVuCIrDCpnHhDz9UY bytes.(*Buffer).Next __llgo_stub.bytes.(*Buffer).Next - 7 Peek _llgo_func$c8Vvy7bpifdsF4PDKWnpU2KNuhLPRr7XBIDM-4p45sQ bytes.(*Buffer).Peek __llgo_stub.bytes.(*Buffer).Peek - 8 Read _llgo_func$G2hch9Iy9DrhKKsg70PbL54bK-XSl-1IUUORN17J2Dk bytes.(*Buffer).Read __llgo_stub.bytes.(*Buffer).Read - 9 ReadByte _llgo_func$lukqSsfDYBoIp_R8GMojGkZnrYDqaq2iHn8RkCjW7iQ bytes.(*Buffer).ReadByte __llgo_stub.bytes.(*Buffer).ReadByte - 10 ReadBytes _llgo_func$aJkaU3jhXr0Q2QraTe2_TTdupeMMW2MD66UwBxynRM0 bytes.(*Buffer).ReadBytes __llgo_stub.bytes.(*Buffer).ReadBytes - 11 ReadFrom _llgo_func$uVmBDI0DMcrui3Q9y-g_hbtVN8JckQ18V2wmO5_G7A8 bytes.(*Buffer).ReadFrom __llgo_stub.bytes.(*Buffer).ReadFrom - 12 ReadRune _llgo_func$q-bw-_pPYBCXnr1TXIF8sOD4fVVzzIlpHqD-A13AB4Y bytes.(*Buffer).ReadRune __llgo_stub.bytes.(*Buffer).ReadRune - 13 ReadString _llgo_func$TBlCn7YTQdraI1HMiBWmkrqIGG-8UgD1UVyJy62Z_0o bytes.(*Buffer).ReadString __llgo_stub.bytes.(*Buffer).ReadString - 14 Reset _llgo_func$2_iS07vIlF2_rZqWB5eU0IvP_9HviM4MYZNkXZDvbac bytes.(*Buffer).Reset __llgo_stub.bytes.(*Buffer).Reset - 15 String _llgo_func$zNDVRsWTIpUPKouNUS805RGX--IV9qVK8B31IZbg5to bytes.(*Buffer).String __llgo_stub.bytes.(*Buffer).String - 16 Truncate _llgo_func$VZ-8VPNF1RaLICwxc1Ghn7BbgyFX3v762OCdx127EkA bytes.(*Buffer).Truncate __llgo_stub.bytes.(*Buffer).Truncate - 17 UnreadByte _llgo_func$8rsrSd_r3UHd_2DiYTyaOKR7BYkei4zw5ysG35KF38w bytes.(*Buffer).UnreadByte __llgo_stub.bytes.(*Buffer).UnreadByte - 18 UnreadRune _llgo_func$8rsrSd_r3UHd_2DiYTyaOKR7BYkei4zw5ysG35KF38w bytes.(*Buffer).UnreadRune __llgo_stub.bytes.(*Buffer).UnreadRune - 19 Write _llgo_func$G2hch9Iy9DrhKKsg70PbL54bK-XSl-1IUUORN17J2Dk bytes.(*Buffer).Write __llgo_stub.bytes.(*Buffer).Write - 20 WriteByte _llgo_func$w4tN9iibS_UimF5vLUWoKP0uAk2tJZF26VqETo_8LVg bytes.(*Buffer).WriteByte __llgo_stub.bytes.(*Buffer).WriteByte - 21 WriteRune _llgo_func$uf8yw1UkUdbDuCneSpNKIq_NThWIEVE7f1IYfJGz_bw bytes.(*Buffer).WriteRune __llgo_stub.bytes.(*Buffer).WriteRune - 22 WriteString _llgo_func$thH5FBpdXzJNnCpSfiLU5ItTntFU6LWp0RJhDm2XJjw bytes.(*Buffer).WriteString __llgo_stub.bytes.(*Buffer).WriteString - 23 WriteTo _llgo_func$vSv85k0UY6JWccAc3T-lvdCx9J-4GM-oZC9zGLrxW1M bytes.(*Buffer).WriteTo __llgo_stub.bytes.(*Buffer).WriteTo - 24 bytes.empty _llgo_func$YHeRw3AOvQtzv982-ZO3Yn8vh3Fx89RM3VvI8E4iKVk bytes.(*Buffer).empty __llgo_stub.bytes.(*Buffer).empty - 25 bytes.grow _llgo_func$ekGNsrYBSzltfAjxbl6T8H6Yq8j16wzqS3nDj2xxGMU bytes.(*Buffer).grow __llgo_stub.bytes.(*Buffer).grow - 26 bytes.readSlice _llgo_func$aJkaU3jhXr0Q2QraTe2_TTdupeMMW2MD66UwBxynRM0 bytes.(*Buffer).readSlice __llgo_stub.bytes.(*Buffer).readSlice - 27 bytes.tryGrowByReslice _llgo_func$qVJ5SH6qhXP_h0AM41vpBGzQEMp-fQIfvwQEJy5NI8M bytes.(*Buffer).tryGrowByReslice __llgo_stub.bytes.(*Buffer).tryGrowByReslice + 0 Available _llgo_func$ETeB8WwW04JEq0ztcm-XPTJtuYvtpkjIsAc0-2NT9zA bytes.(*Buffer).Available bytes.(*Buffer).Available + 1 AvailableBuffer _llgo_func$Z_-7GWzB37LCYRTQLsSYmEihg_hqBK8o_GbT88pqnPY bytes.(*Buffer).AvailableBuffer bytes.(*Buffer).AvailableBuffer + 2 Bytes _llgo_func$Z_-7GWzB37LCYRTQLsSYmEihg_hqBK8o_GbT88pqnPY bytes.(*Buffer).Bytes bytes.(*Buffer).Bytes + 3 Cap _llgo_func$ETeB8WwW04JEq0ztcm-XPTJtuYvtpkjIsAc0-2NT9zA bytes.(*Buffer).Cap bytes.(*Buffer).Cap + 4 Grow _llgo_func$VZ-8VPNF1RaLICwxc1Ghn7BbgyFX3v762OCdx127EkA bytes.(*Buffer).Grow bytes.(*Buffer).Grow + 5 Len _llgo_func$ETeB8WwW04JEq0ztcm-XPTJtuYvtpkjIsAc0-2NT9zA bytes.(*Buffer).Len bytes.(*Buffer).Len + 6 Next _llgo_func$d4kMA_oCkLwnd1j8nVlv1hwRarEVuCIrDCpnHhDz9UY bytes.(*Buffer).Next bytes.(*Buffer).Next + 7 Peek _llgo_func$c8Vvy7bpifdsF4PDKWnpU2KNuhLPRr7XBIDM-4p45sQ bytes.(*Buffer).Peek bytes.(*Buffer).Peek + 8 Read _llgo_func$G2hch9Iy9DrhKKsg70PbL54bK-XSl-1IUUORN17J2Dk bytes.(*Buffer).Read bytes.(*Buffer).Read + 9 ReadByte _llgo_func$lukqSsfDYBoIp_R8GMojGkZnrYDqaq2iHn8RkCjW7iQ bytes.(*Buffer).ReadByte bytes.(*Buffer).ReadByte + 10 ReadBytes _llgo_func$aJkaU3jhXr0Q2QraTe2_TTdupeMMW2MD66UwBxynRM0 bytes.(*Buffer).ReadBytes bytes.(*Buffer).ReadBytes + 11 ReadFrom _llgo_func$uVmBDI0DMcrui3Q9y-g_hbtVN8JckQ18V2wmO5_G7A8 bytes.(*Buffer).ReadFrom bytes.(*Buffer).ReadFrom + 12 ReadRune _llgo_func$q-bw-_pPYBCXnr1TXIF8sOD4fVVzzIlpHqD-A13AB4Y bytes.(*Buffer).ReadRune bytes.(*Buffer).ReadRune + 13 ReadString _llgo_func$TBlCn7YTQdraI1HMiBWmkrqIGG-8UgD1UVyJy62Z_0o bytes.(*Buffer).ReadString bytes.(*Buffer).ReadString + 14 Reset _llgo_func$2_iS07vIlF2_rZqWB5eU0IvP_9HviM4MYZNkXZDvbac bytes.(*Buffer).Reset bytes.(*Buffer).Reset + 15 String _llgo_func$zNDVRsWTIpUPKouNUS805RGX--IV9qVK8B31IZbg5to bytes.(*Buffer).String bytes.(*Buffer).String + 16 Truncate _llgo_func$VZ-8VPNF1RaLICwxc1Ghn7BbgyFX3v762OCdx127EkA bytes.(*Buffer).Truncate bytes.(*Buffer).Truncate + 17 UnreadByte _llgo_func$8rsrSd_r3UHd_2DiYTyaOKR7BYkei4zw5ysG35KF38w bytes.(*Buffer).UnreadByte bytes.(*Buffer).UnreadByte + 18 UnreadRune _llgo_func$8rsrSd_r3UHd_2DiYTyaOKR7BYkei4zw5ysG35KF38w bytes.(*Buffer).UnreadRune bytes.(*Buffer).UnreadRune + 19 Write _llgo_func$G2hch9Iy9DrhKKsg70PbL54bK-XSl-1IUUORN17J2Dk bytes.(*Buffer).Write bytes.(*Buffer).Write + 20 WriteByte _llgo_func$w4tN9iibS_UimF5vLUWoKP0uAk2tJZF26VqETo_8LVg bytes.(*Buffer).WriteByte bytes.(*Buffer).WriteByte + 21 WriteRune _llgo_func$uf8yw1UkUdbDuCneSpNKIq_NThWIEVE7f1IYfJGz_bw bytes.(*Buffer).WriteRune bytes.(*Buffer).WriteRune + 22 WriteString _llgo_func$thH5FBpdXzJNnCpSfiLU5ItTntFU6LWp0RJhDm2XJjw bytes.(*Buffer).WriteString bytes.(*Buffer).WriteString + 23 WriteTo _llgo_func$vSv85k0UY6JWccAc3T-lvdCx9J-4GM-oZC9zGLrxW1M bytes.(*Buffer).WriteTo bytes.(*Buffer).WriteTo + 24 bytes.empty _llgo_func$YHeRw3AOvQtzv982-ZO3Yn8vh3Fx89RM3VvI8E4iKVk bytes.(*Buffer).empty bytes.(*Buffer).empty + 25 bytes.grow _llgo_func$ekGNsrYBSzltfAjxbl6T8H6Yq8j16wzqS3nDj2xxGMU bytes.(*Buffer).grow bytes.(*Buffer).grow + 26 bytes.readSlice _llgo_func$aJkaU3jhXr0Q2QraTe2_TTdupeMMW2MD66UwBxynRM0 bytes.(*Buffer).readSlice bytes.(*Buffer).readSlice + 27 bytes.tryGrowByReslice _llgo_func$qVJ5SH6qhXP_h0AM41vpBGzQEMp-fQIfvwQEJy5NI8M bytes.(*Buffer).tryGrowByReslice bytes.(*Buffer).tryGrowByReslice [InterfaceInfo] _llgo_iface$uycIKA3bbxRhudEjW1hHKWKdLqHQsCVy8NdW1bkQmNw: diff --git a/cl/_testmeta/reflect_dynamic/meta-expect.txt b/cl/_testmeta/reflect_dynamic/meta-expect.txt index cbf96a6272..628325a77c 100644 --- a/cl/_testmeta/reflect_dynamic/meta-expect.txt +++ b/cl/_testmeta/reflect_dynamic/meta-expect.txt @@ -10,24 +10,16 @@ _llgo_main.T: [OrdinaryEdges] *_llgo_func$2_iS07vIlF2_rZqWB5eU0IvP_9HviM4MYZNkXZDvbac: - __llgo_stub.github.com/goplus/llgo/runtime/internal/runtime.memequalptr _llgo_func$2_iS07vIlF2_rZqWB5eU0IvP_9HviM4MYZNkXZDvbac + github.com/goplus/llgo/runtime/internal/runtime.memequalptr *_llgo_main.T: - __llgo_stub.github.com/goplus/llgo/runtime/internal/runtime.memequalptr _llgo_main.T -__llgo_stub.github.com/goplus/llgo/runtime/internal/runtime.memequal0: - github.com/goplus/llgo/runtime/internal/runtime.memequal0 -__llgo_stub.github.com/goplus/llgo/runtime/internal/runtime.memequalptr: github.com/goplus/llgo/runtime/internal/runtime.memequalptr -__llgo_stub.main.(*T).M: - main.(*T).M -__llgo_stub.main.T.M: - main.T.M _llgo_func$2_iS07vIlF2_rZqWB5eU0IvP_9HviM4MYZNkXZDvbac: *_llgo_func$2_iS07vIlF2_rZqWB5eU0IvP_9HviM4MYZNkXZDvbac _llgo_main.T: *_llgo_main.T - __llgo_stub.github.com/goplus/llgo/runtime/internal/runtime.memequal0 + github.com/goplus/llgo/runtime/internal/runtime.memequal0 main.(*T).M: github.com/goplus/llgo/runtime/internal/runtime.AssertNilDeref github.com/goplus/llgo/runtime/internal/runtime.PanicWrapNilPointer @@ -49,9 +41,9 @@ main.use: [MethodInfo] *_llgo_main.T: - 0 M _llgo_func$2_iS07vIlF2_rZqWB5eU0IvP_9HviM4MYZNkXZDvbac main.(*T).M __llgo_stub.main.(*T).M + 0 M _llgo_func$2_iS07vIlF2_rZqWB5eU0IvP_9HviM4MYZNkXZDvbac main.(*T).M main.(*T).M _llgo_main.T: - 0 M _llgo_func$2_iS07vIlF2_rZqWB5eU0IvP_9HviM4MYZNkXZDvbac main.(*T).M __llgo_stub.main.T.M + 0 M _llgo_func$2_iS07vIlF2_rZqWB5eU0IvP_9HviM4MYZNkXZDvbac main.(*T).M main.T.M [Reflect] main.use diff --git a/cl/_testmeta/reflect_named/meta-expect.txt b/cl/_testmeta/reflect_named/meta-expect.txt index 77bc7b262b..c3093e6bcd 100644 --- a/cl/_testmeta/reflect_named/meta-expect.txt +++ b/cl/_testmeta/reflect_named/meta-expect.txt @@ -10,28 +10,16 @@ _llgo_main.T: [OrdinaryEdges] *_llgo_func$2_iS07vIlF2_rZqWB5eU0IvP_9HviM4MYZNkXZDvbac: - __llgo_stub.github.com/goplus/llgo/runtime/internal/runtime.memequalptr _llgo_func$2_iS07vIlF2_rZqWB5eU0IvP_9HviM4MYZNkXZDvbac + github.com/goplus/llgo/runtime/internal/runtime.memequalptr *_llgo_main.T: - __llgo_stub.github.com/goplus/llgo/runtime/internal/runtime.memequalptr _llgo_main.T -__llgo_stub.github.com/goplus/llgo/runtime/internal/runtime.memequal0: - github.com/goplus/llgo/runtime/internal/runtime.memequal0 -__llgo_stub.github.com/goplus/llgo/runtime/internal/runtime.memequalptr: github.com/goplus/llgo/runtime/internal/runtime.memequalptr -__llgo_stub.main.(*T).M: - main.(*T).M -__llgo_stub.main.(*T).m: - main.(*T).m -__llgo_stub.main.T.M: - main.T.M -__llgo_stub.main.T.m: - main.T.m _llgo_func$2_iS07vIlF2_rZqWB5eU0IvP_9HviM4MYZNkXZDvbac: *_llgo_func$2_iS07vIlF2_rZqWB5eU0IvP_9HviM4MYZNkXZDvbac _llgo_main.T: *_llgo_main.T - __llgo_stub.github.com/goplus/llgo/runtime/internal/runtime.memequal0 + github.com/goplus/llgo/runtime/internal/runtime.memequal0 main.(*T).M: github.com/goplus/llgo/runtime/internal/runtime.AssertNilDeref github.com/goplus/llgo/runtime/internal/runtime.PanicWrapNilPointer @@ -66,11 +54,11 @@ main.main: [MethodInfo] *_llgo_main.T: - 0 M _llgo_func$2_iS07vIlF2_rZqWB5eU0IvP_9HviM4MYZNkXZDvbac main.(*T).M __llgo_stub.main.(*T).M - 1 main.m _llgo_func$2_iS07vIlF2_rZqWB5eU0IvP_9HviM4MYZNkXZDvbac main.(*T).m __llgo_stub.main.(*T).m + 0 M _llgo_func$2_iS07vIlF2_rZqWB5eU0IvP_9HviM4MYZNkXZDvbac main.(*T).M main.(*T).M + 1 main.m _llgo_func$2_iS07vIlF2_rZqWB5eU0IvP_9HviM4MYZNkXZDvbac main.(*T).m main.(*T).m _llgo_main.T: - 0 M _llgo_func$2_iS07vIlF2_rZqWB5eU0IvP_9HviM4MYZNkXZDvbac main.(*T).M __llgo_stub.main.T.M - 1 main.m _llgo_func$2_iS07vIlF2_rZqWB5eU0IvP_9HviM4MYZNkXZDvbac main.(*T).m __llgo_stub.main.T.m + 0 M _llgo_func$2_iS07vIlF2_rZqWB5eU0IvP_9HviM4MYZNkXZDvbac main.(*T).M main.T.M + 1 main.m _llgo_func$2_iS07vIlF2_rZqWB5eU0IvP_9HviM4MYZNkXZDvbac main.(*T).m main.T.m [InterfaceInfo] github.com/goplus/llgo/runtime/internal/lib/reflect.iface$mD8cc0P9iPHqG1cgYNbFpshv9b41oJ45HmjD5KeBlWw: diff --git a/cl/_testmeta/typechildren_basic/meta-expect.txt b/cl/_testmeta/typechildren_basic/meta-expect.txt index 658704e3fe..e989a483dc 100644 --- a/cl/_testmeta/typechildren_basic/meta-expect.txt +++ b/cl/_testmeta/typechildren_basic/meta-expect.txt @@ -21,26 +21,20 @@ _llgo_string: [OrdinaryEdges] *_llgo_int: - __llgo_stub.github.com/goplus/llgo/runtime/internal/runtime.memequalptr _llgo_int + github.com/goplus/llgo/runtime/internal/runtime.memequalptr *_llgo_main.Inner: - __llgo_stub.github.com/goplus/llgo/runtime/internal/runtime.memequalptr _llgo_main.Inner + github.com/goplus/llgo/runtime/internal/runtime.memequalptr *_llgo_main.Outer: - __llgo_stub.github.com/goplus/llgo/runtime/internal/runtime.memequalptr _llgo_main.Outer + github.com/goplus/llgo/runtime/internal/runtime.memequalptr *_llgo_string: - __llgo_stub.github.com/goplus/llgo/runtime/internal/runtime.memequalptr _llgo_string -__llgo_stub.github.com/goplus/llgo/runtime/internal/runtime.memequal64: - github.com/goplus/llgo/runtime/internal/runtime.memequal64 -__llgo_stub.github.com/goplus/llgo/runtime/internal/runtime.memequalptr: github.com/goplus/llgo/runtime/internal/runtime.memequalptr -__llgo_stub.github.com/goplus/llgo/runtime/internal/runtime.strequal: - github.com/goplus/llgo/runtime/internal/runtime.strequal _llgo_int: *_llgo_int - __llgo_stub.github.com/goplus/llgo/runtime/internal/runtime.memequal64 + github.com/goplus/llgo/runtime/internal/runtime.memequal64 _llgo_main.Inner: *_llgo_main.Inner _llgo_struct$MTAKiWNMPODH0G9-y5PI3BUGLd6hRciSbX1QTpCDOZg$fields @@ -51,7 +45,7 @@ _llgo_main.Outer: github.com/goplus/llgo/runtime/internal/runtime.structequal _llgo_string: *_llgo_string - __llgo_stub.github.com/goplus/llgo/runtime/internal/runtime.strequal + github.com/goplus/llgo/runtime/internal/runtime.strequal _llgo_struct$MTAKiWNMPODH0G9-y5PI3BUGLd6hRciSbX1QTpCDOZg$fields: _llgo_string _llgo_struct$Z-8Mj1VAYg5xS_jUvJKfmUcA_2fP_OEHpanbgA_46rE$fields: diff --git a/cl/_testrt/any/in.go b/cl/_testrt/any/in.go index e96e33052d..e7a4412ac7 100644 --- a/cl/_testrt/any/in.go +++ b/cl/_testrt/any/in.go @@ -77,15 +77,3 @@ func main() { // CHECK-NEXT: %4 = call i32 (ptr, ...) @printf(ptr @3, ptr %0, i64 %3) // CHECK-NEXT: ret void // CHECK-NEXT: } - -// CHECK-LABEL: define linkonce i1 @"__llgo_stub.{{.*}}/runtime/internal/runtime.memequal8"(ptr %0, ptr %1, ptr %2){{.*}} { -// CHECK-NEXT: _llgo_0: -// CHECK-NEXT: %3 = tail call i1 @"{{.*}}/runtime/internal/runtime.memequal8"(ptr %1, ptr %2) -// CHECK-NEXT: ret i1 %3 -// CHECK-NEXT: } - -// CHECK-LABEL: define linkonce i1 @"__llgo_stub.{{.*}}/runtime/internal/runtime.memequal64"(ptr %0, ptr %1, ptr %2){{.*}} { -// CHECK-NEXT: _llgo_0: -// CHECK-NEXT: %3 = tail call i1 @"{{.*}}/runtime/internal/runtime.memequal64"(ptr %1, ptr %2) -// CHECK-NEXT: ret i1 %3 -// CHECK-NEXT: } diff --git a/cl/_testrt/builtin/in.go b/cl/_testrt/builtin/in.go index fdc7ff8da0..efa6b87f49 100644 --- a/cl/_testrt/builtin/in.go +++ b/cl/_testrt/builtin/in.go @@ -266,7 +266,7 @@ func demo() { // CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.PrintByte"(i8 10) // CHECK-NEXT: %89 = call ptr @"{{.*}}/runtime/internal/runtime.AllocZ"(i64 16) // CHECK-NEXT: %90 = getelementptr inbounds { ptr, ptr }, ptr %89, i64 0 -// CHECK-NEXT: store { ptr, ptr } { ptr @"__llgo_stub.main.main$1", ptr null }, ptr %90, align 8 +// CHECK-NEXT: store { ptr, ptr } { ptr @"main.main$1", ptr null }, ptr %90, align 8 // CHECK-NEXT: %91 = insertvalue %"{{.*}}/runtime/internal/runtime.Slice" undef, ptr %89, 0 // CHECK-NEXT: %92 = insertvalue %"{{.*}}/runtime/internal/runtime.Slice" %91, i64 1, 1 // CHECK-NEXT: %93 = insertvalue %"{{.*}}/runtime/internal/runtime.Slice" %92, i64 1, 2 @@ -505,7 +505,7 @@ func main() { println("fn") } - // CHECK-LABEL: define void @"main.main$3"(ptr %0){{.*}} { + // CHECK-LABEL: define void @"main.main$3"(ptr {{(nest|swiftself)}} %0){{.*}} { // CHECK-NEXT: _llgo_0: // CHECK-NEXT: %1 = load { ptr }, ptr %0, align 8 // CHECK-NEXT: %2 = extractvalue { ptr } %1, 0 @@ -534,15 +534,3 @@ func main() { s2 := "abd" println(s1 == "abc", s1 == s2, s1 != s2, s1 < s2, s1 <= s2, s1 > s2, s1 >= s2) } - -// CHECK-LABEL: define linkonce void @"__llgo_stub.main.main$1"(ptr %0){{.*}} { -// CHECK-NEXT: _llgo_0: -// CHECK-NEXT: tail call void @"main.main$1"() -// CHECK-NEXT: ret void -// CHECK-NEXT: } - -// CHECK-LABEL: define linkonce i1 @"__llgo_stub.{{.*}}/runtime/internal/runtime.memequal64"(ptr %0, ptr %1, ptr %2){{.*}} { -// CHECK-NEXT: _llgo_0: -// CHECK-NEXT: %3 = tail call i1 @"{{.*}}/runtime/internal/runtime.memequal64"(ptr %1, ptr %2) -// CHECK-NEXT: ret i1 %3 -// CHECK-NEXT: } diff --git a/cl/_testrt/callback/in.go b/cl/_testrt/callback/in.go index ea178d22a0..60c5c12d30 100644 --- a/cl/_testrt/callback/in.go +++ b/cl/_testrt/callback/in.go @@ -9,7 +9,8 @@ import ( // CHECK-NEXT: _llgo_0: // CHECK-NEXT: %2 = extractvalue { ptr, ptr } %1, 1 // CHECK-NEXT: %3 = extractvalue { ptr, ptr } %1, 0 -// CHECK-NEXT: call void %3(ptr %2, ptr %0) +// CHECK-NEXT: %__llgo_funcval_code = call ptr asm "", "=r,0"(ptr %3) +// CHECK-NEXT: call void %__llgo_funcval_code(ptr {{(nest|swiftself)}} %2, ptr %0) // CHECK-NEXT: ret void // CHECK-NEXT: } func callback(msg *c.Char, f func(*c.Char)) { @@ -18,8 +19,8 @@ func callback(msg *c.Char, f func(*c.Char)) { // CHECK-LABEL: define void @main.main(){{.*}} { // CHECK-NEXT: _llgo_0: -// CHECK-NEXT: call void @main.callback(ptr @0, { ptr, ptr } { ptr @__llgo_stub.main.print, ptr null }) -// CHECK-NEXT: call void @main.callback(ptr @1, { ptr, ptr } { ptr @__llgo_stub.main.print, ptr null }) +// CHECK-NEXT: call void @main.callback(ptr @0, { ptr, ptr } { ptr @main.print, ptr null }) +// CHECK-NEXT: call void @main.callback(ptr @1, { ptr, ptr } { ptr @main.print, ptr null }) // CHECK-NEXT: ret void // CHECK-NEXT: } func main() { @@ -33,11 +34,6 @@ func main() { // CHECK-NEXT: ret void // CHECK-NEXT: } -// CHECK-LABEL: define linkonce void @__llgo_stub.main.print(ptr %0, ptr %1){{.*}} { -// CHECK-NEXT: _llgo_0: -// CHECK-NEXT: tail call void @main.print(ptr %1) -// CHECK-NEXT: ret void -// CHECK-NEXT: } func print(msg *c.Char) { c.Printf(msg) } diff --git a/cl/_testrt/closure/in.go b/cl/_testrt/closure/in.go index 9f9b3571ee..2fe0f79057 100644 --- a/cl/_testrt/closure/in.go +++ b/cl/_testrt/closure/in.go @@ -9,14 +9,15 @@ import ( // CHECK-NEXT: _llgo_0: // CHECK-NEXT: call void @"main.main$1"(i64 100, i64 200) // CHECK-NEXT: %0 = call ptr @"{{.*}}/runtime/internal/runtime.AllocZ"(i64 16) -// CHECK-NEXT: store { ptr, ptr } { ptr @"__llgo_stub.main.main$2", ptr null }, ptr %0, align 8 +// CHECK-NEXT: store { ptr, ptr } { ptr @"main.main$2", ptr null }, ptr %0, align 8 // CHECK-NEXT: %1 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 8) // CHECK-NEXT: %2 = getelementptr inbounds { ptr }, ptr %1, i32 0, i32 0 // CHECK-NEXT: store ptr %0, ptr %2, align 8 // CHECK-NEXT: %3 = insertvalue { ptr, ptr } { ptr @"main.main$3", ptr undef }, ptr %1, 1 // CHECK-NEXT: %4 = extractvalue { ptr, ptr } %3, 1 // CHECK-NEXT: %5 = extractvalue { ptr, ptr } %3, 0 -// CHECK-NEXT: call void %5(ptr %4) +// CHECK-NEXT: %__llgo_funcval_code = call ptr asm "", "=r,0"(ptr %5) +// CHECK-NEXT: call void %__llgo_funcval_code(ptr {{(nest|swiftself)}} %4) // CHECK-NEXT: ret void // CHECK-NEXT: } func main() { @@ -38,14 +39,15 @@ func main() { c.Printf(c.Str("%d %d\n"), n1, n2) } - // CHECK-LABEL: define void @"main.main$3"(ptr %0){{.*}} { + // CHECK-LABEL: define void @"main.main$3"(ptr {{(nest|swiftself)}} %0){{.*}} { // CHECK-NEXT: _llgo_0: // CHECK-NEXT: %1 = load { ptr }, ptr %0, align 8 // CHECK-NEXT: %2 = extractvalue { ptr } %1, 0 // CHECK-NEXT: %3 = load { ptr, ptr }, ptr %2, align 8 // CHECK-NEXT: %4 = extractvalue { ptr, ptr } %3, 1 // CHECK-NEXT: %5 = extractvalue { ptr, ptr } %3, 0 - // CHECK-NEXT: call void %5(ptr %4, i64 100, i64 200) + // CHECK-NEXT: %__llgo_funcval_code = call ptr asm "", "=r,0"(ptr %5) + // CHECK-NEXT: call void %__llgo_funcval_code(ptr {{(nest|swiftself)}} %4, i64 100, i64 200) // CHECK-NEXT: ret void // CHECK-NEXT: } fn2 := func() { @@ -53,9 +55,3 @@ func main() { } fn2() } - -// CHECK-LABEL: define linkonce void @"__llgo_stub.main.main$2"(ptr %0, i64 %1, i64 %2){{.*}} { -// CHECK-NEXT: _llgo_0: -// CHECK-NEXT: tail call void @"main.main$2"(i64 %1, i64 %2) -// CHECK-NEXT: ret void -// CHECK-NEXT: } diff --git a/cl/_testrt/closurebound/in.go b/cl/_testrt/closurebound/in.go index 0c0914df94..9e5364b6b5 100644 --- a/cl/_testrt/closurebound/in.go +++ b/cl/_testrt/closurebound/in.go @@ -67,11 +67,7 @@ func main() { // CHECK-EMPTY: // CHECK-NEXT: _llgo_1: ; preds = %_llgo_0 // CHECK-NEXT: store i1 true, ptr @"main.init$guard", align 1 -// CHECK-NEXT: %1 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 0) -// CHECK-NEXT: %2 = getelementptr inbounds { %main.demo2 }, ptr %1, i32 0, i32 0 -// CHECK-NEXT: store %main.demo2 zeroinitializer, ptr %2, align 1 -// CHECK-NEXT: %3 = insertvalue { ptr, ptr } { ptr @"main.demo2.encode$bound", ptr undef }, ptr %1, 1 -// CHECK-NEXT: store { ptr, ptr } %3, ptr @main.my, align 8 +// CHECK-NEXT: store { ptr, ptr } { ptr @"main.demo2.encode$bound", ptr @"__llgo.moduleZeroSizedAlloc$" }, ptr @main.my, align 8 // CHECK-NEXT: br label %_llgo_2 // CHECK-EMPTY: // CHECK-NEXT: _llgo_2: ; preds = %_llgo_1, %_llgo_0 @@ -80,28 +76,22 @@ func main() { // CHECK-LABEL: define void @main.main(){{.*}} { // CHECK-NEXT: _llgo_0: -// CHECK-NEXT: %0 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 0) -// CHECK-NEXT: %1 = getelementptr inbounds { %main.demo1 }, ptr %0, i32 0, i32 0 -// CHECK-NEXT: store %main.demo1 zeroinitializer, ptr %1, align 1 -// CHECK-NEXT: %2 = insertvalue { ptr, ptr } { ptr @"main.demo1.encode$bound", ptr undef }, ptr %0, 1 -// CHECK-NEXT: %3 = extractvalue { ptr, ptr } %2, 1 -// CHECK-NEXT: %4 = extractvalue { ptr, ptr } %2, 0 -// CHECK-NEXT: %5 = call i64 %4(ptr %3) -// CHECK-NEXT: %6 = icmp ne i64 %5, 1 -// CHECK-NEXT: br i1 %6, label %_llgo_1, label %_llgo_2 +// CHECK-NEXT: %0 = call i64 @"main.demo1.encode$bound"(ptr {{(nest|swiftself)}} @"__llgo.moduleZeroSizedAlloc$") +// CHECK-NEXT: %1 = icmp ne i64 %0, 1 +// CHECK-NEXT: br i1 %1, label %_llgo_1, label %_llgo_2 // CHECK-EMPTY: // CHECK-NEXT: _llgo_1: ; preds = %_llgo_0 -// CHECK-NEXT: %7 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 16) -// CHECK-NEXT: store %"{{.*}}/runtime/internal/runtime.String" { ptr @3, i64 5 }, ptr %7, align 8 -// CHECK-NEXT: %8 = insertvalue %"{{.*}}/runtime/internal/runtime.eface" { ptr @_llgo_string, ptr undef }, ptr %7, 1 -// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.Panic"(%"{{.*}}/runtime/internal/runtime.eface" %8) +// CHECK-NEXT: %2 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 16) +// CHECK-NEXT: store %"{{.*}}/runtime/internal/runtime.String" { ptr @3, i64 5 }, ptr %2, align 8 +// CHECK-NEXT: %3 = insertvalue %"{{.*}}/runtime/internal/runtime.eface" { ptr @_llgo_string, ptr undef }, ptr %2, 1 +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.Panic"(%"{{.*}}/runtime/internal/runtime.eface" %3) // CHECK-NEXT: unreachable // CHECK-EMPTY: // CHECK-NEXT: _llgo_2: ; preds = %_llgo_0 // CHECK-NEXT: ret void // CHECK-NEXT: } -// CHECK-LABEL: define i64 @"main.demo2.encode$bound"(ptr %0){{.*}} { +// CHECK-LABEL: define i64 @"main.demo2.encode$bound"(ptr {{(nest|swiftself)}} %0){{.*}} { // CHECK-NEXT: _llgo_0: // CHECK-NEXT: %1 = icmp eq ptr %0, null // CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.AssertNilDeref"(i1 %1) @@ -109,7 +99,7 @@ func main() { // CHECK-NEXT: ret i64 %2 // CHECK-NEXT: } -// CHECK-LABEL: define i64 @"main.demo1.encode$bound"(ptr %0){{.*}} { +// CHECK-LABEL: define i64 @"main.demo1.encode$bound"(ptr {{(nest|swiftself)}} %0){{.*}} { // CHECK-NEXT: _llgo_0: // CHECK-NEXT: %1 = icmp eq ptr %0, null // CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.AssertNilDeref"(i1 %1) diff --git a/cl/_testrt/closureconv/in.go b/cl/_testrt/closureconv/in.go index 853b7da618..6d63cf3c07 100644 --- a/cl/_testrt/closureconv/in.go +++ b/cl/_testrt/closureconv/in.go @@ -74,7 +74,7 @@ func demo2() Func { // CHECK-LABEL: define %main.Func @main.demo3(){{.*}} { // CHECK-NEXT: _llgo_0: -// CHECK-NEXT: ret %main.Func { ptr @__llgo_stub.main.add, ptr null } +// CHECK-NEXT: ret %main.Func { ptr @main.add, ptr null } // CHECK-NEXT: } func demo3() Func { @@ -83,7 +83,7 @@ func demo3() Func { // CHECK-LABEL: define %main.Func @main.demo4(){{.*}} { // CHECK-NEXT: _llgo_0: -// CHECK-NEXT: ret %main.Func { ptr @"__llgo_stub.main.demo4$1", ptr null } +// CHECK-NEXT: ret %main.Func { ptr @"main.demo4$1", ptr null } // CHECK-NEXT: } // CHECK-LABEL: define i64 @"main.demo4$1"(i64 %0, i64 %1){{.*}} { @@ -109,7 +109,7 @@ func demo4() Func { // CHECK-NEXT: ret %main.Func %6 // CHECK-NEXT: } -// CHECK-LABEL: define i64 @"main.demo5$1"(ptr %0, i64 %1, i64 %2){{.*}} { +// CHECK-LABEL: define i64 @"main.demo5$1"(ptr {{(nest|swiftself)}} %0, i64 %1, i64 %2){{.*}} { // CHECK-NEXT: _llgo_0: // CHECK-NEXT: %3 = add i64 %1, %2 // CHECK-NEXT: %4 = load { ptr }, ptr %0, align 8 @@ -127,31 +127,36 @@ func demo5(n int) Func { // CHECK-NEXT: %0 = call %main.Func @main.demo1(i64 1) // CHECK-NEXT: %1 = extractvalue %main.Func %0, 1 // CHECK-NEXT: %2 = extractvalue %main.Func %0, 0 -// CHECK-NEXT: %3 = call i64 %2(ptr %1, i64 99, i64 200) +// CHECK-NEXT: %__llgo_funcval_code = call ptr asm "", "=r,0"(ptr %2) +// CHECK-NEXT: %3 = call i64 %__llgo_funcval_code(ptr {{(nest|swiftself)}} %1, i64 99, i64 200) // CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.PrintInt"(i64 %3) // CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.PrintByte"(i8 10) // CHECK-NEXT: %4 = call %main.Func @main.demo2() // CHECK-NEXT: %5 = extractvalue %main.Func %4, 1 // CHECK-NEXT: %6 = extractvalue %main.Func %4, 0 -// CHECK-NEXT: %7 = call i64 %6(ptr %5, i64 100, i64 200) +// CHECK-NEXT: %__llgo_funcval_code1 = call ptr asm "", "=r,0"(ptr %6) +// CHECK-NEXT: %7 = call i64 %__llgo_funcval_code1(ptr {{(nest|swiftself)}} %5, i64 100, i64 200) // CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.PrintInt"(i64 %7) // CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.PrintByte"(i8 10) // CHECK-NEXT: %8 = call %main.Func @main.demo3() // CHECK-NEXT: %9 = extractvalue %main.Func %8, 1 // CHECK-NEXT: %10 = extractvalue %main.Func %8, 0 -// CHECK-NEXT: %11 = call i64 %10(ptr %9, i64 100, i64 200) +// CHECK-NEXT: %__llgo_funcval_code2 = call ptr asm "", "=r,0"(ptr %10) +// CHECK-NEXT: %11 = call i64 %__llgo_funcval_code2(ptr {{(nest|swiftself)}} %9, i64 100, i64 200) // CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.PrintInt"(i64 %11) // CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.PrintByte"(i8 10) // CHECK-NEXT: %12 = call %main.Func @main.demo4() // CHECK-NEXT: %13 = extractvalue %main.Func %12, 1 // CHECK-NEXT: %14 = extractvalue %main.Func %12, 0 -// CHECK-NEXT: %15 = call i64 %14(ptr %13, i64 100, i64 200) +// CHECK-NEXT: %__llgo_funcval_code3 = call ptr asm "", "=r,0"(ptr %14) +// CHECK-NEXT: %15 = call i64 %__llgo_funcval_code3(ptr {{(nest|swiftself)}} %13, i64 100, i64 200) // CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.PrintInt"(i64 %15) // CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.PrintByte"(i8 10) // CHECK-NEXT: %16 = call %main.Func @main.demo5(i64 1) // CHECK-NEXT: %17 = extractvalue %main.Func %16, 1 // CHECK-NEXT: %18 = extractvalue %main.Func %16, 0 -// CHECK-NEXT: %19 = call i64 %18(ptr %17, i64 99, i64 200) +// CHECK-NEXT: %__llgo_funcval_code4 = call ptr asm "", "=r,0"(ptr %18) +// CHECK-NEXT: %19 = call i64 %__llgo_funcval_code4(ptr {{(nest|swiftself)}} %17, i64 99, i64 200) // CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.PrintInt"(i64 %19) // CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.PrintByte"(i8 10) // CHECK-NEXT: %20 = call %main.Func @main.demo5(i64 1) @@ -160,7 +165,8 @@ func demo5(n int) Func { // CHECK-NEXT: %22 = load { ptr, ptr }, ptr %21, align 8 // CHECK-NEXT: %23 = extractvalue { ptr, ptr } %22, 1 // CHECK-NEXT: %24 = extractvalue { ptr, ptr } %22, 0 -// CHECK-NEXT: %25 = call i64 %24(ptr %23, i64 99, i64 200) +// CHECK-NEXT: %__llgo_funcval_code5 = call ptr asm "", "=r,0"(ptr %24) +// CHECK-NEXT: %25 = call i64 %__llgo_funcval_code5(ptr {{(nest|swiftself)}} %23, i64 99, i64 200) // CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.PrintInt"(i64 %25) // CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.PrintByte"(i8 10) // CHECK-NEXT: %26 = call %main.Func @main.demo5(i64 1) @@ -170,7 +176,8 @@ func demo5(n int) Func { // CHECK-NEXT: %30 = insertvalue %main.Func2 %28, ptr %29, 1 // CHECK-NEXT: %31 = extractvalue %main.Func2 %30, 1 // CHECK-NEXT: %32 = extractvalue %main.Func2 %30, 0 -// CHECK-NEXT: %33 = call i64 %32(ptr %31, i64 99, i64 200) +// CHECK-NEXT: %__llgo_funcval_code6 = call ptr asm "", "=r,0"(ptr %32) +// CHECK-NEXT: %33 = call i64 %__llgo_funcval_code6(ptr {{(nest|swiftself)}} %31, i64 99, i64 200) // CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.PrintInt"(i64 %33) // CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.PrintByte"(i8 10) // CHECK-NEXT: ret void @@ -199,22 +206,10 @@ func main() { println(fn2(99, 200)) } -// CHECK-LABEL: define i64 @"main.(*Call).add$bound"(ptr %0, i64 %1, i64 %2){{.*}} { +// CHECK-LABEL: define i64 @"main.(*Call).add$bound"(ptr {{(nest|swiftself)}} %0, i64 %1, i64 %2){{.*}} { // CHECK-NEXT: _llgo_0: // CHECK-NEXT: %3 = load { ptr }, ptr %0, align 8 // CHECK-NEXT: %4 = extractvalue { ptr } %3, 0 // CHECK-NEXT: %5 = call i64 @"main.(*Call).add"(ptr %4, i64 %1, i64 %2) // CHECK-NEXT: ret i64 %5 // CHECK-NEXT: } - -// CHECK-LABEL: define linkonce i64 @__llgo_stub.main.add(ptr %0, i64 %1, i64 %2){{.*}} { -// CHECK-NEXT: _llgo_0: -// CHECK-NEXT: %3 = tail call i64 @main.add(i64 %1, i64 %2) -// CHECK-NEXT: ret i64 %3 -// CHECK-NEXT: } - -// CHECK-LABEL: define linkonce i64 @"__llgo_stub.main.demo4$1"(ptr %0, i64 %1, i64 %2){{.*}} { -// CHECK-NEXT: _llgo_0: -// CHECK-NEXT: %3 = tail call i64 @"main.demo4$1"(i64 %1, i64 %2) -// CHECK-NEXT: ret i64 %3 -// CHECK-NEXT: } diff --git a/cl/_testrt/closureiface/in.go b/cl/_testrt/closureiface/in.go index 3d6b9308c1..37f277e152 100644 --- a/cl/_testrt/closureiface/in.go +++ b/cl/_testrt/closureiface/in.go @@ -26,7 +26,8 @@ package main // CHECK-NEXT: _llgo_2: ; preds = %_llgo_5 // CHECK-NEXT: %10 = extractvalue { ptr, ptr } %18, 1 // CHECK-NEXT: %11 = extractvalue { ptr, ptr } %18, 0 -// CHECK-NEXT: %12 = call i64 %11(ptr %10, i64 100) +// CHECK-NEXT: %__llgo_funcval_code = call ptr asm "", "=r,0"(ptr %11) +// CHECK-NEXT: %12 = call i64 %__llgo_funcval_code(ptr {{(nest|swiftself)}} %10, i64 100) // CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.PrintInt"(i64 %12) // CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.PrintByte"(i8 10) // CHECK-NEXT: ret void @@ -49,7 +50,7 @@ package main // CHECK-NEXT: } func main() { var m int = 200 - // CHECK-LABEL: define i64 @"main.main$1"(ptr %0, i64 %1){{.*}} { + // CHECK-LABEL: define i64 @"main.main$1"(ptr {{(nest|swiftself)}} %0, i64 %1){{.*}} { // CHECK-NEXT: _llgo_0: // CHECK-NEXT: %2 = load { ptr }, ptr %0, align 8 // CHECK-NEXT: %3 = extractvalue { ptr } %2, 0 diff --git a/cl/_testrt/eface/in.go b/cl/_testrt/eface/in.go index 68b29347b3..ff3bcf7e9a 100644 --- a/cl/_testrt/eface/in.go +++ b/cl/_testrt/eface/in.go @@ -199,9 +199,3 @@ func main() { var t T dump(t) } - -// CHECK-LABEL: define linkonce void @"__llgo_stub.main.main$1"(ptr %0){{.*}} { -// CHECK-NEXT: _llgo_0: -// CHECK-NEXT: tail call void @"main.main$1"() -// CHECK-NEXT: ret void -// CHECK-NEXT: } diff --git a/cl/_testrt/freevars/in.go b/cl/_testrt/freevars/in.go index 0a717e8bf5..e5fd293f12 100644 --- a/cl/_testrt/freevars/in.go +++ b/cl/_testrt/freevars/in.go @@ -3,7 +3,7 @@ package main // CHECK-LABEL: define void @main.main(){{.*}} { // CHECK-NEXT: _llgo_0: -// CHECK-NEXT: call void @"main.main$1"({ ptr, ptr } { ptr @"__llgo_stub.main.main$2", ptr null }) +// CHECK-NEXT: call void @"main.main$1"({ ptr, ptr } { ptr @"main.main$2", ptr null }) // CHECK-NEXT: ret void // CHECK-NEXT: } func main() { @@ -17,12 +17,13 @@ func main() { // CHECK-NEXT: %4 = insertvalue { ptr, ptr } { ptr @"main.main$1$1", ptr undef }, ptr %2, 1 // CHECK-NEXT: %5 = extractvalue { ptr, ptr } %4, 1 // CHECK-NEXT: %6 = extractvalue { ptr, ptr } %4, 0 - // CHECK-NEXT: call void %6(ptr %5, %"{{.*}}/runtime/internal/runtime.iface" zeroinitializer) + // CHECK-NEXT: %__llgo_funcval_code = call ptr asm "", "=r,0"(ptr %6) + // CHECK-NEXT: call void %__llgo_funcval_code(ptr {{(nest|swiftself)}} %5, %"{{.*}}/runtime/internal/runtime.iface" zeroinitializer) // CHECK-NEXT: ret void // CHECK-NEXT: } func(resolve func(error)) { - // CHECK-LABEL: define void @"main.main$1$1"(ptr %0, %"{{.*}}/runtime/internal/runtime.iface" %1){{.*}} { + // CHECK-LABEL: define void @"main.main$1$1"(ptr {{(nest|swiftself)}} %0, %"{{.*}}/runtime/internal/runtime.iface" %1){{.*}} { // CHECK-NEXT: _llgo_0: // CHECK-NEXT: %2 = load { ptr }, ptr %0, align 8 // CHECK-NEXT: %3 = call ptr @"{{.*}}/runtime/internal/runtime.IfaceType"(%"{{.*}}/runtime/internal/runtime.iface" %1) @@ -41,7 +42,8 @@ func main() { // CHECK-NEXT: %13 = load { ptr, ptr }, ptr %12, align 8 // CHECK-NEXT: %14 = extractvalue { ptr, ptr } %13, 1 // CHECK-NEXT: %15 = extractvalue { ptr, ptr } %13, 0 - // CHECK-NEXT: call void %15(ptr %14, %"{{.*}}/runtime/internal/runtime.iface" %1) + // CHECK-NEXT: %__llgo_funcval_code = call ptr asm "", "=r,0"(ptr %15) + // CHECK-NEXT: call void %__llgo_funcval_code(ptr {{(nest|swiftself)}} %14, %"{{.*}}/runtime/internal/runtime.iface" %1) // CHECK-NEXT: ret void // CHECK-EMPTY: // CHECK-NEXT: _llgo_2: ; preds = %_llgo_0 @@ -49,7 +51,8 @@ func main() { // CHECK-NEXT: %17 = load { ptr, ptr }, ptr %16, align 8 // CHECK-NEXT: %18 = extractvalue { ptr, ptr } %17, 1 // CHECK-NEXT: %19 = extractvalue { ptr, ptr } %17, 0 - // CHECK-NEXT: call void %19(ptr %18, %"{{.*}}/runtime/internal/runtime.iface" zeroinitializer) + // CHECK-NEXT: %__llgo_funcval_code1 = call ptr asm "", "=r,0"(ptr %19) + // CHECK-NEXT: call void %__llgo_funcval_code1(ptr {{(nest|swiftself)}} %18, %"{{.*}}/runtime/internal/runtime.iface" zeroinitializer) // CHECK-NEXT: ret void // CHECK-NEXT: } @@ -67,9 +70,3 @@ func main() { }(func(err error) { }) } - -// CHECK-LABEL: define linkonce void @"__llgo_stub.main.main$2"(ptr %0, %"{{.*}}/runtime/internal/runtime.iface" %1){{.*}} { -// CHECK-NEXT: _llgo_0: -// CHECK-NEXT: tail call void @"main.main$2"(%"{{.*}}/runtime/internal/runtime.iface" %1) -// CHECK-NEXT: ret void -// CHECK-NEXT: } diff --git a/cl/_testrt/funcdecl/in.go b/cl/_testrt/funcdecl/in.go index 8efd3f4635..2bc82e1ee9 100644 --- a/cl/_testrt/funcdecl/in.go +++ b/cl/_testrt/funcdecl/in.go @@ -12,7 +12,7 @@ import ( // CHECK-LABEL: define void @main.check({ ptr, ptr } %0){{.*}} { // CHECK-NEXT: _llgo_0: // CHECK-NEXT: %1 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 16) -// CHECK-NEXT: store { ptr, ptr } { ptr @__llgo_stub.main.demo, ptr null }, ptr %1, align 8 +// CHECK-NEXT: store { ptr, ptr } { ptr @main.demo, ptr null }, ptr %1, align 8 // CHECK-NEXT: %2 = insertvalue %"{{.*}}/runtime/internal/runtime.eface" { ptr @"_llgo_closure$b7Su1hWaFih-M0M9hMk6nO_RD1K_GQu5WjIXQp6Q2e8", ptr undef }, ptr %1, 1 // CHECK-NEXT: %3 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 16) // CHECK-NEXT: store { ptr, ptr } %0, ptr %3, align 8 @@ -122,7 +122,7 @@ func demo() { // CHECK-NEXT: _llgo_0: // CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.PrintString"(%"{{.*}}/runtime/internal/runtime.String" { ptr @6, i64 5 }) // CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.PrintByte"(i8 10) -// CHECK-NEXT: call void @main.check({ ptr, ptr } { ptr @__llgo_stub.main.demo, ptr null }) +// CHECK-NEXT: call void @main.check({ ptr, ptr } { ptr @main.demo, ptr null }) // CHECK-NEXT: ret void // CHECK-NEXT: } @@ -130,9 +130,3 @@ func main() { println("hello") check(demo) } - -// CHECK-LABEL: define linkonce void @__llgo_stub.main.demo(ptr %0){{.*}} { -// CHECK-NEXT: _llgo_0: -// CHECK-NEXT: tail call void @main.demo() -// CHECK-NEXT: ret void -// CHECK-NEXT: } diff --git a/cl/_testrt/intgen/in.go b/cl/_testrt/intgen/in.go index cc8d1d42a3..40ee12c681 100644 --- a/cl/_testrt/intgen/in.go +++ b/cl/_testrt/intgen/in.go @@ -20,7 +20,8 @@ import ( // CHECK-NEXT: _llgo_2: ; preds = %_llgo_1 // CHECK-NEXT: %7 = extractvalue { ptr, ptr } %1, 1 // CHECK-NEXT: %8 = extractvalue { ptr, ptr } %1, 0 -// CHECK-NEXT: %9 = call i32 %8(ptr %7) +// CHECK-NEXT: %__llgo_funcval_code = call ptr asm "", "=r,0"(ptr %8) +// CHECK-NEXT: %9 = call i32 %__llgo_funcval_code(ptr {{(nest|swiftself)}} %7) // CHECK-NEXT: %10 = extractvalue %"{{.*}}/runtime/internal/runtime.Slice" %2, 0 // CHECK-NEXT: %11 = extractvalue %"{{.*}}/runtime/internal/runtime.Slice" %2, 1 // CHECK-NEXT: %12 = icmp slt i64 %5, 0 @@ -64,7 +65,7 @@ type generator struct { // CHECK-LABEL: define void @main.main(){{.*}} { // CHECK-NEXT: _llgo_0: -// CHECK-NEXT: %0 = call %"{{.*}}/runtime/internal/runtime.Slice" @main.genInts(i64 5, { ptr, ptr } { ptr @__llgo_stub.rand, ptr null }) +// CHECK-NEXT: %0 = call %"{{.*}}/runtime/internal/runtime.Slice" @main.genInts(i64 5, { ptr, ptr } { ptr @rand, ptr null }) // CHECK-NEXT: %1 = extractvalue %"{{.*}}/runtime/internal/runtime.Slice" %0, 1 // CHECK-NEXT: br label %_llgo_1 // CHECK-EMPTY: @@ -156,7 +157,7 @@ func main() { initVal := c.Int(1) ints := genInts(5, func() c.Int { - // CHECK-LABEL: define i32 @"main.main$1"(ptr %0){{.*}} { + // CHECK-LABEL: define i32 @"main.main$1"(ptr {{(nest|swiftself)}} %0){{.*}} { // CHECK-NEXT: _llgo_0: // CHECK-NEXT: %1 = load { ptr }, ptr %0, align 8 // CHECK-NEXT: %2 = extractvalue { ptr } %1, 0 @@ -179,14 +180,9 @@ func main() { for _, v := range genInts(5, g.next) { c.Printf(c.Str("%d\n"), v) } - // CHECK-LABEL: define linkonce i32 @__llgo_stub.rand(ptr %0){{.*}} { - // CHECK-NEXT: _llgo_0: - // CHECK-NEXT: %1 = tail call i32 @rand() - // CHECK-NEXT: ret i32 %1 - // CHECK-NEXT: } } -// CHECK-LABEL: define i32 @"main.(*generator).next$bound"(ptr %0){{.*}} { +// CHECK-LABEL: define i32 @"main.(*generator).next$bound"(ptr {{(nest|swiftself)}} %0){{.*}} { // CHECK-NEXT: _llgo_0: // CHECK-NEXT: %1 = load { ptr }, ptr %0, align 8 // CHECK-NEXT: %2 = extractvalue { ptr } %1, 0 diff --git a/cl/_testrt/makemap/in.go b/cl/_testrt/makemap/in.go index d3693bcb69..d7f35d1e62 100644 --- a/cl/_testrt/makemap/in.go +++ b/cl/_testrt/makemap/in.go @@ -853,21 +853,3 @@ func make7() { } println(m[1]) } - -// CHECK-LABEL: define linkonce i1 @"__llgo_stub.{{.*}}/runtime/internal/runtime.memequal64"(ptr %0, ptr %1, ptr %2){{.*}} { -// CHECK-NEXT: _llgo_0: -// CHECK-NEXT: %3 = tail call i1 @"{{.*}}/runtime/internal/runtime.memequal64"(ptr %1, ptr %2) -// CHECK-NEXT: ret i1 %3 -// CHECK-NEXT: } - -// CHECK-LABEL: define linkonce i1 @"__llgo_stub.{{.*}}/runtime/internal/runtime.memequal8"(ptr %0, ptr %1, ptr %2){{.*}} { -// CHECK-NEXT: _llgo_0: -// CHECK-NEXT: %3 = tail call i1 @"{{.*}}/runtime/internal/runtime.memequal8"(ptr %1, ptr %2) -// CHECK-NEXT: ret i1 %3 -// CHECK-NEXT: } - -// CHECK-LABEL: define linkonce i1 @"__llgo_stub.{{.*}}/runtime/internal/runtime.nilinterequal"(ptr %0, ptr %1, ptr %2){{.*}} { -// CHECK-NEXT: _llgo_0: -// CHECK-NEXT: %3 = tail call i1 @"{{.*}}/runtime/internal/runtime.nilinterequal"(ptr %1, ptr %2) -// CHECK-NEXT: ret i1 %3 -// CHECK-NEXT: } diff --git a/cl/_testrt/mapclosure/in.go b/cl/_testrt/mapclosure/in.go index a866b94a17..1347fded25 100644 --- a/cl/_testrt/mapclosure/in.go +++ b/cl/_testrt/mapclosure/in.go @@ -55,13 +55,15 @@ var ( // CHECK-NEXT: %14 = insertvalue %"{{.*}}/runtime/internal/runtime.iface" %13, ptr %0, 1 // CHECK-NEXT: %15 = extractvalue { ptr, ptr } %5, 1 // CHECK-NEXT: %16 = extractvalue { ptr, ptr } %5, 0 -// CHECK-NEXT: %17 = call %"{{.*}}/runtime/internal/runtime.String" %16(ptr %15, %"{{.*}}/runtime/internal/runtime.iface" %14) +// CHECK-NEXT: %__llgo_funcval_code = call ptr asm "", "=r,0"(ptr %16) +// CHECK-NEXT: %17 = call %"{{.*}}/runtime/internal/runtime.String" %__llgo_funcval_code(ptr {{(nest|swiftself)}} %15, %"{{.*}}/runtime/internal/runtime.iface" %14) // CHECK-NEXT: %18 = call ptr @"{{.*}}/runtime/internal/runtime.NewItab"(ptr @"_llgo_iface$O6rEVxIuA5O1E0KWpQBCgGx26X5gYhJ_nnJnHVL8_7U", ptr @"*_llgo_main.typ") // CHECK-NEXT: %19 = insertvalue %"{{.*}}/runtime/internal/runtime.iface" undef, ptr %18, 0 // CHECK-NEXT: %20 = insertvalue %"{{.*}}/runtime/internal/runtime.iface" %19, ptr %0, 1 // CHECK-NEXT: %21 = extractvalue { ptr, ptr } %11, 1 // CHECK-NEXT: %22 = extractvalue { ptr, ptr } %11, 0 -// CHECK-NEXT: %23 = call %"{{.*}}/runtime/internal/runtime.String" %22(ptr %21, %"{{.*}}/runtime/internal/runtime.iface" %20) +// CHECK-NEXT: %__llgo_funcval_code1 = call ptr asm "", "=r,0"(ptr %22) +// CHECK-NEXT: %23 = call %"{{.*}}/runtime/internal/runtime.String" %__llgo_funcval_code1(ptr {{(nest|swiftself)}} %21, %"{{.*}}/runtime/internal/runtime.iface" %20) // CHECK-NEXT: %24 = call i1 @"{{.*}}/runtime/internal/runtime.StringEqual"(%"{{.*}}/runtime/internal/runtime.String" %17, %"{{.*}}/runtime/internal/runtime.String" %23) // CHECK-NEXT: %25 = xor i1 %24, true // CHECK-NEXT: br i1 %25, label %_llgo_1, label %_llgo_2 @@ -95,9 +97,3 @@ func main() { func (t *typ) String() string { return t.s } - -// CHECK-LABEL: define linkonce %"{{.*}}/runtime/internal/runtime.String" @__llgo_stub.main.demo(ptr %0, %"{{.*}}/runtime/internal/runtime.iface" %1){{.*}} { -// CHECK-NEXT: _llgo_0: -// CHECK-NEXT: %2 = tail call %"{{.*}}/runtime/internal/runtime.String" @main.demo(%"{{.*}}/runtime/internal/runtime.iface" %1) -// CHECK-NEXT: ret %"{{.*}}/runtime/internal/runtime.String" %2 -// CHECK-NEXT: } diff --git a/cl/_testrt/methodthunk/in.go b/cl/_testrt/methodthunk/in.go index afe1ec56b3..95e01b60f8 100644 --- a/cl/_testrt/methodthunk/in.go +++ b/cl/_testrt/methodthunk/in.go @@ -40,10 +40,10 @@ func (i *InnerInt) M() int { // CHECK-LABEL: define void @main.main(){{.*}} { // CHECK-NEXT: _llgo_0: // CHECK-NEXT: %0 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 16) -// CHECK-NEXT: store { ptr, ptr } { ptr @"__llgo_stub.main.(*outer).M$thunk", ptr null }, ptr %0, align 8 +// CHECK-NEXT: store { ptr, ptr } { ptr @"main.(*outer).M$thunk", ptr null }, ptr %0, align 8 // CHECK-NEXT: %1 = insertvalue %"{{.*}}/runtime/internal/runtime.eface" { ptr @"_llgo_closure${{[-A-Za-z0-9_]+}}", ptr undef }, ptr %0, 1 // CHECK-NEXT: %2 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 16) -// CHECK-NEXT: store { ptr, ptr } { ptr @"__llgo_stub.main.(*InnerInt).M$thunk", ptr null }, ptr %2, align 8 +// CHECK-NEXT: store { ptr, ptr } { ptr @"main.(*InnerInt).M$thunk", ptr null }, ptr %2, align 8 // CHECK-NEXT: %3 = insertvalue %"{{.*}}/runtime/internal/runtime.eface" { ptr @"_llgo_closure${{[-A-Za-z0-9_]+}}", ptr undef }, ptr %2, 1 // CHECK-NEXT: %4 = extractvalue %"{{.*}}/runtime/internal/runtime.eface" %1, 0 // CHECK-NEXT: %5 = call i1 @"{{.*}}/runtime/internal/runtime.MatchesClosure"(ptr @"_llgo_closure${{[-A-Za-z0-9_]+}}", ptr %4) @@ -127,26 +127,8 @@ func (m *outer) M() {} // CHECK-NEXT: ret void // CHECK-NEXT: } -// CHECK-LABEL: define linkonce void @"__llgo_stub.main.(*outer).M$thunk"(ptr %0, ptr %1){{.*}} { -// CHECK-NEXT: _llgo_0: -// CHECK-NEXT: tail call void @"main.(*outer).M$thunk"(ptr %1) -// CHECK-NEXT: ret void -// CHECK-NEXT: } - -// CHECK-LABEL: define linkonce i1 @"__llgo_stub.github.com/goplus/llgo/runtime/internal/runtime.memequal64"(ptr %0, ptr %1, ptr %2){{.*}} { -// CHECK-NEXT: _llgo_0: -// CHECK-NEXT: %3 = tail call i1 @"{{.*}}/runtime/internal/runtime.memequal64"(ptr %1, ptr %2) -// CHECK-NEXT: ret i1 %3 -// CHECK-NEXT: } - // CHECK-LABEL: define i64 @"main.(*InnerInt).M$thunk"(ptr %0){{.*}} { // CHECK-NEXT: _llgo_0: // CHECK-NEXT: %1 = call i64 @"main.(*InnerInt).M"(ptr %0) // CHECK-NEXT: ret i64 %1 // CHECK-NEXT: } - -// CHECK-LABEL: define linkonce i64 @"__llgo_stub.main.(*InnerInt).M$thunk"(ptr %0, ptr %1){{.*}} { -// CHECK-NEXT: _llgo_0: -// CHECK-NEXT: %2 = tail call i64 @"main.(*InnerInt).M$thunk"(ptr %1) -// CHECK-NEXT: ret i64 %2 -// CHECK-NEXT: } diff --git a/cl/_testrt/named/in.go b/cl/_testrt/named/in.go index 07d435287a..540e414d5b 100644 --- a/cl/_testrt/named/in.go +++ b/cl/_testrt/named/in.go @@ -99,7 +99,8 @@ type mspan struct { // CHECK-NEXT: %61 = load { ptr, ptr }, ptr %60, align 8 // CHECK-NEXT: %62 = extractvalue { ptr, ptr } %61, 1 // CHECK-NEXT: %63 = extractvalue { ptr, ptr } %61, 0 -// CHECK-NEXT: %64 = call i64 %63(ptr %62, i64 -2) +// CHECK-NEXT: %__llgo_funcval_code = call ptr asm "", "=r,0"(ptr %63) +// CHECK-NEXT: %64 = call i64 %__llgo_funcval_code(ptr {{(nest|swiftself)}} %62, i64 -2) // CHECK-NEXT: %65 = load ptr, ptr %0, align 8 // CHECK-NEXT: %66 = getelementptr inbounds %main.mspan, ptr %65, i32 0, i32 3 // CHECK-NEXT: %67 = getelementptr inbounds %main.minfo, ptr %66, i32 0, i32 0 @@ -108,7 +109,8 @@ type mspan struct { // CHECK-NEXT: %70 = load { ptr, ptr }, ptr %69, align 8 // CHECK-NEXT: %71 = extractvalue { ptr, ptr } %70, 1 // CHECK-NEXT: %72 = extractvalue { ptr, ptr } %70, 0 -// CHECK-NEXT: %73 = call i64 %72(ptr %71, i64 -3) +// CHECK-NEXT: %__llgo_funcval_code1 = call ptr asm "", "=r,0"(ptr %72) +// CHECK-NEXT: %73 = call i64 %__llgo_funcval_code1(ptr {{(nest|swiftself)}} %71, i64 -3) // CHECK-NEXT: %74 = call i32 (ptr, ...) @printf(ptr @0, i64 %41, i64 %48, i64 %52, i64 %58, i64 %64, i64 %73) // CHECK-NEXT: ret void // CHECK-NEXT: } @@ -125,7 +127,7 @@ func main() { m.check = func(n int) int { return m.value * n } - // CHECK-LABEL: define i64 @"main.main$1"(ptr %0, i64 %1){{.*}} { + // CHECK-LABEL: define i64 @"main.main$1"(ptr {{(nest|swiftself)}} %0, i64 %1){{.*}} { // CHECK-NEXT: _llgo_0: // CHECK-NEXT: %2 = load { ptr }, ptr %0, align 8 // CHECK-NEXT: %3 = extractvalue { ptr } %2, 0 diff --git a/cl/_testrt/reflectclosureenv/expect.txt b/cl/_testrt/reflectclosureenv/expect.txt new file mode 100644 index 0000000000..9766475a41 --- /dev/null +++ b/cl/_testrt/reflectclosureenv/expect.txt @@ -0,0 +1 @@ +ok diff --git a/cl/_testrt/reflectclosureenv/in.go b/cl/_testrt/reflectclosureenv/in.go new file mode 100644 index 0000000000..690a5b03d7 --- /dev/null +++ b/cl/_testrt/reflectclosureenv/in.go @@ -0,0 +1,89 @@ +// LITTEST +package main + +import "reflect" + +type receiver struct { + base int +} + +func (r receiver) Sum(a, b, c, d, e, f, g, h, i int) int { + return r.base + a + b + c + d + e + f + g + h + i +} + +// CHECK-LABEL: define double @"main.makeFloatSum$1"(ptr {{(nest|swiftself)}} %0, double %1, double %2, double %3, double %4, double %5, double %6, double %7, double %8, double %9){{.*}} { + +// CHECK-LABEL: define i64 @"main.makeSum$1"(ptr {{(nest|swiftself)}} %0, i64 %1, i64 %2, i64 %3, i64 %4, i64 %5, i64 %6, i64 %7, i64 %8, i64 %9){{.*}} { + +func makeSum(base int) func(int, int, int, int, int, int, int, int, int) int { + return func(a, b, c, d, e, f, g, h, i int) int { + return base + a + b + c + d + e + f + g + h + i + } +} + +func makeFloatSum(base float64) func(float64, float64, float64, float64, float64, float64, float64, float64, float64) float64 { + return func(a, b, c, d, e, f, g, h, i float64) float64 { + return base + a + b + c + d + e + f + g + h + i + } +} + +func makeNestedSum(base int) func(int, int, int, int, int, int, int, int, int) int { + return func(a, b, c, d, e, f, g, h, i int) int { + args := []reflect.Value{ + reflect.ValueOf(a), reflect.ValueOf(b), reflect.ValueOf(c), + reflect.ValueOf(d), reflect.ValueOf(e), reflect.ValueOf(f), + reflect.ValueOf(g), reflect.ValueOf(h), reflect.ValueOf(i), + } + return int(reflect.ValueOf(makeSum(base)).Call(args)[0].Int()) + } +} + +func intArgs() []reflect.Value { + args := make([]reflect.Value, 9) + for i := range args { + args[i] = reflect.ValueOf(i + 1) + } + return args +} + +func floatArgs() []reflect.Value { + args := make([]reflect.Value, 9) + for i := range args { + args[i] = reflect.ValueOf(float64(i + 1)) + } + return args +} + +func checkInt(value reflect.Value, args []reflect.Value) { + if got := value.Call(args)[0].Int(); got != 55 { + panic(got) + } +} + +func main() { + ints := intArgs() + checkInt(reflect.ValueOf(makeSum(10)), ints) + checkInt(reflect.ValueOf(makeNestedSum(10)), ints) + + ft := reflect.TypeOf(func(int, int, int, int, int, int, int, int, int) int { return 0 }) + made := reflect.MakeFunc(ft, func(args []reflect.Value) []reflect.Value { + var sum int64 = 10 + for _, arg := range args { + sum += arg.Int() + } + return []reflect.Value{reflect.ValueOf(int(sum))} + }) + checkInt(made, ints) + + method := reflect.ValueOf(receiver{base: 10}).MethodByName("Sum") + checkInt(method, ints) + bound := method.Interface().(func(int, int, int, int, int, int, int, int, int) int) + if got := bound(1, 2, 3, 4, 5, 6, 7, 8, 9); got != 55 { + panic(got) + } + + if got := reflect.ValueOf(makeFloatSum(10)).Call(floatArgs())[0].Float(); got != 55 { + panic(got) + } + println("ok") +} diff --git a/cl/_testrt/result/in.go b/cl/_testrt/result/in.go index 34fdd508d5..9caa844bf0 100644 --- a/cl/_testrt/result/in.go +++ b/cl/_testrt/result/in.go @@ -18,7 +18,7 @@ func add() func(int, int) int { // CHECK-LABEL: define { { ptr, ptr }, i64 } @main.add2(){{.*}} { // CHECK-NEXT: _llgo_0: -// CHECK-NEXT: ret { { ptr, ptr }, i64 } { { ptr, ptr } { ptr @"__llgo_stub.main.add2$1", ptr null }, i64 1 } +// CHECK-NEXT: ret { { ptr, ptr }, i64 } { { ptr, ptr } { ptr @"main.add2$1", ptr null }, i64 1 } // CHECK-NEXT: } func add2() (func(int, int) int, int) { // CHECK-LABEL: define i64 @"main.add2$1"(i64 %0, i64 %1){{.*}} { @@ -36,12 +36,14 @@ func add2() (func(int, int) int, int) { // CHECK-NEXT: %0 = call { ptr, ptr } @"main.main$1"() // CHECK-NEXT: %1 = extractvalue { ptr, ptr } %0, 1 // CHECK-NEXT: %2 = extractvalue { ptr, ptr } %0, 0 -// CHECK-NEXT: %3 = call i64 %2(ptr %1, i64 100, i64 200) +// CHECK-NEXT: %__llgo_funcval_code = call ptr asm "", "=r,0"(ptr %2) +// CHECK-NEXT: %3 = call i64 %__llgo_funcval_code(ptr {{(nest|swiftself)}} %1, i64 100, i64 200) // CHECK-NEXT: %4 = call i32 (ptr, ...) @printf(ptr @0, i64 %3) // CHECK-NEXT: %5 = call { ptr, ptr } @main.add() // CHECK-NEXT: %6 = extractvalue { ptr, ptr } %5, 1 // CHECK-NEXT: %7 = extractvalue { ptr, ptr } %5, 0 -// CHECK-NEXT: %8 = call i64 %7(ptr %6, i64 100, i64 200) +// CHECK-NEXT: %__llgo_funcval_code1 = call ptr asm "", "=r,0"(ptr %7) +// CHECK-NEXT: %8 = call i64 %__llgo_funcval_code1(ptr {{(nest|swiftself)}} %6, i64 100, i64 200) // CHECK-NEXT: %9 = call i32 (ptr, ...) @printf(ptr @1, i64 %8) // CHECK-NEXT: %10 = call { { ptr, ptr }, i64 } @main.add2() // CHECK-NEXT: %11 = extractvalue { { ptr, ptr }, i64 } %10, 0 @@ -49,14 +51,15 @@ func add2() (func(int, int) int, int) { // CHECK-NEXT: %13 = call { ptr, ptr } @main.add() // CHECK-NEXT: %14 = extractvalue { ptr, ptr } %13, 1 // CHECK-NEXT: %15 = extractvalue { ptr, ptr } %13, 0 -// CHECK-NEXT: %16 = call i64 %15(ptr %14, i64 100, i64 200) +// CHECK-NEXT: %__llgo_funcval_code2 = call ptr asm "", "=r,0"(ptr %15) +// CHECK-NEXT: %16 = call i64 %__llgo_funcval_code2(ptr {{(nest|swiftself)}} %14, i64 100, i64 200) // CHECK-NEXT: %17 = call i32 (ptr, ...) @printf(ptr @2, i64 %16, i64 %12) // CHECK-NEXT: ret void // CHECK-NEXT: } func main() { // CHECK-LABEL: define { ptr, ptr } @"main.main$1"(){{.*}} { // CHECK-NEXT: _llgo_0: - // CHECK-NEXT: ret { ptr, ptr } { ptr @"__llgo_stub.main.main$1$1", ptr null } + // CHECK-NEXT: ret { ptr, ptr } { ptr @"main.main$1$1", ptr null } // CHECK-NEXT: } fn := func() func(int, int) int { // CHECK-LABEL: define i64 @"main.main$1$1"(i64 %0, i64 %1){{.*}} { @@ -73,21 +76,3 @@ func main() { fn, n := add2() c.Printf(c.Str("%d %d\n"), add()(100, 200), n) } - -// CHECK-LABEL: define linkonce i64 @"__llgo_stub.main.add$1"(ptr %0, i64 %1, i64 %2){{.*}} { -// CHECK-NEXT: _llgo_0: -// CHECK-NEXT: %3 = tail call i64 @"main.add$1"(i64 %1, i64 %2) -// CHECK-NEXT: ret i64 %3 -// CHECK-NEXT: } - -// CHECK-LABEL: define linkonce i64 @"__llgo_stub.main.add2$1"(ptr %0, i64 %1, i64 %2){{.*}} { -// CHECK-NEXT: _llgo_0: -// CHECK-NEXT: %3 = tail call i64 @"main.add2$1"(i64 %1, i64 %2) -// CHECK-NEXT: ret i64 %3 -// CHECK-NEXT: } - -// CHECK-LABEL: define linkonce i64 @"__llgo_stub.main.main$1$1"(ptr %0, i64 %1, i64 %2){{.*}} { -// CHECK-NEXT: _llgo_0: -// CHECK-NEXT: %3 = tail call i64 @"main.main$1$1"(i64 %1, i64 %2) -// CHECK-NEXT: ret i64 %3 -// CHECK-NEXT: } diff --git a/cl/_testrt/tpabi/in.go b/cl/_testrt/tpabi/in.go index 287b027664..76493e4b8a 100644 --- a/cl/_testrt/tpabi/in.go +++ b/cl/_testrt/tpabi/in.go @@ -154,33 +154,3 @@ func main() { // CHECK-NEXT: call void @"main.T[string,int].Info"(%"main.T[string,int]" %2) // CHECK-NEXT: ret void // CHECK-NEXT: } - -// CHECK-LABEL: define linkonce void @"__llgo_stub.main.(*T[string,int]).Demo"(ptr %0, ptr %1){{.*}} { -// CHECK-NEXT: _llgo_0: -// CHECK-NEXT: tail call void @"main.(*T[string,int]).Demo"(ptr %1) -// CHECK-NEXT: ret void -// CHECK-NEXT: } - -// CHECK-LABEL: define linkonce void @"__llgo_stub.main.(*T[string,int]).Info"(ptr %0, ptr %1){{.*}} { -// CHECK-NEXT: _llgo_0: -// CHECK-NEXT: tail call void @"main.(*T[string,int]).Info"(ptr %1) -// CHECK-NEXT: ret void -// CHECK-NEXT: } - -// CHECK-LABEL: define linkonce i1 @"__llgo_stub.{{.*}}/runtime/internal/runtime.memequal64"(ptr %0, ptr %1, ptr %2){{.*}} { -// CHECK-NEXT: _llgo_0: -// CHECK-NEXT: %3 = tail call i1 @"{{.*}}/runtime/internal/runtime.memequal64"(ptr %1, ptr %2) -// CHECK-NEXT: ret i1 %3 -// CHECK-NEXT: } - -// CHECK-LABEL: define linkonce void @"__llgo_stub.main.T[string,int].Info"(ptr %0, %"main.T[string,int]" %1){{.*}} { -// CHECK-NEXT: _llgo_0: -// CHECK-NEXT: tail call void @"main.T[string,int].Info"(%"main.T[string,int]" %1) -// CHECK-NEXT: ret void -// CHECK-NEXT: } - -// CHECK-LABEL: define linkonce i1 @"__llgo_stub.{{.*}}/runtime/internal/runtime.interequal"(ptr %0, ptr %1, ptr %2){{.*}} { -// CHECK-NEXT: _llgo_0: -// CHECK-NEXT: %3 = tail call i1 @"{{.*}}/runtime/internal/runtime.interequal"(ptr %1, ptr %2) -// CHECK-NEXT: ret i1 %3 -// CHECK-NEXT: } diff --git a/cl/_testrt/tpfunc/in.go b/cl/_testrt/tpfunc/in.go index 3612acfe9e..cb39d77b28 100644 --- a/cl/_testrt/tpfunc/in.go +++ b/cl/_testrt/tpfunc/in.go @@ -81,9 +81,3 @@ func main() { } println(unsafe.Sizeof(fn1), unsafe.Sizeof(fn2), unsafe.Sizeof(fn3)) } - -// CHECK-LABEL: define linkonce void @"__llgo_stub.main.main$1"(ptr %0, ptr %1){{.*}} { -// CHECK-NEXT: _llgo_0: -// CHECK-NEXT: tail call void @"main.main$1"(ptr %1) -// CHECK-NEXT: ret void -// CHECK-NEXT: } diff --git a/cl/_testrt/tpmethod/in.go b/cl/_testrt/tpmethod/in.go index 501cbaa649..3e379e2198 100644 --- a/cl/_testrt/tpmethod/in.go +++ b/cl/_testrt/tpmethod/in.go @@ -31,7 +31,7 @@ func Async[T any](fn func(func(T))) Future[T] { // CHECK-LABEL: define %"{{.*}}/runtime/internal/runtime.iface" @main.ReadFile(%"{{.*}}/runtime/internal/runtime.String" %0){{.*}} { // CHECK-NEXT: _llgo_0: -// CHECK-NEXT: %1 = call %"{{.*}}/runtime/internal/runtime.iface" @"main.Async[main.Tuple[error]]"({ ptr, ptr } { ptr @"__llgo_stub.main.ReadFile$1", ptr null }) +// CHECK-NEXT: %1 = call %"{{.*}}/runtime/internal/runtime.iface" @"main.Async[main.Tuple[error]]"({ ptr, ptr } { ptr @"main.ReadFile$1", ptr null }) // CHECK-NEXT: ret %"{{.*}}/runtime/internal/runtime.iface" %1 // CHECK-NEXT: } @@ -45,7 +45,8 @@ func ReadFile(fileName string) Future[Tuple[error]] { // CHECK-NEXT: %3 = load %"main.Tuple[error]", ptr %1, align 8 // CHECK-NEXT: %4 = extractvalue { ptr, ptr } %0, 1 // CHECK-NEXT: %5 = extractvalue { ptr, ptr } %0, 0 - // CHECK-NEXT: call void %5(ptr %4, %"main.Tuple[error]" %3) + // CHECK-NEXT: %__llgo_funcval_code = call ptr asm "", "=r,0"(ptr %5) + // CHECK-NEXT: call void %__llgo_funcval_code(ptr {{(nest|swiftself)}} %4, %"main.Tuple[error]" %3) // CHECK-NEXT: ret void // CHECK-NEXT: } @@ -78,7 +79,7 @@ func ReadFile(fileName string) Future[Tuple[error]] { // CHECK-NEXT: %6 = insertvalue { ptr, ptr } %5, ptr %1, 1 // CHECK-NEXT: %7 = extractvalue { ptr, ptr } %6, 1 // CHECK-NEXT: %8 = extractvalue { ptr, ptr } %6, 0 -// CHECK-NEXT: call void %8(ptr %7, { ptr, ptr } { ptr @"__llgo_stub.main.main$1", ptr null }) +// CHECK-NEXT: call void %8(ptr %7, { ptr, ptr } { ptr @"main.main$1", ptr null }) // CHECK-NEXT: ret void // CHECK-NEXT: } @@ -107,18 +108,6 @@ func main() { // CHECK-NEXT: ret %"{{.*}}/runtime/internal/runtime.iface" %5 // CHECK-NEXT: } -// CHECK-LABEL: define linkonce void @"__llgo_stub.main.ReadFile$1"(ptr %0, { ptr, ptr } %1){{.*}} { -// CHECK-NEXT: _llgo_0: -// CHECK-NEXT: tail call void @"main.ReadFile$1"({ ptr, ptr } %1) -// CHECK-NEXT: ret void -// CHECK-NEXT: } - -// CHECK-LABEL: define linkonce void @"__llgo_stub.main.main$1"(ptr %0, %"main.Tuple[error]" %1){{.*}} { -// CHECK-NEXT: _llgo_0: -// CHECK-NEXT: tail call void @"main.main$1"(%"main.Tuple[error]" %1) -// CHECK-NEXT: ret void -// CHECK-NEXT: } - // CHECK-LABEL: define linkonce %"{{.*}}/runtime/internal/runtime.iface" @"main.Tuple[error].Get"(%"main.Tuple[error]" %0){{.*}} { // CHECK-NEXT: _llgo_0: // CHECK-NEXT: %1 = alloca %"main.Tuple[error]", align 8 @@ -135,7 +124,8 @@ func main() { // CHECK-NEXT: %3 = load { ptr, ptr }, ptr %2, align 8 // CHECK-NEXT: %4 = extractvalue { ptr, ptr } %3, 1 // CHECK-NEXT: %5 = extractvalue { ptr, ptr } %3, 0 -// CHECK-NEXT: call void %5(ptr %4, { ptr, ptr } %1) +// CHECK-NEXT: %__llgo_funcval_code = call ptr asm "", "=r,0"(ptr %5) +// CHECK-NEXT: call void %__llgo_funcval_code(ptr {{(nest|swiftself)}} %4, { ptr, ptr } %1) // CHECK-NEXT: ret void // CHECK-NEXT: } @@ -147,9 +137,3 @@ func main() { // CHECK-NEXT: %3 = call %"{{.*}}/runtime/internal/runtime.iface" @"main.Tuple[error].Get"(%"main.Tuple[error]" %2) // CHECK-NEXT: ret %"{{.*}}/runtime/internal/runtime.iface" %3 // CHECK-NEXT: } - -// CHECK-LABEL: define linkonce i1 @"__llgo_stub.{{.*}}/runtime/internal/runtime.interequal"(ptr %0, ptr %1, ptr %2){{.*}} { -// CHECK-NEXT: _llgo_0: -// CHECK-NEXT: %3 = tail call i1 @"{{.*}}/runtime/internal/runtime.interequal"(ptr %1, ptr %2) -// CHECK-NEXT: ret i1 %3 -// CHECK-NEXT: } diff --git a/cl/_testrt/typed/in.go b/cl/_testrt/typed/in.go index 6a8326097b..7eefecc701 100644 --- a/cl/_testrt/typed/in.go +++ b/cl/_testrt/typed/in.go @@ -114,9 +114,3 @@ func main() { ar, ok := a.(A) println(ar[0], ar[1], ok) } - -// CHECK-LABEL: define linkonce i1 @"__llgo_stub.{{.*}}/runtime/internal/runtime.memequal64"(ptr %0, ptr %1, ptr %2){{.*}} { -// CHECK-NEXT: _llgo_0: -// CHECK-NEXT: %3 = tail call i1 @"{{.*}}/runtime/internal/runtime.memequal64"(ptr %1, ptr %2) -// CHECK-NEXT: ret i1 %3 -// CHECK-NEXT: } diff --git a/cl/compile.go b/cl/compile.go index 9032deb02b..fbe9febd0d 100644 --- a/cl/compile.go +++ b/cl/compile.go @@ -463,7 +463,52 @@ func makeClosureCtx(pkg *types.Package, vars []*ssa.FreeVar) *types.Var { flds[i] = types.NewField(token.NoPos, pkg, name, v.Type(), false) } t := types.NewPointer(types.NewStruct(flds, nil)) - return types.NewParam(token.NoPos, pkg, "__llgo_ctx", t) + return types.NewParam(token.NoPos, pkg, "$env", t) +} + +// canElideZeroSizedClosureEnv reports whether a source closure can recreate +// all of its captured variables from the module's zero-sized sentinel. Go SSA +// represents a lexical capture as a pointer to the captured variable. Captured +// zero-sized variables are heap allocated, and LLGo already gives every such +// allocation the same permitted non-nil sentinel address. +// +// Synthetic wrappers are deliberately excluded: a zero-sized method receiver +// can still carry a semantically significant nil/non-nil pointer value. +func (p *context) canElideZeroSizedClosureEnv(f *ssa.Function) bool { + if f == nil || f.Parent() == nil || f.Synthetic != "" || len(f.FreeVars) == 0 { + return false + } + if _, ok := f.Syntax().(*ast.FuncLit); !ok { + return false + } + for _, freeVar := range f.FreeVars { + if !p.isElidableZeroSizedFreeVar(freeVar) { + return false + } + } + return true +} + +func (p *context) isElidableZeroSizedFreeVar(freeVar *ssa.FreeVar) bool { + typ := p.type_(freeVar.Type(), llssa.InGo) + if p.prog.SizeOf(typ) == 0 { + return true + } + ptr, ok := types.Unalias(p.patchType(freeVar.Type())).Underlying().(*types.Pointer) + return ok && p.prog.SizeOf(p.type_(ptr.Elem(), llssa.InGo)) == 0 +} + +func (p *context) elidedZeroSizedFreeVar(b llssa.Builder, freeVar *ssa.FreeVar) llssa.Expr { + typ := p.type_(freeVar.Type(), llssa.InGo) + if p.prog.SizeOf(typ) == 0 { + return p.prog.Zero(typ) + } + ptr, ok := types.Unalias(p.patchType(freeVar.Type())).Underlying().(*types.Pointer) + if !ok { + panic("zero-sized closure free variable is not reproducible") + } + addr := b.Alloc(p.type_(ptr.Elem(), llssa.InGo), true) + return b.Convert(typ, addr) } func isCgoExternSymbol(f *ssa.Function) bool { @@ -582,20 +627,39 @@ func (p *context) compileFuncDecl(pkg llssa.Package, f *ssa.Function) (llssa.Fun } fn := pkg.FuncOf(name) - if fn != nil && fn.HasBody() { - return fn, nil, goFunc - } - - var hasCtx = len(f.FreeVars) > 0 - if hasCtx { + hasFreeVars := len(f.FreeVars) > 0 + elideFreeVarEnv := p.canElideZeroSizedClosureEnv(f) + hasExplicitEnv := hasClosureEnvDirective(f) + if hasFreeVars && hasExplicitEnv { + panic("llgo:env cannot be combined with Go free variables") + } + hasCtx := hasFreeVars && !elideFreeVarEnv || hasExplicitEnv + var ctx *types.Var + if elideFreeVarEnv { + dbgInstrln("==> NewZeroSizedClosure", name, "type:", sig) + } else if hasFreeVars { dbgInstrln("==> NewClosure", name, "type:", sig) - ctx := makeClosureCtx(pkgTypes, f.FreeVars) - sig = llssa.FuncAddCtx(ctx, sig) + ctx = makeClosureCtx(pkgTypes, f.FreeVars) + } else if hasExplicitEnv { + dbgInstrln("==> NewEnvFunc", name, "type:", sig) + ctx = types.NewVar(token.NoPos, nil, "$env", types.Typ[types.UnsafePointer]) } else { dbgInstrln("==> NewFunc", name, "type:", sig.Recv(), sig, "ftype:", ftype) } + if fn != nil { + if fn.NeedsEnv() != hasCtx { + panic("conflicting closure environment ABI for " + name) + } + if fn.HasBody() { + return fn, nil, goFunc + } + } if fn == nil { - fn = pkg.NewFuncEx(name, sig, llssa.Background(ftype), hasCtx, p.needsLinkOnce(f)) + if hasCtx { + fn = pkg.NewEnvFunc(name, sig, llssa.Background(ftype), ctx, p.needsLinkOnce(f)) + } else { + fn = pkg.NewFuncEx(name, sig, llssa.Background(ftype), false, p.needsLinkOnce(f)) + } } noInlineDirective := hasNoInlineDirective(f) runtimeStackNoInline := needsRuntimeStackNoInline(pkgTypes, f) @@ -708,6 +772,22 @@ func (p *context) compileFuncDecl(pkg llssa.Package, f *ssa.Function) (llssa.Fun return fn, nil, goFunc } +// hasClosureEnvDirective is intentionally source-only. //llgo:env may mark +// only internal bodies emitted in their defining package; external env-bearing +// declarations must be reconstructed explicitly with llssa.NewEnvFunc. +func hasClosureEnvDirective(f *ssa.Function) bool { + decl, _ := f.Syntax().(*ast.FuncDecl) + if decl == nil || decl.Doc == nil { + return false + } + for _, c := range decl.Doc.List { + if strings.TrimSpace(c.Text) == "//llgo:env" { + return true + } + } + return false +} + // funcInfoDisplayName normalizes anonymous functions to gc's pkg.fn.funcN // reporting convention (our linker symbols use $N). Linker symbols are not // affected. @@ -1481,7 +1561,11 @@ func (p *context) compileInstrOrValue(b llssa.Builder, iv instrOrValue, asValue ret = b.MakeMap(t, nReserve) case *ssa.MakeClosure: fn := p.compileValue(b, v.Fn) - bindings := p.compileValues(b, v.Bindings, 0) + var bindings []llssa.Expr + goFn, _ := v.Fn.(*ssa.Function) + if !p.canElideZeroSizedClosureEnv(goFn) { + bindings = p.compileValues(b, v.Bindings, 0) + } ret = b.MakeClosure(fn, bindings) case *ssa.TypeAssert: x := p.compileValue(b, v.X) @@ -1873,6 +1957,9 @@ func (p *context) compileValue(b llssa.Builder, v ssa.Value) llssa.Expr { fn := v.Parent() for idx, freeVar := range fn.FreeVars { if freeVar == v { + if p.canElideZeroSizedClosureEnv(fn) { + return p.elidedZeroSizedFreeVar(b, v) + } return p.fn.FreeVar(b, idx) } } diff --git a/cl/compile_test.go b/cl/compile_test.go index 2e61753a50..5eecf6cbd5 100644 --- a/cl/compile_test.go +++ b/cl/compile_test.go @@ -113,6 +113,8 @@ var embedTargetConfigs = []embedTargetConfig{ "./_testrt/tpfunc", // unexpected output: type size mismatch (got 8 4 4, expected 16 8 8) "./_testrt/typalias", // fast fail: build constraints exclude all Go files "./_testrt/unreachable", // timeout: emulator panic (Instruction access fault), no auto-exit + + "./_testrt/reflectclosureenv", // baseline embedded runtime cannot build this reflect path }, "./_testdata": { "./_testdata/debug", // llgo panic: unsatisfied import internal/runtime/sys @@ -155,6 +157,8 @@ var embedTargetConfigs = []embedTargetConfig{ "./_testrt/struct", // panic: runtime index out of range "./_testrt/tpfunc", // unexpected output "./_testrt/typalias", // panic: runtime index out of range + + "./_testrt/reflectclosureenv", // baseline embedded runtime cannot build this reflect path }, "./_testdata": { "./_testdata/cpkgimp", // unexpected output diff --git a/cl/import.go b/cl/import.go index 85e4cfc9fd..0e493f3c27 100644 --- a/cl/import.go +++ b/cl/import.go @@ -563,6 +563,7 @@ const ( llgoAtomicCmpXchgOK = llgoInstrBase + 0x45 llgoAtomicAddReturnNew = llgoInstrBase + 0x46 llgoBoolToUint8 = llgoInstrBase + 0x47 + llgoClosureEnv = llgoInstrBase + 0x49 llgoAtomicOpLast = llgoAtomicOpBase + int(llssa.OpUMin) ) diff --git a/cl/instr.go b/cl/instr.go index 7e091eee82..e1ff870cfc 100644 --- a/cl/instr.go +++ b/cl/instr.go @@ -599,6 +599,7 @@ var llgoInstrs = map[string]int{ "skip": llgoSkip, "syscall": llgoSyscall, "boolToUint8": llgoBoolToUint8, + "closureEnv": llgoClosureEnv, "pystr": llgoPyStr, "pyList": llgoPyList, "pyTuple": llgoPyTuple, @@ -665,7 +666,12 @@ func (p *context) funcOf(fn *ssa.Function) (aFn llssa.Function, pyFn llssa.PyObj return nil, nil, ignoredFunc } sig := p.patchType(fn.Signature).(*types.Signature) - aFn = pkg.NewFuncEx(name, sig, llssa.Background(ftype), false, p.needsLinkOnce(fn)) + if hasClosureEnvDirective(fn) { + env := types.NewVar(token.NoPos, nil, "$env", types.Typ[types.UnsafePointer]) + aFn = pkg.NewEnvFunc(name, sig, llssa.Background(ftype), env, p.needsLinkOnce(fn)) + } else { + aFn = pkg.NewFuncEx(name, sig, llssa.Background(ftype), false, p.needsLinkOnce(fn)) + } if disableInline { aFn.Inline(llssa.NoInline) } @@ -2072,6 +2078,11 @@ func (p *context) callEx(b llssa.Builder, act llssa.DoAction, call *ssa.CallComm ret = b.Do(act, llssa.Nil, func(b llssa.Builder, _ llssa.Expr, args ...llssa.Expr) llssa.Expr { return p.boolToUint8(b, args) }, args...) + case llgoClosureEnv: + if len(args) != 0 || p.fn == nil || !p.fn.NeedsEnv() { + panic("closureEnv(): called outside an env-bearing function") + } + ret = p.fn.Env() case llgoUnreachable: // func unreachable() b.Unreachable() case llgoAtomicLoad: diff --git a/cl/rewrite_internal_test.go b/cl/rewrite_internal_test.go index ce5d370d33..e491101e46 100644 --- a/cl/rewrite_internal_test.go +++ b/cl/rewrite_internal_test.go @@ -27,6 +27,10 @@ func init() { } func compileWithRewrites(t *testing.T, src string, rewrites map[string]string) string { + return compileWithRewritesTarget(t, src, rewrites, nil) +} + +func compileWithRewritesTarget(t *testing.T, src string, rewrites map[string]string, target *llssa.Target) string { t.Helper() fset := token.NewFileSet() file, err := parser.ParseFile(fset, "rewrite.go", src, parser.ParseComments) @@ -40,8 +44,12 @@ func compileWithRewrites(t *testing.T, src string, rewrites map[string]string) s if err != nil { t.Fatalf("build package failed: %v", err) } - prog := ssatest.NewProgramEx(t, nil, importer) - prog.TypeSizes(types.SizesFor("gc", runtime.GOARCH)) + prog := ssatest.NewProgramEx(t, target, importer) + goarch := runtime.GOARCH + if target != nil && target.GOARCH != "" { + goarch = target.GOARCH + } + prog.TypeSizes(types.SizesFor("gc", goarch)) ret, _, err := NewPackageEx(prog, nil, rewrites, pkg, []*ast.File{file}) if err != nil { t.Fatalf("NewPackageEx failed: %v", err) @@ -49,6 +57,56 @@ func compileWithRewrites(t *testing.T, src string, rewrites map[string]string) s return ret.String() } +func TestClosureEnvIntrinsicRequiresEnvBearingEntry(t *testing.T) { + valid := `package closureenv + +import "unsafe" + +//go:linkname closureEnv llgo.closureEnv +func closureEnv() unsafe.Pointer + +//llgo:env +func use() unsafe.Pointer { return closureEnv() } +` + ir := compileWithRewrites(t, valid, nil) + if !strings.Contains(ir, `define ptr @closureenv.use(ptr `) || + !strings.Contains(ir, `ret ptr %0`) || + (!strings.Contains(ir, `ptr nest %0`) && !strings.Contains(ir, `ptr swiftself %0`)) { + t.Fatalf("closureEnv intrinsic did not return the physical environment:\n%s", ir) + } + + for _, test := range []struct { + name string + src string + }{ + { + name: "plain entry", + src: `package closureenv +import "unsafe" +//go:linkname closureEnv llgo.closureEnv +func closureEnv() unsafe.Pointer +func use() unsafe.Pointer { return closureEnv() } +`, + }, + { + name: "arguments", + src: `package closureenv +import "unsafe" +//go:linkname closureEnv llgo.closureEnv +func closureEnv(int) unsafe.Pointer +//llgo:env +func use() unsafe.Pointer { return closureEnv(1) } +`, + }, + } { + t.Run(test.name, func(t *testing.T) { + mustPanic(t, "invalid closureEnv intrinsic", func() { + compileWithRewrites(t, test.src, nil) + }) + }) + } +} + func assertNoStoreToGlobal(t *testing.T, ir, global string) { t.Helper() for _, line := range strings.Split(ir, "\n") { diff --git a/cl/zero_size_deref_test.go b/cl/zero_size_deref_test.go index 6ece9780ea..48de2b8d67 100644 --- a/cl/zero_size_deref_test.go +++ b/cl/zero_size_deref_test.go @@ -6,6 +6,8 @@ package cl import ( "strings" "testing" + + llssa "github.com/goplus/llgo/ssa" ) func TestZeroSizedFieldDerefEmitsBaseNilGuard(t *testing.T) { @@ -23,3 +25,49 @@ func Eq(p, q *T) bool { t.Fatalf("zero-sized field comparison should guard field bases and loads, got %d guards:\n%s", got, ir) } } + +func TestZeroSizedSourceClosureElidesEnvironment(t *testing.T) { + const src = `package zeroclosure + +func makeValue() (func() *struct{}, *struct{}) { + value := struct{}{} + return func() *struct{} { return &value }, &value +} + +func compareLocal() bool { + value := struct{}{} + closure := func() *struct{} { return &value } + return closure() == &value +} + +func keepPointer(pointer *struct{}) func() bool { + return func() bool { return pointer == nil } +} +` + targets := []struct { + name string + target *llssa.Target + }{ + {name: "native"}, + {name: "wasm-explicit", target: &llssa.Target{GOOS: "wasip1", GOARCH: "wasm"}}, + } + for _, target := range targets { + t.Run(target.name, func(t *testing.T) { + ir := compileWithRewritesTarget(t, src, nil, target.target) + for _, want := range []string{ + `{ ptr @"zeroclosure.makeValue$1", ptr null }`, + `define ptr @"zeroclosure.makeValue$1"()`, + `define ptr @"zeroclosure.compareLocal$1"()`, + `ret ptr @"__llgo.moduleZeroSizedAlloc$"`, + } { + if !strings.Contains(ir, want) { + t.Fatalf("zero-sized source closure did not elide its environment; missing %q:\n%s", want, ir) + } + } + if !strings.Contains(ir, `define i1 @"zeroclosure.keepPointer$1"(ptr `) || + !strings.Contains(ir, `@"zeroclosure.keepPointer$1", ptr undef`) { + t.Fatalf("captured pointer value incorrectly lost its environment:\n%s", ir) + } + }) + } +} diff --git a/doc/closure.md b/doc/closure.md index 3191b7ce8c..423b5eb5e9 100644 --- a/doc/closure.md +++ b/doc/closure.md @@ -1,84 +1,106 @@ -# Closure Implementation Notes - -This document describes the current LLGo SSA closure implementation. - -## Goals - -- Keep function values pointing to **real symbols** (no global stub for every - closure). For non-ctx functions, a thin `__llgo_stub` wrapper is used as the - callable symbol. -- Preserve a `funcval`-like layout: `{fn, data}`. -- Use an explicit `ctx` parameter in the call ABI (no runtime branching); - adaptation happens at conversion time via wrappers. - -## Representation - -Closures are lowered to a 2-field struct: - -``` -{ fn: *func, data: unsafe.Pointer } -``` - -- `fn` is always a function whose signature **includes** a `__llgo_ctx` - parameter. -- `data` is: - - `nil` for plain functions or wrappers that ignore ctx. - - a pointer to a heap-allocated context for free variables. - - a pointer to a heap cell that stores a function pointer (for `func` values - represented as raw function pointers). - -## Calling a Closure - -Calls to **closure values** always emit: - -``` -fn(ctx, args...) +# Closure ABI + +This document records the phase-one design from +[proposal #2170](https://github.com/xgo-dev/llgo/issues/2170). + +## Decisions + +- Keep the existing two-word function value: `{fn, env}`. This change does not + add flags or switch to Go's one-pointer funcval layout. +- A Go/go-types function signature never contains an environment parameter. + `llssa.Function` records independently whether its physical entry needs env. +- Plain Go functions and C functions use `{real entry, nil}`. Closures and + bound method wrappers use `{real entry, non-nil env}`. +- `env == nil` means that the physical entry has no env parameter. A source + closure whose captures are all zero-sized is reclassified as a no-env entry; + it recreates their permitted shared non-nil address from the module sentinel. + Other required environments never use nil. A nil pointer receiver method + value is represented by an allocated environment cell, and an interface + method value captures the complete interface state. +- A statically known call uses the entry's `NeedsEnv` property. An + explicit-context dynamic funcval call (including WebAssembly) branches once + on `env != nil` and emits two exact LLVM call edges: `fn(args...)` and + `fn(env, args...)`. +- Native hidden env parameters use LLVM `nest` or `swiftself` parameter + attributes. WebAssembly and targets without a validated hidden-register FFI + bridge use an explicit physical env parameter, but only on env-bearing + entries. +- Direct interface invocation remains a transient `(method entry, receiver)` + operation. Its receiver is an ordinary ABI argument; first-class interface + method values are lowered through the normal bound-wrapper closure path. +- Function values point directly at their physical entries; closure calls do + not add a generated adapter layer. C function values point directly at the C + entry. + +Native dynamic calls always use one hidden-env call edge, including when env is +nil. An optimizer barrier keeps the indirect code pointer opaque: LLVM IR +considers `R(ptr nest, args...)` and `R(args...)` different prototypes and must +not devirtualize a plain entry into the hidden-env call edge. The barrier emits +no machine instruction. + +The backend selects this ABI from the resolved LLVM target triple, not from +`GOARCH`. `GOOS/GOARCH` select Go source files and type sizes, but named targets +may intentionally reuse a compatible Go architecture: for example, +`wasm-unknown`, `wasip2`, Xtensa, AVR, and some RISC-V targets use `GOARCH=arm` +while emitting a different physical architecture. The triple is what LLVM uses +to assign `nest`/`swiftself` registers. + +## Physical entry ABI + +An env-bearing entry is created from the semantic signature plus one backend +parameter: + +```text +semantic: R func(A, B) +physical: R entry(env, A, B) ``` -There is no runtime `ctx==nil` check and no sentinel. Any function value that -does not naturally accept a ctx is adapted at conversion time (see below). +The physical env parameter is: -## Function Value -> Closure Wrappers +- `nest` on validated x86, RISC-V, and AArch64 platforms where X18 is + available; +- `swiftself` on ARM and platforms where AArch64 X18 is reserved; +- an ordinary leading parameter on the explicit fallback. -To keep the explicit-ctx ABI while avoiding mismatched calls: +Windows currently uses the explicit fallback because this phase does not add a +Windows final-hop FFI bridge. This is not an LLVM `nest` limitation: for +example, x86-64 Win64 can use its static-chain register once the corresponding +bridge is available and tested. -- **Function declarations** without ctx are wrapped by a thin adapter: - - Name: `__llgo_stub.` - - Signature: `func(__llgo_ctx unsafe.Pointer, args...)` - - Body: ignores ctx, calls the original function. - - Linkage: `linkonce` -- **Function pointers** use a generic wrapper: - - Name: `__llgo_stub._llgo_func$` - - Signature: `func(__llgo_ctx unsafe.Pointer, args...)` - - Body: treats `__llgo_ctx` as a pointer to a stored function pointer, loads - it, and calls it. - - Linkage: `linkonce` - - Note: the ctx pointer is guaranteed non-nil for this wrapper; we do not - emit runtime null checks. +LLVM parameter attributes are preserved when LLGo rewrites large aggregate +returns or lowers its C ABI. -This is the only remaining use of the `__llgo_stub.` prefix; it is no longer -used to generate a global stub for every closure. +## FFI and reflection -## Interface Method Values +`reflect.Value.Call` starts from the semantic libffi signature: -Interface method signatures in `go/types` include a receiver. When turning an -interface method into a closure: +- explicit env target: add the env type/value only when `env != nil`; otherwise + use the semantic signature. This is the only `env != nil` decision in the + reflection/FFI path; +- native hidden env target: `ffi.CallWithEnv` first uses `ffi_call_go` when the + linked libffi exports it and its Go static-chain register matches LLGo's + `nest` ABI. Otherwise stock `ffi_call` marshals the semantic arguments into a + small runtime final-hop trampoline. The trampoline preserves those arguments, + obtains `{fn, env}` from thread-local call state, installs the target's + `nest` or `swiftself` register (including nil), and enters fn with the original + stack pointer. Transports in caller-saved registers tail-jump; ARM `swiftself` + returns through a continuation that restores its callee-saved self register. -- The receiver parameter is dropped from the closure signature. -- The resulting closure is built with `{fn, data}` and will be wrapped if it - does not already accept `__llgo_ctx`. +Although libffi's C implementation of `ffi_call_go` is a thin wrapper, it calls +an architecture-private `ffi_call_int(..., closure)` and matching assembly; it +cannot be reproduced outside libffi by wrapping public `ffi_call` alone. The +optional direct path plus public-API fallback requires neither a patched libffi +nor rebuilding it. AArch64 libffi's Go ABI writes X18, so Apple/Android +`swiftself`/X20 deliberately uses the fallback. `reflect.MakeFunc` remains a +normal libffi C closure: its funcval has `env == nil`, while libffi userdata owns +the callback state separately. -## Covered Scenarios +## Scope -- Plain functions (no free variables). -- Closures with captured variables (`__llgo_ctx`). -- Method values / method expressions. -- Interface method values (receiver dropped). -- Variadic functions (`__llgo_va_list`). -- `go:linkname` to C (`C.xxx`) and `llgo:type C` callback parameters. -- `defer` / `go` invocation of closure values. -- `FuncPCABI0` points at the real symbol (wrappers only for ctx adaptation). +This phase includes closure creation/calls, method values, C function values, +ABI rewriting, reflection, FFI, and direct-entry function values. -## Notes / Limitations +It deliberately excludes: -- Python closures are intentionally out of scope for now. +- a WebAssembly TLS/mutable-global optimization for `g.ctxt`; +- flags or a future one-pointer funcval representation. diff --git a/doc/design/pclntab-linkphase.md b/doc/design/pclntab-linkphase.md index cbbbaf776e..10363244cc 100644 --- a/doc/design/pclntab-linkphase.md +++ b/doc/design/pclntab-linkphase.md @@ -41,7 +41,6 @@ linker-agnostic. 1. **Parse** the linked binary's metadata sections (`debug/elf`, `debug/macho` from the Go stdlib — the tool runs on the host): - `llgo_funcinfo_entry` / `__DATA,__llgo_fie`: `{pc, symbolID}` records. - - `llgo_funcinfo_stubsite` / `__DATA,__llgo_stub`: same layout. - Zero records are skipped, as in the runtime today. 2. **Dedup by symbolID**: LTO inline copies register the same symbolID at several PCs. The true entry is the record whose PC lies inside the text @@ -93,9 +92,8 @@ change is strictly additive and safe to land incrementally. platforms; assert `llgo funcinfo: ... entries= prebuilt` via LLGO_FUNCINFO_DEBUG. - **P3** (done) Mach-O bind-record resolution: pointer slots naming exported - functions — every `__llgo_stub.*` and any exported Go function — are - chained-fixup BIND nodes, not rebases; without decoding them through the - imports table, all stub records miss the prebuilt ftab and function-value + Go functions are chained-fixup BIND nodes, not rebases; without decoding + them through the imports table, exported records miss the prebuilt ftab and `FuncForPC` silently pays a dladdr per fresh pc (~6µs). Also: the prebuilt header's base slot is spliced back into the fixup chain as a live rebase node, so the runtime reads a dyld-slid runtime PC directly (no slide diff --git a/internal/abi/large.go b/internal/abi/large.go index b1da090581..63548276d3 100644 --- a/internal/abi/large.go +++ b/internal/abi/large.go @@ -86,6 +86,7 @@ func (l largeAggregateLowerer) transformCall(m llvm.Module, call llvm.Value) { } newCall := llvm.CreateCall(b, newType, call.CalledValue(), params) newCall.AddCallSiteAttribute(1, sretAttribute(ctx, retType)) + copyClosureEnvCallAttrs(call, newCall, 1) if !reflectMethodByName.IsNil() { newCall.AddCallSiteAttribute(-1, reflectMethodByName) } @@ -239,6 +240,17 @@ func sretAttribute(ctx llvm.Context, typ llvm.Type) llvm.Attribute { return ctx.CreateTypeAttribute(llvm.AttributeKindID("sret"), typ) } +func copyClosureEnvCallAttrs(from, to llvm.Value, paramOffset int) { + for i := 0; i < from.CalledFunctionType().ParamTypesCount(); i++ { + for _, name := range []string{"nest", "swiftself"} { + kind := llvm.AttributeKindID(name) + if attr := from.GetCallSiteEnumAttribute(i+1, kind); !attr.IsNil() { + to.AddCallSiteAttribute(i+1+paramOffset, attr) + } + } + } +} + func hasSingleUse(value, user llvm.Value) bool { use := value.FirstUse() return !use.IsNil() && use.User() == user && use.NextUse().IsNil() diff --git a/internal/abi/large_test.go b/internal/abi/large_test.go index 0f2df71ffe..0a9373dfcb 100644 --- a/internal/abi/large_test.go +++ b/internal/abi/large_test.go @@ -154,3 +154,86 @@ attributes #1 = { noinline } t.Fatalf("transformed module is invalid: %v\n%s", err, mod.String()) } } + +func TestLowerLargeAggregatePreservesClosureEnvAttribute(t *testing.T) { + const testIR = ` +%Large = type [65537 x i8] + +define %Large @callee(ptr nest %env) { +entry: + ret %Large zeroinitializer +} + +define %Large @calleeSwift(ptr swiftself %env) { +entry: + ret %Large zeroinitializer +} + +define void @caller(ptr %env) { +entry: + %unused = call %Large @callee(ptr nest %env) + %unusedSwift = call %Large @calleeSwift(ptr swiftself %env) + ret void +} +` + ctx := llvm.NewContext() + defer ctx.Dispose() + path := filepath.Join(t.TempDir(), "large_closure_env.ll") + if err := os.WriteFile(path, []byte(testIR), 0o644); err != nil { + t.Fatal(err) + } + buf, err := llvm.NewMemoryBufferFromFile(path) + if err != nil { + t.Fatal(err) + } + mod, err := ctx.ParseIR(buf) + if err != nil { + t.Fatal(err) + } + defer mod.Dispose() + td := llvm.NewTargetData("e-m:o-i64:64-i128:128-n32:64-S128") + defer td.Dispose() + + LowerLargeAggregates(td, mod) + + nest := llvm.AttributeKindID("nest") + callee := mod.NamedFunction("callee") + if attr := callee.GetEnumAttributeAtIndex(2, nest); attr.IsNil() { + t.Fatalf("large return lowering lost nest after inserting sret:\n%s", callee.String()) + } + if attr := callee.GetEnumAttributeAtIndex(1, nest); !attr.IsNil() { + t.Fatalf("large return lowering left nest on the new sret parameter:\n%s", callee.String()) + } + swiftself := llvm.AttributeKindID("swiftself") + calleeSwift := mod.NamedFunction("calleeSwift") + if attr := calleeSwift.GetEnumAttributeAtIndex(2, swiftself); attr.IsNil() { + t.Fatalf("large return lowering lost swiftself after inserting sret:\n%s", calleeSwift.String()) + } + + caller := mod.NamedFunction("caller") + var nestedCall, swiftselfCall llvm.Value + for block := caller.FirstBasicBlock(); !block.IsNil(); block = llvm.NextBasicBlock(block) { + for instruction := block.FirstInstruction(); !instruction.IsNil(); instruction = llvm.NextInstruction(instruction) { + if call := instruction.IsACallInst(); !call.IsNil() { + switch call.CalledValue().Name() { + case "callee": + nestedCall = call + case "calleeSwift": + swiftselfCall = call + } + } + } + } + if nestedCall.IsNil() { + t.Fatalf("large return lowering removed the callee call:\n%s", caller.String()) + } + if attr := nestedCall.GetCallSiteEnumAttribute(2, nest); attr.IsNil() { + t.Fatalf("large return call lowering lost nest after inserting sret:\n%s", caller.String()) + } + if swiftselfCall.IsNil() || swiftselfCall.GetCallSiteEnumAttribute(2, swiftself).IsNil() { + t.Fatalf("large return call lowering lost swiftself after inserting sret:\n%s", caller.String()) + } + if err := llvm.VerifyModule(mod, llvm.ReturnStatusAction); err != nil { + t.Fatalf("large-return closure-env module is invalid: %v\n%s", err, mod.String()) + } +} diff --git a/internal/build/build.go b/internal/build/build.go index 9607c9d00a..c5c6676979 100644 --- a/internal/build/build.go +++ b/internal/build/build.go @@ -397,7 +397,14 @@ func Build(inv Invocation) ([]Package, error) { } verbose := conf.Verbose patterns := slices.Clone(inv.Args) - tags := defaultBuildTags(conf.Goarch, conf.Target) + target := &llssa.Target{ + GOOS: conf.Goos, + GOARCH: conf.Goarch, + Target: conf.Target, + LLVMTarget: export.LLVMTarget, + OptLevel: conf.OptLevel, + } + tags := defaultBuildTags(conf.Goarch, conf.Target) + "," + target.ClosureEnvBuildTag() if conf.PCLNMode == PCLNExternal { // Select the optional runtime loader as part of the normal package // cache key. Embedded and none builds do not compile any loader or @@ -438,13 +445,6 @@ func Build(inv Invocation) ([]Package, error) { llssa.Initialize(llssa.InitAll) }) - target := &llssa.Target{ - GOOS: conf.Goos, - GOARCH: conf.Goarch, - Target: conf.Target, - OptLevel: conf.OptLevel, - } - prog := llssa.NewProgram(target) prog.DisableBoundsChecks(conf.DisableBoundsChecks) if conf.Mode != ModeGen { @@ -1368,11 +1368,9 @@ func linkMainPkg(ctx *context, pkg *packages.Package, pkgs []*aPackage, outputPa // Use a stable synthetic name to avoid confusing it with the real main package in traces/logs. var funcInfo []funcInfoRecord var pcLineInfo []pcLineRecord - var funcInfoStubs []funcInfoStubRecord if ctx.buildConf.PCLNMode != PCLNNone { funcInfo = prepareFuncInfoTableRecords(collectFuncInfo(linkedOrder), nil) pcLineInfo = collectPCLineInfo(linkedOrder) - funcInfoStubs = collectFuncInfoStubRecords(linkedOrder, funcInfo) } entryPkg := genMainModule(ctx, llssa.PkgRuntime, pkg, &genConfig{ rtInit: needRuntime, @@ -1383,7 +1381,6 @@ func linkMainPkg(ctx *context, pkg *packages.Package, pkgs []*aPackage, outputPa abiSymbols: linkedModuleGlobals(linkedOrder), funcInfo: funcInfo, pcLineInfo: pcLineInfo, - funcInfoStubs: funcInfoStubs, }) if ctx.buildConf.deadcodeDropEnabled() { if err := applyDeadcodeDropOverrides(linkedOrder, entryPkg, needRuntime, verbose); err != nil { @@ -1852,7 +1849,6 @@ func buildPkg(ctx *context, aPkg *aPackage, verbose bool) error { } } emitFuncInfoEntrySites(ctx, ret) - emitFuncInfoStubSites(ctx, ret) printCmds := ctx.shouldPrintCommands(verbose) cgoLLFiles, cgoLdflags, err := buildCgo(ctx, aPkg, aPkg.Package.Syntax, externs, printCmds) diff --git a/internal/build/funcinfo_table.go b/internal/build/funcinfo_table.go index b36aa29654..b8882d9ef6 100644 --- a/internal/build/funcinfo_table.go +++ b/internal/build/funcinfo_table.go @@ -37,12 +37,8 @@ const ( funcInfoHashMaskSymbol = "__llgo_funcinfo_hash_mask" funcInfoSymbolIndexSymbol = "__llgo_funcinfo_symbol_index" funcInfoSymbolIndexCountSymbol = "__llgo_funcinfo_symbol_index_count" - funcInfoStubIndexesSymbol = "__llgo_funcinfo_stub_indexes" - funcInfoStubCountSymbol = "__llgo_funcinfo_stub_count" funcInfoEntryStartPtrSymbol = "__llgo_funcinfo_entry_start" funcInfoEntryEndPtrSymbol = "__llgo_funcinfo_entry_end" - funcInfoStubSiteStartPtrSymbol = "__llgo_funcinfo_stubsite_start" - funcInfoStubSiteEndPtrSymbol = "__llgo_funcinfo_stubsite_end" pcLineTableSymbol = "__llgo_pcline_table" pcLineCountSymbol = "__llgo_pcline_count" pcSiteStartPtrSymbol = "__llgo_pcsite_start" @@ -55,8 +51,6 @@ const ( funcInfoStringOffsetsDataSymbol = "__llgo_funcinfo_string_offsets$data" funcInfoHashDataSymbol = "__llgo_funcinfo_hash$data" funcInfoSymbolIndexDataSymbol = "__llgo_funcinfo_symbol_index$data" - funcInfoStubIndexesDataSymbol = "__llgo_funcinfo_stub_indexes$data" - closureStubPrefix = "__llgo_stub." ) type funcInfoRecord struct { @@ -75,11 +69,6 @@ type pcLineRecord struct { column uint32 } -type funcInfoStubRecord struct { - symbol string - funcIndex uint32 -} - type funcInfoSymbolIndexRecord struct { symbolID uint64 funcIndex uint32 @@ -143,49 +132,6 @@ func collectPCLineInfo(pkgs []Package) []pcLineRecord { return out } -func collectFuncInfoStubRecords(pkgs []Package, records []funcInfoRecord) []funcInfoStubRecord { - if len(records) == 0 { - return nil - } - recordBySymbol := make(map[string]uint32, len(records)) - for i, rec := range records { - if rec.symbol != "" { - recordBySymbol[rec.symbol] = uint32(i + 1) - } - } - seen := make(map[string]funcInfoStubRecord) - for _, pkg := range pkgs { - if pkg == nil || pkg.LPkg == nil { - continue - } - fn := pkg.LPkg.Module().FirstFunction() - for !fn.IsNil() { - if fn.IsDeclaration() || fn.BasicBlocksCount() == 0 { - fn = llvm.NextFunction(fn) - continue - } - name := fn.Name() - if target, ok := strings.CutPrefix(name, closureStubPrefix); ok { - if idx := recordBySymbol[target]; idx != 0 { - seen[name] = funcInfoStubRecord{symbol: name, funcIndex: idx} - } - } - fn = llvm.NextFunction(fn) - } - } - if len(seen) == 0 { - return nil - } - out := make([]funcInfoStubRecord, 0, len(seen)) - for _, rec := range seen { - out = append(out, rec) - } - sort.Slice(out, func(i, j int) bool { - return out[i].symbol < out[j].symbol - }) - return out -} - func collectFuncInfoSymbolIndexRecords(records []funcInfoRecord) []funcInfoSymbolIndexRecord { if len(records) == 0 { return nil @@ -293,7 +239,7 @@ func readPCLineInfo(mod llvm.Module) []pcLineRecord { return out } -func emitFuncInfoTable(ctx *context, pkg llssa.Package, records []funcInfoRecord, pcLines []pcLineRecord, stubRecords []funcInfoStubRecord) { +func emitFuncInfoTable(ctx *context, pkg llssa.Package, records []funcInfoRecord, pcLines []pcLineRecord) { mod := pkg.Module() llvmCtx := mod.Context() i8Type := llvmCtx.Int8Type() @@ -325,10 +271,6 @@ func emitFuncInfoTable(ctx *context, pkg llssa.Package, records []funcInfoRecord llvm.PointerType(i8Type, 0), i64Type, }, false) - stubSiteRecordType := llvmCtx.StructType([]llvm.Type{ - llvm.PointerType(i8Type, 0), - i64Type, - }, false) pcSiteRecordType := llvmCtx.StructType([]llvm.Type{ llvm.PointerType(i8Type, 0), i64Type, @@ -340,8 +282,6 @@ func emitFuncInfoTable(ctx *context, pkg llssa.Package, records []funcInfoRecord pcSiteEndPtr := llvm.AddGlobal(mod, llvm.PointerType(pcSiteRecordType, 0), pcSiteEndPtrSymbol) entryStartPtr := llvm.AddGlobal(mod, llvm.PointerType(funcEntryRecordType, 0), funcInfoEntryStartPtrSymbol) entryEndPtr := llvm.AddGlobal(mod, llvm.PointerType(funcEntryRecordType, 0), funcInfoEntryEndPtrSymbol) - stubSiteStartPtr := llvm.AddGlobal(mod, llvm.PointerType(stubSiteRecordType, 0), funcInfoStubSiteStartPtrSymbol) - stubSiteEndPtr := llvm.AddGlobal(mod, llvm.PointerType(stubSiteRecordType, 0), funcInfoStubSiteEndPtrSymbol) stringsPtr := llvm.AddGlobal(mod, llvm.PointerType(i8Type, 0), funcInfoStringsSymbol) stringOffsetsPtr := llvm.AddGlobal(mod, llvm.PointerType(i32Type, 0), funcInfoStringOffsetsSymbol) stringCount := llvm.AddGlobal(mod, countType, funcInfoStringCountSymbol) @@ -354,8 +294,6 @@ func emitFuncInfoTable(ctx *context, pkg llssa.Package, records []funcInfoRecord // to relative dynamic relocations in the writable metadata section. symbolIndexPtr.SetVisibility(llvm.HiddenVisibility) symbolIndexCount.SetVisibility(llvm.HiddenVisibility) - stubIndexesPtr := llvm.AddGlobal(mod, llvm.PointerType(i32Type, 0), funcInfoStubIndexesSymbol) - stubCount := llvm.AddGlobal(mod, countType, funcInfoStubCountSymbol) pcLineCount := llvm.AddGlobal(mod, countType, pcLineCountSymbol) hashMask := llvm.AddGlobal(mod, countType, funcInfoHashMaskSymbol) // One byte per binary telling the runtime whether Go functions were @@ -368,19 +306,18 @@ func emitFuncInfoTable(ctx *context, pkg llssa.Package, records []funcInfoRecord } fpChain.SetInitializer(llvm.ConstInt(i8Type, fpChainVal, false)) if ctx.buildConf.PCLNMode == PCLNExternal { - emitExternalFuncInfoTable(ctx, mod, records, pcLines, stubRecords, externalFuncInfoGlobals{ + emitExternalFuncInfoTable(ctx, mod, records, pcLines, externalFuncInfoGlobals{ tablePtr: tablePtr, pcLinePtr: pcLinePtr, pcSiteStartPtr: pcSiteStartPtr, pcSiteEndPtr: pcSiteEndPtr, entryStartPtr: entryStartPtr, entryEndPtr: entryEndPtr, - stubSiteStartPtr: stubSiteStartPtr, stubSiteEndPtr: stubSiteEndPtr, stringsPtr: stringsPtr, stringOffsetsPtr: stringOffsetsPtr, stringCount: stringCount, hashPtr: hashPtr, hashMask: hashMask, symbolIndexPtr: symbolIndexPtr, symbolIndexCount: symbolIndexCount, - count: count, stubIndexesPtr: stubIndexesPtr, stubCount: stubCount, + count: count, pcLineCount: pcLineCount, }, externalFuncInfoTypes{ i8: i8Type, count: countType, - entryRecord: funcEntryRecordType, stubRecord: stubSiteRecordType, + entryRecord: funcEntryRecordType, pcSiteRecord: pcSiteRecordType, }) return @@ -392,8 +329,6 @@ func emitFuncInfoTable(ctx *context, pkg llssa.Package, records []funcInfoRecord pcSiteEndPtr.SetInitializer(llvm.ConstPointerNull(pcSiteEndPtr.GlobalValueType())) entryStartPtr.SetInitializer(llvm.ConstPointerNull(entryStartPtr.GlobalValueType())) entryEndPtr.SetInitializer(llvm.ConstPointerNull(entryEndPtr.GlobalValueType())) - stubSiteStartPtr.SetInitializer(llvm.ConstPointerNull(stubSiteStartPtr.GlobalValueType())) - stubSiteEndPtr.SetInitializer(llvm.ConstPointerNull(stubSiteEndPtr.GlobalValueType())) stringsPtr.SetInitializer(llvm.ConstPointerNull(stringsPtr.GlobalValueType())) stringOffsetsPtr.SetInitializer(llvm.ConstPointerNull(stringOffsetsPtr.GlobalValueType())) stringCount.SetInitializer(llvm.ConstInt(countType, 0, false)) @@ -401,8 +336,6 @@ func emitFuncInfoTable(ctx *context, pkg llssa.Package, records []funcInfoRecord symbolIndexPtr.SetInitializer(llvm.ConstPointerNull(symbolIndexPtr.GlobalValueType())) count.SetInitializer(llvm.ConstInt(countType, 0, false)) symbolIndexCount.SetInitializer(llvm.ConstInt(countType, 0, false)) - stubIndexesPtr.SetInitializer(llvm.ConstPointerNull(stubIndexesPtr.GlobalValueType())) - stubCount.SetInitializer(llvm.ConstInt(countType, 0, false)) pcLineCount.SetInitializer(llvm.ConstInt(countType, 0, false)) hashMask.SetInitializer(llvm.ConstInt(countType, 0, false)) return @@ -419,8 +352,6 @@ func emitFuncInfoTable(ctx *context, pkg llssa.Package, records []funcInfoRecord pcSiteEndPtr.SetInitializer(llvm.ConstPointerNull(pcSiteEndPtr.GlobalValueType())) entryStartPtr.SetInitializer(llvm.ConstPointerNull(entryStartPtr.GlobalValueType())) entryEndPtr.SetInitializer(llvm.ConstPointerNull(entryEndPtr.GlobalValueType())) - stubSiteStartPtr.SetInitializer(llvm.ConstPointerNull(stubSiteStartPtr.GlobalValueType())) - stubSiteEndPtr.SetInitializer(llvm.ConstPointerNull(stubSiteEndPtr.GlobalValueType())) stringsPtr.SetInitializer(llvm.ConstPointerNull(stringsPtr.GlobalValueType())) stringOffsetsPtr.SetInitializer(llvm.ConstPointerNull(stringOffsetsPtr.GlobalValueType())) stringCount.SetInitializer(llvm.ConstInt(countType, 0, false)) @@ -428,8 +359,6 @@ func emitFuncInfoTable(ctx *context, pkg llssa.Package, records []funcInfoRecord symbolIndexPtr.SetInitializer(llvm.ConstPointerNull(symbolIndexPtr.GlobalValueType())) count.SetInitializer(llvm.ConstInt(countType, 0, false)) symbolIndexCount.SetInitializer(llvm.ConstInt(countType, 0, false)) - stubIndexesPtr.SetInitializer(llvm.ConstPointerNull(stubIndexesPtr.GlobalValueType())) - stubCount.SetInitializer(llvm.ConstInt(countType, 0, false)) pcLineCount.SetInitializer(llvm.ConstInt(countType, 0, false)) hashMask.SetInitializer(llvm.ConstInt(countType, 0, false)) return @@ -497,8 +426,7 @@ func emitFuncInfoTable(ctx *context, pkg llssa.Package, records []funcInfoRecord machOSites := shouldEmitRuntimeMachOSites(ctx) emitSites := shouldEmitRuntimeSites(ctx) emitEntrySites := shouldEmitRuntimeEntryELFSites(ctx) && len(encoded.Records) != 0 - emitStubSites := shouldEmitRuntimeStubELFSites(ctx) - emitRuntimeFuncInfoSites(mod, ctx.prog.PointerSize(), machOSites, emitSites && len(pcLineValues) != 0, emitEntrySites, emitStubSites && len(stubRecords) != 0) + emitRuntimeFuncInfoSites(mod, ctx.prog.PointerSize(), machOSites, emitSites && len(pcLineValues) != 0, emitEntrySites) if emitEntrySites { startName, endName := entrySiteSectionInfo.boundary(machOSites) entryStart := llvm.AddGlobal(mod, funcEntryRecordType, startName) @@ -509,16 +437,6 @@ func emitFuncInfoTable(ctx *context, pkg llssa.Package, records []funcInfoRecord entryStartPtr.SetInitializer(llvm.ConstPointerNull(entryStartPtr.GlobalValueType())) entryEndPtr.SetInitializer(llvm.ConstPointerNull(entryEndPtr.GlobalValueType())) } - if emitStubSites && len(stubRecords) != 0 { - startName, endName := stubSiteSectionInfo.boundary(machOSites) - stubSiteStart := llvm.AddGlobal(mod, stubSiteRecordType, startName) - stubSiteEnd := llvm.AddGlobal(mod, stubSiteRecordType, endName) - stubSiteStartPtr.SetInitializer(stubSiteStart) - stubSiteEndPtr.SetInitializer(stubSiteEnd) - } else { - stubSiteStartPtr.SetInitializer(llvm.ConstPointerNull(stubSiteStartPtr.GlobalValueType())) - stubSiteEndPtr.SetInitializer(llvm.ConstPointerNull(stubSiteEndPtr.GlobalValueType())) - } stringArrayType := llvm.ArrayType(i8Type, len(encoded.Strings)) stringData := llvm.AddGlobal(mod, stringArrayType, funcInfoStringsDataSymbol) @@ -603,65 +521,34 @@ func emitFuncInfoTable(ctx *context, pkg llssa.Package, records []funcInfoRecord })) symbolIndexCount.SetInitializer(llvm.ConstInt(countType, uint64(len(symbolIndexValues)), false)) } - stubIndexSeen := make(map[uint32]none, len(stubRecords)) - stubIndexValues := make([]llvm.Value, 0, len(stubRecords)) - for _, stub := range stubRecords { - idx := stub.funcIndex - if idx == 0 || int(idx) > len(encoded.Records) { - continue - } - if _, ok := stubIndexSeen[idx]; ok { - continue - } - stubIndexSeen[idx] = none{} - stubIndexValues = append(stubIndexValues, llvm.ConstInt(i32Type, uint64(idx), false)) - } - if len(stubIndexValues) == 0 { - stubIndexesPtr.SetInitializer(llvm.ConstPointerNull(stubIndexesPtr.GlobalValueType())) - stubCount.SetInitializer(llvm.ConstInt(countType, 0, false)) - } else { - stubIndexArrayType := llvm.ArrayType(i32Type, len(stubIndexValues)) - stubIndexData := llvm.AddGlobal(mod, stubIndexArrayType, funcInfoStubIndexesDataSymbol) - stubIndexData.SetInitializer(llvm.ConstArray(i32Type, stubIndexValues)) - stubIndexData.SetLinkage(llvm.PrivateLinkage) - stubIndexData.SetGlobalConstant(true) - stubIndexData.SetUnnamedAddr(true) - stubIndexData.SetAlignment(4) - stubIndexesPtr.SetInitializer(llvm.ConstInBoundsGEP(stubIndexArrayType, stubIndexData, []llvm.Value{ - llvm.ConstInt(countType, 0, false), - llvm.ConstInt(countType, 0, false), - })) - stubCount.SetInitializer(llvm.ConstInt(countType, uint64(len(stubIndexValues)), false)) - } } type externalFuncInfoGlobals struct { tablePtr, pcLinePtr llvm.Value pcSiteStartPtr, pcSiteEndPtr llvm.Value entryStartPtr, entryEndPtr llvm.Value - stubSiteStartPtr, stubSiteEndPtr llvm.Value stringsPtr, stringOffsetsPtr, stringCount llvm.Value hashPtr, hashMask llvm.Value symbolIndexPtr, symbolIndexCount llvm.Value - count, stubIndexesPtr, stubCount llvm.Value + count llvm.Value pcLineCount llvm.Value } type externalFuncInfoTypes struct { - i8, count llvm.Type - entryRecord, stubRecord, pcSiteRecord llvm.Type + i8, count llvm.Type + entryRecord, pcSiteRecord llvm.Type } func initExternalFuncInfoGlobals(g externalFuncInfoGlobals, countType llvm.Type) { for _, ptr := range []llvm.Value{ g.tablePtr, g.pcLinePtr, g.pcSiteStartPtr, g.pcSiteEndPtr, - g.entryStartPtr, g.entryEndPtr, g.stubSiteStartPtr, g.stubSiteEndPtr, - g.stringsPtr, g.stringOffsetsPtr, g.hashPtr, g.symbolIndexPtr, g.stubIndexesPtr, + g.entryStartPtr, g.entryEndPtr, + g.stringsPtr, g.stringOffsetsPtr, g.hashPtr, g.symbolIndexPtr, } { ptr.SetInitializer(llvm.ConstPointerNull(ptr.GlobalValueType())) } for _, count := range []llvm.Value{ - g.stringCount, g.hashMask, g.symbolIndexCount, g.count, g.stubCount, g.pcLineCount, + g.stringCount, g.hashMask, g.symbolIndexCount, g.count, g.pcLineCount, } { count.SetInitializer(llvm.ConstInt(countType, 0, false)) } @@ -671,7 +558,7 @@ func initExternalFuncInfoGlobals(g externalFuncInfoGlobals, countType llvm.Type) // site boundaries and a post-link identity slot. The table payload is kept in // the build context and serialized beside the linked executable; it is never // materialized as LLVM constants in the executable. -func emitExternalFuncInfoTable(ctx *context, mod llvm.Module, records []funcInfoRecord, pcLines []pcLineRecord, stubRecords []funcInfoStubRecord, g externalFuncInfoGlobals, typ externalFuncInfoTypes) { +func emitExternalFuncInfoTable(ctx *context, mod llvm.Module, records []funcInfoRecord, pcLines []pcLineRecord, g externalFuncInfoGlobals, typ externalFuncInfoTypes) { initExternalFuncInfoGlobals(g, typ.count) encoded, err := buildfuncinfo.EncodeWithPCLines(toFuncInfoRecords(records), toPCLineRecords(pcLines)) if err != nil { @@ -717,8 +604,7 @@ func emitExternalFuncInfoTable(ctx *context, mod llvm.Module, records []funcInfo emitSites := shouldEmitRuntimeSites(ctx) emitPCSites := emitSites && len(encoded.PCLines) != 0 emitEntrySites := shouldEmitRuntimeEntryELFSites(ctx) && len(encoded.Records) != 0 - emitStubSites := shouldEmitRuntimeStubELFSites(ctx) && len(stubRecords) != 0 - emitRuntimeFuncInfoSites(mod, ctx.prog.PointerSize(), machO, emitPCSites, emitEntrySites, emitStubSites) + emitRuntimeFuncInfoSites(mod, ctx.prog.PointerSize(), machO, emitPCSites, emitEntrySites) if emitPCSites { start, end := pcLineSiteSectionInfo.boundary(machO) startGlobal := llvm.AddGlobal(mod, typ.pcSiteRecord, start) @@ -733,13 +619,6 @@ func emitExternalFuncInfoTable(ctx *context, mod llvm.Module, records []funcInfo g.entryStartPtr.SetInitializer(startGlobal) g.entryEndPtr.SetInitializer(endGlobal) } - if emitStubSites { - start, end := stubSiteSectionInfo.boundary(machO) - startGlobal := llvm.AddGlobal(mod, typ.stubRecord, start) - endGlobal := llvm.AddGlobal(mod, typ.stubRecord, end) - g.stubSiteStartPtr.SetInitializer(startGlobal) - g.stubSiteEndPtr.SetInitializer(endGlobal) - } } func shouldEmitRuntimeELFSites(ctx *context) bool { @@ -773,10 +652,6 @@ func shouldEmitRuntimeSites(ctx *context) bool { return shouldEmitRuntimeELFSites(ctx) || shouldEmitRuntimeMachOSites(ctx) } -func shouldEmitRuntimeStubELFSites(ctx *context) bool { - return shouldEmitRuntimeSites(ctx) -} - func shouldEmitRuntimeEntryELFSites(ctx *context) bool { return shouldEmitRuntimeSites(ctx) } @@ -790,7 +665,6 @@ type siteSectionInfo struct { var ( entrySiteSectionInfo = siteSectionInfo{elf: "llgo_funcinfo_entry", machO: "__DATA,__llgo_fie"} - stubSiteSectionInfo = siteSectionInfo{elf: "llgo_funcinfo_stubsite", machO: "__DATA,__llgo_stub"} pcLineSiteSectionInfo = siteSectionInfo{elf: "llgo_pcline", machO: "__DATA,__llgo_pcl"} ) @@ -932,54 +806,6 @@ func emitFuncInfoEntrySites(ctx *context, pkg llssa.Package) { } } -func emitFuncInfoStubSites(ctx *context, pkg llssa.Package) { - if !shouldEmitRuntimeStubELFSites(ctx) || pkg == nil || !ctx.prog.FuncInfoMetadataEnabled() { - return - } - machO := shouldEmitRuntimeMachOSites(ctx) - mod := pkg.Module() - llvmCtx := mod.Context() - builder := llvmCtx.NewBuilder() - defer builder.Dispose() - asmType := llvm.FunctionType(llvmCtx.VoidType(), nil, false) - ptrDirective := ".quad" - align := "3" - if ctx.prog.PointerSize() == 4 { - ptrDirective = ".long" - align = "2" - } - for fn := mod.FirstFunction(); !fn.IsNil(); fn = llvm.NextFunction(fn) { - if fn.IsDeclaration() || fn.BasicBlocksCount() == 0 { - continue - } - symbol := fn.Name() - target, ok := strings.CutPrefix(symbol, closureStubPrefix) - if !ok || target == "" { - continue - } - entry := fn.EntryBasicBlock() - if entry.IsNil() { - continue - } - first := entry.FirstInstruction() - if first.IsNil() { - builder.SetInsertPointAtEnd(entry) - } else { - builder.SetInsertPointBefore(first) - } - anchor := siteAnchorLabel(machO, "funcinfo_stubsite") - instruction := anchor + ":\n" + - stubSiteSectionInfo.push(machO, anchor) + "\n" + - ".p2align " + align + "\n" + - stubSiteSectionInfo.recordSymbol(machO, "funcinfo_stubsite") + - ptrDirective + " " + anchor + "\n" + - ".quad " + uint64Hex(funcInfoSymbolID(target)) + "\n" + - ".popsection" - asm := llvm.InlineAsm(asmType, instruction, "", true, false, llvm.InlineAsmDialectATT, false) - builder.CreateCall(asmType, asm, nil, "") - } -} - func funcInfoSymbolID(symbol string) uint64 { const ( offset = uint64(14695981039346656037) @@ -1015,8 +841,8 @@ func uint64Hex(v uint64) string { // internal/pclnpost ("LLGOMET1" little-endian). const funcInfoMetaRecordMagic = uint64(0x3154454D4F474C4C) -func emitRuntimeFuncInfoSites(mod llvm.Module, pointerSize int, machO bool, pcSite bool, entrySite bool, stubSite bool) { - if !pcSite && !entrySite && !stubSite { +func emitRuntimeFuncInfoSites(mod llvm.Module, pointerSize int, machO bool, pcSite bool, entrySite bool) { + if !pcSite && !entrySite { return } ptrDirective := ".quad" @@ -1055,9 +881,6 @@ func emitRuntimeFuncInfoSites(mod llvm.Module, pointerSize int, machO bool, pcSi asm.WriteString(ptrDirective + " " + cntSym + "\n") asm.WriteString(".quad 0\n") } - if stubSite { - writeZeroRecord(stubSiteSectionInfo, "funcinfo_stubsite") - } mod.SetInlineAsm(asm.String()) } diff --git a/internal/build/funcinfo_table_test.go b/internal/build/funcinfo_table_test.go index d606f0549f..638ac1140e 100644 --- a/internal/build/funcinfo_table_test.go +++ b/internal/build/funcinfo_table_test.go @@ -74,8 +74,6 @@ func TestFuncInfoTableMaterializesMetadataWithoutFunctionPointers(t *testing.T) "@__llgo_funcinfo_symbol_index_count = hidden global i64 1", "@__llgo_funcinfo_entry_start = global ptr @__start_llgo_funcinfo_entry", "@__llgo_funcinfo_entry_end = global ptr @__stop_llgo_funcinfo_entry", - "@__llgo_funcinfo_stub_indexes = global ptr null", - "@__llgo_funcinfo_stub_count = global i64 0", "@__llgo_pcline_count = global i64 0", "@__llgo_funcinfo_hash_mask = global i64 1", "module asm \".section llgo_funcinfo_entry", @@ -200,9 +198,8 @@ func TestFuncInfoTableSitesDisabledKeepsTables(t *testing.T) { prog.EnableFuncInfoSites(false) emitFuncInfoEntrySites(ctx, src) - emitFuncInfoStubSites(ctx, src) srcIR := src.String() - for _, bad := range []string{"llgo_funcinfo_entry", "llgo_funcinfo_stubsite", "call void asm sideeffect"} { + for _, bad := range []string{"llgo_funcinfo_entry", "call void asm sideeffect"} { if strings.Contains(srcIR, bad) { t.Fatalf("sites disabled: package IR should not contain %q:\n%s", bad, srcIR) } @@ -228,7 +225,6 @@ func TestFuncInfoTableSitesDisabledKeepsTables(t *testing.T) { // ...while the site sections and their boundary symbols must not. for _, bad := range []string{ "@__start_llgo_funcinfo_entry", - "@__start_llgo_funcinfo_stubsite", "@__start_llgo_pcline", "module asm \".section llgo_", } { @@ -238,97 +234,6 @@ func TestFuncInfoTableSitesDisabledKeepsTables(t *testing.T) { } } -func TestFuncInfoTableMaterializesClosureStubIndexes(t *testing.T) { - prog := llssa.NewProgram(nil) - src := prog.NewPackage("example.com/p", "example.com/p") - src.EmitFuncInfo("example.com/p.live", "example.com/p.Live", "live.go", 17, 3) - src.EmitFuncInfo("example.com/p.other", "example.com/p.Other", "other.go", 23, 1) - stubFn := src.NewFunc(closureStubPrefix+"example.com/p.live", llssa.NoArgsNoRet, llssa.InC) - stubFn.MakeBody(1).Return() - ctx := &context{ - prog: prog, - buildConf: &Config{ - BuildMode: BuildModeExe, - Goos: "linux", - Goarch: "amd64", - }, - } - prog.EnableFuncInfoMetadata(true) - prog.EnableFuncInfoSites(true) - emitFuncInfoStubSites(ctx, src) - srcIR := src.String() - for _, want := range []string{ - "call void asm sideeffect", - ".pushsection llgo_funcinfo_stubsite", - ".Lllgo_funcinfo_stubsite_anchor_", - ".quad .Lllgo_funcinfo_stubsite_anchor_", - ".quad 0x", - } { - if !strings.Contains(srcIR, want) { - t.Fatalf("package stub site IR missing %q:\n%s", want, srcIR) - } - } - if strings.Contains(srcIR, `.quad \22__llgo_stub.example.com/p.live\22`) { - t.Fatalf("package stub site must not reference stub function symbols:\n%s", srcIR) - } - - records := collectFuncInfo([]Package{{LPkg: src}}) - stubs := collectFuncInfoStubRecords([]Package{{LPkg: src}}, records) - if len(stubs) != 1 || records[stubs[0].funcIndex-1].symbol != "example.com/p.live" || - stubs[0].symbol != closureStubPrefix+"example.com/p.live" { - t.Fatalf("stub indexes = %+v for records %+v, want live", stubs, records) - } - - entry := genMainModule(ctx, llssa.PkgRuntime, &packages.Package{ - PkgPath: "example.com/main", - ExportFile: "main.a", - }, &genConfig{funcInfo: records, funcInfoStubs: stubs}) - ir := entry.LPkg.String() - for _, want := range []string{ - "@__llgo_funcinfo_stub_indexes = global ptr", - "@__llgo_funcinfo_stub_count = global i64 1", - "@__llgo_funcinfo_symbol_index = hidden global ptr", - "@__llgo_funcinfo_symbol_index_count = hidden global i64 2", - "@__llgo_funcinfo_stubsite_start = global ptr @__start_llgo_funcinfo_stubsite", - "@__llgo_funcinfo_stubsite_end = global ptr @__stop_llgo_funcinfo_stubsite", - `@"__llgo_funcinfo_stub_indexes$data" = private unnamed_addr constant [1 x i32]`, - "@__llgo_funcinfo_count = global i64 2", - "module asm \".section llgo_funcinfo_stubsite", - ".quad 0", - } { - if !strings.Contains(ir, want) { - t.Fatalf("funcinfo stub index table IR missing %q:\n%s", want, ir) - } - } - if strings.Contains(ir, closureStubPrefix+"example.com/p.live\\00") { - t.Fatalf("stub index table should not add stub symbol strings:\n%s", ir) - } - - ltoCtx := &context{ - prog: prog, - buildConf: &Config{ - BuildMode: BuildModeExe, - Goos: "linux", - Goarch: "amd64", - LTO: lto.Full, - }, - } - ltoEntry := genMainModule(ltoCtx, llssa.PkgRuntime, &packages.Package{ - PkgPath: "example.com/main", - ExportFile: "main.a", - }, &genConfig{funcInfo: records, funcInfoStubs: stubs}) - ltoIR := ltoEntry.LPkg.String() - for _, want := range []string{ - "@__llgo_funcinfo_stubsite_start = global ptr @__start_llgo_funcinfo_stubsite", - "@__llgo_funcinfo_stubsite_end = global ptr @__stop_llgo_funcinfo_stubsite", - "module asm \".section llgo_funcinfo_stubsite", - } { - if !strings.Contains(ltoIR, want) { - t.Fatalf("full LTO funcinfo stub site table IR missing %q:\n%s", want, ltoIR) - } - } -} - func TestFuncInfoTableMaterializesPCLineMetadata(t *testing.T) { prog := llssa.NewProgram(nil) prog.EnableFuncInfoSites(true) @@ -455,8 +360,6 @@ func TestFuncInfoTableEmptyDefinitions(t *testing.T) { "@__llgo_funcinfo_symbol_index_count = hidden global i64 0", "@__llgo_funcinfo_entry_start = global ptr null", "@__llgo_funcinfo_entry_end = global ptr null", - "@__llgo_funcinfo_stub_indexes = global ptr null", - "@__llgo_funcinfo_stub_count = global i64 0", "@__llgo_pcline_count = global i64 0", "@__llgo_funcinfo_hash_mask = global i64 0", } { @@ -530,8 +433,6 @@ func TestFuncInfoTableEmissionMatrix(t *testing.T) { src.EmitPCLineInfo(0x1234, `example.com/p.we$ird"sym`, "call.go", 23, 5) fn := src.NewFunc(`example.com/p.we$ird"sym`, llssa.NoArgsNoRet, llssa.InGo) fn.MakeBody(1).Return() - stub := src.NewFunc(`__llgo_stub.example.com/p.we$ird"sym`, llssa.NoArgsNoRet, llssa.InGo) - stub.MakeBody(1).Return() } ctx := &context{ prog: prog, @@ -543,10 +444,8 @@ func TestFuncInfoTableEmissionMatrix(t *testing.T) { } records := collectFuncInfo([]Package{{LPkg: src}}) pcLines := collectPCLineInfo([]Package{{LPkg: src}}) - stubs := collectFuncInfoStubRecords([]Package{{LPkg: src}}, records) - emitFuncInfoTable(ctx, src, records, pcLines, stubs) + emitFuncInfoTable(ctx, src, records, pcLines) emitFuncInfoEntrySites(ctx, src) - emitFuncInfoStubSites(ctx, src) ir := src.String() if c.empty { if !strings.Contains(ir, "__llgo_funcinfo_count") { @@ -617,7 +516,7 @@ func TestELFFuncInfoMetadataLinksIntoSharedLibrary(t *testing.T) { emitFuncInfoEntrySites(ctx, src) metadata := prog.NewPackage("example.com/runtime", "example.com/runtime") - emitFuncInfoTable(ctx, metadata, records, nil, nil) + emitFuncInfoTable(ctx, metadata, records, nil) dir := t.TempDir() writeObject := func(name string, mod llvm.Module) string { @@ -728,7 +627,7 @@ func TestFuncInfoTableEmptyEncodedInitializers(t *testing.T) { Goarch: "amd64", }, } - emitFuncInfoTable(ctx, src, nil, nil, nil) + emitFuncInfoTable(ctx, src, nil, nil) ir := src.String() for _, want := range []string{ "@__llgo_funcinfo_table = global ptr null", @@ -771,7 +670,7 @@ func TestExternalFuncInfoTableKeepsPayloadOutOfIR(t *testing.T) { } records := collectFuncInfo([]Package{{LPkg: src}}) pcLines := collectPCLineInfo([]Package{{LPkg: src}}) - emitFuncInfoTable(ctx, src, records, pcLines, nil) + emitFuncInfoTable(ctx, src, records, pcLines) if ctx.pclnExternal == nil || len(ctx.pclnExternal.Table.Records) != 1 || len(ctx.pclnExternal.Table.PCLines) != 1 || len(ctx.pclnExternal.SymbolIndex) != 1 { t.Fatalf("external payload = %+v", ctx.pclnExternal) } @@ -816,7 +715,7 @@ func TestFuncInfoTableFPChainOff(t *testing.T) { Goarch: "amd64", }, } - emitFuncInfoTable(ctx, src, nil, nil, nil) + emitFuncInfoTable(ctx, src, nil, nil) if ir := src.String(); !strings.Contains(ir, "@__llgo_fp_chain = global i8 0") { t.Fatalf("missing fp_chain=0 in:\n%s", ir) } diff --git a/internal/build/main_module.go b/internal/build/main_module.go index eb57ee8b49..2ff9d54d0a 100644 --- a/internal/build/main_module.go +++ b/internal/build/main_module.go @@ -44,7 +44,6 @@ type genConfig struct { abiSymbols map[string]none funcInfo []funcInfoRecord pcLineInfo []pcLineRecord - funcInfoStubs []funcInfoStubRecord } // genMainModule generates the main entry module for an llgo program. @@ -62,7 +61,7 @@ func genMainModule(ctx *context, rtPkgPath string, pkg *packages.Package, cfg *g argvValueType := prog.Pointer(prog.CStr()) argvVar := mainPkg.NewVarEx("__llgo_argv", prog.Pointer(argvValueType)) argvVar.InitNil() - emitFuncInfoTable(ctx, mainPkg, cfg.funcInfo, cfg.pcLineInfo, cfg.funcInfoStubs) + emitFuncInfoTable(ctx, mainPkg, cfg.funcInfo, cfg.pcLineInfo) exportFile := pkg.ExportFile if exportFile == "" { diff --git a/internal/build/pcln_mode_test.go b/internal/build/pcln_mode_test.go index 2f6f939906..57e56de42b 100644 --- a/internal/build/pcln_mode_test.go +++ b/internal/build/pcln_mode_test.go @@ -235,7 +235,7 @@ func TestFinalizeRuntimePCLNRemovesStaleSidecar(t *testing.T) { } } -func TestFilterExternalPCLNJoinsKeepsEntryAndStubKindsSeparate(t *testing.T) { +func TestFilterExternalPCLNJoins(t *testing.T) { idA := funcInfoSymbolID("example.com/p.A") idB := funcInfoSymbolID("example.com/p.B") data := pclnmap.Data{ @@ -253,10 +253,6 @@ func TestFilterExternalPCLNJoinsKeepsEntryAndStubKindsSeparate(t *testing.T) { {PCOffset: 0x100, ID: idB}, // same-PC alias is deterministically dropped {PCOffset: 0x200, ID: 99}, // missing funcinfo join }, - StubSites: []pclnmap.Site{ - {PCOffset: 0x80, ID: idA}, - {PCOffset: 0x90, ID: 99}, // missing funcinfo join - }, PCSites: []pclnmap.Site{ {PCOffset: 0x110, ID: 101}, {PCOffset: 0x120, ID: 101}, // A's pcline copied into B @@ -269,9 +265,6 @@ func TestFilterExternalPCLNJoinsKeepsEntryAndStubKindsSeparate(t *testing.T) { if len(data.EntrySites) != 1 || data.EntrySites[0] != (pclnmap.Site{PCOffset: 0x100, ID: idA}) { t.Fatalf("entry sites = %#v", data.EntrySites) } - if len(data.StubSites) != 1 || data.StubSites[0] != (pclnmap.Site{PCOffset: 0x80, ID: idA}) { - t.Fatalf("stub sites = %#v", data.StubSites) - } wantPCSites := []pclnmap.Site{{PCOffset: 0x110, ID: 101}, {PCOffset: 0x130, ID: 202}} if !reflect.DeepEqual(data.PCSites, wantPCSites) { t.Fatalf("pcline sites = %#v, want %#v", data.PCSites, wantPCSites) diff --git a/internal/build/pclntab_external.go b/internal/build/pclntab_external.go index c463156ae4..8cd59ce933 100644 --- a/internal/build/pclntab_external.go +++ b/internal/build/pclntab_external.go @@ -70,10 +70,6 @@ func writeExternalPCLN(ctx *context, out *OutFmtDetails, verbose bool) (err erro for i, site := range analysis.EntrySites { data.EntrySites[i] = pclnmap.Site{PCOffset: site.PCOffset, ID: site.ID} } - data.StubSites = make([]pclnmap.Site, len(analysis.StubSites)) - for i, site := range analysis.StubSites { - data.StubSites[i] = pclnmap.Site{PCOffset: site.PCOffset, ID: site.ID} - } data.PCSites = make([]pclnmap.Site, len(analysis.PCLineSites)) pcSiteOwners := make([]string, len(analysis.PCLineSites)) for i, site := range analysis.PCLineSites { @@ -122,8 +118,8 @@ func writeExternalPCLN(ctx *context, out *OutFmtDetails, verbose bool) (err erro return err } if verbose { - fmt.Fprintf(os.Stderr, "llgo: external pclntab: %d entries, %d stubs, %d pcline sites (%d bytes) -> %s\n", - len(data.EntrySites), len(data.StubSites), len(data.PCSites), len(raw), out.PCLN) + fmt.Fprintf(os.Stderr, "llgo: external pclntab: %d entries, %d pcline sites (%d bytes) -> %s\n", + len(data.EntrySites), len(data.PCSites), len(raw), out.PCLN) } return nil } @@ -145,7 +141,6 @@ func filterExternalPCLNJoins(data *pclnmap.Data, pcSiteOwners []string) error { return filtered } data.EntrySites = filterSymbolSites(data.EntrySites) - data.StubSites = filterSymbolSites(data.StubSites) if len(data.EntrySites) == 0 { return fmt.Errorf("external pclntab has no entry sites joined to funcinfo") } diff --git a/internal/build/pclntab_modes_integration_test.go b/internal/build/pclntab_modes_integration_test.go index 641ae39367..d9919b08e9 100644 --- a/internal/build/pclntab_modes_integration_test.go +++ b/internal/build/pclntab_modes_integration_test.go @@ -37,9 +37,9 @@ import ( "github.com/goplus/llgo/internal/pclnmap" ) -// The fixture obtains both a closure ABI stub entry PC and a real target -// mid-function PC. Together those lookups and the stack APIs exercise the -// full metadata contract, including its deliberate absence in pclntab=none. +// The fixture obtains both a function-value entry PC and a target mid-function +// PC. Together those lookups and the stack APIs exercise the full metadata +// contract, including its deliberate absence in pclntab=none. const pclntabModesFixture = `package main import ( @@ -60,8 +60,7 @@ func pclnTarget() uintptr { } // Keep the target body comfortably larger than the entry-anchor slack. // This makes the returned mid-function PC unambiguously belong to the - // target on both fixed-width arm64 and byte-aligned amd64, while the - // function value below still exposes the separate closure ABI stub. + // target on both fixed-width arm64 and byte-aligned amd64. value := pc for i := uintptr(0); i < 64; i++ { value = value*33 + i @@ -101,16 +100,16 @@ func pclnClosurePCState(fn *runtime.Func, pc uintptr) string { } func pclnClosureState() string { - stubPC := reflect.ValueOf(pclnTarget).Pointer() + funcvalPC := reflect.ValueOf(pclnTarget).Pointer() targetPC := pclnTarget() - stubFn := runtime.FuncForPC(stubPC) + funcvalFn := runtime.FuncForPC(funcvalPC) targetFn := runtime.FuncForPC(targetPC) - separate := stubFn != nil && targetFn != nil && - stubFn.Name() == targetFn.Name() && - stubFn.Entry() == stubPC && targetFn.Entry() != 0 && - targetFn.Entry() != stubFn.Entry() && targetFn.Entry() <= targetPC - return fmt.Sprintf("target=%s stub=%s separate=%t", - pclnClosurePCState(targetFn, targetPC), pclnClosurePCState(stubFn, stubPC), separate) + sameEntry := funcvalFn != nil && targetFn != nil && + funcvalFn.Name() == targetFn.Name() && + funcvalFn.Entry() == funcvalPC && targetFn.Entry() == funcvalFn.Entry() && + targetFn.Entry() <= targetPC + return fmt.Sprintf("target=%s funcval=%s same-entry=%t", + pclnClosurePCState(targetFn, targetPC), pclnClosurePCState(funcvalFn, funcvalPC), sameEntry) } //go:noinline @@ -317,8 +316,8 @@ func TestPCLNModeNativeIntegration(t *testing.T) { if got := runPCLNIntegrationBinary(t, bin, "once"); got != "FULL\n" { t.Fatalf("runtime metadata state = %q, want FULL", got) } - if got := runPCLNIntegrationBinary(t, bin, "closure"); got != "target=FULL stub=FULL separate=true\n" { - t.Fatalf("closure target/stub metadata = %q", got) + if got := runPCLNIntegrationBinary(t, bin, "closure"); got != "target=FULL funcval=FULL same-entry=true\n" { + t.Fatalf("closure target/funcval metadata = %q", got) } }) diff --git a/internal/cabi/cabi.go b/internal/cabi/cabi.go index 2e37b6bc99..df72a7267a 100644 --- a/internal/cabi/cabi.go +++ b/internal/cabi/cabi.go @@ -319,10 +319,15 @@ func (p *Transformer) GetFuncInfo(ctx llvm.Context, typ llvm.Type) (info FuncInf return } -func (p *Transformer) transformFuncType(ctx llvm.Context, info *FuncInfo) (llvm.Type, map[int]llvm.Attribute) { +func (p *Transformer) transformFuncType( + ctx llvm.Context, info *FuncInfo, +) (llvm.Type, map[int]llvm.Attribute, []int) { var paramTypes []llvm.Type var returnType llvm.Type attrs := make(map[int]llvm.Attribute) + // paramMap maps each zero-based source parameter to its one-based + // transformed LLVM attribute index. Zero means the parameter was elided. + paramMap := make([]int, len(info.Params)) switch info.Return.Kind { case AttrPointer: returnType = ctx.VoidType() @@ -336,7 +341,10 @@ func (p *Transformer) transformFuncType(ctx llvm.Context, info *FuncInfo) (llvm. returnType = info.Return.Type1 } - for _, ti := range info.Params { + for i, ti := range info.Params { + if ti.Kind != AttrVoid { + paramMap[i] = len(paramTypes) + 1 + } switch ti.Kind { case AttrVoid: // skip @@ -354,7 +362,7 @@ func (p *Transformer) transformFuncType(ctx llvm.Context, info *FuncInfo) (llvm. paramTypes = append(paramTypes, subs...) } } - return llvm.FunctionType(returnType, paramTypes, info.Type.IsFunctionVarArg()), attrs + return llvm.FunctionType(returnType, paramTypes, info.Type.IsFunctionVarArg()), attrs, paramMap } func (p *Transformer) transformFunc(m llvm.Module, fn llvm.Value) bool { @@ -366,7 +374,7 @@ func (p *Transformer) transformFunc(m llvm.Module, fn llvm.Value) bool { if !info.HasWrap() { return false } - nft, attrs := p.transformFuncType(ctx, &info) + nft, attrs, paramMap := p.transformFuncType(ctx, &info) preloweredSRet := fn.GetEnumAttributeAtIndex(1, llvm.AttributeKindID("sret")) fname := fn.Name() fn.SetName("") @@ -374,6 +382,7 @@ func (p *Transformer) transformFunc(m llvm.Module, fn llvm.Value) bool { for i, attr := range attrs { nfn.AddAttributeAtIndex(i, attr) } + copyClosureEnvFunctionAttrs(fn, nfn, paramMap) if !preloweredSRet.IsNil() { nfn.AddAttributeAtIndex(1, preloweredSRet) } @@ -540,7 +549,7 @@ func (p *Transformer) transformCallInstr(m llvm.Module, ctx llvm.Context, call l if !info.HasWrap() { return false } - nft, attrs := p.transformFuncType(ctx, &info) + nft, attrs, paramMap := p.transformFuncType(ctx, &info) preloweredSRet := call.GetCallSiteEnumAttribute(1, llvm.AttributeKindID("sret")) reflectMethodByNameAttr := call.GetCallSiteStringAttribute(-1, "llgo.reflect.methodbyname") b := ctx.NewBuilder() @@ -599,21 +608,22 @@ func (p *Transformer) transformCallInstr(m llvm.Module, ctx llvm.Context, call l } } - updateCallAttr := func(call llvm.Value) { + updateCallAttr := func(replacement llvm.Value) { for i, attr := range attrs { - call.AddCallSiteAttribute(i, attr) + replacement.AddCallSiteAttribute(i, attr) } if !preloweredSRet.IsNil() { - call.AddCallSiteAttribute(1, preloweredSRet) + replacement.AddCallSiteAttribute(1, preloweredSRet) } if !reflectMethodByNameAttr.IsNil() { - call.AddCallSiteAttribute(-1, reflectMethodByNameAttr) + replacement.AddCallSiteAttribute(-1, reflectMethodByNameAttr) } if remappedReflectMethodByNameArgAttrIndex >= 0 { - call.AddCallSiteAttribute(remappedReflectMethodByNameArgAttrIndex, ctx.CreateStringAttribute( + replacement.AddCallSiteAttribute(remappedReflectMethodByNameArgAttrIndex, ctx.CreateStringAttribute( "llgo.reflect.methodbyname.name", "1", )) } + copyClosureEnvCallAttrs(call, replacement, paramMap) } var instr llvm.Value @@ -678,7 +688,7 @@ func (p *Transformer) transformCallbackFunc(m llvm.Module, fn llvm.Value) (wrap return fn, false } - nft, attrs := p.transformFuncType(ctx, &info) + nft, attrs, paramMap := p.transformFuncType(ctx, &info) fname := fn.Name() wrapName := "__llgo_cdecl$" + fname @@ -692,6 +702,7 @@ func (p *Transformer) transformCallbackFunc(m llvm.Module, fn llvm.Value) (wrap for i, attr := range attrs { wrapFunc.AddAttributeAtIndex(i, attr) } + copyClosureEnvFunctionAttrs(fn, wrapFunc, paramMap) b := ctx.NewBuilder() block := ctx.AddBasicBlock(wrapFunc, "entry") @@ -706,6 +717,7 @@ func (p *Transformer) transformCallbackFunc(m llvm.Module, fn llvm.Value) (wrap for _, ti := range info.Params { switch ti.Kind { default: + nparams = append(nparams, params[index]) case AttrVoid: // none case AttrPointer: @@ -738,14 +750,17 @@ func (p *Transformer) transformCallbackFunc(m llvm.Module, fn llvm.Value) (wrap switch info.Return.Kind { case AttrVoid: - llvm.CreateCall(b, info.Type, fn, nparams) + call := llvm.CreateCall(b, info.Type, fn, nparams) + copyClosureEnvFunctionAttrsToCall(fn, call) b.CreateRetVoid() case AttrPointer: ret := llvm.CreateCall(b, info.Type, fn, nparams) + copyClosureEnvFunctionAttrsToCall(fn, ret) b.CreateStore(ret, params[0]) b.CreateRetVoid() case AttrWidthType, AttrWidthType2: ret := llvm.CreateCall(b, info.Type, fn, nparams) + copyClosureEnvFunctionAttrsToCall(fn, ret) ptr := llvm.CreateAlloca(b, info.Return.Type) b.CreateStore(ret, ptr) returnType := nft.ReturnType() @@ -753,11 +768,53 @@ func (p *Transformer) transformCallbackFunc(m llvm.Module, fn llvm.Value) (wrap b.CreateRet(b.CreateLoad(returnType, iptr, "")) default: ret := llvm.CreateCall(b, info.Type, fn, nparams) + copyClosureEnvFunctionAttrsToCall(fn, ret) b.CreateRet(ret) } return wrapFunc, true } +var closureEnvAttributeKinds = []uint{ + llvm.AttributeKindID("nest"), + llvm.AttributeKindID("swiftself"), +} + +func copyClosureEnvFunctionAttrs(from, to llvm.Value, paramMap []int) { + for oldIndex, newIndex := range paramMap { + if newIndex == 0 { + continue + } + for _, kind := range closureEnvAttributeKinds { + if attr := from.GetEnumAttributeAtIndex(oldIndex+1, kind); !attr.IsNil() { + to.AddAttributeAtIndex(newIndex, attr) + } + } + } +} + +func copyClosureEnvCallAttrs(from, to llvm.Value, paramMap []int) { + for oldIndex, newIndex := range paramMap { + if newIndex == 0 { + continue + } + for _, kind := range closureEnvAttributeKinds { + if attr := from.GetCallSiteEnumAttribute(oldIndex+1, kind); !attr.IsNil() { + to.AddCallSiteAttribute(newIndex, attr) + } + } + } +} + +func copyClosureEnvFunctionAttrsToCall(from, to llvm.Value) { + for i := 0; i < from.GlobalValueType().ParamTypesCount(); i++ { + for _, kind := range closureEnvAttributeKinds { + if attr := from.GetEnumAttributeAtIndex(i+1, kind); !attr.IsNil() { + to.AddCallSiteAttribute(i+1, attr) + } + } + } +} + func (p *Transformer) callMemcpy(_ llvm.Module, ctx llvm.Context, b llvm.Builder, dst llvm.Value, src llvm.Value, size int) llvm.Value { sz := llvm.ConstInt(ctx.IntType(p.prog.PointerSize()*8), uint64(size), false) return b.CreateIntrinsic(ctx.VoidType(), llvm.LookupIntrinsicID("llvm.memcpy"), []llvm.Value{ diff --git a/internal/cabi/cabi_patch_test.go b/internal/cabi/cabi_patch_test.go index 7254459e37..d9afe8d089 100644 --- a/internal/cabi/cabi_patch_test.go +++ b/internal/cabi/cabi_patch_test.go @@ -76,6 +76,140 @@ func TestDevLTOGlobalDCEFuncNoUnwindCreatesNounwindAttribute(t *testing.T) { } } +func TestClosureEnvAttributeRemappedByCABI(t *testing.T) { + llvm.InitializeAllTargets() + llvm.InitializeAllTargetMCs() + llvm.InitializeAllTargetInfos() + + const testIR = ` +%Value = type { ptr, ptr, i64 } + +define %Value @callee(ptr %g, ptr %out, ptr nest %env, %Value %value) { +entry: + ret %Value %value +} + +define %Value @caller(ptr %g, ptr %out, ptr nest %env, %Value %value) { +entry: + %result = call %Value @callee(ptr %g, ptr %out, ptr nest %env, %Value %value) + ret %Value %result +} +` + ctx := llvm.NewContext() + defer ctx.Dispose() + path := filepath.Join(t.TempDir(), "closure_env.ll") + if err := os.WriteFile(path, []byte(testIR), 0o644); err != nil { + t.Fatal(err) + } + buf, err := llvm.NewMemoryBufferFromFile(path) + if err != nil { + t.Fatal(err) + } + mod, err := ctx.ParseIR(buf) + if err != nil { + t.Fatal(err) + } + defer mod.Dispose() + + prog := llssa.NewProgram(&llssa.Target{GOOS: "linux", GOARCH: "amd64"}) + defer prog.Dispose() + tr := NewTransformer(prog, "amd64-unknown-linux-gnu", "", ModeAllFunc, true) + tr.TransformModule("test", mod) + + nest := llvm.AttributeKindID("nest") + callee := mod.NamedFunction("callee") + if attr := callee.GetEnumAttributeAtIndex(4, nest); attr.IsNil() { + t.Fatalf("C ABI lowering lost/remapped nest on the definition:\n%s", callee.String()) + } + if attr := callee.GetEnumAttributeAtIndex(3, nest); !attr.IsNil() { + t.Fatalf("C ABI lowering left nest on the old definition parameter:\n%s", callee.String()) + } + + caller := mod.NamedFunction("caller") + var nestedCall llvm.Value + for block := caller.FirstBasicBlock(); !block.IsNil(); block = llvm.NextBasicBlock(block) { + for instruction := block.FirstInstruction(); !instruction.IsNil(); instruction = llvm.NextInstruction(instruction) { + if call := instruction.IsACallInst(); !call.IsNil() && call.CalledValue().Name() == "callee" { + nestedCall = call + } + } + } + if nestedCall.IsNil() { + t.Fatalf("transformed caller has no callee call:\n%s", caller.String()) + } + if attr := nestedCall.GetCallSiteEnumAttribute(4, nest); attr.IsNil() { + t.Fatalf("C ABI lowering lost/remapped nest on the call:\n%s", caller.String()) + } + if attr := nestedCall.GetCallSiteEnumAttribute(3, nest); !attr.IsNil() { + t.Fatalf("C ABI lowering left nest on the old call parameter:\n%s", caller.String()) + } + if err := llvm.VerifyModule(mod, llvm.ReturnStatusAction); err != nil { + t.Fatalf("C ABI closure-env module is invalid: %v\n%s", err, mod.String()) + } +} + +func TestClosureEnvAttributePreservedByCallbackWrapper(t *testing.T) { + llvm.InitializeAllTargets() + llvm.InitializeAllTargetMCs() + llvm.InitializeAllTargetInfos() + + const testIR = ` +%Value = type { ptr, ptr, i64 } + +define %Value @callback(ptr ATTR %env, %Value %value) { +entry: + ret %Value %value +} +` + for _, attrName := range []string{"nest", "swiftself"} { + t.Run(attrName, func(t *testing.T) { + ctx := llvm.NewContext() + defer ctx.Dispose() + path := filepath.Join(t.TempDir(), "closure_env_callback.ll") + if err := os.WriteFile(path, []byte(strings.ReplaceAll(testIR, "ATTR", attrName)), 0o644); err != nil { + t.Fatal(err) + } + buf, err := llvm.NewMemoryBufferFromFile(path) + if err != nil { + t.Fatal(err) + } + mod, err := ctx.ParseIR(buf) + if err != nil { + t.Fatal(err) + } + defer mod.Dispose() + + prog := llssa.NewProgram(&llssa.Target{GOOS: "linux", GOARCH: "amd64"}) + defer prog.Dispose() + tr := NewTransformer(prog, "amd64-unknown-linux-gnu", "", ModeAllFunc, true) + callback := mod.NamedFunction("callback") + wrapper, ok := tr.transformCallbackFunc(mod, callback) + if !ok { + t.Fatalf("callback wrapper was not required:\n%s", mod.String()) + } + + kind := llvm.AttributeKindID(attrName) + if got := wrapper.GetEnumAttributeAtIndex(2, kind); got.IsNil() { + t.Fatalf("callback wrapper lost/remapped %s:\n%s", attrName, wrapper.String()) + } + var callbackCall llvm.Value + for block := wrapper.FirstBasicBlock(); !block.IsNil(); block = llvm.NextBasicBlock(block) { + for instruction := block.FirstInstruction(); !instruction.IsNil(); instruction = llvm.NextInstruction(instruction) { + if call := instruction.IsACallInst(); !call.IsNil() && call.CalledValue() == callback { + callbackCall = call + } + } + } + if callbackCall.IsNil() || callbackCall.GetCallSiteEnumAttribute(1, kind).IsNil() { + t.Fatalf("callback wrapper call lost %s:\n%s", attrName, wrapper.String()) + } + if err := llvm.VerifyModule(mod, llvm.ReturnStatusAction); err != nil { + t.Fatalf("C ABI callback closure-env module is invalid: %v\n%s", err, mod.String()) + } + }) + } +} + func TestSetSkipFuncsAndShouldSkipCall(t *testing.T) { tr := &Transformer{} tr.SetSkipFuncs([]string{" foo ", "", "bar"}) diff --git a/internal/pclnmap/pclnmap.go b/internal/pclnmap/pclnmap.go index e9e9d8da6d..e08672565a 100644 --- a/internal/pclnmap/pclnmap.go +++ b/internal/pclnmap/pclnmap.go @@ -31,7 +31,7 @@ import ( const ( Magic = "LLGOPCL1" - Version = uint32(3) + Version = uint32(4) ABIVersion = uint32(1) HeaderSize = uint32(256) @@ -70,7 +70,6 @@ const ( descHash descSymbolIndex descEntrySites - descStubSites descPCSites descCount ) @@ -92,17 +91,15 @@ type SymbolIndexEntry struct { } // Site is a final linked PC expressed relative to the image base. ID is a -// symbol ID for EntrySites and StubSites, and a pcline record ID for PCSites. +// symbol ID for EntrySites and a pcline record ID for PCSites. type Site struct { PCOffset uint64 ID uint64 } // Data is the complete immutable payload needed by the external runtime -// loader. EntrySites and StubSites have each been normalized and -// LTO-deduplicated by the post-link analyzer. Keeping them distinct preserves -// the target function's canonical entry while still making closure ABI stubs -// independently symbolizable. +// loader. EntrySites have been normalized and LTO-deduplicated by the +// post-link analyzer. type Data struct { GOOS string GOARCH string @@ -114,7 +111,6 @@ type Data struct { Table funcinfo.Table SymbolIndex []SymbolIndexEntry EntrySites []Site - StubSites []Site PCSites []Site } @@ -200,7 +196,6 @@ func Encode(data Data) ([]byte, error) { {uint64(len(data.Table.Hash)), hashSize, 2}, {uint64(len(data.SymbolIndex)), symbolIndexSize, 8}, {uint64(len(data.EntrySites)), siteSize, 8}, - {uint64(len(data.StubSites)), siteSize, 8}, {uint64(len(data.PCSites)), siteSize, 8}, } @@ -284,7 +279,6 @@ func Encode(data Data) ([]byte, error) { } } writeSites(sections[descEntrySites], data.EntrySites) - writeSites(sections[descStubSites], data.StubSites) writeSites(sections[descPCSites], data.PCSites) binary.LittleEndian.PutUint64(out[headerPayloadHash:], fnv64(out[HeaderSize:])) return out, nil @@ -317,7 +311,7 @@ func descriptorSize(index int) uint64 { return hashSize case descSymbolIndex: return symbolIndexSize - case descEntrySites, descStubSites, descPCSites: + case descEntrySites, descPCSites: return siteSize default: return 0 @@ -328,7 +322,7 @@ func descriptorAlignment(index int) uint64 { switch index { case descRecords, descStringOffsets: return 4 - case descPCLines, descSymbolIndex, descEntrySites, descStubSites, descPCSites: + case descPCLines, descSymbolIndex, descEntrySites, descPCSites: return 8 case descHash: return 2 diff --git a/internal/pclnmap/pclnmap_test.go b/internal/pclnmap/pclnmap_test.go index e47efe7133..c331b18403 100644 --- a/internal/pclnmap/pclnmap_test.go +++ b/internal/pclnmap/pclnmap_test.go @@ -31,7 +31,6 @@ func sampleData(t *testing.T) Data { Table: table, SymbolIndex: []SymbolIndexEntry{{SymbolID: 11, FuncIndex: 1}}, EntrySites: []Site{{PCOffset: 0x1010, ID: 11}}, - StubSites: []Site{{PCOffset: 0x1008, ID: 11}}, PCSites: []Site{{PCOffset: 0x1020, ID: 7}}, } } @@ -57,13 +56,6 @@ func TestEncodeParse(t *testing.T) { if got := view.Sections[descPCSites].Count; got != 1 { t.Fatalf("pcsite count = %d", got) } - if got := view.Sections[descStubSites].Count; got != 1 { - t.Fatalf("stub-site count = %d", got) - } - stub := raw[view.Sections[descStubSites].Offset:] - if pc, id := binary.LittleEndian.Uint64(stub), binary.LittleEndian.Uint64(stub[8:]); pc != 0x1008 || id != 11 { - t.Fatalf("stub site = {%#x, %d}, want {%#x, %d}", pc, id, uint64(0x1008), 11) - } raw2, err := Encode(sampleData(t)) if err != nil { t.Fatal(err) @@ -147,29 +139,6 @@ func TestParseRejectsMisalignedSections(t *testing.T) { } } -func TestParseRejectsInvalidStubSection(t *testing.T) { - raw, err := Encode(sampleData(t)) - if err != nil { - t.Fatal(err) - } - stubDescriptor := headerDescriptors + descStubSites*16 - offset := binary.LittleEndian.Uint64(raw[stubDescriptor:]) - binary.LittleEndian.PutUint64(raw[stubDescriptor:], offset+1) - if _, err := Parse(raw); err == nil { - t.Fatal("Parse accepted a misaligned stub-site section") - } - - raw, err = Encode(sampleData(t)) - if err != nil { - t.Fatal(err) - } - binary.LittleEndian.PutUint64(raw[stubDescriptor:], uint64(len(raw))) - binary.LittleEndian.PutUint64(raw[stubDescriptor+8:], 1) - if _, err := Parse(raw); err == nil { - t.Fatal("Parse accepted an out-of-bounds stub-site section") - } -} - func TestEncodeRejectsUnsupportedTarget(t *testing.T) { data := sampleData(t) data.GOOS = "windows" diff --git a/internal/pclnpost/binary.go b/internal/pclnpost/binary.go index 7a5ec61572..310ae06791 100644 --- a/internal/pclnpost/binary.go +++ b/internal/pclnpost/binary.go @@ -16,7 +16,7 @@ // Package pclnpost implements the P1/P2 prototype of link-phase ftab/findfunctab // generation (doc/design/pclntab-linkphase.md). It parses a linked LLGo -// binary's funcinfo site sections, deduplicates LTO inline copies against the +// binary's funcinfo site section, deduplicates LTO inline copies against the // symbol table, sorts the entries, builds the Go-layout findfunctab via // internal/pclntab, and prints what the P2 build integration would write // back. It performs no writes; its purpose is to prove the risky steps on @@ -55,7 +55,6 @@ type binaryInfo struct { format string raw []byte entrySec []byte - stubSec []byte pcLineSec []byte textStart uint64 textEnd uint64 @@ -71,7 +70,6 @@ type binaryInfo struct { bindTargets []uint64 entryVMAddr, entryVMSize, entryFileOff uint64 - stubVMAddr, stubVMSize, stubFileOff uint64 pcLineVMSize, pcLineFileOff uint64 identityVMSize, identityFileOff uint64 hasCodeSignature bool @@ -122,13 +120,6 @@ func load(path string) (*binaryInfo, error) { } info.entryVMAddr, info.entryVMSize, info.entryFileOff = s.Addr, s.Size, uint64(s.Offset) } - if s := mf.Section("__llgo_stub"); s != nil { - info.stubSec, err = sectionBytes(info.raw, uint64(s.Offset), s.Size) - if err != nil { - return nil, fmt.Errorf("Mach-O __llgo_stub: %w", err) - } - info.stubVMAddr, info.stubVMSize, info.stubFileOff = s.Addr, s.Size, uint64(s.Offset) - } if s := mf.Section("__llgo_pcl"); s != nil { info.pcLineSec, err = sectionBytes(info.raw, uint64(s.Offset), s.Size) if err != nil { @@ -212,13 +203,6 @@ func load(path string) (*binaryInfo, error) { } info.entryVMAddr, info.entryVMSize, info.entryFileOff = s.Addr, s.Size, s.Offset } - if s := ef.Section("llgo_funcinfo_stubsite"); s != nil { - info.stubSec, err = sectionBytes(info.raw, s.Offset, s.Size) - if err != nil { - return nil, fmt.Errorf("ELF llgo_funcinfo_stubsite: %w", err) - } - info.stubVMAddr, info.stubVMSize, info.stubFileOff = s.Addr, s.Size, s.Offset - } if s := ef.Section("llgo_pcline"); s != nil { info.pcLineSec, err = sectionBytes(info.raw, s.Offset, s.Size) if err != nil { @@ -291,8 +275,7 @@ func parseRecords(info *binaryInfo, sec []byte) []siteRecord { // Mach-O pointer slots in the on-disk file hold dyld chained-fixup // encodings; dyld rewrites them at load. Rebase nodes // (DYLD_CHAINED_PTR_64) carry the target in the low 36 bits. Anchors - // naming *exported* functions — every `__llgo_stub.*` and any - // exported Go function — are emitted as BIND nodes instead (bit 63 + // naming exported functions are emitted as BIND nodes instead (bit 63 // set, import ordinal in the low 24 bits, addend above), even though // they bind back into this same image, so those resolve through the // imports table. The P2 write-back avoids the problem entirely by @@ -342,23 +325,15 @@ func fnv64(name string) uint64 { return h } -const stubPrefix = "__llgo_stub." - // canonicalOwner reports whether owner symbol `name` is the function the -// record's symbolID names, or that function's `__llgo_stub.` wrapper. +// record's symbolID names. // Mach-O symbol names carry a C-mangling underscore, and debug/macho's // suffix-shared string table can surface one underscore more or less than // the source-level name, so try each plausible normalization — matching a // specific 64-bit FNV makes a false positive practically impossible. func canonicalOwner(info *binaryInfo, name string, symbolID uint64) bool { for { - cand := name - if len(cand) > len(stubPrefix) { - if i := stringIndex(cand, stubPrefix); i >= 0 { - cand = cand[i+len(stubPrefix):] - } - } - if fnv64(cand) == symbolID { + if fnv64(name) == symbolID { return true } if info.format == "macho" && len(name) > 1 && name[0] == '_' { @@ -369,25 +344,11 @@ func canonicalOwner(info *binaryInfo, name string, symbolID uint64) bool { } } -func stringIndex(s, prefix string) int { - // prefix at the start, allowing for leading mangling underscores only - for i := 0; i+len(prefix) <= len(s) && i <= 2; i++ { - if s[i:i+len(prefix)] == prefix { - return i - } - if s[i] != '_' { - break - } - } - return -1 -} - // dedupe keeps exactly the canonical record per emitting function: a record // is canonical when the symbol that owns its anchor PC is the function the -// symbolID names (id == fnv64(owner)) or that function's closure stub -// (owner "__llgo_stub.X" with id == fnv64(X) — stubs share the target's -// symbolID by design). Everything else with a known owner is an LTO inline -// copy: inlining duplicated the body-embedded record into a host function. +// symbolID names (id == fnv64(owner)). Everything else with a known owner is +// an LTO inline copy: inlining duplicated the body-embedded record into a host +// function. // Kept records are normalized to their owner's true entry address. Records // whose owner cannot be determined are dropped conservatively. func dedupe(info *binaryInfo, recs []siteRecord, verbose bool) (kept []siteRecord, droppedInline, droppedUnknown int) { diff --git a/internal/pclnpost/binary_test.go b/internal/pclnpost/binary_test.go index b1b185cc8d..4d2ed130e0 100644 --- a/internal/pclnpost/binary_test.go +++ b/internal/pclnpost/binary_test.go @@ -34,17 +34,13 @@ func TestCanonicalOwner(t *testing.T) { }{ // ELF: symbol names are source-level. {elf, "example.com/p.F", true}, - {elf, "__llgo_stub.example.com/p.F", true}, {elf, "example.com/p.G", false}, // Mach-O: one C-mangling underscore, and debug/macho's suffix-shared // string table can surface one underscore more or less. {macho, "_example.com/p.F", true}, {macho, "example.com/p.F", true}, - {macho, "___llgo_stub.example.com/p.F", true}, - {macho, "__llgo_stub.example.com/p.F", true}, // An LTO inline copy: record id names F but the owner is the host. {macho, "_example.com/p.Host", false}, - {macho, "___llgo_stub.example.com/p.G", false}, } for _, c := range cases { if got := canonicalOwner(c.info, c.name, id); got != c.want { diff --git a/internal/pclnpost/elf_fixture_test.go b/internal/pclnpost/elf_fixture_test.go index ab11abba2e..2549499531 100644 --- a/internal/pclnpost/elf_fixture_test.go +++ b/internal/pclnpost/elf_fixture_test.go @@ -24,19 +24,19 @@ import ( "testing" ) -// buildELF fabricates the minimal ELF load() understands: .text, the two -// funcinfo site sections, a data section holding the symbol index, .symtab +// buildELF fabricates the minimal ELF load() understands: .text, the funcinfo +// entry-site section, a data section holding the symbol index, .symtab // and .strtab. Layout is one flat file segment; vmaddr == file offset + 0x10000. type elfFn struct { name string size uint64 } -func buildELF(t *testing.T, fns []elfFn, entryRecs, stubRecs func(addrOf func(string) uint64) []byte, entryPad, stubPad int) string { - return buildELFExternal(t, fns, entryRecs, stubRecs, entryPad, stubPad, nil, nil) +func buildELF(t *testing.T, fns []elfFn, entryRecs func(addrOf func(string) uint64) []byte, entryPad int) string { + return buildELFExternal(t, fns, entryRecs, entryPad, nil, nil) } -func buildELFExternal(t *testing.T, fns []elfFn, entryRecs, stubRecs func(addrOf func(string) uint64) []byte, entryPad, stubPad int, pcLine, identity []byte) string { +func buildELFExternal(t *testing.T, fns []elfFn, entryRecs func(addrOf func(string) uint64) []byte, entryPad int, pcLine, identity []byte) string { t.Helper() const base = uint64(0x10000) var text bytes.Buffer @@ -48,8 +48,6 @@ func buildELFExternal(t *testing.T, fns []elfFn, entryRecs, stubRecs func(addrOf addrOf := func(n string) uint64 { return addr[n] } entry := entryRecs(addrOf) entry = append(entry, make([]byte, entryPad)...) - stub := stubRecs(addrOf) - stub = append(stub, make([]byte, stubPad)...) // Symbol index: sorted {u64 fnv(name), u32 funcIndex, u32 pad}. type sie struct { @@ -102,7 +100,7 @@ func buildELFExternal(t *testing.T, fns []elfFn, entryRecs, stubRecs func(addrOf binary.Write(&symtab, binary.LittleEndian, fn.size) } - sectionNames := []string{".text", "llgo_funcinfo_entry", "llgo_funcinfo_stubsite"} + sectionNames := []string{".text", "llgo_funcinfo_entry"} if pcLine != nil { sectionNames = append(sectionNames, "llgo_pcline") } @@ -129,7 +127,6 @@ func buildELFExternal(t *testing.T, fns []elfFn, entryRecs, stubRecs func(addrOf secs := []sec{ {".text", 1, base, text.Bytes(), 0, 0}, {"llgo_funcinfo_entry", 1, base + 0x4000, entry, 0, 0}, - {"llgo_funcinfo_stubsite", 1, base + 0x6000, stub, 0, 0}, } if pcLine != nil { secs = append(secs, sec{"llgo_pcline", 1, base + 0x7000, pcLine, 0, 0}) @@ -195,7 +192,6 @@ func fixtureFns() []elfFn { return []elfFn{ {"example.com/p.A", 64}, {"example.com/p.B", 64}, - {"__llgo_stub.example.com/p.A", 16}, } } @@ -204,17 +200,13 @@ func fixtureEntry(addrOf func(string) uint64) []byte { return append(out, rec(addrOf("example.com/p.B")+4, fnv64("example.com/p.B"))...) } -func fixtureStub(addrOf func(string) uint64) []byte { - return rec(addrOf("__llgo_stub.example.com/p.A")+4, fnv64("example.com/p.A")) -} - func TestRewriteELFInPlace(t *testing.T) { - path := buildELF(t, fixtureFns(), fixtureEntry, fixtureStub, 4096, 256) + path := buildELF(t, fixtureFns(), fixtureEntry, 4096) st, err := Rewrite(path) if err != nil { t.Fatal(err) } - if st.FtabEntries != 4 { // A, B, stub, sentinel + if st.FtabEntries != 3 { // A, B, sentinel t.Fatalf("stats %+v", st) } // Idempotence guard. @@ -233,42 +225,10 @@ func TestRewriteELFInPlace(t *testing.T) { if base != 0x10000 { // first function entry t.Fatalf("base %#x", base) } - // Stub section voided. - for _, b := range info.stubSec { - if b != 0 { - t.Fatal("stub section not zeroed") - } - } -} - -func TestRewriteELFSpillsToStubSection(t *testing.T) { - // Entry section too small for the blob, stub section large enough. - path := buildELF(t, fixtureFns(), fixtureEntry, fixtureStub, 0, 8192) - st, err := Rewrite(path) - if err != nil { - t.Fatal(err) - } - if st.FtabEntries != 4 { - t.Fatalf("stats %+v", st) - } - info, err := load(path) - if err != nil { - t.Fatal(err) - } - if got := binary.LittleEndian.Uint64(info.entrySec[0:]); got != redirectMagic { - t.Fatalf("entry magic %#x", got) - } - if got := binary.LittleEndian.Uint64(info.stubSec[0:]); got != prebuiltMagic { - t.Fatalf("stub magic %#x", got) - } - if ptr := binary.LittleEndian.Uint64(info.entrySec[16:]); ptr != info.stubVMAddr { - t.Fatalf("redirect ptr %#x want %#x", ptr, info.stubVMAddr) - } } func TestRewriteELFOverflowFallsBack(t *testing.T) { - // Neither section fits: Rewrite must fail (no gap-y table). - path := buildELF(t, fixtureFns(), fixtureEntry, fixtureStub, 0, 0) + path := buildELF(t, fixtureFns(), fixtureEntry, 0) before, _ := os.ReadFile(path) if _, err := Rewrite(path); err == nil { t.Fatal("expected overflow error") @@ -282,7 +242,7 @@ func TestRewriteELFOverflowFallsBack(t *testing.T) { func TestRewriteErrorPaths(t *testing.T) { // No entry records at all. empty := func(addrOf func(string) uint64) []byte { return nil } - path := buildELF(t, fixtureFns(), empty, empty, 4096, 256) + path := buildELF(t, fixtureFns(), empty, 4096) if _, err := Rewrite(path); err == nil { t.Fatal("expected no-entry-records error") } @@ -290,7 +250,7 @@ func TestRewriteErrorPaths(t *testing.T) { orphan := func(addrOf func(string) uint64) []byte { return rec(0xdead0000, 42) } - path = buildELF(t, fixtureFns(), orphan, empty, 4096, 256) + path = buildELF(t, fixtureFns(), orphan, 4096) if _, err := Rewrite(path); err == nil { t.Fatal("expected no-survivors error") } diff --git a/internal/pclnpost/external.go b/internal/pclnpost/external.go index 136e66e70a..12bace90ff 100644 --- a/internal/pclnpost/external.go +++ b/internal/pclnpost/external.go @@ -47,8 +47,7 @@ type ExternalSite struct { // ExternalAnalysis is the immutable input for an external pclntab sidecar. // TextStart and TextEnd are link-time virtual addresses; sites are expressed -// relative to ImageBase. EntrySites and StubSites retain their distinct -// runtime meanings after LTO-copy deduplication against the final symbol +// relative to ImageBase after LTO-copy deduplication against the final symbol // table. Identity is SHA-256 of the complete, unmodified linked binary. type ExternalAnalysis struct { Format string @@ -59,18 +58,16 @@ type ExternalAnalysis struct { Identity [sha256.Size]byte EntrySites []ExternalSite - StubSites []ExternalSite PCLineSites []ExternalSite EntryRecords int - StubRecords int PCLineRecords int InlineCopies int NoSymbol int } // AnalyzeExternal reads a linked ELF or Mach-O executable without modifying -// it. It resolves Mach-O chained pointer slots, deduplicates function/stub +// it. It resolves Mach-O chained pointer slots, deduplicates function // records against final text symbols, and returns deterministic image-base- // relative site lists suitable for an external sidecar. func AnalyzeExternal(path string) (ExternalAnalysis, error) { @@ -83,29 +80,22 @@ func AnalyzeExternal(path string) (ExternalAnalysis, error) { return out, err } if len(info.entrySec) >= 8 { - if magic := binary.LittleEndian.Uint64(info.entrySec); magic == prebuiltMagic || magic == redirectMagic { + if magic := binary.LittleEndian.Uint64(info.entrySec); magic == prebuiltMagic { return out, fmt.Errorf("entry sites have already been rewritten") } } entries := parseRecords(info, info.entrySec) - stubs := parseRecords(info, info.stubSec) pcLines := parseRecords(info, info.pcLineSec) out.EntryRecords = len(entries) - out.StubRecords = len(stubs) out.PCLineRecords = len(pcLines) if len(entries) == 0 { return out, fmt.Errorf("no entry records") } - kept, inline, noSymbol := dedupe(info, append(entries, stubs...), false) + kept, inline, noSymbol := dedupe(info, entries, false) if len(kept) == 0 { return out, fmt.Errorf("no records survived dedup") } - keptEntries, keptStubs := partitionExternalEntries(info, kept) - if len(keptEntries) == 0 { - return out, fmt.Errorf("no entry records survived dedup") - } - out.Format = info.format out.PointerSize = info.pointerSize out.ImageBase = info.imageBase @@ -114,34 +104,11 @@ func AnalyzeExternal(path string) (ExternalAnalysis, error) { out.Identity = sha256.Sum256(info.raw) out.InlineCopies = inline out.NoSymbol = noSymbol - out.EntrySites = externalSites(info, keptEntries) - out.StubSites = externalSites(info, keptStubs) + out.EntrySites = externalSites(info, kept) out.PCLineSites = externalPCLineSites(info, pcLines) return out, nil } -// partitionExternalEntries classifies normalized records by their final -// linked owner, not by the input section that carried the anchor. LTO can -// inline a target body (and its entry anchor) into the target's closure stub, -// or retain a stub anchor in the target. In either case the final owner kind -// is authoritative for the runtime's canonical-entry semantics. -func partitionExternalEntries(info *binaryInfo, kept []siteRecord) (entries, stubs []siteRecord) { - entries = make([]siteRecord, 0, len(kept)) - stubs = make([]siteRecord, 0, len(kept)) - for _, record := range kept { - owner, ok := owner(info, record.pc) - if !ok { - continue - } - if stringIndex(owner.name, stubPrefix) >= 0 { - stubs = append(stubs, record) - } else { - entries = append(entries, record) - } - } - return entries, stubs -} - func validateExternalLayout(info *binaryInfo) error { if info.format != ExternalFormatELF && info.format != ExternalFormatMachO { return fmt.Errorf("unsupported binary format %q", info.format) @@ -209,7 +176,7 @@ func externalPCLineSites(info *binaryInfo, records []siteRecord) []ExternalSite sites = append(sites, ExternalSite{ PCOffset: record.pc - info.imageBase, ID: record.symbolID, - OwnerSymbol: externalOwnerSymbolName(sym.name), + OwnerSymbol: sym.name, }) } sort.Slice(sites, func(i, j int) bool { @@ -235,16 +202,9 @@ func externalPCLineSites(info *binaryInfo, records []siteRecord) []ExternalSite return out } -func externalOwnerSymbolName(name string) string { - if i := stringIndex(name, stubPrefix); i >= 0 { - return name[i+len(stubPrefix):] - } - return name -} - // DetachExternal verifies that identity still names the unmodified binary, // writes it into the dedicated 32-byte identity section, and clears all -// link-only entry, stub, and PC-line site sections. Mach-O chained fixups in +// link-only entry and PC-line site sections. Mach-O chained fixups in // those ranges are removed before the bytes are cleared. A signed Mach-O is // ad-hoc re-signed once, after all mutations, before the replacement is // published atomically. @@ -287,9 +247,6 @@ func DetachExternal(path string, identity [sha256.Size]byte) error { if err := addRange("entry-site", info.entryFileOff, info.entryVMSize); err != nil { return err } - if err := addRange("stub-site", info.stubFileOff, info.stubVMSize); err != nil { - return err - } if err := addRange("pcline-site", info.pcLineFileOff, info.pcLineVMSize); err != nil { return err } diff --git a/internal/pclnpost/external_test.go b/internal/pclnpost/external_test.go index 7eb85ab49a..5ee3636787 100644 --- a/internal/pclnpost/external_test.go +++ b/internal/pclnpost/external_test.go @@ -34,15 +34,7 @@ func externalELFFixture(t *testing.T, identitySize int) string { // LTO-style copy of A's body record in B: AnalyzeExternal must drop it. out = append(out, rec(addrOf("example.com/p.B")+8, idA)...) out = append(out, rec(addrOf("example.com/p.B")+4, fnv64("example.com/p.B"))...) - // LTO may also copy a target's entry-section anchor into its closure - // stub. Final-owner classification must keep this only as a stub site. - return append(out, rec(addrOf("__llgo_stub.example.com/p.A")+8, idA)...) - } - stub := func(addrOf func(string) uint64) []byte { - out := fixtureStub(addrOf) - // Conversely, a stub-section anchor retained in its real target must - // remain an ordinary entry and must not create a duplicate stub site. - return append(out, rec(addrOf("example.com/p.B")+12, fnv64("example.com/p.B"))...) + return out } const imageBase = uint64(0x10000) pcLine := rec(imageBase+8, 101) @@ -50,7 +42,7 @@ func externalELFFixture(t *testing.T, identitySize int) string { pcLine = append(pcLine, rec(imageBase+72, 202)...) pcLine = append(pcLine, rec(imageBase+76, 101)...) // A's pcline copied into B pcLine = append(pcLine, rec(0xdead0000, 303)...) // outside text - path := buildELFExternal(t, fixtureFns(), entry, stub, 256, 64, + path := buildELFExternal(t, fixtureFns(), entry, 256, pcLine, make([]byte, identitySize)) addELFLoadSegments(t, path, imageBase) return path @@ -99,13 +91,13 @@ func TestAnalyzeExternalELF(t *testing.T) { if analysis.Format != ExternalFormatELF || analysis.PointerSize != 8 { t.Fatalf("target = %s/%d", analysis.Format, analysis.PointerSize) } - if analysis.ImageBase != 0x10000 || analysis.TextStart != 0x10000 || analysis.TextEnd != 0x10090 { + if analysis.ImageBase != 0x10000 || analysis.TextStart != 0x10000 || analysis.TextEnd != 0x10080 { t.Fatalf("layout base=%#x text=[%#x,%#x)", analysis.ImageBase, analysis.TextStart, analysis.TextEnd) } if analysis.Identity != sha256.Sum256(before) { t.Fatal("identity is not the pre-mutation binary SHA-256") } - if analysis.EntryRecords != 4 || analysis.StubRecords != 2 || analysis.InlineCopies != 1 || analysis.NoSymbol != 0 { + if analysis.EntryRecords != 3 || analysis.InlineCopies != 1 || analysis.NoSymbol != 0 { t.Fatalf("analysis stats: %+v", analysis) } wantEntries := []ExternalSite{ @@ -115,10 +107,6 @@ func TestAnalyzeExternalELF(t *testing.T) { if !reflect.DeepEqual(analysis.EntrySites, wantEntries) { t.Fatalf("entry sites = %#v, want %#v", analysis.EntrySites, wantEntries) } - wantStubs := []ExternalSite{{PCOffset: 128, ID: fnv64("example.com/p.A")}} - if !reflect.DeepEqual(analysis.StubSites, wantStubs) { - t.Fatalf("stub sites = %#v, want %#v", analysis.StubSites, wantStubs) - } wantPCLines := []ExternalSite{ {PCOffset: 8, ID: 101, OwnerSymbol: "example.com/p.A"}, {PCOffset: 72, ID: 202, OwnerSymbol: "example.com/p.B"}, @@ -140,21 +128,6 @@ func TestAnalyzeExternalELF(t *testing.T) { } } -func TestExternalOwnerSymbolNameNormalizesStubs(t *testing.T) { - for _, name := range []string{ - "__llgo_stub.example.com/p.F", - "___llgo_stub.example.com/p.F", - "____llgo_stub.example.com/p.F", - } { - if got := externalOwnerSymbolName(name); got != "example.com/p.F" { - t.Fatalf("externalOwnerSymbolName(%q) = %q", name, got) - } - } - if got := externalOwnerSymbolName("__example.com/p.F"); got != "__example.com/p.F" { - t.Fatalf("ordinary owner was changed to %q", got) - } -} - func TestDetachExternalELF(t *testing.T) { path := externalELFFixture(t, sha256.Size) analysis, err := AnalyzeExternal(path) @@ -170,7 +143,6 @@ func TestDetachExternalELF(t *testing.T) { } for name, section := range map[string][]byte{ "entry": info.entrySec, - "stub": info.stubSec, "pcline": info.pcLineSec, } { if !bytes.Equal(section, make([]byte, len(section))) { @@ -232,20 +204,16 @@ func TestAnalyzeAndDetachExternalMachO(t *testing.T) { fns := []elfFn{ {name: "example.com/p.A", size: 0x10}, {name: "example.com/p.B", size: 0x40}, - {name: "__llgo_stub.example.com/p.A", size: 0x80}, } addr := func(off uint64) uint64 { return imageBase + 0x1000 + off } idA, idB := fnv64("example.com/p.A"), fnv64("example.com/p.B") entry := rec(addr(0x10)+4, idA) entry = append(entry, rec(addr(0x40)+8, idA)...) // inline A copy in B entry = append(entry, rec(addr(0x40)+4, idB)...) - entry = append(entry, rec(addr(0x80)+8, idA)...) // entry anchor copied into stub - stub := rec(addr(0x80)+4, idA) - stub = append(stub, rec(addr(0x40)+12, idB)...) // stub anchor retained in target pcLine := rec(addr(0x10)+8, 11) pcLine = append(pcLine, rec(addr(0x40)+8, 22)...) pcLine = append(pcLine, rec(addr(0x40)+12, 11)...) // A's pcline copied into B - path := buildMachOExternal(t, entry, stub, pcLine, make([]byte, sha256.Size), fns) + path := buildMachOExternal(t, entry, pcLine, make([]byte, sha256.Size), fns) pageStartOff := chainMachOSitePointers(t, path) analysis, err := AnalyzeExternal(path) @@ -262,10 +230,6 @@ func TestAnalyzeAndDetachExternalMachO(t *testing.T) { if !reflect.DeepEqual(analysis.EntrySites, wantEntries) || analysis.InlineCopies != 1 { t.Fatalf("entry analysis = %#v inline=%d", analysis.EntrySites, analysis.InlineCopies) } - wantStubs := []ExternalSite{{PCOffset: 0x1080, ID: idA}} - if !reflect.DeepEqual(analysis.StubSites, wantStubs) { - t.Fatalf("stub analysis = %#v, want %#v", analysis.StubSites, wantStubs) - } wantPCLines := []ExternalSite{ {PCOffset: 0x1018, ID: 11, OwnerSymbol: "example.com/p.A"}, {PCOffset: 0x1048, ID: 22, OwnerSymbol: "example.com/p.B"}, @@ -283,7 +247,6 @@ func TestAnalyzeAndDetachExternalMachO(t *testing.T) { } for name, section := range map[string][]byte{ "entry": info.entrySec, - "stub": info.stubSec, "pcline": info.pcLineSec, } { if !bytes.Equal(section, make([]byte, len(section))) { @@ -341,7 +304,7 @@ func TestExternalSitesFilterSortAndDedupe(t *testing.T) { textEnd: 0x1200, syms: []textSym{ {addr: 0x1100, size: 0x40, name: "example.com/p.A"}, - {addr: 0x1140, size: 0x40, name: "__llgo_stub.example.com/p.B"}, + {addr: 0x1140, size: 0x40, name: "example.com/p.B"}, }, } records := []siteRecord{ @@ -378,14 +341,6 @@ func TestExternalSitesFilterSortAndDedupe(t *testing.T) { t.Fatalf("singleton pcline sites = %#v", got) } - entries, stubs := partitionExternalEntries(info, []siteRecord{ - {pc: 0x1100, symbolID: 1}, - {pc: 0x1140, symbolID: 2}, - {pc: 0x1190, symbolID: 3}, - }) - if len(entries) != 1 || len(stubs) != 1 { - t.Fatalf("partition = (%#v, %#v)", entries, stubs) - } } func TestAnalyzeExternalRejectsInvalidRecordStates(t *testing.T) { @@ -394,13 +349,10 @@ func TestAnalyzeExternalRejectsInvalidRecordStates(t *testing.T) { inlineOnly := func(addrOf func(string) uint64) []byte { return rec(addrOf("example.com/p.A")+4, fnv64("example.com/p.B")) } - validStub := func(addrOf func(string) uint64) []byte { - return rec(addrOf("__llgo_stub.example.com/p.A")+4, fnv64("example.com/p.A")) - } tests := map[string]string{ - "no records": buildELFExternal(t, fixtureFns(), noRecords, noRecords, 0, 0, nil, make([]byte, sha256.Size)), - "no survivors": buildELFExternal(t, fixtureFns(), unknownRecord, noRecords, 0, 0, nil, make([]byte, sha256.Size)), - "stub only": buildELFExternal(t, fixtureFns(), inlineOnly, validStub, 0, 0, nil, make([]byte, sha256.Size)), + "no records": buildELFExternal(t, fixtureFns(), noRecords, 0, nil, make([]byte, sha256.Size)), + "no survivors": buildELFExternal(t, fixtureFns(), unknownRecord, 0, nil, make([]byte, sha256.Size)), + "inline only": buildELFExternal(t, fixtureFns(), inlineOnly, 0, nil, make([]byte, sha256.Size)), } for name, path := range tests { t.Run(name, func(t *testing.T) { @@ -457,7 +409,6 @@ func chainMachOSitePointers(t *testing.T, path string) uint64 { data []byte }{ {info.entryFileOff, info.entrySec}, - {info.stubFileOff, info.stubSec}, {info.pcLineFileOff, info.pcLineSec}, } { for off := 0; off+16 <= len(section.data); off += 16 { diff --git a/internal/pclnpost/logic_test.go b/internal/pclnpost/logic_test.go index 16b68da0e5..cd4cebef36 100644 --- a/internal/pclnpost/logic_test.go +++ b/internal/pclnpost/logic_test.go @@ -65,22 +65,20 @@ func TestDedupeCanonicalAndInline(t *testing.T) { info := &binaryInfo{format: "elf", textStart: 0x1000, textEnd: 0x4000, syms: []textSym{ {addr: 0x1000, size: 0x100, name: fn}, {addr: 0x1100, size: 0x100, name: host}, - {addr: 0x1200, size: 0x10, name: "__llgo_stub." + fn}, }} id := fnv64(fn) recs := []siteRecord{ {pc: 0x1004, symbolID: id}, // canonical, inside F {pc: 0x1104, symbolID: id}, // inline copy inside Host - {pc: 0x1204, symbolID: id}, // stub wrapper, canonical {pc: 0x1008, symbolID: id}, // duplicate owner, collapsed {pc: 0x9999, symbolID: id}, // no owner } kept, inline, nosym := dedupe(info, recs, false) - if len(kept) != 2 || inline != 1 || nosym != 1 { + if len(kept) != 1 || inline != 1 || nosym != 1 { t.Fatalf("kept=%d inline=%d nosym=%d", len(kept), inline, nosym) } - if kept[0].pc != 0x1000 || kept[1].pc != 0x1200 { - t.Fatalf("normalized pcs %#x %#x", kept[0].pc, kept[1].pc) + if kept[0].pc != 0x1000 { + t.Fatalf("normalized pc %#x", kept[0].pc) } } @@ -116,14 +114,14 @@ func TestFnv64NonZero(t *testing.T) { } func TestSymbolAddrBothFormats(t *testing.T) { - elfPath := buildELF(t, fixtureFns(), fixtureEntry, fixtureStub, 4096, 256) + elfPath := buildELF(t, fixtureFns(), fixtureEntry, 4096) if addr, err := symbolAddr(elfPath, "example.com/p.A"); err != nil || addr != 0x10000 { t.Fatalf("elf symbolAddr = %#x, %v", addr, err) } if _, err := symbolAddr(elfPath, "no.such.symbol"); err == nil { t.Fatal("expected missing-symbol error on elf") } - machoPath := buildMachO(t, rec(0, 0), rec(0, 0), + machoPath := buildMachO(t, rec(0, 0), []elfFn{{name: "example.com/p.M", size: 0x10}}) if addr, err := symbolAddr(machoPath, "example.com/p.M"); err != nil || addr == 0 { t.Fatalf("macho symbolAddr = %#x, %v", addr, err) diff --git a/internal/pclnpost/macho_fixture_test.go b/internal/pclnpost/macho_fixture_test.go index dcbdf67744..9200e11828 100644 --- a/internal/pclnpost/macho_fixture_test.go +++ b/internal/pclnpost/macho_fixture_test.go @@ -26,13 +26,13 @@ import ( // buildMachO fabricates a minimal 64-bit Mach-O that debug/macho can Open: // one __TEXT segment (__text) and one __DATA segment carrying __llgo_fie / -// __llgo_stub, plus LC_SYMTAB and an LC_DYLD_CHAINED_FIXUPS whose imports +// optional pcline data, plus LC_SYMTAB and an LC_DYLD_CHAINED_FIXUPS whose imports // table binds ordinal 1 to a local symbol. -func buildMachO(t *testing.T, entry, stub []byte, syms []elfFn) string { - return buildMachOExternal(t, entry, stub, nil, nil, syms) +func buildMachO(t *testing.T, entry []byte, syms []elfFn) string { + return buildMachOExternal(t, entry, nil, nil, syms) } -func buildMachOExternal(t *testing.T, entry, stub, pcLine, identity []byte, syms []elfFn) string { +func buildMachOExternal(t *testing.T, entry, pcLine, identity []byte, syms []elfFn) string { t.Helper() const base = uint64(0x100000000) text := make([]byte, 0x40000) // big enough that findfunctab buckets outgrow a tiny entry section @@ -68,8 +68,7 @@ func buildMachOExternal(t *testing.T, entry, stub, pcLine, identity []byte, syms // File layout (fixed offsets, one page apart). const textOff = uint64(0x1000) const entryOff = uint64(0x2000) - stubOff := entryOff + uint64(len(entry)) - dataEnd := stubOff + uint64(len(stub)) + dataEnd := entryOff + uint64(len(entry)) pcLineOff := dataEnd if pcLine != nil { dataEnd += uint64(len(pcLine)) @@ -89,7 +88,6 @@ func buildMachOExternal(t *testing.T, entry, stub, pcLine, identity []byte, syms })}) dataSections := [][]byte{ sect("__llgo_fie", "__DATA", base+entryOff, entryOff, uint64(len(entry))), - sect("__llgo_stub", "__DATA", base+stubOff, stubOff, uint64(len(stub))), } if pcLine != nil { dataSections = append(dataSections, sect("__llgo_pcl", "__DATA", base+pcLineOff, pcLineOff, uint64(len(pcLine)))) @@ -192,7 +190,6 @@ func buildMachOExternal(t *testing.T, entry, stub, pcLine, identity []byte, syms copy(raw[32:], cmdBytes) copy(raw[textOff:], text) copy(raw[entryOff:], entry) - copy(raw[stubOff:], stub) if pcLine != nil { copy(raw[pcLineOff:], pcLine) } @@ -221,9 +218,7 @@ func TestLoadMachOFixture(t *testing.T) { badBind := uint64(1) << 63 entry := append(rec(rebase, fnv64("example.com/p.B")), rec(bind, fnv64("example.com/p.A"))...) entry = append(entry, rec(badBind, 99)...) - stub := rec(0, 0) - - path := buildMachO(t, entry, stub, fns) + path := buildMachO(t, entry, fns) info, err := load(path) if err != nil { t.Fatal(err) @@ -252,7 +247,7 @@ func TestLoadMachOFixture(t *testing.T) { // machoRewriteFixture: records anchored inside real text symbols so dedupe // keeps them, plus a meta record advertising the symbol index inside the // entry section (readVM resolves it through the __DATA section). -func machoRewriteFixture(t *testing.T, entryPad, stubPad int) string { +func machoRewriteFixture(t *testing.T, entryPad int) string { t.Helper() const base = uint64(0x100000000) fns := []elfFn{{name: "example.com/p.A", size: 0x10}, {name: "example.com/p.B", size: 0x3F000}} // far apart: findfunctab spans many buckets @@ -298,12 +293,11 @@ func machoRewriteFixture(t *testing.T, entryPad, stubPad int) string { binary.LittleEndian.PutUint64(entry[16:], ptrAddr) binary.LittleEndian.PutUint64(entry[32:], cntAddr) entry = append(entry, make([]byte, entryPad)...) - stub := append(rec(0, 0), make([]byte, stubPad)...) - return buildMachO(t, entry, stub, fns) + return buildMachO(t, entry, fns) } func TestRewriteMachOInPlace(t *testing.T) { - path := machoRewriteFixture(t, 4096, 512) + path := machoRewriteFixture(t, 4096) st, err := Rewrite(path) if err != nil { t.Fatal(err) @@ -319,24 +313,3 @@ func TestRewriteMachOInPlace(t *testing.T) { t.Fatalf("magic %#x", got) } } - -func TestRewriteMachOSpill(t *testing.T) { - path := machoRewriteFixture(t, 0, 8192) - st, err := Rewrite(path) - if err != nil { - t.Fatal(err) - } - if st.FtabEntries != 3 { - t.Fatalf("stats %+v", st) - } - info, err := load(path) - if err != nil { - t.Fatal(err) - } - if got := binary.LittleEndian.Uint64(info.entrySec[0:]); got != redirectMagic { - t.Fatalf("entry magic %#x", got) - } - if got := binary.LittleEndian.Uint64(info.stubSec[0:]); got != prebuiltMagic { - t.Fatalf("stub magic %#x", got) - } -} diff --git a/internal/pclnpost/pclnpost.go b/internal/pclnpost/pclnpost.go index 053c9ed5fe..91bc59b802 100644 --- a/internal/pclnpost/pclnpost.go +++ b/internal/pclnpost/pclnpost.go @@ -25,7 +25,6 @@ import ( type Stats struct { Format string EntryRecords int - StubRecords int Kept int InlineCopies int NoSymbol int @@ -35,7 +34,7 @@ type Stats struct { // Rewrite parses the linked binary's funcinfo site sections, deduplicates // LTO inline copies against the symbol table, builds the Go-layout prebuilt -// table and rewrites the entry section in place (voiding the stub section). +// table and rewrites the entry section in place. // The runtime adopts the table when it sees the magic header and falls back // to first-use construction otherwise, so failures here leave a fully // functional binary. @@ -47,29 +46,22 @@ func Rewrite(path string) (Stats, error) { } st.Format = info.format if len(info.entrySec) >= 8 { - if m := binary.LittleEndian.Uint64(info.entrySec); m == prebuiltMagic || m == redirectMagic { + if m := binary.LittleEndian.Uint64(info.entrySec); m == prebuiltMagic { return st, fmt.Errorf("already rewritten") } } entries := parseRecords(info, info.entrySec) - stubs := parseRecords(info, info.stubSec) - st.EntryRecords, st.StubRecords = len(entries), len(stubs) + st.EntryRecords = len(entries) if len(entries) == 0 { return st, fmt.Errorf("no entry records") } - kept, inline, nosym := dedupe(info, append(entries, stubs...), false) + kept, inline, nosym := dedupe(info, entries, false) st.Kept, st.InlineCopies, st.NoSymbol = len(kept), inline, nosym if len(kept) == 0 { return st, fmt.Errorf("no records survived dedup") } ftab, buckets, err := writeBack(path, info, kept) if err != nil { - // Includes errBlobOverflow when the blob fits neither the entry nor - // the stub section. Never drop stub rows to squeeze in: a table with - // gaps attributes pcs inside a gap to the previous function - // (nearest-below), which silently returns wrong names on platforms - // where dladdr cannot rescue (non-PIE ELF). First-use construction - // is slower but correct. return st, err } st.FtabEntries, st.Buckets = ftab, buckets diff --git a/internal/pclnpost/write.go b/internal/pclnpost/write.go index def30eed2e..413f4048a0 100644 --- a/internal/pclnpost/write.go +++ b/internal/pclnpost/write.go @@ -20,7 +20,6 @@ import ( "debug/elf" "debug/macho" "encoding/binary" - "errors" "fmt" "os" "os/exec" @@ -41,19 +40,6 @@ import ( // on non-PIE ELF the link-time value already equals the runtime address. const prebuiltMagic = uint64(0x314254464F474C4C) -// errBlobOverflow reports that the prebuilt blob fits neither the entry -// section nor the (larger) stub section; the caller retries without stub -// rows before giving up. -var errBlobOverflow = errors.New("prebuilt blob does not fit entry or stub section") - -// redirectMagic ("LLGOFTB2" little-endian) marks a 32-byte entry-section -// header whose third word points at the real blob, written into the stub -// section when the table outgrows the entry section (stub rows can double -// the count). The pointer slot is a live relocation like the in-place base -// slot: dyld rebases it on Mach-O, and non-PIE ELF link addresses already -// equal runtime addresses. -const redirectMagic = uint64(0x324254464F474C4C) - const ( bucketSize = 4096 subbucketCnt = 16 @@ -66,8 +52,7 @@ type symIndexEntry struct { idx uint32 } -// writeBack rewrites the entry-site section in place with the prebuilt table -// and voids the stub section (its records are merged into the table). +// writeBack rewrites the entry-site section in place with the prebuilt table. func writeBack(path string, info *binaryInfo, kept []siteRecord) (ftabCount, bucketCount int, err error) { symIdx, err := loadSymbolIndex(path, info) if err != nil { @@ -131,22 +116,12 @@ func writeBack(path string, info *binaryInfo, kept []siteRecord) (ftabCount, buc } need := 32 + count*8 + len(buckets) - entrySize := int(info.entryVMSize) - spill := need > entrySize - if spill && need > int(info.stubVMSize) { - return 0, 0, errBlobOverflow - } - blobSect := int(info.entryVMSize) - blobFileOff := info.entryFileOff - blobVMAddr := info.entryVMAddr - if spill { - blobSect = int(info.stubVMSize) - blobFileOff = info.stubFileOff - blobVMAddr = info.stubVMAddr + if need > int(info.entryVMSize) { + return 0, 0, fmt.Errorf("prebuilt blob needs %d bytes; entry section has %d", need, info.entryVMSize) } - blob := make([]byte, blobSect) // zero tail + blob := make([]byte, int(info.entryVMSize)) // zero tail binary.LittleEndian.PutUint64(blob[0:], prebuiltMagic) - binary.LittleEndian.PutUint64(blob[8:], blobVMAddr) + binary.LittleEndian.PutUint64(blob[8:], info.entryVMAddr) binary.LittleEndian.PutUint64(blob[16:], base) binary.LittleEndian.PutUint32(blob[24:], uint32(count)) binary.LittleEndian.PutUint32(blob[28:], uint32(len(buckets)/bucketBytes)) @@ -165,51 +140,23 @@ func writeBack(path string, info *binaryInfo, kept []siteRecord) (ftabCount, buc copy(raw, info.raw) var pending []pendingWrite if info.format == "macho" { - // Remove the rewritten sections' pointer slots from dyld's chained + // Remove the rewritten section's pointer slots from dyld's chained // fixup page chains first: otherwise dyld rebases 8-byte slots - // inside the new table at load time, and a chain terminating early - // inside the zeroed stub section would skip unrelated fixups later - // in the same page. + // inside the new table at load time. ranges := [][2]uint64{{info.entryFileOff, info.entryFileOff + info.entryVMSize}} - if info.stubVMSize > 0 { - ranges = append(ranges, [2]uint64{info.stubFileOff, info.stubFileOff + info.stubVMSize}) - } // Pointer slots are spliced back into the chain as live rebase // nodes: dyld writes *slid* addresses at load, so the runtime reads // ready runtime pointers with no slide arithmetic. - inserts := []fixupInsert{{fileOff: blobFileOff + 16, targetVM: base}} - if spill { - inserts = append(inserts, fixupInsert{fileOff: info.entryFileOff + 16, targetVM: info.stubVMAddr}) - } + inserts := []fixupInsert{{fileOff: info.entryFileOff + 16, targetVM: base}} pending, err = unchainRanges(raw, ranges, inserts) if err != nil { return 0, 0, fmt.Errorf("chained fixups: %w", err) } } - if spill { - // Entry section: zero + 32-byte redirect header to the stub-section - // blob. Zeroed records keep the runtime's fallback scans empty. - zero := raw[info.entryFileOff : info.entryFileOff+info.entryVMSize] - for i := range zero { - zero[i] = 0 - } - binary.LittleEndian.PutUint64(zero[0:], redirectMagic) - binary.LittleEndian.PutUint64(zero[8:], info.entryVMAddr) - binary.LittleEndian.PutUint64(zero[16:], info.stubVMAddr) - } - copy(raw[blobFileOff:], blob) + copy(raw[info.entryFileOff:], blob) for _, pw := range pending { binary.LittleEndian.PutUint64(raw[pw.fileOff:], pw.val) } - // Void the stub section when the blob lives in the entry section: zero - // its records so the runtime's fallback scan finds nothing (stub entries - // are already merged into the table above). - if !spill && info.stubVMSize > 0 { - zero := raw[info.stubFileOff : info.stubFileOff+info.stubVMSize] - for i := range zero { - zero[i] = 0 - } - } st, err := os.Stat(path) if err != nil { return 0, 0, err diff --git a/runtime/internal/clite/ffi/_wrap/libffi.c b/runtime/internal/clite/ffi/_wrap/libffi.c index 016a74ec3d..6b82c7732e 100644 --- a/runtime/internal/clite/ffi/_wrap/libffi.c +++ b/runtime/internal/clite/ffi/_wrap/libffi.c @@ -3,3 +3,344 @@ void *llgo_ffi_closure_alloc(void **code) { return ffi_closure_alloc(sizeof(ffi_closure), code); } + +/* + * ffi_call does not expose a portable static-chain argument. Keep the real + * target and environment in a per-thread context while it marshals arguments. + * The trampoline is its final target: it saves the already-marshalled argument + * registers, obtains that context, and installs LLVM's nest/swiftself register + * for the real entry. A callee-saved swiftself register is restored afterward; + * caller-saved transports can tail-jump. No generated function needs an adapter. + * + * Use libffi's optional Go-ABI entry when it is exported and its static-chain + * register matches LLGo's nest transport. Common system libffi builds omit + * that symbol, so the public-ffi_call trampoline remains the fallback. + */ +#if !defined(_WIN32) && \ + (defined(__x86_64__) || defined(__i386__) || defined(__aarch64__) || \ + defined(__arm__) || defined(__riscv) || defined(__riscv__)) + +struct llgo_ffi_call_context { + void (*target)(void); + void *env; + void *saved_callee; + void *saved_self; + void *saved_return; +}; + +static _Thread_local struct llgo_ffi_call_context llgo_ffi_call_current; + +__attribute__((noinline, used)) static struct llgo_ffi_call_context * +llgo_ffi_current_call(void) { + return &llgo_ffi_call_current; +} + +/* libffi implements ffi_call_go by passing this final argument through its + * private argument marshaller into the target's static-chain register. Apple + * headers may declare a symbol that the dylib omits, so use the public path + * there; reference the optional symbol weakly on other matching targets. */ +#if !defined(__APPLE__) && \ + (defined(__x86_64__) || defined(__i386__) || defined(__riscv) || \ + defined(__riscv__) || \ + (defined(__aarch64__) && !defined(__ANDROID__))) +#define LLGO_FFI_GO_ABI_MATCHES 1 +extern void ffi_call_go(ffi_cif *, void (*)(void), void *, void **, void *) + __attribute__((weak)); +#endif + +#if defined(__APPLE__) +#define LLGO_ASM_CSYM(name) "_" #name +#else +#define LLGO_ASM_CSYM(name) #name +#endif + +#if defined(__x86_64__) + +__attribute__((naked)) static void llgo_ffi_env_trampoline(void) { + __asm__ volatile( + "subq $200, %rsp\n\t" + "movq %rdi, 0(%rsp)\n\t" + "movq %rsi, 8(%rsp)\n\t" + "movq %rdx, 16(%rsp)\n\t" + "movq %rcx, 24(%rsp)\n\t" + "movq %r8, 32(%rsp)\n\t" + "movq %r9, 40(%rsp)\n\t" + "movq %rax, 48(%rsp)\n\t" + "movdqu %xmm0, 64(%rsp)\n\t" + "movdqu %xmm1, 80(%rsp)\n\t" + "movdqu %xmm2, 96(%rsp)\n\t" + "movdqu %xmm3, 112(%rsp)\n\t" + "movdqu %xmm4, 128(%rsp)\n\t" + "movdqu %xmm5, 144(%rsp)\n\t" + "movdqu %xmm6, 160(%rsp)\n\t" + "movdqu %xmm7, 176(%rsp)\n\t" + "callq " LLGO_ASM_CSYM(llgo_ffi_current_call) "\n\t" + "movq 0(%rax), %r11\n\t" + "movq 8(%rax), %r10\n\t" + "movdqu 64(%rsp), %xmm0\n\t" + "movdqu 80(%rsp), %xmm1\n\t" + "movdqu 96(%rsp), %xmm2\n\t" + "movdqu 112(%rsp), %xmm3\n\t" + "movdqu 128(%rsp), %xmm4\n\t" + "movdqu 144(%rsp), %xmm5\n\t" + "movdqu 160(%rsp), %xmm6\n\t" + "movdqu 176(%rsp), %xmm7\n\t" + "movq 0(%rsp), %rdi\n\t" + "movq 8(%rsp), %rsi\n\t" + "movq 16(%rsp), %rdx\n\t" + "movq 24(%rsp), %rcx\n\t" + "movq 32(%rsp), %r8\n\t" + "movq 40(%rsp), %r9\n\t" + "movq 48(%rsp), %rax\n\t" + "addq $200, %rsp\n\t" + "jmpq *%r11"); +} + +#elif defined(__i386__) + +__attribute__((naked)) static void llgo_ffi_env_trampoline(void) { + __asm__ volatile( + "subl $12, %esp\n\t" + "calll " LLGO_ASM_CSYM(llgo_ffi_current_call) "\n\t" + "movl 0(%eax), %edx\n\t" + "movl 4(%eax), %ecx\n\t" + "addl $12, %esp\n\t" + "jmpl *%edx"); +} + +#elif defined(__aarch64__) + +__attribute__((naked)) static void llgo_ffi_env_trampoline(void) { + __asm__ volatile( + "sub sp, sp, #224\n\t" + "stp x0, x1, [sp, #0]\n\t" + "stp x2, x3, [sp, #16]\n\t" + "stp x4, x5, [sp, #32]\n\t" + "stp x6, x7, [sp, #48]\n\t" + "str x8, [sp, #64]\n\t" + "str x30, [sp, #72]\n\t" + "stp q0, q1, [sp, #80]\n\t" + "stp q2, q3, [sp, #112]\n\t" + "stp q4, q5, [sp, #144]\n\t" + "stp q6, q7, [sp, #176]\n\t" + "bl " LLGO_ASM_CSYM(llgo_ffi_current_call) "\n\t" + "mov x16, x0\n\t" + "ldr x17, [x16, #0]\n\t" +#if defined(__APPLE__) || defined(__ANDROID__) + /* X20 is callee-saved. Keep the TLS context in X19 across the real + * target so it can restore both registers after the target returns. + * The real target is entered with the original SP, preserving stack + * argument offsets. */ + "str x19, [x16, #16]\n\t" + "str x20, [x16, #24]\n\t" + "ldr x15, [sp, #72]\n\t" + "str x15, [x16, #32]\n\t" + "mov x19, x16\n\t" + "ldr x20, [x16, #8]\n\t" +#else + "ldr x18, [x16, #8]\n\t" +#endif + "ldp q0, q1, [sp, #80]\n\t" + "ldp q2, q3, [sp, #112]\n\t" + "ldp q4, q5, [sp, #144]\n\t" + "ldp q6, q7, [sp, #176]\n\t" + "ldr x8, [sp, #64]\n\t" + "ldp x0, x1, [sp, #0]\n\t" + "ldp x2, x3, [sp, #16]\n\t" + "ldp x4, x5, [sp, #32]\n\t" + "ldp x6, x7, [sp, #48]\n\t" + "add sp, sp, #224\n\t" +#if defined(__APPLE__) || defined(__ANDROID__) + "adr x30, 1f\n\t" + "br x17\n\t" + "1:\n\t" + "ldr x16, [x19, #16]\n\t" + "ldr x20, [x19, #24]\n\t" + "ldr x30, [x19, #32]\n\t" + "mov x19, x16\n\t" + "ret" +#else + "br x17" +#endif + ); +} + +#elif defined(__arm__) + +#if defined(__ARM_PCS_VFP) +#define LLGO_ARM_SAVED_LR_OFFSET 84 +#else +#define LLGO_ARM_SAVED_LR_OFFSET 20 +#endif +#define LLGO_ARM_ASM_STR1(value) #value +#define LLGO_ARM_ASM_STR(value) LLGO_ARM_ASM_STR1(value) + +__attribute__((naked)) static void llgo_ffi_env_trampoline(void) { + __asm__ volatile( + "push {r0-r3, r10, lr}\n\t" +#if defined(__ARM_PCS_VFP) + "vpush {d0-d7}\n\t" +#endif + "bl " LLGO_ASM_CSYM(llgo_ffi_current_call) "\n\t" + "mov r12, r0\n\t" + "str r4, [r12, #8]\n\t" + "str r10, [r12, #12]\n\t" + "ldr r3, [sp, #" LLGO_ARM_ASM_STR(LLGO_ARM_SAVED_LR_OFFSET) "]\n\t" + "str r3, [r12, #16]\n\t" + "mov r4, r12\n\t" + "ldr r10, [r12, #4]\n\t" + "ldr r12, [r12, #0]\n\t" +#if defined(__ARM_PCS_VFP) + "vpop {d0-d7}\n\t" +#endif + "ldmia sp, {r0-r3}\n\t" + "add sp, sp, #24\n\t" + "adr lr, 1f\n\t" + "bx r12\n\t" + "1:\n\t" + "ldr r12, [r4, #8]\n\t" + "ldr r10, [r4, #12]\n\t" + "ldr lr, [r4, #16]\n\t" + "mov r4, r12\n\t" + "bx lr"); +} + +#elif defined(__riscv) || defined(__riscv__) + +#define LLGO_ASM_STR1(value) #value +#define LLGO_ASM_STR(value) LLGO_ASM_STR1(value) + +#if __riscv_xlen == 64 +#define LLGO_RISCV_FP_OFFSET 80 +#define LLGO_RISCV_BASE_FRAME 80 +#else +#define LLGO_RISCV_FP_OFFSET 48 +#define LLGO_RISCV_BASE_FRAME 48 +#endif + +#if defined(__riscv_float_abi_double) +#define LLGO_RISCV_FRAME (LLGO_RISCV_BASE_FRAME + 64) +#define LLGO_RISCV_SAVE_FP \ + "fsd fa0, " LLGO_ASM_STR(LLGO_RISCV_FP_OFFSET + 0) "(sp)\n\t" \ + "fsd fa1, " LLGO_ASM_STR(LLGO_RISCV_FP_OFFSET + 8) "(sp)\n\t" \ + "fsd fa2, " LLGO_ASM_STR(LLGO_RISCV_FP_OFFSET + 16) "(sp)\n\t" \ + "fsd fa3, " LLGO_ASM_STR(LLGO_RISCV_FP_OFFSET + 24) "(sp)\n\t" \ + "fsd fa4, " LLGO_ASM_STR(LLGO_RISCV_FP_OFFSET + 32) "(sp)\n\t" \ + "fsd fa5, " LLGO_ASM_STR(LLGO_RISCV_FP_OFFSET + 40) "(sp)\n\t" \ + "fsd fa6, " LLGO_ASM_STR(LLGO_RISCV_FP_OFFSET + 48) "(sp)\n\t" \ + "fsd fa7, " LLGO_ASM_STR(LLGO_RISCV_FP_OFFSET + 56) "(sp)\n\t" +#define LLGO_RISCV_RESTORE_FP \ + "fld fa0, " LLGO_ASM_STR(LLGO_RISCV_FP_OFFSET + 0) "(sp)\n\t" \ + "fld fa1, " LLGO_ASM_STR(LLGO_RISCV_FP_OFFSET + 8) "(sp)\n\t" \ + "fld fa2, " LLGO_ASM_STR(LLGO_RISCV_FP_OFFSET + 16) "(sp)\n\t" \ + "fld fa3, " LLGO_ASM_STR(LLGO_RISCV_FP_OFFSET + 24) "(sp)\n\t" \ + "fld fa4, " LLGO_ASM_STR(LLGO_RISCV_FP_OFFSET + 32) "(sp)\n\t" \ + "fld fa5, " LLGO_ASM_STR(LLGO_RISCV_FP_OFFSET + 40) "(sp)\n\t" \ + "fld fa6, " LLGO_ASM_STR(LLGO_RISCV_FP_OFFSET + 48) "(sp)\n\t" \ + "fld fa7, " LLGO_ASM_STR(LLGO_RISCV_FP_OFFSET + 56) "(sp)\n\t" +#elif defined(__riscv_float_abi_single) +#define LLGO_RISCV_FRAME (LLGO_RISCV_BASE_FRAME + 32) +#define LLGO_RISCV_SAVE_FP \ + "fsw fa0, " LLGO_ASM_STR(LLGO_RISCV_FP_OFFSET + 0) "(sp)\n\t" \ + "fsw fa1, " LLGO_ASM_STR(LLGO_RISCV_FP_OFFSET + 4) "(sp)\n\t" \ + "fsw fa2, " LLGO_ASM_STR(LLGO_RISCV_FP_OFFSET + 8) "(sp)\n\t" \ + "fsw fa3, " LLGO_ASM_STR(LLGO_RISCV_FP_OFFSET + 12) "(sp)\n\t" \ + "fsw fa4, " LLGO_ASM_STR(LLGO_RISCV_FP_OFFSET + 16) "(sp)\n\t" \ + "fsw fa5, " LLGO_ASM_STR(LLGO_RISCV_FP_OFFSET + 20) "(sp)\n\t" \ + "fsw fa6, " LLGO_ASM_STR(LLGO_RISCV_FP_OFFSET + 24) "(sp)\n\t" \ + "fsw fa7, " LLGO_ASM_STR(LLGO_RISCV_FP_OFFSET + 28) "(sp)\n\t" +#define LLGO_RISCV_RESTORE_FP \ + "flw fa0, " LLGO_ASM_STR(LLGO_RISCV_FP_OFFSET + 0) "(sp)\n\t" \ + "flw fa1, " LLGO_ASM_STR(LLGO_RISCV_FP_OFFSET + 4) "(sp)\n\t" \ + "flw fa2, " LLGO_ASM_STR(LLGO_RISCV_FP_OFFSET + 8) "(sp)\n\t" \ + "flw fa3, " LLGO_ASM_STR(LLGO_RISCV_FP_OFFSET + 12) "(sp)\n\t" \ + "flw fa4, " LLGO_ASM_STR(LLGO_RISCV_FP_OFFSET + 16) "(sp)\n\t" \ + "flw fa5, " LLGO_ASM_STR(LLGO_RISCV_FP_OFFSET + 20) "(sp)\n\t" \ + "flw fa6, " LLGO_ASM_STR(LLGO_RISCV_FP_OFFSET + 24) "(sp)\n\t" \ + "flw fa7, " LLGO_ASM_STR(LLGO_RISCV_FP_OFFSET + 28) "(sp)\n\t" +#else +#define LLGO_RISCV_FRAME LLGO_RISCV_BASE_FRAME +#define LLGO_RISCV_SAVE_FP +#define LLGO_RISCV_RESTORE_FP +#endif + +__attribute__((naked)) static void llgo_ffi_env_trampoline(void) { +#if __riscv_xlen == 64 + __asm__ volatile( + "addi sp, sp, -" LLGO_ASM_STR(LLGO_RISCV_FRAME) "\n\t" + "sd a0, 0(sp)\n\t" + "sd a1, 8(sp)\n\t" + "sd a2, 16(sp)\n\t" + "sd a3, 24(sp)\n\t" + "sd a4, 32(sp)\n\t" + "sd a5, 40(sp)\n\t" + "sd a6, 48(sp)\n\t" + "sd a7, 56(sp)\n\t" + "sd ra, 64(sp)\n\t" + LLGO_RISCV_SAVE_FP + "call " LLGO_ASM_CSYM(llgo_ffi_current_call) "\n\t" + "mv t1, a0\n\t" + "ld t0, 0(t1)\n\t" + "ld t2, 8(t1)\n\t" + LLGO_RISCV_RESTORE_FP + "ld ra, 64(sp)\n\t" + "ld a0, 0(sp)\n\t" + "ld a1, 8(sp)\n\t" + "ld a2, 16(sp)\n\t" + "ld a3, 24(sp)\n\t" + "ld a4, 32(sp)\n\t" + "ld a5, 40(sp)\n\t" + "ld a6, 48(sp)\n\t" + "ld a7, 56(sp)\n\t" + "addi sp, sp, " LLGO_ASM_STR(LLGO_RISCV_FRAME) "\n\t" + "jr t0"); +#else + __asm__ volatile( + "addi sp, sp, -" LLGO_ASM_STR(LLGO_RISCV_FRAME) "\n\t" + "sw a0, 0(sp)\n\t" + "sw a1, 4(sp)\n\t" + "sw a2, 8(sp)\n\t" + "sw a3, 12(sp)\n\t" + "sw a4, 16(sp)\n\t" + "sw a5, 20(sp)\n\t" + "sw a6, 24(sp)\n\t" + "sw a7, 28(sp)\n\t" + "sw ra, 32(sp)\n\t" + LLGO_RISCV_SAVE_FP + "call " LLGO_ASM_CSYM(llgo_ffi_current_call) "\n\t" + "mv t1, a0\n\t" + "lw t0, 0(t1)\n\t" + "lw t2, 4(t1)\n\t" + LLGO_RISCV_RESTORE_FP + "lw ra, 32(sp)\n\t" + "lw a0, 0(sp)\n\t" + "lw a1, 4(sp)\n\t" + "lw a2, 8(sp)\n\t" + "lw a3, 12(sp)\n\t" + "lw a4, 16(sp)\n\t" + "lw a5, 20(sp)\n\t" + "lw a6, 24(sp)\n\t" + "lw a7, 28(sp)\n\t" + "addi sp, sp, " LLGO_ASM_STR(LLGO_RISCV_FRAME) "\n\t" + "jr t0"); +#endif +} + +#endif + +void llgo_ffi_call_with_env(ffi_cif *cif, void (*fn)(void), void *rvalue, + void **avalue, void *env) { +#if defined(LLGO_FFI_GO_ABI_MATCHES) + if (ffi_call_go != NULL) { + ffi_call_go(cif, fn, rvalue, avalue, env); + return; + } +#endif + struct llgo_ffi_call_context previous = llgo_ffi_call_current; + llgo_ffi_call_current.target = fn; + llgo_ffi_call_current.env = env; + ffi_call(cif, llgo_ffi_env_trampoline, rvalue, avalue); + llgo_ffi_call_current = previous; +} + +#endif diff --git a/runtime/internal/clite/ffi/ffi_link.go b/runtime/internal/clite/ffi/ffi_link.go index b3a908641d..2085ae0452 100644 --- a/runtime/internal/clite/ffi/ffi_link.go +++ b/runtime/internal/clite/ffi/ffi_link.go @@ -42,6 +42,9 @@ void ffi_call(ffi_cif *cif, //go:linkname Call C.ffi_call func Call(cif *Cif, fn unsafe.Pointer, rvalue unsafe.Pointer, avalue *unsafe.Pointer) +//go:linkname CallWithEnv C.llgo_ffi_call_with_env +func CallWithEnv(cif *Cif, fn unsafe.Pointer, rvalue unsafe.Pointer, avalue *unsafe.Pointer, env unsafe.Pointer) + // void *ffi_closure_alloc (size_t size, void **code); // //go:linkname ClosureAlloc C.llgo_ffi_closure_alloc diff --git a/runtime/internal/ffi/call_llgo_explicit.go b/runtime/internal/ffi/call_llgo_explicit.go new file mode 100644 index 0000000000..a5e20237d3 --- /dev/null +++ b/runtime/internal/ffi/call_llgo_explicit.go @@ -0,0 +1,15 @@ +//go:build !llgo || llgo_closure_env_explicit || (llgo && !llgo_closure_env_nest && !llgo_closure_env_swiftself) + +package ffi + +import "unsafe" + +// ClosureEnvExplicit is a compile-time target property. +const ClosureEnvExplicit = true + +// CallWithEnv calls fn through libffi. On explicit-context targets the signature +// passed by the caller already contains the leading env type; this function +// supplies the corresponding value before reaching this final call helper. +func CallWithEnv(cif *Signature, fn, _ unsafe.Pointer, ret unsafe.Pointer, args ...unsafe.Pointer) { + Call(cif, fn, ret, args...) +} diff --git a/runtime/internal/ffi/call_llgo_nest.go b/runtime/internal/ffi/call_llgo_nest.go new file mode 100644 index 0000000000..8bb84870c5 --- /dev/null +++ b/runtime/internal/ffi/call_llgo_nest.go @@ -0,0 +1,21 @@ +//go:build llgo && llgo_closure_env_nest + +package ffi + +import ( + "unsafe" + + "github.com/goplus/llgo/runtime/internal/clite/ffi" +) + +const ClosureEnvExplicit = false + +// CallWithEnv uses the runtime's libffi trampoline to place env in LLVM's nest +// register at the final call without changing the user-visible signature. +func CallWithEnv(cif *Signature, fn, env, ret unsafe.Pointer, args ...unsafe.Pointer) { + var avalues *unsafe.Pointer + if len(args) > 0 { + avalues = &args[0] + } + ffi.CallWithEnv(cif, fn, ret, avalues, env) +} diff --git a/runtime/internal/ffi/call_llgo_swiftself.go b/runtime/internal/ffi/call_llgo_swiftself.go new file mode 100644 index 0000000000..bf924e250e --- /dev/null +++ b/runtime/internal/ffi/call_llgo_swiftself.go @@ -0,0 +1,22 @@ +//go:build llgo && llgo_closure_env_swiftself + +package ffi + +import ( + "unsafe" + + "github.com/goplus/llgo/runtime/internal/clite/ffi" +) + +const ClosureEnvExplicit = false + +// CallWithEnv uses the runtime's libffi trampoline to preserve env across +// argument marshalling and place it in swiftself's register at the final call. +// Nil is written as well so native dynamic calls have one uniform path. +func CallWithEnv(cif *Signature, fn, env, ret unsafe.Pointer, args ...unsafe.Pointer) { + var avalues *unsafe.Pointer + if len(args) > 0 { + avalues = &args[0] + } + ffi.CallWithEnv(cif, fn, ret, avalues, env) +} diff --git a/runtime/internal/lib/reflect/makefunc.go b/runtime/internal/lib/reflect/makefunc.go index e0ea7e2103..b4892b16dc 100644 --- a/runtime/internal/lib/reflect/makefunc.go +++ b/runtime/internal/lib/reflect/makefunc.go @@ -36,35 +36,27 @@ type funcData struct { tout []*abi.Type fn func(args []Value) (results []Value) nin int - off int } func MakeFunc(typ Type, fn func(args []Value) (results []Value)) Value { - return makeFunc(typ, false, fn) + return makeFunc(typ, fn) } -func makeFunc(typ Type, method bool, fn func(args []Value) (results []Value)) Value { +func makeFunc(typ Type, fn func(args []Value) (results []Value)) Value { if typ.Kind() != Func { panic("reflect: call of MakeFunc with non-Func type") } t := typ.common() ftyp := (*funcType)(unsafe.Pointer(t)) - var ins []*abi.Type - var off int - if method { - ins = ftyp.In - } else { - ins = append([]*abi.Type{unsafePointerType}, ftyp.In...) - off = 1 - } + ins := ftyp.In sig, err := toFFISig(ins, ftyp.Out) if err != nil { panic(err) } outs := toRuntimeTypes(ftyp.Out) closure := ffi.NewClosure() - userdata := &funcData{ftyp: ftyp, fn: fn, nin: len(ftyp.In), off: off, tout: outs} + userdata := &funcData{ftyp: ftyp, fn: fn, nin: len(ftyp.In), tout: outs} switch len(ftyp.Out) { case 0: @@ -86,7 +78,7 @@ func makeFunc(typ Type, method bool, fn func(args []Value) (results []Value)) Va fv := &struct { fn unsafe.Pointer env unsafe.Pointer - }{closure.Fn, unsafe.Pointer(&fn)} + }{closure.Fn, nil} return Value{styp, unsafe.Pointer(fv), flagIndir | flag(Func)} } @@ -99,7 +91,7 @@ func bind0(cif *ffi.Signature, ret unsafe.Pointer, args *unsafe.Pointer, userdat fd := (*funcData)(userdata) ins := make([]Value, fd.nin) for i := 0; i < fd.nin; i++ { - ins[i] = ffiToValue(ffi.Index(args, uintptr(i+fd.off)), fd.ftyp.In[i]) + ins[i] = ffiToValue(ffi.Index(args, uintptr(i)), fd.ftyp.In[i]) } fd.fn(ins) } @@ -108,7 +100,7 @@ func bind1(cif *ffi.Signature, ret unsafe.Pointer, args *unsafe.Pointer, userdat fd := (*funcData)(userdata) ins := make([]Value, fd.nin) for i := 0; i < fd.nin; i++ { - ins[i] = ffiToValue(ffi.Index(args, uintptr(i+fd.off)), fd.ftyp.In[i]) + ins[i] = ffiToValue(ffi.Index(args, uintptr(i)), fd.ftyp.In[i]) } out := validateMakeFuncResults(fd.fn(ins), fd.ftyp, fd.tout) storeMakeFuncResult(ret, out[0], fd.tout[0]) @@ -118,7 +110,7 @@ func bindn(cif *ffi.Signature, ret unsafe.Pointer, args *unsafe.Pointer, userdat fd := (*funcData)(userdata) ins := make([]Value, fd.nin) for i := 0; i < fd.nin; i++ { - ins[i] = ffiToValue(ffi.Index(args, uintptr(i+fd.off)), fd.ftyp.In[i]) + ins[i] = ffiToValue(ffi.Index(args, uintptr(i)), fd.ftyp.In[i]) } outs := validateMakeFuncResults(fd.fn(ins), fd.ftyp, fd.tout) var offset uintptr = 0 @@ -276,20 +268,25 @@ func makeMethodValue(op string, v Value) Value { fl |= flag(v.typ().Kind()) rcvr := Value{v.typ(), v.ptr, fl} - // v.Type returns the actual type of the method value. - _, _, fn := methodReceiver(op, rcvr, int(v.flag)>>flagMethodShift) - var ptr unsafe.Pointer - storeRcvr(v, unsafe.Pointer(&ptr)) - fv := &struct { - fn unsafe.Pointer - env unsafe.Pointer - }{fn, ptr} - ftyp := (*funcType)(unsafe.Pointer(v.Type().(*rtype))) - typ := closureOf(ftyp) + // Validate the method now so Interface and Convert keep their eager panic + // behavior. The resulting libffi closure is a true no-env C entry; its + // userdata owns the receiver state. Pointing a hidden-env funcval directly + // at Ifn would be invalid because Ifn expects the receiver as an ordinary + // first ABI argument. + methodReceiver(op, rcvr, int(v.flag)>>flagMethodShift) + method := v + callOp := "Call" + if method.Type().(*rtype).t.FuncType().Variadic() { + callOp = "CallSlice" + } + ret := makeFunc(v.Type(), func(args []Value) []Value { + return method.call(callOp, args) + }) // Cause panic if method is not appropriate. // The panic would still happen during the call if we omit this, // but we want Interface() and other operations to fail early. - return Value{typ, unsafe.Pointer(fv), v.flag&flagRO | flagIndir | flag(Func)} + ret.flag |= v.flag & flagRO + return ret } var unsafePointerType = rtypeOf(unsafe.Pointer(nil)) diff --git a/runtime/internal/lib/reflect/value.go b/runtime/internal/lib/reflect/value.go index a17ca0374a..a1d169644c 100644 --- a/runtime/internal/lib/reflect/value.go +++ b/runtime/internal/lib/reflect/value.go @@ -2458,19 +2458,24 @@ func (v Value) call(op string, in []Value) (out []Value) { tin []*abi.Type args []unsafe.Pointer fn unsafe.Pointer + env unsafe.Pointer ret unsafe.Pointer ioff int ) if v.typ_.IsClosure() && v.flag&flagMethod == 0 { ft = v.typ_.StructType().Fields[0].Typ.FuncType() - tin = append([]*abi.Type{rtypeOf(unsafe.Pointer(nil))}, ft.In...) c := (*struct { fn unsafe.Pointer env unsafe.Pointer })(v.ptr) fn = c.fn - ioff = 1 - args = append(args, unsafe.Pointer(&c.env)) + env = c.env + tin = ft.In + if env != nil && ffi.ClosureEnvExplicit { + tin = append([]*abi.Type{rtypeOf(unsafe.Pointer(nil))}, tin...) + ioff = 1 + args = append(args, unsafe.Pointer(&env)) + } } else { if v.flag&flagMethod != 0 { var ( @@ -2579,7 +2584,7 @@ func (v Value) call(op string, in []Value) (out []Value) { ret = unsafe.Pointer(&v) } - ffi.Call(sig, fn, ret, args...) + ffi.CallWithEnv(sig, fn, env, ret, args...) tout := toRuntimeTypes(ft.Out) switch n := len(tout); n { case 0: @@ -3414,7 +3419,7 @@ func mapiternext(it *hiter) //go:linkname mapclear github.com/goplus/llgo/runtime/internal/runtime.mapclear func mapclear(t *abi.Type, m unsafe.Pointer) -//go:linkname typehash github.com/goplus/llgo/runtime/internal/runtime.typehash +//go:linkname typehash github.com/goplus/llgo/runtime/internal/runtime.typehashImpl func typehash(t *abi.Type, p unsafe.Pointer, h uintptr) uintptr //go:linkname makechan github.com/goplus/llgo/runtime/internal/runtime.NewChan diff --git a/runtime/internal/lib/runtime/pclntab_external.go b/runtime/internal/lib/runtime/pclntab_external.go index 9a065e415a..307a8ff0c7 100644 --- a/runtime/internal/lib/runtime/pclntab_external.go +++ b/runtime/internal/lib/runtime/pclntab_external.go @@ -13,7 +13,7 @@ import ( const ( externalPCLNMagic = "LLGOPCL1" - externalPCLNVersion = uint32(3) + externalPCLNVersion = uint32(4) externalPCLNABIVersion = uint32(1) externalPCLNHeaderSize = uintptr(256) externalPCLNMaxSize = int64(512 << 20) @@ -43,7 +43,6 @@ const ( externalDescHash externalDescSymbolIndex externalDescEntrySites - externalDescStubSites externalDescPCSites externalDescCount ) @@ -193,7 +192,7 @@ func externalSectionSize(index int) uintptr { return externalHashSize case externalDescSymbolIndex: return externalSymbolIndexSize - case externalDescEntrySites, externalDescStubSites, externalDescPCSites: + case externalDescEntrySites, externalDescPCSites: return externalSiteSize } return 0 @@ -266,7 +265,7 @@ func externalSectionAlignment(index int) uintptr { switch index { case externalDescRecords, externalDescStringOffsets: return 4 - case externalDescPCLines, externalDescSymbolIndex, externalDescEntrySites, externalDescStubSites, externalDescPCSites: + case externalDescPCLines, externalDescSymbolIndex, externalDescEntrySites, externalDescPCSites: return 8 case externalDescHash: return 2 @@ -310,13 +309,12 @@ func installExternalPCLN(raw []byte, view externalPCLNView, loadBase uintptr) bo hash := view.sections[externalDescHash] symbols := view.sections[externalDescSymbolIndex] entries := view.sections[externalDescEntrySites] - stubs := view.sections[externalDescStubSites] pcsites := view.sections[externalDescPCSites] // String IDs are uint32. The offset section and sidecar size bound their // count now, rather than the old uint16 ID limit. if records.count == 0 || records.count > 1<<20 || offsets.count == 0 || stringsSec.count == 0 || stringsSec.count > 1<<30 || pclines.count > 1<<22 || - symbols.count > records.count || entries.count > records.count*16 || stubs.count > records.count*16 || pcsites.count > 1<<24 { + symbols.count > records.count || entries.count > records.count*16 || pcsites.count > 1<<24 { return false } // Validate every string ID before any runtime pointer is published. @@ -384,7 +382,7 @@ func installExternalPCLN(raw []byte, view externalPCLNView, loadBase uintptr) bo } return true } - if !relocateSites(entries) || !relocateSites(stubs) || !relocateSites(pcsites) { + if !relocateSites(entries) || !relocateSites(pcsites) { return false } @@ -401,8 +399,6 @@ func installExternalPCLN(raw []byte, view externalPCLNView, loadBase uintptr) bo } runtimeFuncInfoSymbolIndex = (*runtimeFuncInfoSymbolIndexRecord)(symbolBase) runtimeFuncInfoSymbolIndexCount = symbols.count - runtimeFuncInfoStubIndexes = nil - runtimeFuncInfoStubCount = 0 runtimePCLineTable = (*runtimePCLineRecord)(pclineBase) runtimePCLineCount = pclines.count runtimeFuncInfoEntryStart = (*runtimeFuncInfoEntryRecord)(externalSectionPtr(raw, entries)) @@ -411,12 +407,6 @@ func installExternalPCLN(raw []byte, view externalPCLNView, loadBase uintptr) bo } else { runtimeFuncInfoEntryEnd = nil } - runtimeFuncInfoStubSiteStart = (*runtimeFuncInfoStubSiteRecord)(externalSectionPtr(raw, stubs)) - if stubs.count != 0 { - runtimeFuncInfoStubSiteEnd = (*runtimeFuncInfoStubSiteRecord)(unsafe.Add(externalSectionPtr(raw, stubs), stubs.count*externalSiteSize)) - } else { - runtimeFuncInfoStubSiteEnd = nil - } runtimePCSiteStart = (*runtimePCSiteRecord)(externalSectionPtr(raw, pcsites)) if pcsites.count != 0 { runtimePCSiteEnd = (*runtimePCSiteRecord)(unsafe.Add(externalSectionPtr(raw, pcsites), pcsites.count*externalSiteSize)) diff --git a/runtime/internal/lib/runtime/symtab.go b/runtime/internal/lib/runtime/symtab.go index 75854a9434..f21b22fbba 100644 --- a/runtime/internal/lib/runtime/symtab.go +++ b/runtime/internal/lib/runtime/symtab.go @@ -182,12 +182,6 @@ var runtimeFuncInfoSymbolIndex *runtimeFuncInfoSymbolIndexRecord //go:linkname runtimeFuncInfoSymbolIndexCount __llgo_funcinfo_symbol_index_count var runtimeFuncInfoSymbolIndexCount uintptr -//go:linkname runtimeFuncInfoStubIndexes __llgo_funcinfo_stub_indexes -var runtimeFuncInfoStubIndexes *uint32 - -//go:linkname runtimeFuncInfoStubCount __llgo_funcinfo_stub_count -var runtimeFuncInfoStubCount uintptr - type runtimeFuncInfoEntryRecord struct { pc uintptr symbolID uint64 @@ -199,17 +193,6 @@ var runtimeFuncInfoEntryStart *runtimeFuncInfoEntryRecord //go:linkname runtimeFuncInfoEntryEnd __llgo_funcinfo_entry_end var runtimeFuncInfoEntryEnd *runtimeFuncInfoEntryRecord -type runtimeFuncInfoStubSiteRecord struct { - pc uintptr - symbolID uint64 -} - -//go:linkname runtimeFuncInfoStubSiteStart __llgo_funcinfo_stubsite_start -var runtimeFuncInfoStubSiteStart *runtimeFuncInfoStubSiteRecord - -//go:linkname runtimeFuncInfoStubSiteEnd __llgo_funcinfo_stubsite_end -var runtimeFuncInfoStubSiteEnd *runtimeFuncInfoStubSiteRecord - type runtimePCLineRecord struct { id uint64 funcIndex uint32 @@ -289,8 +272,6 @@ const ( runtimeFuncInfoInitUninit uint32 = iota runtimeFuncInfoInitDone runtimeFuncInfoInitBusy - runtimeClosureStubPrefix = "__llgo_stub." - runtimePublicClosureStubPrefix = "_llgo_stub." ) func hasStringPrefix(s, prefix string) bool { @@ -398,11 +379,6 @@ func pcLineAt(i uintptr) *runtimePCLineRecord { return (*runtimePCLineRecord)(unsafe.Add(unsafe.Pointer(runtimePCLineTable), i*size)) } -func funcInfoStubIndexAt(i uintptr) uint32 { - size := unsafe.Sizeof(*runtimeFuncInfoStubIndexes) - return *(*uint32)(unsafe.Add(unsafe.Pointer(runtimeFuncInfoStubIndexes), i*size)) -} - func funcInfoHashString(s string) uintptr { const ( offset = uint32(2166136261) @@ -520,12 +496,6 @@ func symbolPCFuncInfoName(buf []byte, pkgID, nameID uint32) uintptr { return symbolPCBytes(name) } -func symbolPCPrefixedFuncInfoName(buf []byte, prefix string, pkgID, nameID uint32) uintptr { - name := append(buf[:0], prefix...) - name = appendFuncInfoName(name, pkgID, nameID) - return symbolPCBytes(name) -} - func funcInfoFunctionName(fn *runtimeFuncInfoRecord) string { if fn == nil { return "" @@ -577,16 +547,7 @@ func funcInfoForSymbol(symbol string) *runtimeFuncInfoRecord { } func funcInfoForRuntimeSymbol(symbol string) *runtimeFuncInfoRecord { - if rec := funcInfoForSymbol(symbol); rec != nil { - return rec - } - if hasStringPrefix(symbol, runtimeClosureStubPrefix) { - return funcInfoForSymbol(symbol[len(runtimeClosureStubPrefix):]) - } - if hasStringPrefix(symbol, runtimePublicClosureStubPrefix) { - return funcInfoForSymbol(symbol[len(runtimePublicClosureStubPrefix):]) - } - return nil + return funcInfoForSymbol(symbol) } func applyFuncInfo(sym *pcSymbol, rawFunction string) { @@ -682,7 +643,6 @@ func runtimeFuncPCFramesBuilt() bool { var runtimeFuncInfoDebugState uint32 var runtimeFuncPCFramesFromSites bool -var runtimeFuncPCStubsFromSites bool func runtimeFuncInfoDebugEnabled() bool { state := latomic.LoadUint32(&runtimeFuncInfoDebugState) @@ -717,10 +677,8 @@ func reportRuntimeFuncPCDebug() { return } entrySrc := runtimeFuncInfoDebugSource(runtimeFuncPCFramesFromSites) - stubSrc := runtimeFuncInfoDebugSource(runtimeFuncPCStubsFromSites) if runtimeFuncPCFramesPrebuilt { entrySrc = "prebuilt" - stubSrc = "prebuilt" } frameCount := len(runtimeFuncPCFrames) if runtimeFuncPCFramesPrebuilt { @@ -729,8 +687,7 @@ func reportRuntimeFuncPCDebug() { println("llgo funcinfo: func table frames=", frameCount, " buckets=", len(runtimeFuncPCIndex.buckets), " index=", runtimeFuncInfoDebugIndex(runtimeFuncPCIndex), - " entries=", entrySrc, - " stubs=", stubSrc) + " entries=", entrySrc) } func reportRuntimePCLineDebug() { @@ -780,12 +737,8 @@ func initRuntimeFuncPCFramesSlow() { // // The tool sorts, deduplicates LTO inline copies against the symbol table, // and normalizes entries to true symbol starts, so adopting the table also -// retires first-use sorting and the dlsym/stub fallbacks. +// retires first-use sorting and the dlsym fallback. const runtimePrebuiltMagic = uint64(0x314254464F474C4C) // "LLGOFTB1" little-endian -// "LLGOFTB2": the entry section holds only a 32-byte redirect whose third -// word is the runtime address of the real blob, written into the (larger) -// stub section when the table outgrew the entry section. -const runtimePrebuiltRedirectMagic = uint64(0x324254464F474C4C) const runtimePrebuiltHeaderSize = 8 + 8 + 8 + 4 + 4 type runtimePrebuiltFtabEntry struct { @@ -845,20 +798,6 @@ func adoptPrebuiltFuncPCTable() bool { if end < start+runtimePrebuiltHeaderSize { return false } - if *(*uint64)(unsafe.Pointer(start)) == runtimePrebuiltRedirectMagic { - // Blob spilled into the stub section; the pointer slot is a live - // relocation, so it already holds the runtime address. - blob := uintptr(*(*uint64)(unsafe.Pointer(start + 16))) - if blob == 0 || runtimeFuncInfoStubSiteStart == nil || runtimeFuncInfoStubSiteEnd == nil { - return false - } - stubStart := uintptr(unsafe.Pointer(runtimeFuncInfoStubSiteStart)) - stubEnd := uintptr(unsafe.Pointer(runtimeFuncInfoStubSiteEnd)) - if blob != stubStart || stubEnd < stubStart { - return false - } - start, end = blob, stubEnd - } if *(*uint64)(unsafe.Pointer(start)) != runtimePrebuiltMagic { return false } @@ -878,7 +817,6 @@ func adoptPrebuiltFuncPCTable() bool { } runtimeFuncPCFramesPrebuilt = true runtimeFuncPCFramesFromSites = true - runtimeFuncPCStubsFromSites = true runtimePrebuiltFuncs = make([]unsafe.Pointer, count) return true } @@ -951,7 +889,7 @@ func initRuntimeFuncPCFramesOnce() { frameSize := unsafe.Sizeof(frames[0]) entryBase := unsafe.Pointer(&entries[0]) nframes := 0 - symbolBuf = make([]byte, 0, maxFuncInfoSymbolLen()+len(runtimeClosureStubPrefix)+1) + symbolBuf = make([]byte, 0, maxFuncInfoSymbolLen()+1) for i := uintptr(0); i < runtimeFuncInfoCount; i++ { fn := funcInfoAt(i) pc := symbolPCFuncInfoName(symbolBuf, fn.symbolPkg, fn.symbolName) @@ -971,49 +909,12 @@ func initRuntimeFuncPCFramesOnce() { } frames = frames[:nframes] } - frames, usedStubSites := appendRuntimeFuncInfoStubSiteFrames(frames) - // Closure stubs are an ABI adapter and may go away in a future closure - // lowering. Keep the fallback compatibility table light: it stores only - // target funcinfo record indexes. When the stub-site section is present it - // is authoritative (linkers do not expose local stubs through dlsym), and - // skipping the dlsym loop below matters: each dlsym is a dynamic-loader - // query, and one query per stub used to dominate first-use latency. - if !usedStubSites && runtimeFuncInfoStubIndexes != nil && runtimeFuncInfoStubCount != 0 && runtimeFuncInfoStubCount <= runtimeFuncInfoCount { - if symbolBuf == nil { - symbolBuf = make([]byte, 0, maxFuncInfoSymbolLen()+len(runtimeClosureStubPrefix)+1) - } - base := len(frames) - grown := make([]runtimeFuncPCFrame, base+int(runtimeFuncInfoStubCount)) - copy(grown, frames) - frames = grown - frameBase := unsafe.Pointer(&frames[0]) - frameSize := unsafe.Sizeof(frames[0]) - nframes := base - for i := uintptr(0); i < runtimeFuncInfoStubCount; i++ { - index := funcInfoStubIndexAt(i) - if index == 0 || uintptr(index) > runtimeFuncInfoCount { - continue - } - fn := funcInfoAt(uintptr(index) - 1) - pc := symbolPCPrefixedFuncInfoName(symbolBuf, runtimeClosureStubPrefix, fn.symbolPkg, fn.symbolName) - if pc == 0 { - continue - } - *(*runtimeFuncPCFrame)(unsafe.Add(frameBase, uintptr(nframes)*frameSize)) = runtimeFuncPCFrame{ - entry: pc, - funcIndex: index, - } - nframes++ - } - frames = frames[:nframes] - } sortRuntimeFuncPCFrames(frames) frames = uniqueRuntimeFuncPCFrames(frames) runtimeFuncPCFrames = frames runtimeFuncPCEntries = entries runtimeFuncPCIndex = buildRuntimeFuncPCIndex(frames) runtimeFuncPCFramesFromSites = usedEntrySites - runtimeFuncPCStubsFromSites = usedStubSites } func appendRuntimeFuncInfoEntryFrames(frames []runtimeFuncPCFrame, entries []uintptr) ([]runtimeFuncPCFrame, bool) { @@ -1065,50 +966,6 @@ func appendRuntimeFuncInfoEntryFrames(frames []runtimeFuncPCFrame, entries []uin return frames[:nframes], used } -func appendRuntimeFuncInfoStubSiteFrames(frames []runtimeFuncPCFrame) ([]runtimeFuncPCFrame, bool) { - if runtimeFuncInfoStubSiteStart == nil || runtimeFuncInfoStubSiteEnd == nil { - return frames, false - } - start := uintptr(unsafe.Pointer(runtimeFuncInfoStubSiteStart)) - end := uintptr(unsafe.Pointer(runtimeFuncInfoStubSiteEnd)) - size := unsafe.Sizeof(*runtimeFuncInfoStubSiteStart) - if end <= start || size == 0 || (end-start)%size != 0 { - return frames, false - } - nsite := (end - start) / size - if nsite > runtimeFuncInfoCount*16 || nsite > 1<<20 { - return frames, false - } - if nsite == 0 { - return frames, false - } - base := len(frames) - grown := make([]runtimeFuncPCFrame, base+int(nsite)) - copy(grown, frames) - frames = grown - frameBase := unsafe.Pointer(&frames[0]) - frameSize := unsafe.Sizeof(frames[0]) - nframes := base - used := false - for i := uintptr(0); i < nsite; i++ { - site := (*runtimeFuncInfoStubSiteRecord)(unsafe.Pointer(start + i*size)) - if site == nil || site.pc == 0 || site.symbolID == 0 { - continue - } - funcIndex := funcInfoIndexForSymbolID(site.symbolID) - if funcIndex == 0 || uintptr(funcIndex) > runtimeFuncInfoCount { - continue - } - *(*runtimeFuncPCFrame)(unsafe.Add(frameBase, uintptr(nframes)*frameSize)) = runtimeFuncPCFrame{ - entry: site.pc, - funcIndex: funcIndex, - } - nframes++ - used = true - } - return frames[:nframes], used -} - func funcInfoIndexForSymbolID(symbolID uint64) uint32 { if symbolID == 0 || runtimeFuncInfoSymbolIndex == nil || runtimeFuncInfoSymbolIndexCount == 0 { return 0 @@ -1432,11 +1289,9 @@ func funcEntryForIndex(index uint32) uintptr { } // coldFuncInfoEntryLookup resolves an exact function-entry PC by scanning the -// raw entry-site and stub-site sections, without building the sorted frame -// table and without any dynamic-loader query. Function values can point at -// either a real function entry or its closure stub, so both sections are -// scanned. The scan is linear, so it is capped: for larger binaries the -// dladdr cold path is cheaper than streaming the whole section. +// raw entry-site section, without building the sorted frame table and without +// any dynamic-loader query. The scan is linear, so it is capped: for larger +// binaries the dladdr cold path is cheaper than streaming the whole section. const coldFuncInfoEntryScanLimit = 4096 // coldFuncInfoScanRange scans one {pc, symbolID} record section for the @@ -1502,7 +1357,7 @@ func prebuiltFuncPCTablePresent() bool { return false } m := *(*uint64)(unsafe.Pointer(start)) - return m == runtimePrebuiltMagic || m == runtimePrebuiltRedirectMagic + return m == runtimePrebuiltMagic } // runtimeFuncInfoWarmSink keeps the warm-up loads observable. @@ -1539,8 +1394,7 @@ func init() { sink += *(*byte)(unsafe.Pointer(p + n - 1)) runtimeFuncInfoWarmSink = sink } - // The adopted blob may live in the entry section or (spilled) in the - // stub section; derive its range from the adopted views. + // Derive the adopted blob's range from its zero-copy views. if n := len(runtimePrebuiltFtab); n > 0 { touch(unsafe.Pointer(&runtimePrebuiltFtab[0]), uintptr(n)*8) } @@ -1590,14 +1444,6 @@ func coldFuncInfoEntryLookup(pc uintptr) (pcSymbol, bool) { uintptr(unsafe.Pointer(runtimeFuncInfoEntryEnd)), unsafe.Sizeof(*runtimeFuncInfoEntryStart), pc, bestDelta) } - if bestDelta != 0 && runtimeFuncInfoStubSiteStart != nil && runtimeFuncInfoStubSiteEnd != nil { - if idx, _ := coldFuncInfoScanRange( - uintptr(unsafe.Pointer(runtimeFuncInfoStubSiteStart)), - uintptr(unsafe.Pointer(runtimeFuncInfoStubSiteEnd)), - unsafe.Sizeof(*runtimeFuncInfoStubSiteStart), pc, bestDelta); idx != 0 { - bestIndex = idx - } - } if bestIndex == 0 { return pcSymbol{}, false } diff --git a/runtime/internal/runtime/alg.go b/runtime/internal/runtime/alg.go index 1abeadcb48..dd6f79fff7 100644 --- a/runtime/internal/runtime/alg.go +++ b/runtime/internal/runtime/alg.go @@ -11,6 +11,9 @@ import ( "github.com/goplus/llgo/runtime/internal/runtime/goarch" ) +//go:linkname closureEnv llgo.closureEnv +func closureEnv() unsafe.Pointer + const ( c0 = uintptr((8-goarch.PtrSize)/4*2860486313 + (goarch.PtrSize-4)/4*33054211828000289) c1 = uintptr((8-goarch.PtrSize)/4*3267000013 + (goarch.PtrSize-4)/4*23344194077549503) @@ -104,9 +107,9 @@ func interhash(p unsafe.Pointer, h uintptr) uintptr { panic(errorString("hash of unhashable type " + t.String())) } if isDirectIface(t) { - return c1 * typehash(t, unsafe.Pointer(&a.data), h^c0) + return c1 * typehashImpl(t, unsafe.Pointer(&a.data), h^c0) } else { - return c1 * typehash(t, a.data, h^c0) + return c1 * typehashImpl(t, a.data, h^c0) } } @@ -121,9 +124,9 @@ func nilinterhash(p unsafe.Pointer, h uintptr) uintptr { panic(errorString("hash of unhashable type " + t.String())) } if isDirectIface(t) { - return c1 * typehash(t, unsafe.Pointer(&a.data), h^c0) + return c1 * typehashImpl(t, unsafe.Pointer(&a.data), h^c0) } else { - return c1 * typehash(t, a.data, h^c0) + return c1 * typehashImpl(t, a.data, h^c0) } } @@ -137,7 +140,7 @@ func nilinterhash(p unsafe.Pointer, h uintptr) uintptr { // maps generated by reflect.MapOf (reflect_typehash, below). // Note: this function must match the compiler generated // functions exactly. See issue 37716. -func typehash(t *_type, p unsafe.Pointer, h uintptr) uintptr { +func typehashImpl(t *_type, p unsafe.Pointer, h uintptr) uintptr { if t.TFlag&abi.TFlagRegularMemory != 0 { // Handle ptr sizes specially, see issue 37086. switch t.Size_ { @@ -169,7 +172,7 @@ func typehash(t *_type, p unsafe.Pointer, h uintptr) uintptr { case abi.Array: a := (*arraytype)(unsafe.Pointer(t)) for i := uintptr(0); i < a.Len; i++ { - h = typehash(a.Elem, add(p, i*a.Elem.Size_), h) + h = typehashImpl(a.Elem, add(p, i*a.Elem.Size_), h) } return h case abi.Struct: @@ -178,7 +181,7 @@ func typehash(t *_type, p unsafe.Pointer, h uintptr) uintptr { if f.Name_ == "_" { continue } - h = typehash(f.Typ, add(p, f.Offset), h) + h = typehashImpl(f.Typ, add(p, f.Offset), h) } return h default: @@ -188,6 +191,11 @@ func typehash(t *_type, p unsafe.Pointer, h uintptr) uintptr { } } +//llgo:env +func typehash(p unsafe.Pointer, h uintptr) uintptr { + return typehashImpl((*_type)(closureEnv()), p, h) +} + func memequalptr(p, q unsafe.Pointer) bool { return *(*uintptr)(p) == *(*uintptr)(q) } @@ -323,8 +331,9 @@ func typeEqualMayPanic(t *_type) bool { return false } -func structequal(t, p, q unsafe.Pointer) bool { - x := (*structtype)(t) +//llgo:env +func structequal(p, q unsafe.Pointer) bool { + x := (*structtype)(closureEnv()) fields := x.Fields segmentStart := 0 for i, ft := range fields { @@ -365,8 +374,9 @@ func structequal(t, p, q unsafe.Pointer) bool { return true } -func arrayequal(t, p, q unsafe.Pointer) bool { - x := (*arraytype)(t) +//llgo:env +func arrayequal(p, q unsafe.Pointer) bool { + x := (*arraytype)(closureEnv()) elem := x.Elem for i := uintptr(0); i < x.Len; i++ { pi := add(p, i*elem.Size_) diff --git a/ssa/abitype.go b/ssa/abitype.go index 4cc1cb8c6d..7c6c1eebfa 100644 --- a/ssa/abitype.go +++ b/ssa/abitype.go @@ -115,7 +115,7 @@ func (b Builder) abiCommonFields(t types.Type, name string, hasUncommon bool, gl case "": equal = prog.Nil(prog.Type(equalFunc, InGo)) case "structequal", "arrayequal": - equal = b.Pkg.rtFunc(name) + equal = b.Pkg.rtEnvFunc(name) b.Pkg.recordAbiTypeFakeUse(global, equal.impl) env := b.abiType(t) equal = b.aggregateValue(prog.Type(equalFunc, InGo), equal.impl, env.impl) @@ -293,7 +293,7 @@ func (b Builder) abiExtendedFields(t types.Type, name string, global llvm.Value) case *types.Map: bucket := prog.abi.MapBucket(t) flags := prog.abi.MapFlags(t) - hash := b.Pkg.rtFunc("typehash") + hash := b.Pkg.rtEnvFunc("typehash") b.Pkg.recordAbiTypeFakeUse(global, hash.impl) env := b.abiType(t.Key()) hasher := b.aggregateValue(prog.Type(hashFunc, InGo), hash.impl, env.impl) @@ -516,8 +516,9 @@ func (b Builder) abiUncommonMethods(t types.Type, methods []*types.Selection) ll mSig := m.Type().(*types.Signature) var tfn, ifn llvm.Value tfnFn := b.abiMethodFunc(anonymous, pkg, mName, mSig) - tfnSig := funcType(prog, methodExprSignature(mSig)).(*types.Signature) - tfn = b.Pkg.closureWrapDecl(tfnFn.Expr, tfnSig).impl + // Tfn is used as a method-expression funcval. Its explicit receiver is + // already part of that semantic signature, so it is a no-env entry. + tfn = tfnFn.impl ifn = tfnFn.impl if _, ok := m.Recv().Underlying().(*types.Pointer); !ok { pRecv := types.NewVar(token.NoPos, pkg, "", types.NewPointer(mSig.Recv().Type())) diff --git a/ssa/closure_abi.go b/ssa/closure_abi.go new file mode 100644 index 0000000000..66cb28f952 --- /dev/null +++ b/ssa/closure_abi.go @@ -0,0 +1,132 @@ +package ssa + +import ( + "strings" + + "github.com/xgo-dev/llvm" +) + +// closureEnvABI describes only the physical transport of an environment +// parameter. The environment is not part of a Go or go/types signature. +type closureEnvABI uint8 + +const ( + // closureEnvExplicit is the typed fallback used by WebAssembly and targets + // for which no hidden parameter transport has been validated. + closureEnvExplicit closureEnvABI = iota + closureEnvNest + closureEnvSwiftSelf +) + +func closureEnvABIForTarget(triple string) closureEnvABI { + triple = strings.ToLower(triple) + arch, _, _ := strings.Cut(triple, "-") + // The current public-libffi final-hop bridge is not implemented for + // Windows. This is a bridge capability, not an LLVM or Win64 restriction: + // x86-64 Win64 can use nest/r10 once that bridge is added. + if strings.Contains(triple, "windows") || strings.Contains(triple, "win32") || strings.Contains(triple, "mingw") { + return closureEnvExplicit + } + switch { + case arch == "arm64", arch == "arm64_32", arch == "aarch64", arch == "aarch64_be": + // Keep a stable runtime ABI across LLVM versions on platforms which + // reserve X18. swiftself uses the callee-saved X20 register and is also + // usable by the libffi bridge without rebuilding libffi. + if aarch64UsesSwiftSelf(triple) { + return closureEnvSwiftSelf + } + return closureEnvNest + case strings.HasPrefix(arch, "arm"), strings.HasPrefix(arch, "thumb"): + // LLVM lowers swiftself through the platform's dedicated self register. + // This keeps the ordinary C arguments in their normal ABI locations. + return closureEnvSwiftSelf + case arch == "x86_64", arch == "amd64", + arch == "x86", arch == "386", + arch == "i386", arch == "i486", arch == "i586", arch == "i686", + arch == "riscv32", arch == "riscv64": + return closureEnvNest + default: + return closureEnvExplicit + } +} + +func aarch64UsesSwiftSelf(triple string) bool { + // Windows was already classified as explicit above. Apple and Android + // reserve X18, so LLGo uses LLVM's swiftself/X20 transport there. + return strings.Contains(triple, "apple") || + strings.Contains(triple, "darwin") || + strings.Contains(triple, "android") +} + +func (p *Target) closureEnvABI() closureEnvABI { + triple := p.LLVMTarget + if triple == "" { + triple = p.Spec().Triple + } + return closureEnvABIForTarget(triple) +} + +// ClosureEnvBuildTag selects the runtime half of the same physical ABI used +// by the backend. It must be added after a named target has resolved its real +// LLVM triple; GOARCH may only be a package-selection compatibility value. +func (p *Target) ClosureEnvBuildTag() string { + switch p.closureEnvABI() { + case closureEnvNest: + return "llgo_closure_env_nest" + case closureEnvSwiftSelf: + return "llgo_closure_env_swiftself" + default: + return "llgo_closure_env_explicit" + } +} + +func (p Program) closureEnvABI() closureEnvABI { + return p.Target().closureEnvABI() +} + +func (p Program) closureEnvAttribute() llvm.Attribute { + var name string + switch p.closureEnvABI() { + case closureEnvNest: + name = "nest" + case closureEnvSwiftSelf: + name = "swiftself" + default: + return llvm.Attribute{} + } + kind := llvm.AttributeKindID(name) + if kind == 0 { + panic("ssa: LLVM has no " + name + " parameter attribute") + } + return p.ctx.CreateEnumAttribute(kind, 0) +} + +func (p Program) markClosureEnvFunction(fn llvm.Value, physicalIndex int) { + attr := p.closureEnvAttribute() + if attr.IsNil() { + return + } + fn.AddAttributeAtIndex(physicalIndex+1, attr) +} + +func (p Program) markClosureEnvCall(call llvm.Value, physicalIndex int) { + attr := p.closureEnvAttribute() + if attr.IsNil() { + return + } + call.AddCallSiteAttribute(physicalIndex+1, attr) +} + +// hideClosureCodeIdentity keeps LLVM from devirtualizing a native funcval call +// across the intentionally different IR prototypes of env and no-env entries. +// The empty tied-register asm is a machine-code no-op: it returns the same code +// pointer, but LLVM can no longer reinterpret a known no-env body as though the +// hidden environment were an ordinary first argument. +func (b Builder) hideClosureCodeIdentity(fn Expr) Expr { + ftype := llvm.FunctionType(fn.Type.ll, []llvm.Type{fn.Type.ll}, false) + asm := llvm.InlineAsm(ftype, "", "=r,0", false, false, llvm.InlineAsmDialectATT, false) + return Expr{ + b.impl.CreateCall(ftype, asm, []llvm.Value{fn.impl}, "__llgo_funcval_code"), + fn.Type, + } +} diff --git a/ssa/closure_env_test.go b/ssa/closure_env_test.go new file mode 100644 index 0000000000..1c6393b87c --- /dev/null +++ b/ssa/closure_env_test.go @@ -0,0 +1,613 @@ +//go:build !llgo + +package ssa + +import ( + "go/token" + "go/types" + "strings" + "testing" + + "github.com/goplus/gogen/packages" + "github.com/xgo-dev/llvm" +) + +func TestClosureEnvABIForTarget(t *testing.T) { + tests := []struct { + triple string + want closureEnvABI + }{ + {"wasm32-unknown-wasip1", closureEnvExplicit}, + {"x86_64-unknown-linux", closureEnvNest}, + {"amd64-unknown-linux", closureEnvNest}, + {"riscv64-unknown-linux", closureEnvNest}, + {"armv7-unknown-linux-gnueabihf", closureEnvSwiftSelf}, + {"aarch64-unknown-linux", closureEnvNest}, + {"arm64-apple-macosx", closureEnvSwiftSelf}, + {"x86_64-pc-windows-gnu", closureEnvExplicit}, + {"x86_64-pc-windows-msvc", closureEnvExplicit}, + {"x86_64-w64-mingw32", closureEnvExplicit}, + {"mips64-unknown-linux", closureEnvExplicit}, + } + for _, test := range tests { + if got := closureEnvABIForTarget(test.triple); got != test.want { + t.Errorf( + "closureEnvABIForTarget(%q) = %d, want %d", + test.triple, got, test.want, + ) + } + } +} + +func TestClosureEnvBuildTag(t *testing.T) { + tests := []struct { + target *Target + want string + }{ + {&Target{LLVMTarget: "x86_64-unknown-linux"}, "llgo_closure_env_nest"}, + {&Target{LLVMTarget: "arm64-apple-macosx"}, "llgo_closure_env_swiftself"}, + {&Target{GOOS: "linux", GOARCH: "arm", LLVMTarget: "wasm32-unknown-unknown"}, "llgo_closure_env_explicit"}, + } + for _, test := range tests { + if got := test.target.ClosureEnvBuildTag(); got != test.want { + t.Errorf("ClosureEnvBuildTag() = %q, want %q", got, test.want) + } + } +} + +func TestClosureEnvABIUsesPhysicalTarget(t *testing.T) { + tests := []struct { + name string + llvmTarget string + want closureEnvABI + }{ + {"esp32", "xtensa", closureEnvExplicit}, + {"esp32c3", "riscv32-esp-elf", closureEnvNest}, + } + for _, test := range tests { + t.Run(test.name, func(t *testing.T) { + // Embedded target configurations use GOARCH=arm for Go package + // selection, while code generation uses a different physical ISA. + prog := NewProgram(&Target{ + GOOS: "linux", + GOARCH: "arm", + Target: test.name, + LLVMTarget: test.llvmTarget, + }) + defer prog.Dispose() + if got := prog.closureEnvABI(); got != test.want { + t.Fatalf("closureEnvABI() = %d, want %d", got, test.want) + } + }) + } +} + +func TestEnvFunctionKeepsSemanticSignatureAndZeroEnvNonNil(t *testing.T) { + prog := NewProgram(nil) + defer prog.Dispose() + pkg := prog.NewPackage("p", "example.com/p") + + sig := types.NewSignatureType(nil, nil, nil, nil, nil, false) + empty := types.NewStruct(nil, nil) + env := types.NewParam(token.NoPos, nil, "$env", types.NewPointer(empty)) + entry := pkg.NewEnvFunc("example.com/p.entry", sig, InGo, env, false) + if !entry.NeedsEnv() || entry.EnvType() == nil { + t.Fatal("environment-bearing entry lost its separate env metadata") + } + if got := entry.Expr.raw.Type.(*types.Signature).Params().Len(); got != 0 { + t.Fatalf("semantic entry signature has %d params, want 0", got) + } + eb := entry.MakeBody(1) + eb.Return() + + out := types.NewTuple(types.NewVar(token.NoPos, nil, "", sig)) + makerSig := types.NewSignatureType(nil, nil, nil, nil, out, false) + maker := pkg.NewFunc("example.com/p.make", makerSig, InGo) + mb := maker.MakeBody(1) + mb.Return(mb.MakeClosure(entry.Expr, nil)) + + ir := pkg.String() + if !strings.Contains(ir, `@"__llgo.moduleZeroSizedAlloc$"`) { + t.Fatalf("zero-sized required env did not use the non-nil sentinel:\n%s", ir) + } + if strings.Contains(ir, "{ ptr @example.com/p.entry, ptr null }") { + t.Fatalf("environment-bearing entry was represented with a nil env:\n%s", ir) + } + if err := llvm.VerifyModule(pkg.Module(), llvm.ReturnStatusAction); err != nil { + t.Fatalf("closure-env module is invalid: %v\n%s", err, ir) + } +} + +func TestClosureEnvMetadataRejectsInvalidUses(t *testing.T) { + prog := NewProgram(nil) + defer prog.Dispose() + pkg := prog.NewPackage("p", "example.com/p") + sig := types.NewSignatureType(nil, nil, nil, nil, nil, false) + env := types.NewParam(token.NoPos, nil, "$env", types.NewPointer(types.NewStruct(nil, nil))) + + tests := []struct { + name string + fn func() + }{ + { + name: "legacy hasFreeVars flag", + fn: func() { + pkg.NewFuncEx("legacy", sig, InGo, true, false) + }, + }, + { + name: "nil environment metadata", + fn: func() { + pkg.NewEnvFunc("nil-env", sig, InGo, nil, false) + }, + }, + { + name: "conflicting entry metadata", + fn: func() { + pkg.NewFunc("conflict", sig, InGo) + pkg.NewEnvFunc("conflict", sig, InGo, env, false) + }, + }, + { + name: "environment from plain entry", + fn: func() { + pkg.NewFunc("plain-env", sig, InGo).Env() + }, + }, + } + for _, test := range tests { + t.Run(test.name, func(t *testing.T) { + defer func() { + if recover() == nil { + t.Fatal("expected panic") + } + }() + test.fn() + }) + } +} + +func TestWasmDynamicClosureUsesTwoExplicitTypedEdges(t *testing.T) { + Initialize(InitAllTargets | InitAllTargetInfos | InitAllTargetMCs) + prog := NewProgram(&Target{GOOS: "wasip1", GOARCH: "wasm"}) + defer prog.Dispose() + pkg := prog.NewPackage("p", "example.com/p") + + params := types.NewTuple(types.NewVar(token.NoPos, nil, "x", types.Typ[types.Int])) + results := types.NewTuple(types.NewVar(token.NoPos, nil, "", types.Typ[types.Int])) + sig := types.NewSignatureType(nil, nil, nil, params, results, false) + callerParams := types.NewTuple( + types.NewVar(token.NoPos, nil, "fn", sig), + types.NewVar(token.NoPos, nil, "x", types.Typ[types.Int]), + ) + caller := pkg.NewFunc( + "example.com/p.call", + types.NewSignatureType(nil, nil, nil, callerParams, results, false), + InGo, + ) + b := caller.MakeBody(1) + b.Return(b.Call(caller.Param(0), caller.Param(1))) + + ir := pkg.String() + for _, want := range []string{ + "icmp ne ptr", + "phi i32", + } { + if !strings.Contains(ir, want) { + t.Fatalf("Wasm dynamic closure call missing %q:\n%s", want, ir) + } + } + paramCounts := make(map[int]int) + for block := caller.impl.FirstBasicBlock(); !block.IsNil(); block = llvm.NextBasicBlock(block) { + for instruction := block.FirstInstruction(); !instruction.IsNil(); instruction = llvm.NextInstruction(instruction) { + if call := instruction.IsACallInst(); !call.IsNil() && call.CalledValue().IsAFunction().IsNil() { + paramCounts[call.CalledFunctionType().ParamTypesCount()]++ + } + } + } + if paramCounts[1] != 1 || paramCounts[2] != 1 { + t.Fatalf("Wasm dynamic closure edges have parameter counts %v, want one 1-param and one 2-param call:\n%s", paramCounts, ir) + } + if strings.Contains(ir, " nest ") || strings.Contains(ir, " swiftself ") { + t.Fatalf("Wasm dynamic closure call unexpectedly used a native env attribute:\n%s", ir) + } + if err := llvm.VerifyModule(pkg.Module(), llvm.ReturnStatusAction); err != nil { + t.Fatalf("Wasm dynamic closure module is invalid: %v\n%s", err, ir) + } +} + +func TestNativeDynamicClosureIdentityBarrierSurvivesO2(t *testing.T) { + for _, pipeline := range []string{"default", "lto"} { + t.Run(pipeline, func(t *testing.T) { + testNativeDynamicClosureIdentityBarrier(t, pipeline) + }) + } +} + +func testNativeDynamicClosureIdentityBarrier(t *testing.T, pipeline string) { + Initialize(InitAllTargets | InitAllTargetInfos | InitAllTargetMCs | InitAllAsmPrinters) + prog := NewProgram(&Target{GOOS: "linux", GOARCH: "amd64"}) + defer prog.Dispose() + setTestRuntime(t, prog) + pkg := prog.NewPackage("p", "example.com/p") + + params := types.NewTuple(types.NewVar(token.NoPos, nil, "x", types.Typ[types.Int])) + results := types.NewTuple(types.NewVar(token.NoPos, nil, "", types.Typ[types.Int])) + sig := types.NewSignatureType(nil, nil, nil, params, results, false) + plain := pkg.NewFunc("plain", sig, InGo) + pb := plain.MakeBody(1) + pb.Return(plain.Param(0)) + caller := newMatrixCaller(pkg, "callPlain", sig, func(b Builder) Expr { + return b.MakeClosure(plain.Expr, nil) + }) + + mod := pkg.Module() + pbo := llvm.NewPassBuilderOptions() + defer pbo.Dispose() + if err := mod.RunPasses(pipeline, prog.TargetMachine(), pbo); err != nil { + t.Fatalf("run %s pipeline: %v", pipeline, err) + } + if err := llvm.VerifyModule(mod, llvm.ReturnStatusAction); err != nil { + t.Fatalf("verify optimized module: %v\n%s", err, mod.String()) + } + + barriers, hiddenCalls := 0, 0 + for block := caller.impl.FirstBasicBlock(); !block.IsNil(); block = llvm.NextBasicBlock(block) { + for instruction := block.FirstInstruction(); !instruction.IsNil(); instruction = llvm.NextInstruction(instruction) { + call := instruction.IsACallInst() + if call.IsNil() { + if instruction.InstructionOpcode() == llvm.ICmp { + t.Fatalf("optimized native call retained an env == nil check:\n%s", mod.String()) + } + continue + } + if !call.CalledValue().IsAInlineAsm().IsNil() { + barriers++ + continue + } + if call.GetCallSiteEnumAttribute(1, llvm.AttributeKindID("nest")).IsNil() { + continue + } + hiddenCalls++ + if !call.CalledValue().IsAFunction().IsNil() { + t.Fatalf("O2 devirtualized hidden-env call to no-env entry:\n%s", mod.String()) + } + } + } + if barriers != 1 || hiddenCalls != 1 { + t.Fatalf("optimized native call has %d barriers and %d hidden calls, want one each:\n%s", barriers, hiddenCalls, mod.String()) + } +} + +func TestClosureObjectCallMatrixAcrossTransports(t *testing.T) { + Initialize(InitAllTargets | InitAllTargetInfos | InitAllTargetMCs) + tests := []struct { + name string + tgt *Target + abi closureEnvABI + attr string + }{ + { + name: "nest", + tgt: &Target{GOOS: "linux", GOARCH: "amd64"}, + abi: closureEnvNest, + attr: "nest", + }, + { + name: "swiftself", + tgt: &Target{GOOS: "darwin", GOARCH: "arm64"}, + abi: closureEnvSwiftSelf, + attr: "swiftself", + }, + { + name: "wasm-explicit", + tgt: &Target{GOOS: "wasip1", GOARCH: "wasm"}, + abi: closureEnvExplicit, + }, + { + name: "xtensa-explicit", + tgt: &Target{ + GOOS: "linux", GOARCH: "arm", Target: "esp32", LLVMTarget: "xtensa", + }, + abi: closureEnvExplicit, + }, + } + for _, test := range tests { + t.Run(test.name, func(t *testing.T) { + prog := NewProgram(test.tgt) + defer prog.Dispose() + if got := prog.closureEnvABI(); got != test.abi { + t.Fatalf("closure transport = %d, want %d", got, test.abi) + } + setTestRuntime(t, prog) + pkg := prog.NewPackage("p", "example.com/p") + + params := types.NewTuple(types.NewVar(token.NoPos, nil, "x", types.Typ[types.Int])) + results := types.NewTuple(types.NewVar(token.NoPos, nil, "", types.Typ[types.Int])) + sig := types.NewSignatureType(nil, nil, nil, params, results, false) + + plain := pkg.NewFunc("plainGo", sig, InGo) + pb := plain.MakeBody(1) + pb.Return(plain.Param(0)) + + cfn := pkg.NewFunc("plainC", sig, InC) + cb := cfn.MakeBody(1) + cb.Return(cfn.Param(0)) + + captured := newMatrixEnvEntry(pkg, "capturedClosure", sig, + types.NewStruct( + []*types.Var{types.NewField(token.NoPos, nil, "capture", types.Typ[types.Int], false)}, + nil, + ), + ) + empty := newMatrixEnvEntry(pkg, "emptyClosure", sig, types.NewStruct(nil, nil)) + nilMethod := newMatrixEnvEntry(pkg, "nilReceiverMethodValue", sig, + types.NewStruct( + []*types.Var{types.NewField( + token.NoPos, nil, "receiver", types.NewPointer(types.Typ[types.Int]), false, + )}, + nil, + ), + ) + + rawMethod := types.NewFunc(token.NoPos, nil, "M", + types.NewSignatureType(nil, nil, nil, params, results, false), + ) + rawIface := types.NewInterfaceType([]*types.Func{rawMethod}, nil).Complete() + ifaceMethodValue := newMatrixEnvEntry(pkg, "interfaceMethodValue", sig, + types.NewStruct( + []*types.Var{types.NewField(token.NoPos, nil, "receiver", rawIface, false)}, + nil, + ), + ) + + type callCase struct { + caller Function + entry Function + } + callers := map[string]callCase{} + callers["plain-go"] = callCase{ + caller: newMatrixCaller(pkg, "callPlainGo", sig, func(b Builder) Expr { + return checkExpr(plain.Expr, prog.Type(sig, InGo).RawType(), b) + }), + entry: plain, + } + callers["plain-c"] = callCase{ + caller: newMatrixCaller(pkg, "callPlainC", sig, func(b Builder) Expr { + return checkExpr(cfn.Expr, prog.Type(sig, InGo).RawType(), b) + }), + entry: cfn, + } + callers["captured-closure"] = callCase{ + caller: newMatrixCaller(pkg, "callCapturedClosure", sig, func(b Builder) Expr { + return b.MakeClosure(captured.Expr, []Expr{prog.Val(7)}) + }), + entry: captured, + } + callers["zero-sized-closure"] = callCase{ + caller: newMatrixCaller(pkg, "callEmptyClosure", sig, func(b Builder) Expr { + return b.MakeClosure(empty.Expr, nil) + }), + entry: empty, + } + callers["nil-receiver-method-value"] = callCase{ + caller: newMatrixCaller(pkg, "callNilReceiverMethodValue", sig, func(b Builder) Expr { + return b.MakeClosure(nilMethod.Expr, []Expr{prog.Nil(prog.Pointer(prog.Int()))}) + }), + entry: nilMethod, + } + callers["interface-method-value"] = callCase{ + caller: newMatrixCaller(pkg, "callInterfaceMethodValue", sig, func(b Builder) Expr { + return b.MakeClosure(ifaceMethodValue.Expr, []Expr{prog.Zero(prog.Type(rawIface, InGo))}) + }), + entry: ifaceMethodValue, + } + + for name, call := range callers { + assertDynamicMatrixCall(t, call.caller, call.entry, name, test.attr) + } + assertMatrixEntryAttribute(t, plain, "", test.attr) + assertMatrixEntryAttribute(t, cfn, "", test.attr) + for _, entry := range []Function{captured, empty, nilMethod, ifaceMethodValue} { + assertMatrixEntryAttribute(t, entry, entry.Name(), test.attr) + } + + // Direct interface invocation is not a funcval. Its receiver is one + // ordinary ABI argument, with no env branch or hidden attribute. + ifaceCaller := newMatrixInterfaceCaller(t, prog, pkg, rawIface) + assertDirectInterfaceMatrixEdge(t, ifaceCaller, test.attr) + ifaceRoutine := newMatrixInterfaceRoutine(t, prog, pkg, rawIface) + assertDirectInterfaceMatrixEdge(t, ifaceRoutine, test.attr) + + ir := pkg.String() + for _, want := range []string{ + "{ ptr @plainGo, ptr null }", + "{ ptr @plainC, ptr null }", + `@"__llgo.moduleZeroSizedAlloc$"`, + } { + if !strings.Contains(ir, want) { + t.Fatalf("%s matrix missing %q:\n%s", test.name, want, ir) + } + } + if err := llvm.VerifyModule(pkg.Module(), llvm.ReturnStatusAction); err != nil { + t.Fatalf("%s matrix module is invalid: %v\n%s", test.name, err, ir) + } + }) + } +} + +func setTestRuntime(t *testing.T, prog Program) { + t.Helper() + fset := token.NewFileSet() + imp := packages.NewImporter(fset) + runtimePkg, err := imp.Import(PkgRuntime) + if err != nil { + t.Fatal(err) + } + prog.SetRuntime(runtimePkg) +} + +func newMatrixEnvEntry(pkg Package, name string, sig *types.Signature, envStruct *types.Struct) Function { + env := types.NewParam(token.NoPos, nil, "$env", types.NewPointer(envStruct)) + entry := pkg.NewEnvFunc(name, sig, InGo, env, false) + b := entry.MakeBody(1) + b.Return(entry.Param(0)) + return entry +} + +func newMatrixCaller(pkg Package, name string, sig *types.Signature, value func(Builder) Expr) Function { + caller := pkg.NewFunc(name, sig, InGo) + b := caller.MakeBody(1) + funcval := value(b) + slot := b.AllocaT(funcval.Type) + b.Store(slot, funcval) + b.Return(b.Call(b.Load(slot), caller.Param(0))) + return caller +} + +func assertDynamicMatrixCall(t *testing.T, caller, entry Function, name, attrName string) { + t.Helper() + paramCounts := make(map[int]int) + barrierCalls := 0 + var envCall llvm.Value + for block := caller.impl.FirstBasicBlock(); !block.IsNil(); block = llvm.NextBasicBlock(block) { + for instruction := block.FirstInstruction(); !instruction.IsNil(); instruction = llvm.NextInstruction(instruction) { + call := instruction.IsACallInst() + if call.IsNil() { + continue + } + called := call.CalledValue() + if !called.IsAInlineAsm().IsNil() { + barrierCalls++ + continue + } + if !called.IsAFunction().IsNil() && called.Name() != entry.impl.Name() { + continue + } + count := call.CalledFunctionType().ParamTypesCount() + paramCounts[count]++ + if count == 2 { + envCall = call + } + } + } + if attrName == "" { + if barrierCalls != 0 { + t.Fatalf("%s explicit call has %d native identity barriers, want none", name, barrierCalls) + } + if paramCounts[1] != 1 || paramCounts[2] != 1 { + t.Fatalf("%s explicit edges have parameter counts %v, want one no-env and one env edge", name, paramCounts) + } + entry := caller.impl.FirstBasicBlock() + if term := entry.LastInstruction(); term.IsNil() || term.InstructionOpcode() != llvm.Br || term.OperandsCount() != 3 { + t.Fatalf("%s explicit call has no env != nil branch", name) + } + } else { + if barrierCalls != 1 { + t.Fatalf("%s native call has %d identity barriers, want one", name, barrierCalls) + } + if paramCounts[1] != 0 || paramCounts[2] != 1 { + t.Fatalf("%s native calls have parameter counts %v, want one hidden-env edge", name, paramCounts) + } + for block := caller.impl.FirstBasicBlock(); !block.IsNil(); block = llvm.NextBasicBlock(block) { + for instruction := block.FirstInstruction(); !instruction.IsNil(); instruction = llvm.NextInstruction(instruction) { + if instruction.InstructionOpcode() == llvm.ICmp { + t.Fatalf("%s native call retained an env == nil check", name) + } + } + } + } + for _, candidate := range []string{"nest", "swiftself"} { + kind := llvm.AttributeKindID(candidate) + got := !envCall.GetCallSiteEnumAttribute(1, kind).IsNil() + if got != (candidate == attrName) { + t.Fatalf("%s env edge %s attribute = %v, want %v", name, candidate, got, candidate == attrName) + } + } +} + +func assertMatrixEntryAttribute(t *testing.T, fn Function, name, attrName string) { + t.Helper() + for _, candidate := range []string{"nest", "swiftself"} { + kind := llvm.AttributeKindID(candidate) + got := !fn.impl.GetEnumAttributeAtIndex(1, kind).IsNil() + want := name != "" && candidate == attrName + if got != want { + t.Fatalf("%s definition %s attribute = %v, want %v", fn.Name(), candidate, got, want) + } + } +} + +func newMatrixInterfaceCaller(t *testing.T, prog Program, pkg Package, rawIface *types.Interface) Function { + t.Helper() + namedIface := types.NewNamed(types.NewTypeName(token.NoPos, nil, "MatrixIface", nil), rawIface, nil) + recv := types.NewVar(token.NoPos, nil, "recv", namedIface) + method := rawIface.Method(0) + recvMethod := types.NewFunc( + token.NoPos, + nil, + method.Name(), + types.NewSignatureType(recv, nil, nil, method.Type().(*types.Signature).Params(), + method.Type().(*types.Signature).Results(), false), + ) + params := types.NewTuple( + types.NewVar(token.NoPos, nil, "recv", namedIface), + types.NewVar(token.NoPos, nil, "x", types.Typ[types.Int]), + ) + results := types.NewTuple(types.NewVar(token.NoPos, nil, "", types.Typ[types.Int])) + caller := pkg.NewFunc("callInterfaceDirect", + types.NewSignatureType(nil, nil, nil, params, results, false), InGo, + ) + b := caller.MakeBody(1) + b.Return(b.Call(b.Imethod(caller.Param(0), recvMethod), caller.Param(1))) + return caller +} + +func newMatrixInterfaceRoutine(t *testing.T, prog Program, pkg Package, rawIface *types.Interface) Function { + t.Helper() + namedIface := types.NewNamed(types.NewTypeName(token.NoPos, nil, "RoutineIface", nil), rawIface, nil) + recv := types.NewVar(token.NoPos, nil, "recv", namedIface) + method := rawIface.Method(0) + recvMethod := types.NewFunc( + token.NoPos, + nil, + method.Name(), + types.NewSignatureType(recv, nil, nil, method.Type().(*types.Signature).Params(), + method.Type().(*types.Signature).Results(), false), + ) + params := types.NewTuple( + types.NewVar(token.NoPos, nil, "recv", namedIface), + types.NewVar(token.NoPos, nil, "x", types.Typ[types.Int]), + ) + owner := pkg.NewFunc("startInterfaceRoutine", + types.NewSignatureType(nil, nil, nil, params, nil, false), InGo, + ) + b := owner.MakeBody(1) + invoke := b.Imethod(owner.Param(0), recvMethod) + startRecord := prog.Struct(invoke.Type, prog.Int()) + routineExpr := pkg.routine(startRecord, invoke, Builder.Call, 1) + b.Return() + return pkg.FuncOf(routineExpr.Name()) +} + +func assertDirectInterfaceMatrixEdge(t *testing.T, caller Function, attrName string) { + t.Helper() + var indirect []llvm.Value + for block := caller.impl.FirstBasicBlock(); !block.IsNil(); block = llvm.NextBasicBlock(block) { + for instruction := block.FirstInstruction(); !instruction.IsNil(); instruction = llvm.NextInstruction(instruction) { + call := instruction.IsACallInst() + if !call.IsNil() && call.CalledValue().IsAFunction().IsNil() { + indirect = append(indirect, call) + } + } + } + if len(indirect) != 1 || indirect[0].CalledFunctionType().ParamTypesCount() != 2 { + t.Fatalf("direct interface invocation has %d indirect edges, want one receiver+arg edge", len(indirect)) + } + for _, candidate := range []string{"nest", "swiftself"} { + kind := llvm.AttributeKindID(candidate) + if attr := indirect[0].GetCallSiteEnumAttribute(1, kind); !attr.IsNil() { + t.Fatalf("direct interface invocation incorrectly carries %s (transport %q)", candidate, attrName) + } + } +} diff --git a/ssa/closure_wrap.go b/ssa/closure_wrap.go deleted file mode 100644 index 470a299caf..0000000000 --- a/ssa/closure_wrap.go +++ /dev/null @@ -1,111 +0,0 @@ -package ssa - -import ( - "go/token" - "go/types" - - "github.com/xgo-dev/llvm" -) - -// removeCtx drops the leading __llgo_ctx parameter, if present. -func removeCtx(sig *types.Signature) *types.Signature { - if closureCtxParam(sig) == nil { - return sig - } - params := sig.Params() - n := params.Len() - args := make([]*types.Var, n-1) - for i := 0; i < n-1; i++ { - args[i] = params.At(i + 1) - } - return types.NewSignature(sig.Recv(), types.NewTuple(args...), sig.Results(), sig.Variadic()) -} - -// closureCtxParam returns the leading __llgo_ctx parameter if present. -func closureCtxParam(sig *types.Signature) *types.Var { - if sig == nil { - return nil - } - params := sig.Params() - if params.Len() == 0 { - return nil - } - first := params.At(0) - if first.Name() != closureCtx { - return nil - } - if _, ok := first.Type().Underlying().(*types.Pointer); !ok { - return nil - } - return first -} - -// closureWrapArgs returns wrapper arguments excluding the ctx parameter. -func closureWrapArgs(fn Function) []Expr { - n := len(fn.params) - if n <= 1 { - return nil - } - args := make([]Expr, n-1) - for i := 1; i < n; i++ { - args[i-1] = fn.Param(i) - } - return args -} - -// closureWrapReturn returns from wrapper, preserving tail-call eligibility. -func closureWrapReturn(b Builder, sig *types.Signature, ret Expr) { - n := sig.Results().Len() - if n == 0 { - if !ret.impl.IsNil() { - ret.impl.SetTailCall(true) - } - b.impl.CreateRetVoid() - return - } - ret.impl.SetTailCall(true) - b.impl.CreateRet(ret.impl) -} - -// closureWrapDecl wraps a function declaration that lacks __llgo_ctx. -// It directly calls the target symbol and ignores the ctx parameter. -func (p Package) closureWrapDecl(fn Expr, sig *types.Signature) Function { - name := closureStub + fn.impl.Name() - if wrap := p.FuncOf(name); wrap != nil { - return wrap - } - ctx := types.NewParam(token.NoPos, nil, closureCtx, types.Typ[types.UnsafePointer]) - sigCtx := FuncAddCtx(ctx, sig) - wrap := p.NewFunc(name, sigCtx, InC) - wrap.impl.SetLinkage(llvm.LinkOnceAnyLinkage) - b := wrap.MakeBody(1) - args := closureWrapArgs(wrap) - ret := b.Call(fn, args...) - closureWrapReturn(b, sig, ret) - return wrap -} - -// closureWrapPtr wraps a raw function pointer by loading it from ctx. -// The ctx parameter is treated as a pointer to a stored function pointer cell. -func (p Package) closureWrapPtr(sig *types.Signature) Function { - name := closureStub + p.Prog.abi.FuncName(sig) - if wrap := p.FuncOf(name); wrap != nil { - return wrap - } - ctx := types.NewParam(token.NoPos, nil, closureCtx, types.Typ[types.UnsafePointer]) - sigCtx := FuncAddCtx(ctx, sig) - wrap := p.NewFunc(name, sigCtx, InC) - wrap.impl.SetLinkage(llvm.LinkOnceAnyLinkage) - b := wrap.MakeBody(1) - ctxArg := wrap.Param(0) - fnType := p.Prog.rawType(sig) - fnPtrType := p.Prog.Pointer(fnType) - // ctxArg is expected to be a non-nil pointer to a stored function pointer cell. - // We intentionally avoid runtime null checks here; invalid ctx is a compiler/user error. - fnPtr := b.Convert(fnPtrType, ctxArg) - fnVal := b.Load(fnPtr) - args := closureWrapArgs(wrap) - ret := b.Call(fnVal, args...) - closureWrapReturn(b, sig, ret) - return wrap -} diff --git a/ssa/decl.go b/ssa/decl.go index a575dd1bee..68087f4380 100644 --- a/ssa/decl.go +++ b/ssa/decl.go @@ -248,7 +248,7 @@ type aFunction struct { params []Type freeVars Expr - base int // base = 1 if hasFreeVars; base = 0 otherwise + env Type hasVArg bool fakeUses []llvm.Value @@ -267,12 +267,45 @@ func (p Package) NewFunc(name string, sig *types.Signature, bg Background) Funct // NewFuncEx creates a new function. func (p Package) NewFuncEx(name string, sig *types.Signature, bg Background, hasFreeVars bool, instantiated bool) Function { + if hasFreeVars { + panic("ssa: NewFuncEx cannot represent an environment; use NewEnvFunc") + } + return p.newFunc(name, sig, bg, nil, instantiated) +} + +// NewEnvFunc creates a function whose Go signature is sig and whose physical +// LLVM entry has an additional compiler-owned environment parameter. +func (p Package) NewEnvFunc( + name string, sig *types.Signature, bg Background, env *types.Var, instantiated bool, +) Function { + if env == nil { + panic("ssa: nil closure environment") + } + return p.newFunc(name, sig, bg, env, instantiated) +} + +func (p Package) newFunc( + name string, sig *types.Signature, bg Background, env *types.Var, instantiated bool, +) Function { if v, ok := p.fns[name]; ok { + if v.NeedsEnv() != (env != nil) { + panic("ssa: conflicting closure environment ABI for " + name) + } return v } t := p.Prog.FuncDecl(sig, bg) - dbgInstrln("NewFunc", name, t.raw.Type, "hasFreeVars:", hasFreeVars) + var envType Type + if env != nil { + envType = p.Prog.Type(env.Type(), InGo) + rawEnv := types.NewParam(env.Pos(), env.Pkg(), env.Name(), envType.raw.Type) + entrySig := FuncAddCtx(rawEnv, t.raw.Type.(*types.Signature)) + t = &aType{p.Prog.toLLVMFunc(entrySig), t.raw, vkFuncDecl} + } + dbgInstrln("NewFunc", name, t.raw.Type, "needsEnv:", envType != nil) fn := llvm.AddFunction(p.mod, name, t.ll) + if envType != nil { + p.Prog.markClosureEnvFunction(fn, 0) + } if bg == InGo { fn.AddFunctionAttr(p.nullPointerIsValidAttr) // Keep frame pointers so the runtime can walk real stacks (FP chain) @@ -290,7 +323,7 @@ func (p Package) NewFuncEx(name string, sig *types.Signature, bg Background, has if p.isPreservedName(name) { p.markLLVMUsed(fn) } - ret := newFunction(fn, t, p, p.Prog, hasFreeVars) + ret := newFunction(fn, t, p, p.Prog, envType) p.fns[name] = ret return ret } @@ -300,18 +333,14 @@ func (p Package) FuncOf(name string) Function { return p.fns[name] } -func newFunction(fn llvm.Value, t Type, pkg Package, prog Program, hasFreeVars bool) Function { +func newFunction(fn llvm.Value, t Type, pkg Package, prog Program, env Type) Function { params, hasVArg := newParams(t, prog) - base := 0 - if hasFreeVars { - base = 1 - } return &aFunction{ Expr: Expr{fn, t}, Pkg: pkg, Prog: prog, params: params, - base: base, + env: env, hasVArg: hasVArg, fakeUses: make([]llvm.Value, 0, 4), fakeUseSet: make(map[llvm.Value]struct{}), @@ -340,16 +369,38 @@ func (p Function) Name() string { // Params returns the function's ith parameter. func (p Function) Param(i int) Expr { - i += p.base // skip if hasFreeVars - return Expr{p.impl.Param(i), p.params[i]} + physical := i + if p.env != nil { + physical++ + } + return Expr{p.impl.Param(physical), p.params[i]} +} + +// NeedsEnv reports whether the physical function entry takes a compiler-owned +// closure environment parameter. +func (p Function) NeedsEnv() bool { + return p.env != nil +} + +// EnvType returns the physical closure environment pointer type, or nil. +func (p Function) EnvType() Type { + return p.env +} + +// Env returns the physical closure environment parameter. +func (p Function) Env() Expr { + if p.env == nil { + panic("ssa: function has no closure environment") + } + return Expr{p.impl.Param(0), p.env} } func (p Function) closureCtx(b Builder) Expr { if p.freeVars.IsNil() { - if p.base == 0 { + if p.env == nil { panic("ssa: function has no free variables") } - ptr := Expr{p.impl.Param(0), p.params[0]} + ptr := p.Env() if b.blk.Index() != 0 { blk := b.impl.GetInsertBlock() b.SetBlockEx(p.blks[0], AtStart, false) diff --git a/ssa/eh.go b/ssa/eh.go index b8ead4eb64..104b8e04af 100644 --- a/ssa/eh.go +++ b/ssa/eh.go @@ -484,12 +484,13 @@ func (b Builder) saveDeferArgs(self *aDefer, kind DoAction, id Expr, fn Expr, ar } func (b Builder) saveDeferArgsTo(argsPtr Expr, kind DoAction, id Expr, fn Expr, args []Expr) Type { - if kind != DeferInLoop && fn != Nil && fn.kind != vkClosure && len(args) == 0 { + saveFn := fn != Nil && (fn.kind == vkClosure || fn.kind == vkIfaceMethod) + if kind != DeferInLoop && fn != Nil && !saveFn && len(args) == 0 { return nil } prog := b.Prog offset := 2 // prev + id - if fn != Nil && fn.kind == vkClosure { + if saveFn { offset++ } typs := make([]Type, len(args)+offset) @@ -498,7 +499,7 @@ func (b Builder) saveDeferArgsTo(argsPtr Expr, kind DoAction, id Expr, fn Expr, flds[0] = b.Load(argsPtr).impl typs[1] = prog.Uintptr() flds[1] = id.impl - if fn != Nil && fn.kind == vkClosure { + if saveFn { typs[2] = fn.Type flds[2] = fn.impl } @@ -529,8 +530,16 @@ func (b Builder) callDefer(self *aDefer, typ Type, buildCall func(Builder, Expr, data := b.Load(Expr{ptr.impl, prog.Pointer(typ)}) offset := 2 // prev + id b.Store(self.argsPtr, Expr{b.getField(data, 0).impl, prog.VoidPtr()}) - if fn != Nil && fn.kind == vkClosure { + if fn != Nil && (fn.kind == vkClosure || fn.kind == vkIfaceMethod) { + savedType := fn.Type fn = b.getField(data, 2) + // A transient interface invocation has the same physical pair as a + // funcval, so aggregate field reconstruction sees vkClosure. Keep + // its call semantics: the saved data word is an ordinary receiver, + // not a hidden closure environment. + if savedType.kind == vkIfaceMethod { + fn.Type = savedType + } offset++ } for i := 0; i < len(args); i++ { diff --git a/ssa/expr.go b/ssa/expr.go index 6f476c9eac..dce7fb24c6 100644 --- a/ssa/expr.go +++ b/ssa/expr.go @@ -705,14 +705,14 @@ func (b Builder) BinOp(op token.Token, x, y Expr) Expr { ret.impl = llvm.CreateNot(b.impl, ret.impl) return ret } - case vkClosure: + case vkClosure, vkIfaceMethod: x = b.Field(x, 0) - if y.kind == vkClosure { + if y.kind == vkClosure || y.kind == vkIfaceMethod { y = b.Field(y, 0) } fallthrough case vkFuncPtr, vkFuncDecl, vkChan, vkMap: - if y.kind == vkClosure { + if y.kind == vkClosure || y.kind == vkIfaceMethod { y = b.Field(y, 0) } switch op { @@ -1194,15 +1194,26 @@ func (b Builder) PtrCast(t Type, x Expr) Expr { func (b Builder) MakeClosure(fn Expr, bindings []Expr) Expr { dbgInstrf("MakeClosure %v, %v\n", fn, bindings) prog := b.Prog - tfn := fn.Type - sig := tfn.raw.Type.(*types.Signature) + sig := fn.raw.Type.(*types.Signature) data := prog.Nil(prog.VoidPtr()).impl - if ctxParam := closureCtxParam(sig); ctxParam != nil { - tctx := ctxParam.Type().Underlying().(*types.Pointer).Elem().(*types.Struct) - ptr := b.aggregateAllocU(prog.rawType(tctx), llvmFields(bindings, tctx, b)...) - data = ptr + if entry := b.Pkg.FuncOf(fn.impl.Name()); entry != nil && entry.NeedsEnv() { + tctx := prog.Elem(entry.EnvType()) + rawCtx := tctx.raw.Type.Underlying().(*types.Struct) + if len(bindings) != rawCtx.NumFields() { + panic("ssa: closure environment binding count mismatch") + } + if prog.SizeOf(tctx) == 0 { + // A required environment must remain distinguishable from a no-env + // entry. Heap zero-sized allocations use the module-wide non-nil + // sentinel. + data = b.Alloc(tctx, true).impl + } else { + data = b.aggregateAllocU(tctx, llvmFields(bindings, rawCtx, b)...) + } + } else if len(bindings) != 0 { + panic("ssa: closure bindings supplied to a no-env function") } - return b.aggregateValue(prog.Closure(removeCtx(sig)), fn.impl, data) + return b.aggregateValue(prog.Closure(sig), fn.impl, data) } // ----------------------------------------------------------------------------- @@ -1237,14 +1248,20 @@ func (b Builder) Call(fn Expr, args ...Expr) (ret Expr) { data = b.Field(fn, 1) fn = b.Field(fn, 0) sig = fn.raw.Type.(*types.Signature) - ctx := types.NewParam(token.NoPos, nil, closureCtx, types.Typ[types.UnsafePointer]) - sigCtx := FuncAddCtx(ctx, sig) + return b.callClosure(fn, data, sig, args) + case vkIfaceMethod: + data = b.Field(fn, 1) + fn = b.Field(fn, 0) + sig = fn.raw.Type.(*types.Signature) + recv := types.NewParam(token.NoPos, nil, "$recv", types.Typ[types.UnsafePointer]) + entrySig := FuncAddCtx(recv, sig) ret.Type = b.Prog.retType(sig) - if sig.Results().Len() == 1 && b.Prog.SizeOf(ret.Type) == 0 { - b.AssertNilDeref(fn) - } - ll = b.Prog.FuncDecl(sigCtx, InC).ll - ret.impl = llvm.CreateCall(b.impl, ll, fn.impl, llvmParamsEx(data, args, sigCtx.Params(), b)) + ret.impl = llvm.CreateCall( + b.impl, + b.Prog.FuncDecl(entrySig, InC).ll, + fn.impl, + llvmParamsEx(data, args, entrySig.Params(), b), + ) return ret case vkFuncPtr: sig = raw.Underlying().(*types.Signature) @@ -1275,6 +1292,96 @@ func (b Builder) Call(fn Expr, args ...Expr) (ret Expr) { return } +func (b Builder) callClosure(fn, data Expr, sig *types.Signature, args []Expr) (ret Expr) { + prog := b.Prog + ret.Type = prog.retType(sig) + if sig.Results().Len() == 1 && prog.SizeOf(ret.Type) == 0 { + b.AssertNilDeref(fn) + } + + // Convert arguments once before splitting the dynamic call edge. Conversion + // may itself emit code and must not be duplicated into both successors. + params := llvmParams(0, args, sig.Params(), b) + envParams := make([]llvm.Value, len(params)+1) + envParams[0] = data.impl + copy(envParams[1:], params) + + noEnvType := prog.FuncDecl(sig, InC).ll + envParam := types.NewParam(token.NoPos, nil, "$env", types.Typ[types.UnsafePointer]) + envSig := FuncAddCtx(envParam, sig) + envType := prog.FuncDecl(envSig, InC).ll + + // A known code pointer uses the entry metadata directly. This preserves the + // exact prototype and avoids the identity barrier needed by dynamic native + // funcval calls. + if direct := fn.impl.IsAFunction(); !direct.IsNil() { + entry := b.Pkg.FuncOf(direct.Name()) + if entry == nil || !entry.NeedsEnv() { + ret.impl = llvm.CreateCall(b.impl, noEnvType, fn.impl, params) + return + } + ret.impl = llvm.CreateCall(b.impl, envType, fn.impl, envParams) + prog.markClosureEnvCall(ret.impl, 0) + return + } + + // On native hidden-context ABIs, the environment occupies a dedicated + // register even when it is nil. Ordinary Go and C entries simply ignore + // that register, so every dynamic funcval call can use the same hot path. + // Explicit-context targets cannot do this: their environment is an + // ordinary leading ABI argument and pure C entries do not accept it. + if prog.closureEnvABI() != closureEnvExplicit { + // The env and no-env LLVM prototypes intentionally differ even though the + // native machine ABI reserves a register for the hidden environment. Hide + // the dynamic code pointer's identity before the call so optimization cannot + // devirtualize a no-env target under the env-bearing IR prototype. + fn = b.hideClosureCodeIdentity(fn) + ret.impl = llvm.CreateCall(b.impl, envType, fn.impl, envParams) + prog.markClosureEnvCall(ret.impl, 0) + return + } + + logicalBlock := b.blk + entryBlock := b.impl.GetInsertBlock() + blks := b.Func.MakeBlocks(3) + hasEnv := Expr{ + llvm.CreateICmp(b.impl, llvm.IntNE, data.impl, prog.Nil(prog.VoidPtr()).impl), + prog.Bool(), + } + b.If(hasEnv, blks[0], blks[1]) + + b.SetBlockEx(blks[0], AtEnd, false) + envCall := llvm.CreateCall(b.impl, envType, fn.impl, envParams) + prog.markClosureEnvCall(envCall, 0) + b.Jump(blks[2]) + + b.SetBlockEx(blks[1], AtEnd, false) + noEnvCall := llvm.CreateCall(b.impl, noEnvType, fn.impl, params) + b.Jump(blks[2]) + + b.SetBlockEx(blks[2], AtEnd, false) + if sig.Results().Len() != 0 { + phi := b.Phi(ret.Type) + phi.impl.AddIncoming( + []llvm.Value{envCall, noEnvCall}, + []llvm.BasicBlock{blks[0].last, blks[1].last}, + ) + ret.impl = phi.impl + } + + // The extra LLVM blocks are an implementation detail inside the current Go + // SSA block. Only explicit-context targets retain this split; native hidden + // context has the uniform dynamic call edge above. + // A closure call may itself be emitted while another lowering helper has + // temporarily selected a synthetic LLVM predecessor with SetBlockEx(..., + // false). Only replace the logical Go block's tail when this split started + // at that tail; otherwise the enclosing helper owns the eventual merge. + if logicalBlock.last == entryBlock { + logicalBlock.last = blks[2].last + } + return +} + const ( ReflectArrayOf = 1 << iota ReflectChanOf @@ -1308,7 +1415,7 @@ func (b Builder) checkReflect(fn Expr, args []Expr) (check ReflectMethodCheck) { reflectKind = ReflectMapOf case "reflect.PointerTo", "reflect.PtrTo": reflectKind = ReflectPointerTo - case "reflect.SliceOf", "reflect.Value.Slice": + case "reflect.SliceOf", "reflect.SliceAt", "reflect.Value.Slice": reflectKind = ReflectSliceOf case "reflect.StructOf": reflectKind = ReflectStructOf @@ -1727,7 +1834,6 @@ func checkExpr(v Expr, t types.Type, b Builder) Expr { return v } prog := b.Prog - origKind := v.kind tclosure := prog.rawType(t) fnType := prog.Field(tclosure, 0) if v.Type != fnType { @@ -1739,11 +1845,6 @@ func checkExpr(v Expr, t types.Type, b Builder) Expr { } } data := prog.Nil(prog.VoidPtr()) - if origKind == vkFuncDecl || origKind == vkFuncPtr { - if sig, ok := fnType.raw.Type.(*types.Signature); ok && closureCtxParam(sig) == nil { - v, data = b.Pkg.closureStub(b, v, sig, origKind) - } - } return b.aggregateValue(tclosure, v.impl, data.impl) } if types.Identical(v.raw.Type, t) || !types.AssignableTo(v.raw.Type, t) { diff --git a/ssa/goroutine.go b/ssa/goroutine.go index 398a5ee376..f8f7c344fb 100644 --- a/ssa/goroutine.go +++ b/ssa/goroutine.go @@ -95,7 +95,14 @@ func (p Package) routine(t Type, fn Expr, buildCall func(Builder, Expr, ...Expr) args := make([]Expr, n) var offset int if fn != Nil && fn.kind != vkBuiltin { + savedType := fn.Type fn = b.getField(data, 0) + // Interface invocation pairs are structurally funcvals, but their data + // word remains an ordinary receiver argument after crossing the + // goroutine startup record. + if savedType.kind == vkIfaceMethod { + fn.Type = savedType + } offset = 1 } for i := 0; i < n; i++ { diff --git a/ssa/goroutine_patch_test.go b/ssa/goroutine_patch_test.go index 53d704dd42..c6db16005d 100644 --- a/ssa/goroutine_patch_test.go +++ b/ssa/goroutine_patch_test.go @@ -21,9 +21,8 @@ func TestGoClosureStartupUsesGCManagedMemory(t *testing.T) { types.NewField(0, nil, "x", types.Typ[types.Int], false), } ctxStruct := types.NewStruct(ctxFields, nil) - ctxParam := types.NewParam(0, nil, "__llgo_ctx", types.NewPointer(ctxStruct)) - innerSig := types.NewSignatureType(nil, nil, nil, types.NewTuple(ctxParam), nil, false) - inner := pkg.NewFunc("inner", innerSig, ssa.InGo) + ctxParam := types.NewParam(0, nil, "$env", types.NewPointer(ctxStruct)) + inner := pkg.NewEnvFunc("inner", ssa.NoArgsNoRet, ssa.InGo, ctxParam, false) ib := inner.MakeBody(1) ib.Return() diff --git a/ssa/interface.go b/ssa/interface.go index 253df5c64b..556bf23baf 100644 --- a/ssa/interface.go +++ b/ssa/interface.go @@ -97,7 +97,10 @@ func (b Builder) Imethod(intf Expr, method *types.Func) Expr { } else { fn = b.Load(pfn) } - ret := b.aggregateValue(tclosure, fn.impl, data.impl) + // This is a transient interface invocation pair, not a first-class + // funcval. The method receiver remains an ordinary ABI parameter. + tmethod := &aType{tclosure.ll, tclosure.raw, vkIfaceMethod} + ret := b.aggregateValue(tmethod, fn.impl, data.impl) return ret } diff --git a/ssa/package.go b/ssa/package.go index db41bae4ab..cc5810ce63 100644 --- a/ssa/package.go +++ b/ssa/package.go @@ -900,6 +900,21 @@ func (p Package) rtFunc(fnName string) Expr { return p.NewFunc(name, sig, InGo).Expr } +// rtEnvFunc returns a runtime entry whose source-level signature excludes its +// compiler-owned environment. Runtime type algorithms use this form when a +// type descriptor supplies the hidden type context. +func (p Package) rtEnvFunc(fnName string) Expr { + p.NeedRuntime = true + fn := p.Prog.runtime().Scope().Lookup(fnName).(*types.Func) + name := FullName(fn.Pkg(), fnName) + if p.fnlink != nil { + name = p.fnlink(name) + } + sig := fn.Type().(*types.Signature) + env := types.NewVar(token.NoPos, nil, "$env", types.Typ[types.UnsafePointer]) + return p.NewEnvFunc(name, sig, InGo, env, false).Expr +} + // RuntimeFunc returns a declaration for a function in LLGo's internal runtime. func (p Package) RuntimeFunc(fnName string) Expr { return p.rtFunc(fnName) @@ -909,30 +924,6 @@ func (p Package) cFunc(fullName string, sig *types.Signature) Expr { return p.NewFunc(fullName, sig, InC).Expr } -const ( - closureCtx = "__llgo_ctx" - closureStub = "__llgo_stub." -) - -// closureStub creates or reuses a wrapper for function values that lack closure ctx. -// It stays on Package to match the original placement of closure stubs. -func (p Package) closureStub(b Builder, fn Expr, sig *types.Signature, origKind valueKind) (Expr, Expr) { - prog := b.Prog - switch origKind { - case vkFuncDecl: - wrap := p.closureWrapDecl(fn, sig) - return wrap.Expr, prog.Nil(prog.VoidPtr()) - case vkFuncPtr: - wrap := p.closureWrapPtr(sig) - ptr := b.AllocU(prog.rawType(sig)) - b.Store(ptr, fn) - data := b.Convert(prog.VoidPtr(), ptr) - return wrap.Expr, data - default: - return fn, prog.Nil(prog.VoidPtr()) - } -} - // ----------------------------------------------------------------------------- // Path returns the package path. diff --git a/ssa/ssa_test.go b/ssa/ssa_test.go index 36ba6b46e7..05f998fae0 100644 --- a/ssa/ssa_test.go +++ b/ssa/ssa_test.go @@ -980,9 +980,9 @@ _llgo_func$2_iS07vIlF2_rZqWB5eU0IvP_9HviM4MYZNkXZDvbac: [MethodInfo] *_llgo_example.com/pkg.T: - 0 M _llgo_func$2_iS07vIlF2_rZqWB5eU0IvP_9HviM4MYZNkXZDvbac example.com/pkg.(*T).M __llgo_stub.example.com/pkg.(*T).M + 0 M _llgo_func$2_iS07vIlF2_rZqWB5eU0IvP_9HviM4MYZNkXZDvbac example.com/pkg.(*T).M example.com/pkg.(*T).M _llgo_example.com/pkg.T: - 0 M _llgo_func$2_iS07vIlF2_rZqWB5eU0IvP_9HviM4MYZNkXZDvbac example.com/pkg.(*T).M __llgo_stub.example.com/pkg.T.M + 0 M _llgo_func$2_iS07vIlF2_rZqWB5eU0IvP_9HviM4MYZNkXZDvbac example.com/pkg.(*T).M example.com/pkg.T.M ` if got := pm.String(); got != want { @@ -1016,6 +1016,21 @@ pkg.named: } } +func TestReflectSliceAtDemandsSliceTypeInit(t *testing.T) { + prog := NewProgram(nil) + defer prog.Dispose() + pkg := prog.NewPackage("pkg", "pkg") + sliceAt := pkg.NewFunc("reflect.SliceAt", NoArgsNoRet, InGo) + caller := pkg.NewFunc("pkg.callSliceAt", NoArgsNoRet, InGo) + b := caller.MakeBody(1) + b.Call(sliceAt.Expr) + b.Return() + + if got := pkg.NeedAbiInit & ReflectSliceOf; got == 0 { + t.Fatal("reflect.SliceAt did not retain slice type-construction metadata") + } +} + func TestRecordUseIface(t *testing.T) { prog := NewProgram(nil) defer prog.Dispose() @@ -1229,16 +1244,10 @@ _llgo_0: define void @holder() #0 { _llgo_0: %0 = alloca { ptr, ptr }, align 8 - store { ptr, ptr } { ptr @__llgo_stub.fn, ptr null }, ptr %0, align 8 + store { ptr, ptr } { ptr @fn, ptr null }, ptr %0, align 8 ret void } -define linkonce i64 @__llgo_stub.fn(ptr %0, i64 %1) { -_llgo_0: - %2 = tail call i64 @fn(i64 %1) - ret i64 %2 -} - attributes #0 = { null_pointer_is_valid "frame-pointer"="non-leaf" } `) } @@ -1270,43 +1279,25 @@ func TestClosureFuncPtrValue(t *testing.T) { hb.Store(ptr, fnPtr) hb.Return() - wrapName := "__llgo_stub." + prog.abi.FuncName(sig) - wrapRef := wrapName - if strings.Contains(wrapName, "$") { - wrapRef = fmt.Sprintf("\"%s\"", wrapName) - } - expected := fmt.Sprintf(`; ModuleID = 'foo/bar' + expected := `; ModuleID = 'foo/bar' source_filename = "foo/bar" ; Function Attrs: null_pointer_is_valid -define i64 @fn(i64 %%0) #0 { +define i64 @fn(i64 %0) #0 { _llgo_0: - ret i64 %%0 + ret i64 %0 } ; Function Attrs: null_pointer_is_valid define void @holder() #0 { _llgo_0: - %%0 = alloca { ptr, ptr }, align 8 - %%1 = call ptr @"github.com/goplus/llgo/runtime/internal/runtime.AllocU"(i64 8) - store ptr @fn, ptr %%1, align 8 - %%2 = insertvalue { ptr, ptr } { ptr @%s, ptr undef }, ptr %%1, 1 - store { ptr, ptr } %%2, ptr %%0, align 8 + %0 = alloca { ptr, ptr }, align 8 + store { ptr, ptr } { ptr @fn, ptr null }, ptr %0, align 8 ret void } -define linkonce i64 @%s(ptr %%0, i64 %%1) { -_llgo_0: - %%2 = load ptr, ptr %%0, align 8 - %%3 = tail call i64 %%2(i64 %%1) - ret i64 %%3 -} - -; Function Attrs: null_pointer_is_valid -declare ptr @"github.com/goplus/llgo/runtime/internal/runtime.AllocU"(i64) #0 - attributes #0 = { null_pointer_is_valid "frame-pointer"="non-leaf" } -`, wrapRef, wrapRef) +` assertPkg(t, pkg, expected) } @@ -1447,7 +1438,8 @@ func TestConvertStringFromWideIntegers(t *testing.T) { } func TestCallClosureDynamic(t *testing.T) { - prog := NewProgram(nil) + prog := NewProgram(&Target{GOOS: "wasip1", GOARCH: "wasm"}) + defer prog.Dispose() pkg := prog.NewPackage("bar", "foo/bar") params := types.NewTuple(types.NewVar(0, nil, "x", types.Typ[types.Int])) @@ -1462,20 +1454,17 @@ func TestCallClosureDynamic(t *testing.T) { b := caller.MakeBody(1) b.Return(b.Call(caller.Param(0), caller.Param(1))) - assertPkg(t, pkg, `; ModuleID = 'foo/bar' -source_filename = "foo/bar" - -; Function Attrs: null_pointer_is_valid -define i64 @caller({ ptr, ptr } %0, i64 %1) #0 { -_llgo_0: - %2 = extractvalue { ptr, ptr } %0, 1 - %3 = extractvalue { ptr, ptr } %0, 0 - %4 = call i64 %3(ptr %2, i64 %1) - ret i64 %4 -} - -attributes #0 = { null_pointer_is_valid "frame-pointer"="non-leaf" } -`) + ir := pkg.String() + for _, want := range []string{ + "icmp ne ptr %2, null", + "call i32 %3(ptr ", + "call i32 %3(i32 %1)", + "phi i32", + } { + if !strings.Contains(ir, want) { + t.Fatalf("dynamic closure call missing %q:\n%s", want, ir) + } + } } func TestMakeClosureWithCtx(t *testing.T) { @@ -1490,13 +1479,13 @@ func TestMakeClosureWithCtx(t *testing.T) { ctxFields := []*types.Var{types.NewField(0, nil, "x", types.Typ[types.Int], false)} ctxStruct := types.NewStruct(ctxFields, nil) ctxPtr := types.NewPointer(ctxStruct) - ctxParam := types.NewParam(0, nil, "__llgo_ctx", ctxPtr) - innerParams := types.NewTuple(ctxParam, types.NewVar(0, nil, "y", types.Typ[types.Int])) + ctxParam := types.NewParam(0, nil, "$env", ctxPtr) + innerParams := types.NewTuple(types.NewVar(0, nil, "y", types.Typ[types.Int])) innerRets := types.NewTuple(types.NewVar(0, nil, "", types.Typ[types.Int])) innerSig := types.NewSignatureType(nil, nil, nil, innerParams, innerRets, false) - inner := pkg.NewFunc("inner", innerSig, InGo) + inner := pkg.NewEnvFunc("inner", innerSig, InGo, ctxParam, false) ib := inner.MakeBody(1) - ib.Return(inner.Param(1)) + ib.Return(inner.Param(0)) outerParams := types.NewTuple(types.NewVar(0, nil, "x", types.Typ[types.Int])) outerRetSig := types.NewSignatureType(nil, nil, nil, @@ -1509,30 +1498,20 @@ func TestMakeClosureWithCtx(t *testing.T) { closure := ob.MakeClosure(inner.Expr, []Expr{outer.Param(0)}) ob.Return(closure) - assertPkg(t, pkg, `; ModuleID = 'foo/bar' -source_filename = "foo/bar" - -; Function Attrs: null_pointer_is_valid -define i64 @inner(ptr %0, i64 %1) #0 { -_llgo_0: - ret i64 %1 -} - -; Function Attrs: null_pointer_is_valid -define { ptr, ptr } @outer(i64 %0) #0 { -_llgo_0: - %1 = call ptr @"github.com/goplus/llgo/runtime/internal/runtime.AllocU"(i64 8) - %2 = getelementptr inbounds { i64 }, ptr %1, i32 0, i32 0 - store i64 %0, ptr %2, align 8 - %3 = insertvalue { ptr, ptr } { ptr @inner, ptr undef }, ptr %1, 1 - ret { ptr, ptr } %3 -} - -; Function Attrs: null_pointer_is_valid -declare ptr @"github.com/goplus/llgo/runtime/internal/runtime.AllocU"(i64) #0 - -attributes #0 = { null_pointer_is_valid "frame-pointer"="non-leaf" } -`) + if got := inner.Expr.raw.Type.(*types.Signature).Params().Len(); got != 1 { + t.Fatalf("semantic closure entry signature has %d params, want 1", got) + } + ir := pkg.String() + for _, want := range []string{ + "define i64 @inner(ptr ", + "i64 %1)", + `call ptr @"github.com/goplus/llgo/runtime/internal/runtime.AllocU"(i64 8)`, + "insertvalue { ptr, ptr } { ptr @inner, ptr undef }", + } { + if !strings.Contains(ir, want) { + t.Fatalf("closure environment IR missing %q:\n%s", want, ir) + } + } } func TestCvtClosureDropsRecv(t *testing.T) { @@ -1644,79 +1623,6 @@ attributes #0 = { null_pointer_is_valid "frame-pointer"="non-leaf" } `) } -func TestClosureCtxHelpers(t *testing.T) { - if closureCtxParam(nil) != nil { - t.Fatal("closureCtxParam should be nil for nil signature") - } - params := types.NewTuple() - rets := types.NewTuple() - sig := types.NewSignatureType(nil, nil, nil, params, rets, false) - if closureCtxParam(sig) != nil { - t.Fatal("closureCtxParam should be nil for empty params") - } - if removeCtx(sig) != sig { - t.Fatal("removeCtx should return original signature when no ctx param") - } - - badCtx := types.NewParam(0, nil, closureCtx, types.Typ[types.Int]) - badSig := types.NewSignatureType(nil, nil, nil, types.NewTuple(badCtx), rets, false) - if closureCtxParam(badSig) != nil { - t.Fatal("closureCtxParam should ignore non-pointer ctx param") - } - - ctxStruct := types.NewStruct([]*types.Var{ - types.NewVar(0, nil, "v", types.Typ[types.Int]), - }, nil) - goodCtx := types.NewParam(0, nil, closureCtx, types.NewPointer(ctxStruct)) - arg := types.NewParam(0, nil, "x", types.Typ[types.Int]) - goodSig := types.NewSignatureType(nil, nil, nil, types.NewTuple(goodCtx, arg), rets, false) - if closureCtxParam(goodSig) == nil { - t.Fatal("closureCtxParam should detect ctx param") - } - noCtx := removeCtx(goodSig) - if noCtx.Params().Len() != 1 || noCtx.Params().At(0).Name() != "x" { - t.Fatalf("removeCtx result mismatch: params=%v", noCtx.Params().Len()) - } -} - -func TestClosureWrapHelpers(t *testing.T) { - prog := NewProgram(nil) - pkg := prog.NewPackage("bar", "foo/bar") - ctx := types.NewParam(0, nil, closureCtx, types.Typ[types.UnsafePointer]) - sig := types.NewSignatureType(nil, nil, nil, types.NewTuple(), types.NewTuple(), false) - sigCtx := FuncAddCtx(ctx, sig) - wrap := pkg.NewFunc("wrap", sigCtx, InGo) - b := wrap.MakeBody(1) - if args := closureWrapArgs(wrap); len(args) != 0 { - t.Fatalf("closureWrapArgs should return 0 args, got %d", len(args)) - } - closureWrapReturn(b, sig, Expr{}) -} - -func TestClosureWrapCache(t *testing.T) { - prog := NewProgram(nil) - pkg := prog.NewPackage("bar", "foo/bar") - - params := types.NewTuple(types.NewVar(0, nil, "x", types.Typ[types.Int])) - rets := types.NewTuple(types.NewVar(0, nil, "", types.Typ[types.Int])) - sig := types.NewSignatureType(nil, nil, nil, params, rets, false) - fn := pkg.NewFunc("fn", sig, InGo) - b := fn.MakeBody(1) - b.Return(fn.Param(0)) - - w1 := pkg.closureWrapDecl(fn.Expr, sig) - w2 := pkg.closureWrapDecl(fn.Expr, sig) - if w1 != w2 { - t.Fatal("closureWrapDecl should reuse existing wrapper") - } - - p1 := pkg.closureWrapPtr(sig) - p2 := pkg.closureWrapPtr(sig) - if p1 != p2 { - t.Fatal("closureWrapPtr should reuse existing wrapper") - } -} - func TestMakeInterfaceKinds(t *testing.T) { prog := NewProgram(nil) prog.sizes = types.SizesFor("gc", runtime.GOARCH) @@ -1989,14 +1895,8 @@ func TestPackageCoverageHelpers(t *testing.T) { t.Fatal("ExportFuncs should be empty for new package") } - // cover closureStub default branch fn := pkg.NewFunc("noop", NoArgsNoRet, InGo) b := fn.MakeBody(1) - expr := prog.Val(1) - got, data := pkg.closureStub(b, expr, nil, vkString) - if got.impl.IsNil() || !data.impl.IsNull() { - t.Fatal("closureStub default branch should return expr and nil data") - } b.Return() } diff --git a/ssa/target.go b/ssa/target.go index a352b477fd..e9317f669c 100644 --- a/ssa/target.go +++ b/ssa/target.go @@ -27,11 +27,12 @@ import ( // ----------------------------------------------------------------------------- type Target struct { - GOOS string - GOARCH string - GOARM string // "5", "6", "7" (default) - Target string // target name from -target flag (e.g., "esp32", "arm7tdmi", "wasi") - OptLevel optlevel.Level + GOOS string + GOARCH string + GOARM string // "5", "6", "7" (default) + Target string // target name from -target flag (e.g., "esp32", "arm7tdmi", "wasi") + LLVMTarget string // physical LLVM target selected by a target configuration + OptLevel optlevel.Level } func (p *Target) targetInfo() (llvm.TargetData, llvm.TargetMachine) { diff --git a/ssa/type.go b/ssa/type.go index 98c9fc4848..c635cf16e9 100644 --- a/ssa/type.go +++ b/ssa/type.go @@ -47,6 +47,7 @@ const ( vkFuncDecl vkFuncPtr vkClosure + vkIfaceMethod vkBuiltin vkPyFuncRef vkPyVarRef From 757043c5df53d48feb70ef49eb6785f7a192336b Mon Sep 17 00:00:00 2001 From: Li Jie Date: Sat, 1 Aug 2026 22:19:44 +0800 Subject: [PATCH 14/73] test: close closure environment coverage gaps --- cl/compile.go | 19 +-- cl/instr.go | 9 +- cl/rewrite_internal_test.go | 17 +++ .../build/pclntab_modes_integration_test.go | 13 +- internal/cabi/cabi_patch_test.go | 113 +++++++++++------- ssa/closure_abi.go | 6 +- ssa/closure_env_test.go | 16 +++ 7 files changed, 117 insertions(+), 76 deletions(-) diff --git a/cl/compile.go b/cl/compile.go index fbe9febd0d..45af85518c 100644 --- a/cl/compile.go +++ b/cl/compile.go @@ -472,15 +472,13 @@ func makeClosureCtx(pkg *types.Package, vars []*ssa.FreeVar) *types.Var { // zero-sized variables are heap allocated, and LLGo already gives every such // allocation the same permitted non-nil sentinel address. // +// A non-synthetic function with a lexical parent is a source closure. // Synthetic wrappers are deliberately excluded: a zero-sized method receiver // can still carry a semantically significant nil/non-nil pointer value. func (p *context) canElideZeroSizedClosureEnv(f *ssa.Function) bool { if f == nil || f.Parent() == nil || f.Synthetic != "" || len(f.FreeVars) == 0 { return false } - if _, ok := f.Syntax().(*ast.FuncLit); !ok { - return false - } for _, freeVar := range f.FreeVars { if !p.isElidableZeroSizedFreeVar(freeVar) { return false @@ -490,23 +488,13 @@ func (p *context) canElideZeroSizedClosureEnv(f *ssa.Function) bool { } func (p *context) isElidableZeroSizedFreeVar(freeVar *ssa.FreeVar) bool { - typ := p.type_(freeVar.Type(), llssa.InGo) - if p.prog.SizeOf(typ) == 0 { - return true - } ptr, ok := types.Unalias(p.patchType(freeVar.Type())).Underlying().(*types.Pointer) return ok && p.prog.SizeOf(p.type_(ptr.Elem(), llssa.InGo)) == 0 } func (p *context) elidedZeroSizedFreeVar(b llssa.Builder, freeVar *ssa.FreeVar) llssa.Expr { typ := p.type_(freeVar.Type(), llssa.InGo) - if p.prog.SizeOf(typ) == 0 { - return p.prog.Zero(typ) - } - ptr, ok := types.Unalias(p.patchType(freeVar.Type())).Underlying().(*types.Pointer) - if !ok { - panic("zero-sized closure free variable is not reproducible") - } + ptr := types.Unalias(p.patchType(freeVar.Type())).Underlying().(*types.Pointer) addr := b.Alloc(p.type_(ptr.Elem(), llssa.InGo), true) return b.Convert(typ, addr) } @@ -630,9 +618,6 @@ func (p *context) compileFuncDecl(pkg llssa.Package, f *ssa.Function) (llssa.Fun hasFreeVars := len(f.FreeVars) > 0 elideFreeVarEnv := p.canElideZeroSizedClosureEnv(f) hasExplicitEnv := hasClosureEnvDirective(f) - if hasFreeVars && hasExplicitEnv { - panic("llgo:env cannot be combined with Go free variables") - } hasCtx := hasFreeVars && !elideFreeVarEnv || hasExplicitEnv var ctx *types.Var if elideFreeVarEnv { diff --git a/cl/instr.go b/cl/instr.go index e1ff870cfc..1520a23495 100644 --- a/cl/instr.go +++ b/cl/instr.go @@ -666,12 +666,9 @@ func (p *context) funcOf(fn *ssa.Function) (aFn llssa.Function, pyFn llssa.PyObj return nil, nil, ignoredFunc } sig := p.patchType(fn.Signature).(*types.Signature) - if hasClosureEnvDirective(fn) { - env := types.NewVar(token.NoPos, nil, "$env", types.Typ[types.UnsafePointer]) - aFn = pkg.NewEnvFunc(name, sig, llssa.Background(ftype), env, p.needsLinkOnce(fn)) - } else { - aFn = pkg.NewFuncEx(name, sig, llssa.Background(ftype), false, p.needsLinkOnce(fn)) - } + // Source env-bearing bodies are created by compileFuncDecl before + // lowering. Imported declarations cannot reconstruct //llgo:env. + aFn = pkg.NewFuncEx(name, sig, llssa.Background(ftype), false, p.needsLinkOnce(fn)) if disableInline { aFn.Inline(llssa.NoInline) } diff --git a/cl/rewrite_internal_test.go b/cl/rewrite_internal_test.go index e491101e46..b4e15cfe0b 100644 --- a/cl/rewrite_internal_test.go +++ b/cl/rewrite_internal_test.go @@ -107,6 +107,23 @@ func use() unsafe.Pointer { return closureEnv(1) } } } +func TestClosureEnvRejectsConflictingEntryABI(t *testing.T) { + const src = `package closureenv + +import _ "unsafe" + +//go:linkname plain closureenv.entry +func plain() {} + +//go:linkname withEnv closureenv.entry +//llgo:env +func withEnv() {} +` + mustPanic(t, "conflicting closure environment ABI", func() { + compileWithRewrites(t, src, nil) + }) +} + func assertNoStoreToGlobal(t *testing.T, ir, global string) { t.Helper() for _, line := range strings.Split(ir, "\n") { diff --git a/internal/build/pclntab_modes_integration_test.go b/internal/build/pclntab_modes_integration_test.go index d9919b08e9..febe859c90 100644 --- a/internal/build/pclntab_modes_integration_test.go +++ b/internal/build/pclntab_modes_integration_test.go @@ -268,7 +268,7 @@ func TestPCLNModeNativeIntegration(t *testing.T) { } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { - bin := buildPCLNIntegrationBinaryAt(t, source, tt.mode, LinkOptions{}, filepath.Join(packagingDir, "pclntab-modes-"+tt.name)) + bin := buildPCLNIntegrationBinaryAt(t, source, tt.mode, LinkOptions{}, filepath.Join(packagingDir, "pclntab-modes-"+tt.name), false) binaries[tt.mode] = bin if tt.mode == PCLNExternal { verifyPCLNIntegrationSignature(t, bin) @@ -397,7 +397,11 @@ func TestPCLNExternalPureCLibraryIdentityRetentionIntegration(t *testing.T) { requireNativePCLNSidecars(t) setPCLNIntegrationEnv(t) source := writePCLNIntegrationSource(t, pclntabPureCLibraryFixture) - bin := buildPCLNIntegrationBinary(t, source, PCLNExternal, LinkOptions{}) + // Exercise the external-sidecar summary as part of a real detach rather + // than mocking the final publication path. + bin := buildPCLNIntegrationBinaryAt( + t, source, PCLNExternal, LinkOptions{}, filepath.Join(t.TempDir(), "pclntab-pure-c"), true, + ) verifyPCLNIntegrationSignature(t, bin) if got := runPCLNIntegrationBinary(t, bin); got != "pure-c-pclntab\n" { t.Fatalf("pure lib/c output = %q", got) @@ -583,10 +587,10 @@ func pclnIntegrationBinaryIdentity(t *testing.T, path string) [32]byte { func buildPCLNIntegrationBinary(t *testing.T, source string, mode PCLNMode, options LinkOptions) string { t.Helper() - return buildPCLNIntegrationBinaryAt(t, source, mode, options, filepath.Join(t.TempDir(), "pclntab-modes")) + return buildPCLNIntegrationBinaryAt(t, source, mode, options, filepath.Join(t.TempDir(), "pclntab-modes"), false) } -func buildPCLNIntegrationBinaryAt(t *testing.T, source string, mode PCLNMode, options LinkOptions, bin string) string { +func buildPCLNIntegrationBinaryAt(t *testing.T, source string, mode PCLNMode, options LinkOptions, bin string, verbose bool) string { t.Helper() started := time.Now() conf := &Config{ @@ -596,6 +600,7 @@ func buildPCLNIntegrationBinaryAt(t *testing.T, source string, mode PCLNMode, op PCLNMode: mode, PCLNModeSet: true, LinkOptions: options, + Verbose: verbose, } if _, err := Do([]string{source}, conf); err != nil { t.Fatalf("build %s PCLN fixture with LinkOptions %+v: %v", mode, options, err) diff --git a/internal/cabi/cabi_patch_test.go b/internal/cabi/cabi_patch_test.go index d9afe8d089..228fbbc501 100644 --- a/internal/cabi/cabi_patch_test.go +++ b/internal/cabi/cabi_patch_test.go @@ -156,55 +156,80 @@ func TestClosureEnvAttributePreservedByCallbackWrapper(t *testing.T) { const testIR = ` %Value = type { ptr, ptr, i64 } -define %Value @callback(ptr ATTR %env, %Value %value) { +define RETURN @callback(ptr ATTR %env, %Value %value) { entry: - ret %Value %value + RET } ` - for _, attrName := range []string{"nest", "swiftself"} { - t.Run(attrName, func(t *testing.T) { - ctx := llvm.NewContext() - defer ctx.Dispose() - path := filepath.Join(t.TempDir(), "closure_env_callback.ll") - if err := os.WriteFile(path, []byte(strings.ReplaceAll(testIR, "ATTR", attrName)), 0o644); err != nil { - t.Fatal(err) - } - buf, err := llvm.NewMemoryBufferFromFile(path) - if err != nil { - t.Fatal(err) - } - mod, err := ctx.ParseIR(buf) - if err != nil { - t.Fatal(err) - } - defer mod.Dispose() - - prog := llssa.NewProgram(&llssa.Target{GOOS: "linux", GOARCH: "amd64"}) - defer prog.Dispose() - tr := NewTransformer(prog, "amd64-unknown-linux-gnu", "", ModeAllFunc, true) - callback := mod.NamedFunction("callback") - wrapper, ok := tr.transformCallbackFunc(mod, callback) - if !ok { - t.Fatalf("callback wrapper was not required:\n%s", mod.String()) - } + returnCases := []struct { + name string + typ string + ret string + }{ + {name: "aggregate", typ: "%Value", ret: "ret %Value %value"}, + {name: "void", typ: "void", ret: "ret void"}, + {name: "scalar", typ: "i64", ret: "ret i64 7"}, + } + for _, returnCase := range returnCases { + t.Run(returnCase.name, func(t *testing.T) { + for _, attrName := range []string{"nest", "swiftself"} { + t.Run(attrName, func(t *testing.T) { + ctx := llvm.NewContext() + defer ctx.Dispose() + path := filepath.Join(t.TempDir(), "closure_env_callback.ll") + ir := strings.NewReplacer( + "RETURN", returnCase.typ, + "RET", returnCase.ret, + "ATTR", attrName, + ).Replace(testIR) + if err := os.WriteFile(path, []byte(ir), 0o644); err != nil { + t.Fatal(err) + } + buf, err := llvm.NewMemoryBufferFromFile(path) + if err != nil { + t.Fatal(err) + } + mod, err := ctx.ParseIR(buf) + if err != nil { + t.Fatal(err) + } + defer mod.Dispose() + + prog := llssa.NewProgram(&llssa.Target{GOOS: "linux", GOARCH: "amd64"}) + defer prog.Dispose() + tr := NewTransformer(prog, "amd64-unknown-linux-gnu", "", ModeAllFunc, true) + callback := mod.NamedFunction("callback") + wrapper, ok := tr.transformCallbackFunc(mod, callback) + if !ok { + t.Fatalf("callback wrapper was not required:\n%s", mod.String()) + } - kind := llvm.AttributeKindID(attrName) - if got := wrapper.GetEnumAttributeAtIndex(2, kind); got.IsNil() { - t.Fatalf("callback wrapper lost/remapped %s:\n%s", attrName, wrapper.String()) - } - var callbackCall llvm.Value - for block := wrapper.FirstBasicBlock(); !block.IsNil(); block = llvm.NextBasicBlock(block) { - for instruction := block.FirstInstruction(); !instruction.IsNil(); instruction = llvm.NextInstruction(instruction) { - if call := instruction.IsACallInst(); !call.IsNil() && call.CalledValue() == callback { - callbackCall = call + kind := llvm.AttributeKindID(attrName) + var wrapperHasAttr bool + for i := 1; i <= wrapper.GlobalValueType().ParamTypesCount(); i++ { + if !wrapper.GetEnumAttributeAtIndex(i, kind).IsNil() { + wrapperHasAttr = true + break + } } - } - } - if callbackCall.IsNil() || callbackCall.GetCallSiteEnumAttribute(1, kind).IsNil() { - t.Fatalf("callback wrapper call lost %s:\n%s", attrName, wrapper.String()) - } - if err := llvm.VerifyModule(mod, llvm.ReturnStatusAction); err != nil { - t.Fatalf("C ABI callback closure-env module is invalid: %v\n%s", err, mod.String()) + if !wrapperHasAttr { + t.Fatalf("callback wrapper lost/remapped %s:\n%s", attrName, wrapper.String()) + } + var callbackCall llvm.Value + for block := wrapper.FirstBasicBlock(); !block.IsNil(); block = llvm.NextBasicBlock(block) { + for instruction := block.FirstInstruction(); !instruction.IsNil(); instruction = llvm.NextInstruction(instruction) { + if call := instruction.IsACallInst(); !call.IsNil() && call.CalledValue() == callback { + callbackCall = call + } + } + } + if callbackCall.IsNil() || callbackCall.GetCallSiteEnumAttribute(1, kind).IsNil() { + t.Fatalf("callback wrapper call lost %s:\n%s", attrName, wrapper.String()) + } + if err := llvm.VerifyModule(mod, llvm.ReturnStatusAction); err != nil { + t.Fatalf("C ABI callback closure-env module is invalid: %v\n%s", err, mod.String()) + } + }) } }) } diff --git a/ssa/closure_abi.go b/ssa/closure_abi.go index 66cb28f952..0d1908f516 100644 --- a/ssa/closure_abi.go +++ b/ssa/closure_abi.go @@ -94,11 +94,7 @@ func (p Program) closureEnvAttribute() llvm.Attribute { default: return llvm.Attribute{} } - kind := llvm.AttributeKindID(name) - if kind == 0 { - panic("ssa: LLVM has no " + name + " parameter attribute") - } - return p.ctx.CreateEnumAttribute(kind, 0) + return p.ctx.CreateEnumAttribute(llvm.AttributeKindID(name), 0) } func (p Program) markClosureEnvFunction(fn llvm.Value, physicalIndex int) { diff --git a/ssa/closure_env_test.go b/ssa/closure_env_test.go index 1c6393b87c..7f00042419 100644 --- a/ssa/closure_env_test.go +++ b/ssa/closure_env_test.go @@ -124,6 +124,10 @@ func TestClosureEnvMetadataRejectsInvalidUses(t *testing.T) { pkg := prog.NewPackage("p", "example.com/p") sig := types.NewSignatureType(nil, nil, nil, nil, nil, false) env := types.NewParam(token.NoPos, nil, "$env", types.NewPointer(types.NewStruct(nil, nil))) + envEntry := pkg.NewEnvFunc("binding-mismatch", sig, InGo, env, false) + plainEntry := pkg.NewFunc("plain-binding", sig, InGo) + caller := pkg.NewFunc("binding-validation", sig, InGo) + b := caller.MakeBody(1) tests := []struct { name string @@ -154,6 +158,18 @@ func TestClosureEnvMetadataRejectsInvalidUses(t *testing.T) { pkg.NewFunc("plain-env", sig, InGo).Env() }, }, + { + name: "environment binding count mismatch", + fn: func() { + b.MakeClosure(envEntry.Expr, []Expr{prog.Val(1)}) + }, + }, + { + name: "binding on plain entry", + fn: func() { + b.MakeClosure(plainEntry.Expr, []Expr{prog.Val(1)}) + }, + }, } for _, test := range tests { t.Run(test.name, func(t *testing.T) { From 0ab21c9c22276d7b0e6d2c0b234c23df532fbba7 Mon Sep 17 00:00:00 2001 From: Li Jie Date: Sun, 2 Aug 2026 00:40:33 +0800 Subject: [PATCH 15/73] cl,ssa,reflect: address closure ABI review feedback --- cl/compile.go | 5 +++-- cl/import.go | 3 ++- cl/rewrite_internal_test.go | 16 ++++++++++------ runtime/internal/clite/ffi/_wrap/libffi.c | 4 ++++ runtime/internal/lib/reflect/makefunc.go | 2 +- ssa/closure_abi.go | 8 ++++++-- 6 files changed, 26 insertions(+), 12 deletions(-) diff --git a/cl/compile.go b/cl/compile.go index 45af85518c..fe0709e2d0 100644 --- a/cl/compile.go +++ b/cl/compile.go @@ -32,6 +32,7 @@ import ( "github.com/goplus/llgo/cl/blocks" "github.com/goplus/llgo/cl/ssawrap" + "github.com/goplus/llgo/internal/directive" "github.com/goplus/llgo/internal/goembed" "github.com/goplus/llgo/internal/typepatch" "golang.org/x/tools/go/ssa" @@ -765,8 +766,8 @@ func hasClosureEnvDirective(f *ssa.Function) bool { if decl == nil || decl.Doc == nil { return false } - for _, c := range decl.Doc.List { - if strings.TrimSpace(c.Text) == "//llgo:env" { + for _, parsed := range directive.ParseGroup(decl.Doc) { + if parsed.Name == "llgo:env" { return true } } diff --git a/cl/import.go b/cl/import.go index 0e493f3c27..420dfd0307 100644 --- a/cl/import.go +++ b/cl/import.go @@ -563,7 +563,8 @@ const ( llgoAtomicCmpXchgOK = llgoInstrBase + 0x45 llgoAtomicAddReturnNew = llgoInstrBase + 0x46 llgoBoolToUint8 = llgoInstrBase + 0x47 - llgoClosureEnv = llgoInstrBase + 0x49 + // 0x48 is reserved for llgoCoroPark in the coroutine backend. + llgoClosureEnv = llgoInstrBase + 0x49 llgoAtomicOpLast = llgoAtomicOpBase + int(llssa.OpUMin) ) diff --git a/cl/rewrite_internal_test.go b/cl/rewrite_internal_test.go index b4e15cfe0b..235de50269 100644 --- a/cl/rewrite_internal_test.go +++ b/cl/rewrite_internal_test.go @@ -65,14 +65,18 @@ import "unsafe" //go:linkname closureEnv llgo.closureEnv func closureEnv() unsafe.Pointer -//llgo:env +DIRECTIVE func use() unsafe.Pointer { return closureEnv() } ` - ir := compileWithRewrites(t, valid, nil) - if !strings.Contains(ir, `define ptr @closureenv.use(ptr `) || - !strings.Contains(ir, `ret ptr %0`) || - (!strings.Contains(ir, `ptr nest %0`) && !strings.Contains(ir, `ptr swiftself %0`)) { - t.Fatalf("closureEnv intrinsic did not return the physical environment:\n%s", ir) + for _, spelling := range []string{"//llgo:env", "// llgo:env"} { + t.Run(spelling, func(t *testing.T) { + ir := compileWithRewrites(t, strings.Replace(valid, "DIRECTIVE", spelling, 1), nil) + if !strings.Contains(ir, `define ptr @closureenv.use(ptr `) || + !strings.Contains(ir, `ret ptr %0`) || + (!strings.Contains(ir, `ptr nest %0`) && !strings.Contains(ir, `ptr swiftself %0`)) { + t.Fatalf("closureEnv intrinsic did not return the physical environment:\n%s", ir) + } + }) } for _, test := range []struct { diff --git a/runtime/internal/clite/ffi/_wrap/libffi.c b/runtime/internal/clite/ffi/_wrap/libffi.c index 6b82c7732e..9960809be1 100644 --- a/runtime/internal/clite/ffi/_wrap/libffi.c +++ b/runtime/internal/clite/ffi/_wrap/libffi.c @@ -28,6 +28,10 @@ struct llgo_ffi_call_context { void *saved_return; }; +/* Targets entered through this context must return normally. A non-local exit + * across ffi_call would skip both the trampoline register restore and the TLS + * restore in llgo_ffi_call_with_env. */ + static _Thread_local struct llgo_ffi_call_context llgo_ffi_call_current; __attribute__((noinline, used)) static struct llgo_ffi_call_context * diff --git a/runtime/internal/lib/reflect/makefunc.go b/runtime/internal/lib/reflect/makefunc.go index b4892b16dc..77f1d667e5 100644 --- a/runtime/internal/lib/reflect/makefunc.go +++ b/runtime/internal/lib/reflect/makefunc.go @@ -71,7 +71,7 @@ func makeFunc(typ Type, fn func(args []Value) (results []Value)) Value { } // keep alive for bdw-gc keepMutex.Lock() - keepAlive = append(keepAlive, &closure.Fn, sig, userdata) + keepAlive = append(keepAlive, closure, sig, userdata) keepMutex.Unlock() styp := closureOf(ftyp) diff --git a/ssa/closure_abi.go b/ssa/closure_abi.go index 0d1908f516..e254acf5a4 100644 --- a/ssa/closure_abi.go +++ b/ssa/closure_abi.go @@ -42,8 +42,12 @@ func closureEnvABIForTarget(triple string) closureEnvABI { return closureEnvSwiftSelf case arch == "x86_64", arch == "amd64", arch == "x86", arch == "386", - arch == "i386", arch == "i486", arch == "i586", arch == "i686", - arch == "riscv32", arch == "riscv64": + arch == "i386", arch == "i486", arch == "i586", arch == "i686": + return closureEnvNest + case arch == "riscv32", arch == "riscv64": + // LLVM lowers the RISC-V nest parameter through t2 (x7). The public + // libffi final-hop bridge installs the environment in the same register; + // the ESP32-C3 suite exercises this transport on riscv32. return closureEnvNest default: return closureEnvExplicit From 229bd78a69b4c3ab5c6dbc8fdd95157c874bc446 Mon Sep 17 00:00:00 2001 From: Li Jie Date: Sun, 2 Aug 2026 00:40:40 +0800 Subject: [PATCH 16/73] cl: preserve named rangefunc yield closure types --- cl/instr.go | 24 ++++++++++- cl/named_closure_internal_test.go | 72 +++++++++++++++++++++++++++++++ test/goroot/xfail.yaml | 4 -- 3 files changed, 95 insertions(+), 5 deletions(-) create mode 100644 cl/named_closure_internal_test.go diff --git a/cl/instr.go b/cl/instr.go index 1520a23495..4b52624f1b 100644 --- a/cl/instr.go +++ b/cl/instr.go @@ -2119,12 +2119,34 @@ func (p *context) callEx(b llssa.Builder, act llssa.DoAction, call *ssa.CallComm } default: fn := p.compileValue(b, cv) - args := p.compileValues(b, args, kind) + args := p.compileDynamicCallValues(b, call, kind) ret = p.emitDo(b, act, ds, fn, llssa.Builder.Call, args...) } return } +func (p *context) compileDynamicCallValues(b llssa.Builder, call *ssa.CallCommon, hasVArg int) []llssa.Expr { + args := p.compileValues(b, call.Args, hasVArg) + params := call.Signature().Params() + n := min(len(call.Args)-hasVArg, params.Len()) + for i, arg := range call.Args[:n] { + want := params.At(i).Type() + if needsNamedClosureChange(arg.Type(), want) { + args[i] = b.ChangeType(p.type_(want, llssa.InGo), args[i]) + } + } + return args +} + +func needsNamedClosureChange(got, want types.Type) bool { + if types.Identical(got, want) { + return false + } + _, gotIsFunc := got.Underlying().(*types.Signature) + _, wantIsFunc := want.Underlying().(*types.Signature) + return gotIsFunc && wantIsFunc && types.Identical(got.Underlying(), want.Underlying()) +} + func (p *context) reflectTypeMethodCheck(call *ssa.CallCommon, method *types.Func) (check llssa.ReflectMethodCheck) { if !isReflectType(call.Value.Type()) { return diff --git a/cl/named_closure_internal_test.go b/cl/named_closure_internal_test.go new file mode 100644 index 0000000000..bfc106fa3c --- /dev/null +++ b/cl/named_closure_internal_test.go @@ -0,0 +1,72 @@ +//go:build !llgo + +package cl + +import ( + "go/token" + "go/types" + "testing" + + "github.com/xgo-dev/llvm" +) + +func TestNeedsNamedClosureChange(t *testing.T) { + pkg := types.NewPackage("example.com/p", "p") + params := types.NewTuple(types.NewParam(token.NoPos, pkg, "value", types.Typ[types.Int])) + results := types.NewTuple(types.NewParam(token.NoPos, pkg, "", types.Typ[types.Bool])) + sig := types.NewSignatureType(nil, nil, nil, params, results, false) + named := types.NewNamed(types.NewTypeName(token.NoPos, pkg, "Func", nil), sig, nil) + different := types.NewSignatureType(nil, nil, nil, nil, results, false) + + tests := []struct { + name string + got types.Type + want types.Type + ok bool + }{ + {name: "anonymous to named", got: sig, want: named, ok: true}, + {name: "named to anonymous", got: named, want: sig, ok: true}, + {name: "identical named", got: named, want: named}, + {name: "different signatures", got: different, want: named}, + {name: "non functions", got: types.Typ[types.Int], want: types.Typ[types.Int64]}, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + if got := needsNamedClosureChange(tt.got, tt.want); got != tt.ok { + t.Fatalf("needsNamedClosureChange(%v, %v) = %v, want %v", tt.got, tt.want, got, tt.ok) + } + }) + } +} + +func TestNamedClosureValuesKeepTheirDeclaredType(t *testing.T) { + const source = `package main + +type Func func(int) bool + +func call(fn Func) bool { return fn(1) } + +func direct() bool { + want := 1 + return call(func(got int) bool { return got == want }) +} + +func iterator() func(Func) { + return func(yield Func) { _ = yield(1) } +} + +func ranged() int { + n := 0 + for range iterator() { n++ } + return n +} + +func main() { + if !direct() || ranged() != 1 { panic("named closure conversion failed") } +} +` + _, module := mustCompileLLPkgFromSrc(t, source) + if err := llvm.VerifyModule(module, llvm.ReturnStatusAction); err != nil { + t.Fatalf("named closure module is invalid: %v\n%s", err, module.String()) + } +} diff --git a/test/goroot/xfail.yaml b/test/goroot/xfail.yaml index cee4671e72..7912d20eb8 100644 --- a/test/goroot/xfail.yaml +++ b/test/goroot/xfail.yaml @@ -2444,10 +2444,6 @@ xfails: directive: run case: nilptr2.go reason: address-of a dereferenced nil pointer does not panic and the run hangs on darwin/arm64 - - platform: darwin/arm64 - directive: run - case: range4.go - reason: range-over-function build exits successfully without producing a binary on darwin/arm64 - platform: darwin/arm64 directive: run case: fixedbugs/issue31546.go From 7b87a5d5d74f4b3ad1c049ee87d2d43d167e7696 Mon Sep 17 00:00:00 2001 From: Li Jie Date: Sun, 2 Aug 2026 06:27:23 +0800 Subject: [PATCH 17/73] cl: collect closure env directives during syntax scan --- cl/compile.go | 12 +++++++--- cl/import.go | 39 +++++++++++++++++++++----------- cl/import_coverage_test.go | 45 ++++++++++++++++++++++++++++++++++--- cl/rewrite_internal_test.go | 33 +++++++++++++++++++++++++++ ssa/closure_env_test.go | 32 ++++++++++++++++++++++++++ ssa/package.go | 38 ++++++++++++++++++++++++++----- 6 files changed, 174 insertions(+), 25 deletions(-) diff --git a/cl/compile.go b/cl/compile.go index fe0709e2d0..d8496c8bca 100644 --- a/cl/compile.go +++ b/cl/compile.go @@ -618,7 +618,7 @@ func (p *context) compileFuncDecl(pkg llssa.Package, f *ssa.Function) (llssa.Fun fn := pkg.FuncOf(name) hasFreeVars := len(f.FreeVars) > 0 elideFreeVarEnv := p.canElideZeroSizedClosureEnv(f) - hasExplicitEnv := hasClosureEnvDirective(f) + hasExplicitEnv := p.hasClosureEnvDirective(pkgTypes, f) hasCtx := hasFreeVars && !elideFreeVarEnv || hasExplicitEnv var ctx *types.Var if elideFreeVarEnv { @@ -761,11 +761,17 @@ func (p *context) compileFuncDecl(pkg llssa.Package, f *ssa.Function) (llssa.Fun // hasClosureEnvDirective is intentionally source-only. //llgo:env may mark // only internal bodies emitted in their defining package; external env-bearing // declarations must be reconstructed explicitly with llssa.NewEnvFunc. -func hasClosureEnvDirective(f *ssa.Function) bool { +func (p *context) hasClosureEnvDirective(pkg *types.Package, f *ssa.Function) bool { decl, _ := f.Syntax().(*ast.FuncDecl) - if decl == nil || decl.Doc == nil { + if decl == nil { return false } + fullName, _ := astFuncName(llssa.PathOf(pkg), decl) + if enabled, ok := p.prog.ClosureEnvDirective(p.goProg.Fset, fullName, decl.Pos()); ok { + return enabled + } + // Keep custom compilation paths that did not preload this declaration + // source-compatible. Normal builds consume the ParsePkgSyntax cache above. for _, parsed := range directive.ParseGroup(decl.Doc) { if parsed.Name == "llgo:env" { return true diff --git a/cl/import.go b/cl/import.go index 420dfd0307..2a1459e16d 100644 --- a/cl/import.go +++ b/cl/import.go @@ -276,19 +276,33 @@ func (p *context) collectSkip(line string, prefix int) { } } -func collectLinknameByDoc(prog llssa.Program, doc *ast.CommentGroup, fullName, inPkgName string) { +// collectDeclarationDirectives caches source metadata needed after the syntax +// pass. funcPos is token.NoPos for non-function declarations. +func collectDeclarationDirectives(prog llssa.Program, fset *token.FileSet, doc *ast.CommentGroup, fullName, inPkgName string, funcPos token.Pos) { directives := directive.ParseGroup(doc) + linkCollected := false + hasClosureEnv := false for n := len(directives) - 1; n >= 0; n-- { - directive := directives[n] - if directive.Name != "go:linkname" && directive.Name != "llgo:link" { - continue - } - fields := strings.Fields(directive.Args) - if len(fields) >= 2 && fields[0] == inPkgName { - prog.SetLinkname(fullName, strings.Join(fields[1:], " ")) - return + item := directives[n] + switch item.Name { + case "go:linkname", "llgo:link": + if linkCollected { + continue + } + fields := strings.Fields(item.Args) + if len(fields) >= 2 && fields[0] == inPkgName { + prog.SetLinkname(fullName, strings.Join(fields[1:], " ")) + linkCollected = true + } + case "llgo:env": + if funcPos.IsValid() { + hasClosureEnv = true + } } } + if funcPos.IsValid() { + prog.SetClosureEnvDirective(fset, fullName, funcPos, hasClosureEnv) + } } func (p *context) processLinknameByDoc(doc *ast.CommentGroup, fullName, inPkgName string, isVar, allowExport bool) bool { @@ -563,8 +577,7 @@ const ( llgoAtomicCmpXchgOK = llgoInstrBase + 0x45 llgoAtomicAddReturnNew = llgoInstrBase + 0x46 llgoBoolToUint8 = llgoInstrBase + 0x47 - // 0x48 is reserved for llgoCoroPark in the coroutine backend. - llgoClosureEnv = llgoInstrBase + 0x49 + llgoClosureEnv = llgoInstrBase + 0x48 llgoAtomicOpLast = llgoAtomicOpBase + int(llssa.OpUMin) ) @@ -775,14 +788,14 @@ func ParsePkgSyntax(prog llssa.Program, fset *token.FileSet, pkg *types.Package, return err } fullName, inPkgName := astFuncName(pkgPath, decl) - collectLinknameByDoc(prog, decl.Doc, fullName, inPkgName) + collectDeclarationDirectives(prog, fset, decl.Doc, fullName, inPkgName, decl.Pos()) ctx.processNoInterfaceByDoc(decl.Doc, fullName) case *ast.GenDecl: if decl.Tok == token.VAR { if len(decl.Specs) == 1 { if names := decl.Specs[0].(*ast.ValueSpec).Names; len(names) == 1 { inPkgName := names[0].Name - collectLinknameByDoc(prog, decl.Doc, pkgPath+"."+inPkgName, inPkgName) + collectDeclarationDirectives(prog, fset, decl.Doc, pkgPath+"."+inPkgName, inPkgName, token.NoPos) } } vars, err := locality.ScanPackageVar(fset, decl) diff --git a/cl/import_coverage_test.go b/cl/import_coverage_test.go index 4afa5b0110..e7a650f808 100644 --- a/cl/import_coverage_test.go +++ b/cl/import_coverage_test.go @@ -251,20 +251,59 @@ func TestParsePkgSyntaxCollectsLinknames(t *testing.T) { }) } prog := llssa.NewProgram(nil) - collectLinknameByDoc(prog, &ast.CommentGroup{List: []*ast.Comment{{Text: "//go:linkname Other C.other"}}}, llssa.PkgRuntime+".Sigsetjmp", "Sigsetjmp") + collectDeclarationDirectives(prog, nil, &ast.CommentGroup{List: []*ast.Comment{{Text: "//go:linkname Other C.other"}}}, llssa.PkgRuntime+".Sigsetjmp", "Sigsetjmp", token.NoPos) if _, ok := prog.Linkname(llssa.PkgRuntime + ".Sigsetjmp"); ok { t.Fatal("mismatched linkname was collected") } } -func TestCollectLinknameByDocIgnoresOtherDirectives(t *testing.T) { +func TestParsePkgSyntaxCollectsClosureEnvDirectives(t *testing.T) { + const src = `package p +//go:linkname env C.old +//llgo:env +//go:linkname env C.new +func env() {} + +// llgo:env +func spaced() {} + +func plain() {} +` + fset := token.NewFileSet() + file, err := parser.ParseFile(fset, "p.go", src, parser.ParseComments) + if err != nil { + t.Fatal(err) + } + prog := llssa.NewProgram(nil) + pkg := types.NewPackage("example.com/p", "p") + if err := ParsePkgSyntax(prog, fset, pkg, []*ast.File{file}); err != nil { + t.Fatal(err) + } + if link, ok := prog.Linkname("example.com/p.env"); !ok || link != "C.new" { + t.Fatalf("combined declaration linkname = (%q, %v), want (C.new, true)", link, ok) + } + want := map[string]bool{"env": true, "spaced": true, "plain": false} + for _, node := range file.Decls { + decl := node.(*ast.FuncDecl) + fullName, _ := astFuncName(pkg.Path(), decl) + got, ok := prog.ClosureEnvDirective(fset, fullName, decl.Pos()) + if !ok || got != want[decl.Name.Name] { + t.Fatalf("ClosureEnvDirective(%s) = (%v, %v), want (%v, true)", decl.Name.Name, got, ok, want[decl.Name.Name]) + } + } + if _, ok := prog.ClosureEnvDirective(fset, "example.com/p.missing", token.NoPos); ok { + t.Fatal("missing declaration unexpectedly has cached directives") + } +} + +func TestCollectDeclarationDirectivesIgnoresOtherDirectives(t *testing.T) { prog := llssa.NewProgram(nil) doc := &ast.CommentGroup{List: []*ast.Comment{ {Text: "//go:noinline"}, {Text: "//llgo:tls"}, }} const fullName = "example.com/p.Value" - collectLinknameByDoc(prog, doc, fullName, "Value") + collectDeclarationDirectives(prog, nil, doc, fullName, "Value", token.NoPos) if _, ok := prog.Linkname(fullName); ok { t.Fatal("non-link directives installed a linkname") } diff --git a/cl/rewrite_internal_test.go b/cl/rewrite_internal_test.go index 235de50269..a825fab95f 100644 --- a/cl/rewrite_internal_test.go +++ b/cl/rewrite_internal_test.go @@ -57,6 +57,39 @@ func compileWithRewritesTarget(t *testing.T, src string, rewrites map[string]str return ret.String() } +func TestClosureEnvDirectiveFallbackWithoutSyntaxPreload(t *testing.T) { + const src = `package fallback +//llgo:env +func withEnv() {} +func plain() {} +` + fset := token.NewFileSet() + file, err := parser.ParseFile(fset, "fallback.go", src, parser.ParseComments) + if err != nil { + t.Fatal(err) + } + importer := gpackages.NewImporter(fset) + pkg, _, err := ssautil.BuildPackage(&types.Config{Importer: importer}, fset, + types.NewPackage("fallback", "fallback"), []*ast.File{file}, ssa.SanityCheckFunctions) + if err != nil { + t.Fatal(err) + } + prog := ssatest.NewProgramEx(t, nil, importer) + ctx := &context{prog: prog, goProg: pkg.Prog} + for _, test := range []struct { + name string + want bool + }{ + {"withEnv", true}, + {"plain", false}, + } { + fn := pkg.Func(test.name) + if got := ctx.hasClosureEnvDirective(pkg.Pkg, fn); got != test.want { + t.Fatalf("hasClosureEnvDirective(%s) = %v, want %v", test.name, got, test.want) + } + } +} + func TestClosureEnvIntrinsicRequiresEnvBearingEntry(t *testing.T) { valid := `package closureenv diff --git a/ssa/closure_env_test.go b/ssa/closure_env_test.go index 7f00042419..9394ab5c73 100644 --- a/ssa/closure_env_test.go +++ b/ssa/closure_env_test.go @@ -12,6 +12,38 @@ import ( "github.com/xgo-dev/llvm" ) +func TestClosureEnvDirectiveCacheUsesSourceIdentity(t *testing.T) { + prog := NewProgram(nil) + defer prog.Dispose() + fset := token.NewFileSet() + otherFset := token.NewFileSet() + const ( + name = "example.com/p.entry" + pos = token.Pos(7) + ) + prog.SetClosureEnvDirective(fset, name, pos, true) + if enabled, ok := prog.ClosureEnvDirective(fset, name, pos); !ok || !enabled { + t.Fatalf("ClosureEnvDirective() = (%v, %v), want (true, true)", enabled, ok) + } + for _, key := range []struct { + fset *token.FileSet + name string + pos token.Pos + }{ + {otherFset, name, pos}, + {fset, "example.com/p.alias", pos}, + {fset, name, pos + 1}, + } { + if _, ok := prog.ClosureEnvDirective(key.fset, key.name, key.pos); ok { + t.Fatalf("distinct source declaration (%p, %q, %d) shared cached directives", key.fset, key.name, key.pos) + } + } + prog.SetClosureEnvDirective(fset, name, pos, false) + if enabled, ok := prog.ClosureEnvDirective(fset, name, pos); !ok || enabled { + t.Fatalf("updated ClosureEnvDirective() = (%v, %v), want (false, true)", enabled, ok) + } +} + func TestClosureEnvABIForTarget(t *testing.T) { tests := []struct { triple string diff --git a/ssa/package.go b/ssa/package.go index cc5810ce63..bf91a649cd 100644 --- a/ssa/package.go +++ b/ssa/package.go @@ -221,12 +221,13 @@ type aProgram struct { printfTy *types.Signature - paramObjPtr_ *types.Var - linknameMu sync.RWMutex - linkname map[string]string // pkgPath.nameInPkg => linkname - localities *localityInfos - noInterface map[string]none // pkgPath.T.method or pkgPath.(*T).method - abiSymbol map[string]*AbiSymbol // abi symbol name => AbiSymbol + paramObjPtr_ *types.Var + linknameMu sync.RWMutex + linkname map[string]string // pkgPath.nameInPkg => linkname + closureEnvDirectives sync.Map // closureEnvDirectiveKey => bool + localities *localityInfos + noInterface map[string]none // pkgPath.T.method or pkgPath.(*T).method + abiSymbol map[string]*AbiSymbol // abi symbol name => AbiSymbol ptrSize int @@ -425,6 +426,31 @@ func (p Program) Linkname(name string) (link string, ok bool) { return } +type closureEnvDirectiveKey struct { + fset *token.FileSet + name string + pos token.Pos +} + +// SetClosureEnvDirective records whether a source function declaration has the +// llgo:env directive. name and pos identify the source declaration rather +// than its resolved linker symbol, so aliases retain independent ABI metadata. +func (p Program) SetClosureEnvDirective(fset *token.FileSet, name string, pos token.Pos, enabled bool) { + key := closureEnvDirectiveKey{fset: fset, name: name, pos: pos} + p.closureEnvDirectives.Store(key, enabled) +} + +// ClosureEnvDirective reports the cached llgo:env state for a source +// function declaration. ok is false when that declaration was not scanned. +func (p Program) ClosureEnvDirective(fset *token.FileSet, name string, pos token.Pos) (enabled, ok bool) { + key := closureEnvDirectiveKey{fset: fset, name: name, pos: pos} + value, ok := p.closureEnvDirectives.Load(key) + if ok { + enabled = value.(bool) + } + return enabled, ok +} + func (p Program) runtime() *types.Package { if p.rt == nil { p.rt = p.rtget() From ea6708beaeec27b72a6ddedf2ce3964ed00da105 Mon Sep 17 00:00:00 2001 From: Li Jie Date: Sun, 2 Aug 2026 06:41:04 +0800 Subject: [PATCH 18/73] cl: make syntax scan the sole closure env extractor --- cl/compile.go | 31 +++++++------------------------ cl/import.go | 4 ++-- cl/import_coverage_test.go | 8 ++++---- cl/rewrite_internal_test.go | 33 --------------------------------- ssa/closure_env_test.go | 12 ++++-------- ssa/package.go | 21 +++++++++------------ 6 files changed, 26 insertions(+), 83 deletions(-) diff --git a/cl/compile.go b/cl/compile.go index d8496c8bca..d15422e878 100644 --- a/cl/compile.go +++ b/cl/compile.go @@ -32,7 +32,6 @@ import ( "github.com/goplus/llgo/cl/blocks" "github.com/goplus/llgo/cl/ssawrap" - "github.com/goplus/llgo/internal/directive" "github.com/goplus/llgo/internal/goembed" "github.com/goplus/llgo/internal/typepatch" "golang.org/x/tools/go/ssa" @@ -618,7 +617,13 @@ func (p *context) compileFuncDecl(pkg llssa.Package, f *ssa.Function) (llssa.Fun fn := pkg.FuncOf(name) hasFreeVars := len(f.FreeVars) > 0 elideFreeVarEnv := p.canElideZeroSizedClosureEnv(f) - hasExplicitEnv := p.hasClosureEnvDirective(pkgTypes, f) + hasExplicitEnv := false + // ParsePkgSyntax is the sole //llgo:env extractor. Lowering only consumes + // its source-declaration cache; imported env entries use NewEnvFunc. + if decl, ok := f.Syntax().(*ast.FuncDecl); ok { + fullName, _ := astFuncName(llssa.PathOf(pkgTypes), decl) + hasExplicitEnv = p.prog.HasClosureEnvDirective(p.goProg.Fset, fullName, decl.Pos()) + } hasCtx := hasFreeVars && !elideFreeVarEnv || hasExplicitEnv var ctx *types.Var if elideFreeVarEnv { @@ -758,28 +763,6 @@ func (p *context) compileFuncDecl(pkg llssa.Package, f *ssa.Function) (llssa.Fun return fn, nil, goFunc } -// hasClosureEnvDirective is intentionally source-only. //llgo:env may mark -// only internal bodies emitted in their defining package; external env-bearing -// declarations must be reconstructed explicitly with llssa.NewEnvFunc. -func (p *context) hasClosureEnvDirective(pkg *types.Package, f *ssa.Function) bool { - decl, _ := f.Syntax().(*ast.FuncDecl) - if decl == nil { - return false - } - fullName, _ := astFuncName(llssa.PathOf(pkg), decl) - if enabled, ok := p.prog.ClosureEnvDirective(p.goProg.Fset, fullName, decl.Pos()); ok { - return enabled - } - // Keep custom compilation paths that did not preload this declaration - // source-compatible. Normal builds consume the ParsePkgSyntax cache above. - for _, parsed := range directive.ParseGroup(decl.Doc) { - if parsed.Name == "llgo:env" { - return true - } - } - return false -} - // funcInfoDisplayName normalizes anonymous functions to gc's pkg.fn.funcN // reporting convention (our linker symbols use $N). Linker symbols are not // affected. diff --git a/cl/import.go b/cl/import.go index 2a1459e16d..728d162049 100644 --- a/cl/import.go +++ b/cl/import.go @@ -300,8 +300,8 @@ func collectDeclarationDirectives(prog llssa.Program, fset *token.FileSet, doc * } } } - if funcPos.IsValid() { - prog.SetClosureEnvDirective(fset, fullName, funcPos, hasClosureEnv) + if hasClosureEnv { + prog.SetClosureEnvDirective(fset, fullName, funcPos) } } diff --git a/cl/import_coverage_test.go b/cl/import_coverage_test.go index e7a650f808..ce11dbf1b8 100644 --- a/cl/import_coverage_test.go +++ b/cl/import_coverage_test.go @@ -286,12 +286,12 @@ func plain() {} for _, node := range file.Decls { decl := node.(*ast.FuncDecl) fullName, _ := astFuncName(pkg.Path(), decl) - got, ok := prog.ClosureEnvDirective(fset, fullName, decl.Pos()) - if !ok || got != want[decl.Name.Name] { - t.Fatalf("ClosureEnvDirective(%s) = (%v, %v), want (%v, true)", decl.Name.Name, got, ok, want[decl.Name.Name]) + got := prog.HasClosureEnvDirective(fset, fullName, decl.Pos()) + if got != want[decl.Name.Name] { + t.Fatalf("HasClosureEnvDirective(%s) = %v, want %v", decl.Name.Name, got, want[decl.Name.Name]) } } - if _, ok := prog.ClosureEnvDirective(fset, "example.com/p.missing", token.NoPos); ok { + if prog.HasClosureEnvDirective(fset, "example.com/p.missing", token.NoPos) { t.Fatal("missing declaration unexpectedly has cached directives") } } diff --git a/cl/rewrite_internal_test.go b/cl/rewrite_internal_test.go index a825fab95f..235de50269 100644 --- a/cl/rewrite_internal_test.go +++ b/cl/rewrite_internal_test.go @@ -57,39 +57,6 @@ func compileWithRewritesTarget(t *testing.T, src string, rewrites map[string]str return ret.String() } -func TestClosureEnvDirectiveFallbackWithoutSyntaxPreload(t *testing.T) { - const src = `package fallback -//llgo:env -func withEnv() {} -func plain() {} -` - fset := token.NewFileSet() - file, err := parser.ParseFile(fset, "fallback.go", src, parser.ParseComments) - if err != nil { - t.Fatal(err) - } - importer := gpackages.NewImporter(fset) - pkg, _, err := ssautil.BuildPackage(&types.Config{Importer: importer}, fset, - types.NewPackage("fallback", "fallback"), []*ast.File{file}, ssa.SanityCheckFunctions) - if err != nil { - t.Fatal(err) - } - prog := ssatest.NewProgramEx(t, nil, importer) - ctx := &context{prog: prog, goProg: pkg.Prog} - for _, test := range []struct { - name string - want bool - }{ - {"withEnv", true}, - {"plain", false}, - } { - fn := pkg.Func(test.name) - if got := ctx.hasClosureEnvDirective(pkg.Pkg, fn); got != test.want { - t.Fatalf("hasClosureEnvDirective(%s) = %v, want %v", test.name, got, test.want) - } - } -} - func TestClosureEnvIntrinsicRequiresEnvBearingEntry(t *testing.T) { valid := `package closureenv diff --git a/ssa/closure_env_test.go b/ssa/closure_env_test.go index 9394ab5c73..299fd83061 100644 --- a/ssa/closure_env_test.go +++ b/ssa/closure_env_test.go @@ -21,9 +21,9 @@ func TestClosureEnvDirectiveCacheUsesSourceIdentity(t *testing.T) { name = "example.com/p.entry" pos = token.Pos(7) ) - prog.SetClosureEnvDirective(fset, name, pos, true) - if enabled, ok := prog.ClosureEnvDirective(fset, name, pos); !ok || !enabled { - t.Fatalf("ClosureEnvDirective() = (%v, %v), want (true, true)", enabled, ok) + prog.SetClosureEnvDirective(fset, name, pos) + if !prog.HasClosureEnvDirective(fset, name, pos) { + t.Fatal("HasClosureEnvDirective() = false, want true") } for _, key := range []struct { fset *token.FileSet @@ -34,14 +34,10 @@ func TestClosureEnvDirectiveCacheUsesSourceIdentity(t *testing.T) { {fset, "example.com/p.alias", pos}, {fset, name, pos + 1}, } { - if _, ok := prog.ClosureEnvDirective(key.fset, key.name, key.pos); ok { + if prog.HasClosureEnvDirective(key.fset, key.name, key.pos) { t.Fatalf("distinct source declaration (%p, %q, %d) shared cached directives", key.fset, key.name, key.pos) } } - prog.SetClosureEnvDirective(fset, name, pos, false) - if enabled, ok := prog.ClosureEnvDirective(fset, name, pos); !ok || enabled { - t.Fatalf("updated ClosureEnvDirective() = (%v, %v), want (false, true)", enabled, ok) - } } func TestClosureEnvABIForTarget(t *testing.T) { diff --git a/ssa/package.go b/ssa/package.go index bf91a649cd..498bbaf942 100644 --- a/ssa/package.go +++ b/ssa/package.go @@ -224,7 +224,7 @@ type aProgram struct { paramObjPtr_ *types.Var linknameMu sync.RWMutex linkname map[string]string // pkgPath.nameInPkg => linkname - closureEnvDirectives sync.Map // closureEnvDirectiveKey => bool + closureEnvDirectives sync.Map // closureEnvDirectiveKey => none localities *localityInfos noInterface map[string]none // pkgPath.T.method or pkgPath.(*T).method abiSymbol map[string]*AbiSymbol // abi symbol name => AbiSymbol @@ -432,23 +432,20 @@ type closureEnvDirectiveKey struct { pos token.Pos } -// SetClosureEnvDirective records whether a source function declaration has the +// SetClosureEnvDirective records that a source function declaration has the // llgo:env directive. name and pos identify the source declaration rather // than its resolved linker symbol, so aliases retain independent ABI metadata. -func (p Program) SetClosureEnvDirective(fset *token.FileSet, name string, pos token.Pos, enabled bool) { +func (p Program) SetClosureEnvDirective(fset *token.FileSet, name string, pos token.Pos) { key := closureEnvDirectiveKey{fset: fset, name: name, pos: pos} - p.closureEnvDirectives.Store(key, enabled) + p.closureEnvDirectives.Store(key, none{}) } -// ClosureEnvDirective reports the cached llgo:env state for a source -// function declaration. ok is false when that declaration was not scanned. -func (p Program) ClosureEnvDirective(fset *token.FileSet, name string, pos token.Pos) (enabled, ok bool) { +// HasClosureEnvDirective reports whether a source function declaration has the +// cached llgo:env directive. +func (p Program) HasClosureEnvDirective(fset *token.FileSet, name string, pos token.Pos) bool { key := closureEnvDirectiveKey{fset: fset, name: name, pos: pos} - value, ok := p.closureEnvDirectives.Load(key) - if ok { - enabled = value.(bool) - } - return enabled, ok + _, ok := p.closureEnvDirectives.Load(key) + return ok } func (p Program) runtime() *types.Package { From 3fcdbc8769c262fbd143096a37e1c936c42dd8b2 Mon Sep 17 00:00:00 2001 From: Li Jie Date: Sun, 2 Aug 2026 07:29:25 +0800 Subject: [PATCH 19/73] pcln: finalize function-centric metadata model --- cl/_testgo/deferclosure/in.go | 2 +- doc/closure.md | 3 ++ doc/design/pclntab-linkphase.md | 34 +++++++++++-------- doc/design/pclntab-packaging.md | 7 ++-- doc/size-report.md | 6 ++-- internal/build/build.go | 2 +- internal/build/funcinfo_table.go | 3 ++ internal/build/funcinfo_table_test.go | 14 ++++++++ .../build/pclntab_modes_integration_test.go | 14 ++++---- internal/build/resolver.go | 8 ----- internal/build/size_report_test.go | 4 +-- internal/pclnmap/pclnmap.go | 6 ++-- internal/pclnmap/pclnmap_test.go | 13 +++++++ internal/pclnpost/binary.go | 2 ++ ssa/funcinfo.go | 2 +- 15 files changed, 77 insertions(+), 43 deletions(-) diff --git a/cl/_testgo/deferclosure/in.go b/cl/_testgo/deferclosure/in.go index 1ae41c8a26..4428ece8d6 100644 --- a/cl/_testgo/deferclosure/in.go +++ b/cl/_testgo/deferclosure/in.go @@ -1,6 +1,6 @@ package main -// Test for covering the closureStub branches in ssa/package.go +// Test deferred closure and method-value lowering. // Type for holding a function type Handler struct { diff --git a/doc/closure.md b/doc/closure.md index 423b5eb5e9..3034b09183 100644 --- a/doc/closure.md +++ b/doc/closure.md @@ -31,6 +31,9 @@ This document records the phase-one design from - Function values point directly at their physical entries; closure calls do not add a generated adapter layer. C function values point directly at the C entry. +- PCLN metadata remains function-centric. A compiler-generated wrapper or + adapter, if one is needed for another purpose, is an ordinary function with + its own function record; closure environment transport is not part of PCLN. Native dynamic calls always use one hidden-env call edge, including when env is nil. An optimizer barrier keeps the indirect code pointer opaque: LLVM IR diff --git a/doc/design/pclntab-linkphase.md b/doc/design/pclntab-linkphase.md index 10363244cc..d426ad15bd 100644 --- a/doc/design/pclntab-linkphase.md +++ b/doc/design/pclntab-linkphase.md @@ -36,6 +36,15 @@ clang/lld and a plugin would need to be maintained per linker flavor (ld64.lld, ld.lld) and per LTO mode. Editing the linked artifact is linker-agnostic. +### Function identity contract + +PCLN is indexed by physical text functions, following Go's linker model. +Source functions and compiler-generated wrappers or adapters all contribute +ordinary function records and entry sites. The symbol names the physical +function; its display name may describe the corresponding Go operation. +Calling conventions, closure environments, and their transport mechanism are +not PCLN properties and must not introduce function-class-specific sections. + ### Data flow 1. **Parse** the linked binary's metadata sections (`debug/elf`, @@ -54,24 +63,19 @@ linker-agnostic. faithful port of `cmd/link`'s algorithm that has been sitting unwired since #2012. Delta overflow is a hard error here, mirroring Go's linker; if it ever fires, fall back to leaving the prebuilt table absent. -5. **Write back** into a reserved section: - - The main module already emits `__llgo_funcinfo_*` globals; add a - `__llgo_pclntab_prebuilt` global sized from the collected package data - (entry-record count is known at main-module emission time; LTO can only - shrink it after dedup) plus a header {magic, version, count, anchorOff}. - - The tool rewrites the section contents in place (same size or smaller; - unused tail is zeroed) and flips the header magic to "valid". +5. **Write back** into the entry-site section: + - The tool replaces the raw entry records in place with a versioned prebuilt + functab/findfunctab blob; unused tail bytes are zeroed. + - If the blob does not fit, the binary is left unchanged and the runtime + uses its first-use construction fallback. No other class of function is + used as overflow storage. ### ASLR -Stored PCs must survive load-time slide. Store **offsets relative to an -anchor symbol** (`__llgo_pclntab_anchor`, placed in the same section). At -startup the runtime computes `slide = &anchor_runtime - anchorOff_stored` -and adds it during lookup (one add on the hot path, same as Go's -`datap.text` bias). Note the entry-site records themselves are already -rebased by the loader (they hold absolute pointers with relocations); the -prebuilt table deliberately holds offsets so the tool does not need to -emit relocations. +Stored table entries are offsets from the first function PC. The header keeps +that base as a runtime address: Mach-O rewrites its slot into the dyld chained +fixup chain, while supported non-PIE ELF outputs already use their runtime +address. The lookup hot path therefore only adds the stored entry offset. ### Runtime integration diff --git a/doc/design/pclntab-packaging.md b/doc/design/pclntab-packaging.md index 8fea3325be..782c13e31a 100644 --- a/doc/design/pclntab-packaging.md +++ b/doc/design/pclntab-packaging.md @@ -169,6 +169,7 @@ the filesystem is never probed repeatedly. The initial implementation uses one bounded read, capped at 512 MiB, instead of `mmap`; read-only mapping remains a possible follow-up optimization. -The initial format is intentionally private to LLGo and versioned. It may grow -additional independently removable symbol classes after the PCLN path has -proved stable on ELF and Mach-O. +The format is intentionally private to LLGo and versioned. Its unit is a +physical function: compiler-generated wrappers and adapters use ordinary +function records, while calling conventions and closure environment transport +remain outside PCLN. diff --git a/doc/size-report.md b/doc/size-report.md index 2cb9799d49..451004ceea 100644 --- a/doc/size-report.md +++ b/doc/size-report.md @@ -28,9 +28,9 @@ document captures the parsing strategy and new aggregation controls. | `module`* | Default. Groups by `pkg.Module.Path` (or `pkg.PkgPath` if the module is nil). | Matching is performed by checking whether the demangled symbol name begins with -`pkg.PkgPath + "."`. Symbols that do not match any package and contain `llgo` are -bucketed into `llgo-stubs`; other unmatched entries keep their original owner -names so we can inspect them later. +`pkg.PkgPath + "."`. Unmatched entries keep the owner derived from their symbol +name so compiler-generated functions remain visible as ordinary functions +rather than being grouped by an implementation-specific category. Defaults: diff --git a/internal/build/build.go b/internal/build/build.go index c5c6676979..4e261c5c3f 100644 --- a/internal/build/build.go +++ b/internal/build/build.go @@ -2455,7 +2455,7 @@ func IsFuncInfoEnabled() bool { // IsFuncInfoSitesEnabled controls the body-embedded site records // independently of the funcinfo tables (LLGO_FUNCINFO_SITES=0 keeps the -// metadata but drops entry/stub/pc-line inline-asm sites). Useful for +// metadata but drops entry and PC-line inline-asm sites). Useful for // isolating codegen perturbation caused by the in-body asm anchors. func IsFuncInfoSitesEnabled() bool { return isEnvOn(llgoFuncInfoSites, true) diff --git a/internal/build/funcinfo_table.go b/internal/build/funcinfo_table.go index b8882d9ef6..754f610455 100644 --- a/internal/build/funcinfo_table.go +++ b/internal/build/funcinfo_table.go @@ -748,6 +748,9 @@ func emitFuncInfoEntrySites(ctx *context, pkg llssa.Package) { // linker has while building pclntab. The inline-asm fragment lives in a // section tied to the function body (SHF_LINK_ORDER on ELF; live_support // on Mach-O), so dead functions do not leave stale entry records behind. + // Compiler-generated wrappers and adapters participate through their own + // ordinary funcinfo record; this path never classifies functions by their + // lowering role or calling convention. // Runtime still sorts these final PCs before building the Go-style // findfunc bucket index, because LLVM IR generation does not know final // linked text order. diff --git a/internal/build/funcinfo_table_test.go b/internal/build/funcinfo_table_test.go index 638ac1140e..5677448837 100644 --- a/internal/build/funcinfo_table_test.go +++ b/internal/build/funcinfo_table_test.go @@ -100,9 +100,14 @@ func TestFuncInfoTableMaterializesEntrySites(t *testing.T) { prog := llssa.NewProgram(nil) src := prog.NewPackage("example.com/p", "example.com/p") src.EmitFuncInfo("example.com/p.live", "example.com/p.Live", "live.go", 17, 3) + // cl/ssawrap.MakeCallWrapper uses this suffix when an intrinsic is used as + // a function value. It is a physical function, not a separate PCLN class. + src.EmitFuncInfo("example.com/p.intrinsic$wrapper", "example.com/p.Live", "live.go", 17, 3) src.EmitFuncInfo("example.com/p.missing", "example.com/p.Missing", "missing.go", 19, 1) liveFn := src.NewFunc("example.com/p.live", llssa.NoArgsNoRet, llssa.InC) liveFn.MakeBody(1).Return() + intrinsicWrapper := src.NewFunc("example.com/p.intrinsic$wrapper", llssa.NoArgsNoRet, llssa.InC) + intrinsicWrapper.MakeBody(1).Return() otherFn := src.NewFunc("example.com/p.other", llssa.NoArgsNoRet, llssa.InC) otherFn.MakeBody(1).Return() ctx := &context{ @@ -130,6 +135,7 @@ func TestFuncInfoTableMaterializesEntrySites(t *testing.T) { } for _, bad := range []string{ `.quad \22example.com/p.live\22`, + `.quad \22example.com/p.intrinsic$wrapper\22`, `.quad \22example.com/p.other\22`, `.quad \22example.com/p.missing\22`, } { @@ -137,6 +143,14 @@ func TestFuncInfoTableMaterializesEntrySites(t *testing.T) { t.Fatalf("package entry site IR should not contain %q:\n%s", bad, srcIR) } } + if got := strings.Count(srcIR, ".pushsection llgo_funcinfo_entry"); got != 2 { + t.Fatalf("entry site count = %d, want one per physical function with funcinfo:\n%s", got, srcIR) + } + for _, symbol := range []string{"example.com/p.live", "example.com/p.intrinsic$wrapper"} { + if id := uint64Hex(funcInfoSymbolID(symbol)); !strings.Contains(srcIR, ".quad "+id) { + t.Fatalf("entry site IR missing physical function %q (id %s):\n%s", symbol, id, srcIR) + } + } records := collectFuncInfo([]Package{{LPkg: src}}) entry := genMainModule(ctx, llssa.PkgRuntime, &packages.Package{ diff --git a/internal/build/pclntab_modes_integration_test.go b/internal/build/pclntab_modes_integration_test.go index febe859c90..b7c3b6ae79 100644 --- a/internal/build/pclntab_modes_integration_test.go +++ b/internal/build/pclntab_modes_integration_test.go @@ -360,7 +360,7 @@ func TestPCLNModeNativeIntegration(t *testing.T) { {name: "wrong-ABI", mutate: mismatchPCLNIntegrationABI}, {name: "wrong-architecture", mutate: mismatchPCLNIntegrationArchitecture}, {name: "overlapping-sections", mutate: overlapPCLNIntegrationSections}, - {name: "misaligned-stub-section", mutate: misalignPCLNIntegrationStubSection}, + {name: "misaligned-pc-site-section", mutate: misalignPCLNIntegrationPCSiteSection}, {name: "unterminated-string-pool", mutate: unterminatePCLNIntegrationStringPool}, } for _, failure := range failures { @@ -782,14 +782,14 @@ func overlapPCLNIntegrationSections(t *testing.T, path string) { }) } -func misalignPCLNIntegrationStubSection(t *testing.T, path string) { +func misalignPCLNIntegrationPCSiteSection(t *testing.T, path string) { t.Helper() mutatePCLNIntegrationHeader(t, path, func(raw []byte) { - // v3 descriptor order: records, pclines, strings, string offsets, - // hash, symbol index, entries, stubs, pc sites. - stub := pclnIntegrationHeaderSections + 7*pclnIntegrationSectionSize - off := binary.LittleEndian.Uint64(raw[stub:]) - binary.LittleEndian.PutUint64(raw[stub:], off+1) + // v4 descriptor order: records, pclines, strings, string offsets, + // hash, symbol index, entries, pc sites. + pcSites := pclnIntegrationHeaderSections + 7*pclnIntegrationSectionSize + off := binary.LittleEndian.Uint64(raw[pcSites:]) + binary.LittleEndian.PutUint64(raw[pcSites:], off+1) }) } diff --git a/internal/build/resolver.go b/internal/build/resolver.go index 16de393720..96f5152a35 100644 --- a/internal/build/resolver.go +++ b/internal/build/resolver.go @@ -2,11 +2,6 @@ package build import "strings" -const ( - llgoStubsCategory = "llgo-stubs" - llgoPrefix = "llgo" -) - // nameResolver maps symbol names to aggregation buckets based on the requested level. type nameResolver struct { level string @@ -54,9 +49,6 @@ func (r *nameResolver) resolve(sym string) string { return mod } } - if strings.Contains(symbol, llgoPrefix) { - return llgoStubsCategory - } return base } diff --git a/internal/build/size_report_test.go b/internal/build/size_report_test.go index a47ad60370..085f7d401a 100644 --- a/internal/build/size_report_test.go +++ b/internal/build/size_report_test.go @@ -185,8 +185,8 @@ func TestNameResolver(t *testing.T) { if full != symbol { t.Fatalf("full level unexpected: %q", full) } - if got := newNameResolver("package", nil).resolve("_llgo_stub.foo"); got != "llgo-stubs" { - t.Fatalf("llgo default grouping failed: %q", got) + if got := newNameResolver("package", nil).resolve("_llgo_helper.foo"); got != "llgo_helper" { + t.Fatalf("unmatched symbol grouping failed: %q", got) } generic := "_slices.SortFunc[[]io/fs.DirEntry,io/fs.DirEntry]" if got := newNameResolver("module", nil).resolve(generic); got != "slices" { diff --git a/internal/pclnmap/pclnmap.go b/internal/pclnmap/pclnmap.go index e08672565a..7ff619571e 100644 --- a/internal/pclnmap/pclnmap.go +++ b/internal/pclnmap/pclnmap.go @@ -98,8 +98,10 @@ type Site struct { } // Data is the complete immutable payload needed by the external runtime -// loader. EntrySites have been normalized and LTO-deduplicated by the -// post-link analyzer. +// loader. EntrySites are physical function entries normalized and +// LTO-deduplicated by the post-link analyzer. Compiler-generated wrappers and +// adapters use ordinary function records and entry sites; calling conventions +// and closure environment transport are deliberately not represented here. type Data struct { GOOS string GOARCH string diff --git a/internal/pclnmap/pclnmap_test.go b/internal/pclnmap/pclnmap_test.go index c331b18403..5bb96a2be5 100644 --- a/internal/pclnmap/pclnmap_test.go +++ b/internal/pclnmap/pclnmap_test.go @@ -65,6 +65,19 @@ func TestEncodeParse(t *testing.T) { } } +func TestVersion4FunctionCentricDescriptorLayout(t *testing.T) { + if Version != 4 { + t.Fatalf("format version = %d, want 4", Version) + } + if descRecords != 0 || descPCLines != 1 || descStrings != 2 || + descStringOffsets != 3 || descHash != 4 || descSymbolIndex != 5 || + descEntrySites != 6 || descPCSites != 7 || descCount != 8 { + t.Fatalf("unexpected v4 descriptor layout: records=%d pclines=%d strings=%d offsets=%d hash=%d symbols=%d entries=%d pcsites=%d count=%d", + descRecords, descPCLines, descStrings, descStringOffsets, descHash, + descSymbolIndex, descEntrySites, descPCSites, descCount) + } +} + func TestEncodePreservesUint32StringIDs(t *testing.T) { data := sampleData(t) const ( diff --git a/internal/pclnpost/binary.go b/internal/pclnpost/binary.go index 310ae06791..36dd4e9091 100644 --- a/internal/pclnpost/binary.go +++ b/internal/pclnpost/binary.go @@ -348,6 +348,8 @@ func canonicalOwner(info *binaryInfo, name string, symbolID uint64) bool { // is canonical when the symbol that owns its anchor PC is the function the // symbolID names (id == fnv64(owner)). Everything else with a known owner is // an LTO inline copy: inlining duplicated the body-embedded record into a host +// function. A compiler-generated wrapper or adapter is therefore represented +// by its own funcinfo symbol and follows exactly the same path as any other // function. // Kept records are normalized to their owner's true entry address. Records // whose owner cannot be determined are dropped conservatively. diff --git a/ssa/funcinfo.go b/ssa/funcinfo.go index 25e792b6c3..f09f3bd3e8 100644 --- a/ssa/funcinfo.go +++ b/ssa/funcinfo.go @@ -38,7 +38,7 @@ func (p Program) FuncInfoMetadataEnabled() bool { } // EnableFuncInfoSites controls emission of the per-function site records -// (entry/stub/pc-line inline-asm fragments inside function bodies). They are +// (entry and PC-line inline-asm fragments inside function bodies). They are // gated separately from the funcinfo metadata tables because the // body-embedded anchors shift instruction/scope layout enough to confuse // debuggers; debug builds keep the tables (FuncForPC name/FileLine fidelity From fbce776de4c5247ace825b0a6213d014bd409cd7 Mon Sep 17 00:00:00 2001 From: Li Jie Date: Sun, 2 Aug 2026 18:31:39 +0800 Subject: [PATCH 20/73] reflect: inline MakeFunc implementation --- runtime/internal/lib/reflect/makefunc.go | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/runtime/internal/lib/reflect/makefunc.go b/runtime/internal/lib/reflect/makefunc.go index 77f1d667e5..09fd3d0f8d 100644 --- a/runtime/internal/lib/reflect/makefunc.go +++ b/runtime/internal/lib/reflect/makefunc.go @@ -39,10 +39,6 @@ type funcData struct { } func MakeFunc(typ Type, fn func(args []Value) (results []Value)) Value { - return makeFunc(typ, fn) -} - -func makeFunc(typ Type, fn func(args []Value) (results []Value)) Value { if typ.Kind() != Func { panic("reflect: call of MakeFunc with non-Func type") } @@ -279,7 +275,7 @@ func makeMethodValue(op string, v Value) Value { if method.Type().(*rtype).t.FuncType().Variadic() { callOp = "CallSlice" } - ret := makeFunc(v.Type(), func(args []Value) []Value { + ret := MakeFunc(v.Type(), func(args []Value) []Value { return method.call(callOp, args) }) // Cause panic if method is not appropriate. From 5bdaccc17548d8f49bc6a5a35f93f44eb4ce48b0 Mon Sep 17 00:00:00 2001 From: Li Jie Date: Sun, 2 Aug 2026 16:19:21 +0800 Subject: [PATCH 21/73] runtime/ffi: call libffi Go ABI directly when compatible --- doc/closure.md | 11 +++-- runtime/internal/clite/ffi/_wrap/libffi.c | 56 +++++++++++------------ 2 files changed, 32 insertions(+), 35 deletions(-) diff --git a/doc/closure.md b/doc/closure.md index 3034b09183..fa69b21f7c 100644 --- a/doc/closure.md +++ b/doc/closure.md @@ -80,9 +80,10 @@ returns or lowers its C ABI. - explicit env target: add the env type/value only when `env != nil`; otherwise use the semantic signature. This is the only `env != nil` decision in the reflection/FFI path; -- native hidden env target: `ffi.CallWithEnv` first uses `ffi_call_go` when the - linked libffi exports it and its Go static-chain register matches LLGo's - `nest` ABI. Otherwise stock `ffi_call` marshals the semantic arguments into a +- native hidden env target: when libffi's headers expose `FFI_GO_CLOSURES` and + its Go static-chain register matches LLGo's `nest` ABI, `ffi.CallWithEnv` + compiles to a direct `ffi_call_go` call without the TLS trampoline. Other + native targets use stock `ffi_call` to marshal the semantic arguments into a small runtime final-hop trampoline. The trampoline preserves those arguments, obtains `{fn, env}` from thread-local call state, installs the target's `nest` or `swiftself` register (including nil), and enters fn with the original @@ -92,8 +93,8 @@ returns or lowers its C ABI. Although libffi's C implementation of `ffi_call_go` is a thin wrapper, it calls an architecture-private `ffi_call_int(..., closure)` and matching assembly; it cannot be reproduced outside libffi by wrapping public `ffi_call` alone. The -optional direct path plus public-API fallback requires neither a patched libffi -nor rebuilding it. AArch64 libffi's Go ABI writes X18, so Apple/Android +compile-time direct path and the public-API fallback require neither a patched +libffi nor rebuilding it. AArch64 libffi's Go ABI writes X18, so Apple/Android `swiftself`/X20 deliberately uses the fallback. `reflect.MakeFunc` remains a normal libffi C closure: its funcval has `env == nil`, while libffi userdata owns the callback state separately. diff --git a/runtime/internal/clite/ffi/_wrap/libffi.c b/runtime/internal/clite/ffi/_wrap/libffi.c index 9960809be1..5be4d054f6 100644 --- a/runtime/internal/clite/ffi/_wrap/libffi.c +++ b/runtime/internal/clite/ffi/_wrap/libffi.c @@ -4,21 +4,36 @@ void *llgo_ffi_closure_alloc(void **code) { return ffi_closure_alloc(sizeof(ffi_closure), code); } -/* - * ffi_call does not expose a portable static-chain argument. Keep the real +/* Use libffi's Go-ABI entry without compiling an intermediate trampoline when + * both its headers and target ABI provide LLGo's nest transport. Keep the + * public-ffi_call trampoline for targets whose static-chain register does not + * match LLGo's hidden-env register. */ +#if !defined(_WIN32) && !defined(__APPLE__) && \ + defined(FFI_GO_CLOSURES) && \ + (defined(__x86_64__) || defined(__i386__) || defined(__riscv) || \ + defined(__riscv__) || \ + (defined(__aarch64__) && !defined(__ANDROID__))) +#define LLGO_FFI_USE_CALL_GO 1 +#endif + +#if defined(LLGO_FFI_USE_CALL_GO) + +void llgo_ffi_call_with_env(ffi_cif *cif, void (*fn)(void), void *rvalue, + void **avalue, void *env) { + ffi_call_go(cif, fn, rvalue, avalue, env); +} + +#elif !defined(_WIN32) && \ + (defined(__x86_64__) || defined(__i386__) || defined(__aarch64__) || \ + defined(__arm__) || defined(__riscv) || defined(__riscv__)) + +/* ffi_call does not expose a portable static-chain argument. Keep the real * target and environment in a per-thread context while it marshals arguments. * The trampoline is its final target: it saves the already-marshalled argument * registers, obtains that context, and installs LLVM's nest/swiftself register * for the real entry. A callee-saved swiftself register is restored afterward; - * caller-saved transports can tail-jump. No generated function needs an adapter. - * - * Use libffi's optional Go-ABI entry when it is exported and its static-chain - * register matches LLGo's nest transport. Common system libffi builds omit - * that symbol, so the public-ffi_call trampoline remains the fallback. - */ -#if !defined(_WIN32) && \ - (defined(__x86_64__) || defined(__i386__) || defined(__aarch64__) || \ - defined(__arm__) || defined(__riscv) || defined(__riscv__)) + * caller-saved transports can tail-jump. No generated function needs an + * adapter. */ struct llgo_ffi_call_context { void (*target)(void); @@ -39,19 +54,6 @@ llgo_ffi_current_call(void) { return &llgo_ffi_call_current; } -/* libffi implements ffi_call_go by passing this final argument through its - * private argument marshaller into the target's static-chain register. Apple - * headers may declare a symbol that the dylib omits, so use the public path - * there; reference the optional symbol weakly on other matching targets. */ -#if !defined(__APPLE__) && \ - (defined(__x86_64__) || defined(__i386__) || defined(__riscv) || \ - defined(__riscv__) || \ - (defined(__aarch64__) && !defined(__ANDROID__))) -#define LLGO_FFI_GO_ABI_MATCHES 1 -extern void ffi_call_go(ffi_cif *, void (*)(void), void *, void **, void *) - __attribute__((weak)); -#endif - #if defined(__APPLE__) #define LLGO_ASM_CSYM(name) "_" #name #else @@ -334,12 +336,6 @@ __attribute__((naked)) static void llgo_ffi_env_trampoline(void) { void llgo_ffi_call_with_env(ffi_cif *cif, void (*fn)(void), void *rvalue, void **avalue, void *env) { -#if defined(LLGO_FFI_GO_ABI_MATCHES) - if (ffi_call_go != NULL) { - ffi_call_go(cif, fn, rvalue, avalue, env); - return; - } -#endif struct llgo_ffi_call_context previous = llgo_ffi_call_current; llgo_ffi_call_current.target = fn; llgo_ffi_call_current.env = env; From dc319bb6c82294f007a221aa452b76d148f5a2ad Mon Sep 17 00:00:00 2001 From: Li Jie Date: Sun, 2 Aug 2026 17:03:26 +0800 Subject: [PATCH 22/73] runtime/ffi: remove redundant env trampolines --- doc/closure.md | 24 +- runtime/internal/clite/ffi/_wrap/libffi.c | 333 +++++----------------- 2 files changed, 84 insertions(+), 273 deletions(-) diff --git a/doc/closure.md b/doc/closure.md index fa69b21f7c..820a026ad1 100644 --- a/doc/closure.md +++ b/doc/closure.md @@ -80,24 +80,24 @@ returns or lowers its C ABI. - explicit env target: add the env type/value only when `env != nil`; otherwise use the semantic signature. This is the only `env != nil` decision in the reflection/FFI path; -- native hidden env target: when libffi's headers expose `FFI_GO_CLOSURES` and - its Go static-chain register matches LLGo's `nest` ABI, `ffi.CallWithEnv` - compiles to a direct `ffi_call_go` call without the TLS trampoline. Other - native targets use stock `ffi_call` to marshal the semantic arguments into a - small runtime final-hop trampoline. The trampoline preserves those arguments, - obtains `{fn, env}` from thread-local call state, installs the target's - `nest` or `swiftself` register (including nil), and enters fn with the original - stack pointer. Transports in caller-saved registers tail-jump; ARM `swiftself` - returns through a continuation that restores its callee-saved self register. +- native hidden env target: x86, RISC-V, and non-Apple/non-Android AArch64 call + stock libffi's `ffi_call_go` directly because its static-chain register is + LLGo's `nest` register. ARM also uses `ffi_call_go`; a short final-hop bridge + moves libffi's IP/R12 context to `swiftself`/R10 without saving argument + registers or using TLS. These targets require the upstream + `FFI_GO_CLOSURES` support enabled by their standard libffi configurations. +- Apple/Android AArch64 libffi disables its X18 Go ABI. Those targets alone use + stock `ffi_call` plus the TLS final-hop trampoline to install + `swiftself`/X20 while preserving the already-marshalled arguments. Although libffi's C implementation of `ffi_call_go` is a thin wrapper, it calls an architecture-private `ffi_call_int(..., closure)` and matching assembly; it cannot be reproduced outside libffi by wrapping public `ffi_call` alone. The compile-time direct path and the public-API fallback require neither a patched libffi nor rebuilding it. AArch64 libffi's Go ABI writes X18, so Apple/Android -`swiftself`/X20 deliberately uses the fallback. `reflect.MakeFunc` remains a -normal libffi C closure: its funcval has `env == nil`, while libffi userdata owns -the callback state separately. +`swiftself`/X20 deliberately uses the public-call fallback. `reflect.MakeFunc` +remains a normal libffi C closure: its funcval has `env == nil`, while libffi +userdata owns the callback state separately. ## Scope diff --git a/runtime/internal/clite/ffi/_wrap/libffi.c b/runtime/internal/clite/ffi/_wrap/libffi.c index 5be4d054f6..93005c4c7a 100644 --- a/runtime/internal/clite/ffi/_wrap/libffi.c +++ b/runtime/internal/clite/ffi/_wrap/libffi.c @@ -4,36 +4,38 @@ void *llgo_ffi_closure_alloc(void **code) { return ffi_closure_alloc(sizeof(ffi_closure), code); } -/* Use libffi's Go-ABI entry without compiling an intermediate trampoline when - * both its headers and target ABI provide LLGo's nest transport. Keep the - * public-ffi_call trampoline for targets whose static-chain register does not - * match LLGo's hidden-env register. */ -#if !defined(_WIN32) && !defined(__APPLE__) && \ - defined(FFI_GO_CLOSURES) && \ - (defined(__x86_64__) || defined(__i386__) || defined(__riscv) || \ - defined(__riscv__) || \ - (defined(__aarch64__) && !defined(__ANDROID__))) -#define LLGO_FFI_USE_CALL_GO 1 +/* + * Use libffi's Go ABI directly when its static-chain register is LLGo's nest + * register. ARM needs only a final register bridge from libffi's IP/R12 to + * swiftself/R10. AArch64 Apple and Android reserve X18, so their stock libffi + * has no Go ABI and still needs the public-ffi_call trampoline. + */ +#if !defined(_WIN32) && \ + (defined(__x86_64__) || defined(__i386__) || defined(__riscv) || \ + defined(__riscv__) || \ + (defined(__aarch64__) && !defined(__APPLE__) && !defined(__ANDROID__))) +#define LLGO_FFI_CALL_GO_DIRECT 1 +#elif !defined(_WIN32) && defined(__arm__) +#define LLGO_FFI_CALL_GO_ARM_BRIDGE 1 +#elif !defined(_WIN32) && defined(__aarch64__) && \ + (defined(__APPLE__) || defined(__ANDROID__)) +#define LLGO_FFI_CALL_PUBLIC_TRAMPOLINE 1 #endif -#if defined(LLGO_FFI_USE_CALL_GO) +#if (defined(LLGO_FFI_CALL_GO_DIRECT) || \ + defined(LLGO_FFI_CALL_GO_ARM_BRIDGE)) && \ + !defined(FFI_GO_CLOSURES) +#error "LLGo hidden closure environments require libffi Go closures on this target" +#endif + +#if defined(LLGO_FFI_CALL_GO_DIRECT) void llgo_ffi_call_with_env(ffi_cif *cif, void (*fn)(void), void *rvalue, void **avalue, void *env) { ffi_call_go(cif, fn, rvalue, avalue, env); } -#elif !defined(_WIN32) && \ - (defined(__x86_64__) || defined(__i386__) || defined(__aarch64__) || \ - defined(__arm__) || defined(__riscv) || defined(__riscv__)) - -/* ffi_call does not expose a portable static-chain argument. Keep the real - * target and environment in a per-thread context while it marshals arguments. - * The trampoline is its final target: it saves the already-marshalled argument - * registers, obtains that context, and installs LLVM's nest/swiftself register - * for the real entry. A callee-saved swiftself register is restored afterward; - * caller-saved transports can tail-jump. No generated function needs an - * adapter. */ +#elif defined(LLGO_FFI_CALL_GO_ARM_BRIDGE) struct llgo_ffi_call_context { void (*target)(void); @@ -43,9 +45,52 @@ struct llgo_ffi_call_context { void *saved_return; }; -/* Targets entered through this context must return normally. A non-local exit - * across ffi_call would skip both the trampoline register restore and the TLS - * restore in llgo_ffi_call_with_env. */ +/* + * ffi_call_go enters this function with the context in IP/R12 and all real + * arguments already marshalled. Preserve the callee-saved registers used by + * the continuation, install swiftself/R10, and enter the target without + * changing SP or any argument register. + */ +__attribute__((naked)) static void llgo_ffi_env_trampoline(void) { + __asm__ volatile( + "str r4, [r12, #8]\n\t" + "str r10, [r12, #12]\n\t" + "str lr, [r12, #16]\n\t" + "mov r4, r12\n\t" + "ldr r10, [r12, #4]\n\t" + "ldr r12, [r12, #0]\n\t" + "blx r12\n\t" + "ldr r12, [r4, #8]\n\t" + "ldr r10, [r4, #12]\n\t" + "ldr lr, [r4, #16]\n\t" + "mov r4, r12\n\t" + "bx lr"); +} + +void llgo_ffi_call_with_env(ffi_cif *cif, void (*fn)(void), void *rvalue, + void **avalue, void *env) { + struct llgo_ffi_call_context call = { + .target = fn, + .env = env, + }; + ffi_call_go(cif, llgo_ffi_env_trampoline, rvalue, avalue, &call); +} + +#elif defined(LLGO_FFI_CALL_PUBLIC_TRAMPOLINE) + +/* + * Public ffi_call cannot transport swiftself. Keep the real target and env in + * per-thread state while libffi marshals the arguments. Its final target saves + * those arguments, obtains the state, installs X20, and enters the real entry + * with the original SP. + */ +struct llgo_ffi_call_context { + void (*target)(void); + void *env; + void *saved_callee; + void *saved_self; + void *saved_return; +}; static _Thread_local struct llgo_ffi_call_context llgo_ffi_call_current; @@ -60,62 +105,6 @@ llgo_ffi_current_call(void) { #define LLGO_ASM_CSYM(name) #name #endif -#if defined(__x86_64__) - -__attribute__((naked)) static void llgo_ffi_env_trampoline(void) { - __asm__ volatile( - "subq $200, %rsp\n\t" - "movq %rdi, 0(%rsp)\n\t" - "movq %rsi, 8(%rsp)\n\t" - "movq %rdx, 16(%rsp)\n\t" - "movq %rcx, 24(%rsp)\n\t" - "movq %r8, 32(%rsp)\n\t" - "movq %r9, 40(%rsp)\n\t" - "movq %rax, 48(%rsp)\n\t" - "movdqu %xmm0, 64(%rsp)\n\t" - "movdqu %xmm1, 80(%rsp)\n\t" - "movdqu %xmm2, 96(%rsp)\n\t" - "movdqu %xmm3, 112(%rsp)\n\t" - "movdqu %xmm4, 128(%rsp)\n\t" - "movdqu %xmm5, 144(%rsp)\n\t" - "movdqu %xmm6, 160(%rsp)\n\t" - "movdqu %xmm7, 176(%rsp)\n\t" - "callq " LLGO_ASM_CSYM(llgo_ffi_current_call) "\n\t" - "movq 0(%rax), %r11\n\t" - "movq 8(%rax), %r10\n\t" - "movdqu 64(%rsp), %xmm0\n\t" - "movdqu 80(%rsp), %xmm1\n\t" - "movdqu 96(%rsp), %xmm2\n\t" - "movdqu 112(%rsp), %xmm3\n\t" - "movdqu 128(%rsp), %xmm4\n\t" - "movdqu 144(%rsp), %xmm5\n\t" - "movdqu 160(%rsp), %xmm6\n\t" - "movdqu 176(%rsp), %xmm7\n\t" - "movq 0(%rsp), %rdi\n\t" - "movq 8(%rsp), %rsi\n\t" - "movq 16(%rsp), %rdx\n\t" - "movq 24(%rsp), %rcx\n\t" - "movq 32(%rsp), %r8\n\t" - "movq 40(%rsp), %r9\n\t" - "movq 48(%rsp), %rax\n\t" - "addq $200, %rsp\n\t" - "jmpq *%r11"); -} - -#elif defined(__i386__) - -__attribute__((naked)) static void llgo_ffi_env_trampoline(void) { - __asm__ volatile( - "subl $12, %esp\n\t" - "calll " LLGO_ASM_CSYM(llgo_ffi_current_call) "\n\t" - "movl 0(%eax), %edx\n\t" - "movl 4(%eax), %ecx\n\t" - "addl $12, %esp\n\t" - "jmpl *%edx"); -} - -#elif defined(__aarch64__) - __attribute__((naked)) static void llgo_ffi_env_trampoline(void) { __asm__ volatile( "sub sp, sp, #224\n\t" @@ -132,20 +121,12 @@ __attribute__((naked)) static void llgo_ffi_env_trampoline(void) { "bl " LLGO_ASM_CSYM(llgo_ffi_current_call) "\n\t" "mov x16, x0\n\t" "ldr x17, [x16, #0]\n\t" -#if defined(__APPLE__) || defined(__ANDROID__) - /* X20 is callee-saved. Keep the TLS context in X19 across the real - * target so it can restore both registers after the target returns. - * The real target is entered with the original SP, preserving stack - * argument offsets. */ "str x19, [x16, #16]\n\t" "str x20, [x16, #24]\n\t" "ldr x15, [sp, #72]\n\t" "str x15, [x16, #32]\n\t" "mov x19, x16\n\t" "ldr x20, [x16, #8]\n\t" -#else - "ldr x18, [x16, #8]\n\t" -#endif "ldp q0, q1, [sp, #80]\n\t" "ldp q2, q3, [sp, #112]\n\t" "ldp q4, q5, [sp, #144]\n\t" @@ -156,184 +137,14 @@ __attribute__((naked)) static void llgo_ffi_env_trampoline(void) { "ldp x4, x5, [sp, #32]\n\t" "ldp x6, x7, [sp, #48]\n\t" "add sp, sp, #224\n\t" -#if defined(__APPLE__) || defined(__ANDROID__) - "adr x30, 1f\n\t" - "br x17\n\t" - "1:\n\t" + "blr x17\n\t" "ldr x16, [x19, #16]\n\t" "ldr x20, [x19, #24]\n\t" "ldr x30, [x19, #32]\n\t" "mov x19, x16\n\t" - "ret" -#else - "br x17" -#endif - ); + "ret"); } -#elif defined(__arm__) - -#if defined(__ARM_PCS_VFP) -#define LLGO_ARM_SAVED_LR_OFFSET 84 -#else -#define LLGO_ARM_SAVED_LR_OFFSET 20 -#endif -#define LLGO_ARM_ASM_STR1(value) #value -#define LLGO_ARM_ASM_STR(value) LLGO_ARM_ASM_STR1(value) - -__attribute__((naked)) static void llgo_ffi_env_trampoline(void) { - __asm__ volatile( - "push {r0-r3, r10, lr}\n\t" -#if defined(__ARM_PCS_VFP) - "vpush {d0-d7}\n\t" -#endif - "bl " LLGO_ASM_CSYM(llgo_ffi_current_call) "\n\t" - "mov r12, r0\n\t" - "str r4, [r12, #8]\n\t" - "str r10, [r12, #12]\n\t" - "ldr r3, [sp, #" LLGO_ARM_ASM_STR(LLGO_ARM_SAVED_LR_OFFSET) "]\n\t" - "str r3, [r12, #16]\n\t" - "mov r4, r12\n\t" - "ldr r10, [r12, #4]\n\t" - "ldr r12, [r12, #0]\n\t" -#if defined(__ARM_PCS_VFP) - "vpop {d0-d7}\n\t" -#endif - "ldmia sp, {r0-r3}\n\t" - "add sp, sp, #24\n\t" - "adr lr, 1f\n\t" - "bx r12\n\t" - "1:\n\t" - "ldr r12, [r4, #8]\n\t" - "ldr r10, [r4, #12]\n\t" - "ldr lr, [r4, #16]\n\t" - "mov r4, r12\n\t" - "bx lr"); -} - -#elif defined(__riscv) || defined(__riscv__) - -#define LLGO_ASM_STR1(value) #value -#define LLGO_ASM_STR(value) LLGO_ASM_STR1(value) - -#if __riscv_xlen == 64 -#define LLGO_RISCV_FP_OFFSET 80 -#define LLGO_RISCV_BASE_FRAME 80 -#else -#define LLGO_RISCV_FP_OFFSET 48 -#define LLGO_RISCV_BASE_FRAME 48 -#endif - -#if defined(__riscv_float_abi_double) -#define LLGO_RISCV_FRAME (LLGO_RISCV_BASE_FRAME + 64) -#define LLGO_RISCV_SAVE_FP \ - "fsd fa0, " LLGO_ASM_STR(LLGO_RISCV_FP_OFFSET + 0) "(sp)\n\t" \ - "fsd fa1, " LLGO_ASM_STR(LLGO_RISCV_FP_OFFSET + 8) "(sp)\n\t" \ - "fsd fa2, " LLGO_ASM_STR(LLGO_RISCV_FP_OFFSET + 16) "(sp)\n\t" \ - "fsd fa3, " LLGO_ASM_STR(LLGO_RISCV_FP_OFFSET + 24) "(sp)\n\t" \ - "fsd fa4, " LLGO_ASM_STR(LLGO_RISCV_FP_OFFSET + 32) "(sp)\n\t" \ - "fsd fa5, " LLGO_ASM_STR(LLGO_RISCV_FP_OFFSET + 40) "(sp)\n\t" \ - "fsd fa6, " LLGO_ASM_STR(LLGO_RISCV_FP_OFFSET + 48) "(sp)\n\t" \ - "fsd fa7, " LLGO_ASM_STR(LLGO_RISCV_FP_OFFSET + 56) "(sp)\n\t" -#define LLGO_RISCV_RESTORE_FP \ - "fld fa0, " LLGO_ASM_STR(LLGO_RISCV_FP_OFFSET + 0) "(sp)\n\t" \ - "fld fa1, " LLGO_ASM_STR(LLGO_RISCV_FP_OFFSET + 8) "(sp)\n\t" \ - "fld fa2, " LLGO_ASM_STR(LLGO_RISCV_FP_OFFSET + 16) "(sp)\n\t" \ - "fld fa3, " LLGO_ASM_STR(LLGO_RISCV_FP_OFFSET + 24) "(sp)\n\t" \ - "fld fa4, " LLGO_ASM_STR(LLGO_RISCV_FP_OFFSET + 32) "(sp)\n\t" \ - "fld fa5, " LLGO_ASM_STR(LLGO_RISCV_FP_OFFSET + 40) "(sp)\n\t" \ - "fld fa6, " LLGO_ASM_STR(LLGO_RISCV_FP_OFFSET + 48) "(sp)\n\t" \ - "fld fa7, " LLGO_ASM_STR(LLGO_RISCV_FP_OFFSET + 56) "(sp)\n\t" -#elif defined(__riscv_float_abi_single) -#define LLGO_RISCV_FRAME (LLGO_RISCV_BASE_FRAME + 32) -#define LLGO_RISCV_SAVE_FP \ - "fsw fa0, " LLGO_ASM_STR(LLGO_RISCV_FP_OFFSET + 0) "(sp)\n\t" \ - "fsw fa1, " LLGO_ASM_STR(LLGO_RISCV_FP_OFFSET + 4) "(sp)\n\t" \ - "fsw fa2, " LLGO_ASM_STR(LLGO_RISCV_FP_OFFSET + 8) "(sp)\n\t" \ - "fsw fa3, " LLGO_ASM_STR(LLGO_RISCV_FP_OFFSET + 12) "(sp)\n\t" \ - "fsw fa4, " LLGO_ASM_STR(LLGO_RISCV_FP_OFFSET + 16) "(sp)\n\t" \ - "fsw fa5, " LLGO_ASM_STR(LLGO_RISCV_FP_OFFSET + 20) "(sp)\n\t" \ - "fsw fa6, " LLGO_ASM_STR(LLGO_RISCV_FP_OFFSET + 24) "(sp)\n\t" \ - "fsw fa7, " LLGO_ASM_STR(LLGO_RISCV_FP_OFFSET + 28) "(sp)\n\t" -#define LLGO_RISCV_RESTORE_FP \ - "flw fa0, " LLGO_ASM_STR(LLGO_RISCV_FP_OFFSET + 0) "(sp)\n\t" \ - "flw fa1, " LLGO_ASM_STR(LLGO_RISCV_FP_OFFSET + 4) "(sp)\n\t" \ - "flw fa2, " LLGO_ASM_STR(LLGO_RISCV_FP_OFFSET + 8) "(sp)\n\t" \ - "flw fa3, " LLGO_ASM_STR(LLGO_RISCV_FP_OFFSET + 12) "(sp)\n\t" \ - "flw fa4, " LLGO_ASM_STR(LLGO_RISCV_FP_OFFSET + 16) "(sp)\n\t" \ - "flw fa5, " LLGO_ASM_STR(LLGO_RISCV_FP_OFFSET + 20) "(sp)\n\t" \ - "flw fa6, " LLGO_ASM_STR(LLGO_RISCV_FP_OFFSET + 24) "(sp)\n\t" \ - "flw fa7, " LLGO_ASM_STR(LLGO_RISCV_FP_OFFSET + 28) "(sp)\n\t" -#else -#define LLGO_RISCV_FRAME LLGO_RISCV_BASE_FRAME -#define LLGO_RISCV_SAVE_FP -#define LLGO_RISCV_RESTORE_FP -#endif - -__attribute__((naked)) static void llgo_ffi_env_trampoline(void) { -#if __riscv_xlen == 64 - __asm__ volatile( - "addi sp, sp, -" LLGO_ASM_STR(LLGO_RISCV_FRAME) "\n\t" - "sd a0, 0(sp)\n\t" - "sd a1, 8(sp)\n\t" - "sd a2, 16(sp)\n\t" - "sd a3, 24(sp)\n\t" - "sd a4, 32(sp)\n\t" - "sd a5, 40(sp)\n\t" - "sd a6, 48(sp)\n\t" - "sd a7, 56(sp)\n\t" - "sd ra, 64(sp)\n\t" - LLGO_RISCV_SAVE_FP - "call " LLGO_ASM_CSYM(llgo_ffi_current_call) "\n\t" - "mv t1, a0\n\t" - "ld t0, 0(t1)\n\t" - "ld t2, 8(t1)\n\t" - LLGO_RISCV_RESTORE_FP - "ld ra, 64(sp)\n\t" - "ld a0, 0(sp)\n\t" - "ld a1, 8(sp)\n\t" - "ld a2, 16(sp)\n\t" - "ld a3, 24(sp)\n\t" - "ld a4, 32(sp)\n\t" - "ld a5, 40(sp)\n\t" - "ld a6, 48(sp)\n\t" - "ld a7, 56(sp)\n\t" - "addi sp, sp, " LLGO_ASM_STR(LLGO_RISCV_FRAME) "\n\t" - "jr t0"); -#else - __asm__ volatile( - "addi sp, sp, -" LLGO_ASM_STR(LLGO_RISCV_FRAME) "\n\t" - "sw a0, 0(sp)\n\t" - "sw a1, 4(sp)\n\t" - "sw a2, 8(sp)\n\t" - "sw a3, 12(sp)\n\t" - "sw a4, 16(sp)\n\t" - "sw a5, 20(sp)\n\t" - "sw a6, 24(sp)\n\t" - "sw a7, 28(sp)\n\t" - "sw ra, 32(sp)\n\t" - LLGO_RISCV_SAVE_FP - "call " LLGO_ASM_CSYM(llgo_ffi_current_call) "\n\t" - "mv t1, a0\n\t" - "lw t0, 0(t1)\n\t" - "lw t2, 4(t1)\n\t" - LLGO_RISCV_RESTORE_FP - "lw ra, 32(sp)\n\t" - "lw a0, 0(sp)\n\t" - "lw a1, 4(sp)\n\t" - "lw a2, 8(sp)\n\t" - "lw a3, 12(sp)\n\t" - "lw a4, 16(sp)\n\t" - "lw a5, 20(sp)\n\t" - "lw a6, 24(sp)\n\t" - "lw a7, 28(sp)\n\t" - "addi sp, sp, " LLGO_ASM_STR(LLGO_RISCV_FRAME) "\n\t" - "jr t0"); -#endif -} - -#endif - void llgo_ffi_call_with_env(ffi_cif *cif, void (*fn)(void), void *rvalue, void **avalue, void *env) { struct llgo_ffi_call_context previous = llgo_ffi_call_current; From 3a659e9337ede04a4622414135313cbd0868e188 Mon Sep 17 00:00:00 2001 From: Li Jie Date: Sun, 2 Aug 2026 17:42:21 +0800 Subject: [PATCH 23/73] runtime/ffi: retain system-libffi x86 fallback --- doc/closure.md | 18 ++--- runtime/internal/clite/ffi/_wrap/libffi.c | 88 +++++++++++++++++++---- 2 files changed, 85 insertions(+), 21 deletions(-) diff --git a/doc/closure.md b/doc/closure.md index 820a026ad1..863934820a 100644 --- a/doc/closure.md +++ b/doc/closure.md @@ -80,15 +80,15 @@ returns or lowers its C ABI. - explicit env target: add the env type/value only when `env != nil`; otherwise use the semantic signature. This is the only `env != nil` decision in the reflection/FFI path; -- native hidden env target: x86, RISC-V, and non-Apple/non-Android AArch64 call - stock libffi's `ffi_call_go` directly because its static-chain register is - LLGo's `nest` register. ARM also uses `ffi_call_go`; a short final-hop bridge - moves libffi's IP/R12 context to `swiftself`/R10 without saving argument - registers or using TLS. These targets require the upstream - `FFI_GO_CLOSURES` support enabled by their standard libffi configurations. -- Apple/Android AArch64 libffi disables its X18 Go ABI. Those targets alone use - stock `ffi_call` plus the TLS final-hop trampoline to install - `swiftself`/X20 while preserving the already-marshalled arguments. +- native hidden env target: x86, RISC-V, and non-Apple/non-Android AArch64 use + libffi's `ffi_call_go` directly when its headers expose `FFI_GO_CLOSURES`, + because its static-chain register is LLGo's `nest` register. ARM also uses + `ffi_call_go`; a short final-hop bridge moves libffi's IP/R12 context to + `swiftself`/R10 without saving argument registers or using TLS. +- Some x86 system libffi builds, including Apple's SDK libffi, omit the Go ABI. + They use stock `ffi_call` plus the TLS final-hop trampoline. Apple/Android + AArch64 use the same fallback because libffi disables its X18 Go ABI there; + their trampoline installs `swiftself`/X20. Although libffi's C implementation of `ffi_call_go` is a thin wrapper, it calls an architecture-private `ffi_call_int(..., closure)` and matching assembly; it diff --git a/runtime/internal/clite/ffi/_wrap/libffi.c b/runtime/internal/clite/ffi/_wrap/libffi.c index 93005c4c7a..ffb773a8cb 100644 --- a/runtime/internal/clite/ffi/_wrap/libffi.c +++ b/runtime/internal/clite/ffi/_wrap/libffi.c @@ -7,24 +7,30 @@ void *llgo_ffi_closure_alloc(void **code) { /* * Use libffi's Go ABI directly when its static-chain register is LLGo's nest * register. ARM needs only a final register bridge from libffi's IP/R12 to - * swiftself/R10. AArch64 Apple and Android reserve X18, so their stock libffi - * has no Go ABI and still needs the public-ffi_call trampoline. + * swiftself/R10. Keep the public-ffi_call trampoline where stock libffi does + * not expose its Go ABI: x86 system libffi builds such as Apple's SDK, and + * AArch64 Apple/Android where X18 is reserved. */ -#if !defined(_WIN32) && \ +#if !defined(_WIN32) && defined(FFI_GO_CLOSURES) && \ (defined(__x86_64__) || defined(__i386__) || defined(__riscv) || \ defined(__riscv__) || \ (defined(__aarch64__) && !defined(__APPLE__) && !defined(__ANDROID__))) #define LLGO_FFI_CALL_GO_DIRECT 1 #elif !defined(_WIN32) && defined(__arm__) #define LLGO_FFI_CALL_GO_ARM_BRIDGE 1 -#elif !defined(_WIN32) && defined(__aarch64__) && \ - (defined(__APPLE__) || defined(__ANDROID__)) +#elif !defined(_WIN32) && \ + (((defined(__x86_64__) || defined(__i386__)) && \ + !defined(FFI_GO_CLOSURES)) || \ + (defined(__aarch64__) && \ + (defined(__APPLE__) || defined(__ANDROID__)))) #define LLGO_FFI_CALL_PUBLIC_TRAMPOLINE 1 #endif -#if (defined(LLGO_FFI_CALL_GO_DIRECT) || \ - defined(LLGO_FFI_CALL_GO_ARM_BRIDGE)) && \ - !defined(FFI_GO_CLOSURES) +#if defined(LLGO_FFI_CALL_GO_ARM_BRIDGE) && !defined(FFI_GO_CLOSURES) +#error "LLGo hidden closure environments require libffi Go closures on ARM" +#elif !defined(_WIN32) && !defined(FFI_GO_CLOSURES) && \ + (defined(__riscv) || defined(__riscv__) || \ + (defined(__aarch64__) && !defined(__APPLE__) && !defined(__ANDROID__))) #error "LLGo hidden closure environments require libffi Go closures on this target" #endif @@ -79,10 +85,10 @@ void llgo_ffi_call_with_env(ffi_cif *cif, void (*fn)(void), void *rvalue, #elif defined(LLGO_FFI_CALL_PUBLIC_TRAMPOLINE) /* - * Public ffi_call cannot transport swiftself. Keep the real target and env in - * per-thread state while libffi marshals the arguments. Its final target saves - * those arguments, obtains the state, installs X20, and enters the real entry - * with the original SP. + * Public ffi_call cannot transport the hidden environment register. Keep the + * real target and env in per-thread state while libffi marshals the arguments. + * Its final target saves those arguments, obtains the state, installs the + * target register, and enters the real entry with the original SP. */ struct llgo_ffi_call_context { void (*target)(void); @@ -105,6 +111,62 @@ llgo_ffi_current_call(void) { #define LLGO_ASM_CSYM(name) #name #endif +#if defined(__x86_64__) + +__attribute__((naked)) static void llgo_ffi_env_trampoline(void) { + __asm__ volatile( + "subq $200, %rsp\n\t" + "movq %rdi, 0(%rsp)\n\t" + "movq %rsi, 8(%rsp)\n\t" + "movq %rdx, 16(%rsp)\n\t" + "movq %rcx, 24(%rsp)\n\t" + "movq %r8, 32(%rsp)\n\t" + "movq %r9, 40(%rsp)\n\t" + "movq %rax, 48(%rsp)\n\t" + "movdqu %xmm0, 64(%rsp)\n\t" + "movdqu %xmm1, 80(%rsp)\n\t" + "movdqu %xmm2, 96(%rsp)\n\t" + "movdqu %xmm3, 112(%rsp)\n\t" + "movdqu %xmm4, 128(%rsp)\n\t" + "movdqu %xmm5, 144(%rsp)\n\t" + "movdqu %xmm6, 160(%rsp)\n\t" + "movdqu %xmm7, 176(%rsp)\n\t" + "callq " LLGO_ASM_CSYM(llgo_ffi_current_call) "\n\t" + "movq 0(%rax), %r11\n\t" + "movq 8(%rax), %r10\n\t" + "movdqu 64(%rsp), %xmm0\n\t" + "movdqu 80(%rsp), %xmm1\n\t" + "movdqu 96(%rsp), %xmm2\n\t" + "movdqu 112(%rsp), %xmm3\n\t" + "movdqu 128(%rsp), %xmm4\n\t" + "movdqu 144(%rsp), %xmm5\n\t" + "movdqu 160(%rsp), %xmm6\n\t" + "movdqu 176(%rsp), %xmm7\n\t" + "movq 0(%rsp), %rdi\n\t" + "movq 8(%rsp), %rsi\n\t" + "movq 16(%rsp), %rdx\n\t" + "movq 24(%rsp), %rcx\n\t" + "movq 32(%rsp), %r8\n\t" + "movq 40(%rsp), %r9\n\t" + "movq 48(%rsp), %rax\n\t" + "addq $200, %rsp\n\t" + "jmpq *%r11"); +} + +#elif defined(__i386__) + +__attribute__((naked)) static void llgo_ffi_env_trampoline(void) { + __asm__ volatile( + "subl $12, %esp\n\t" + "calll " LLGO_ASM_CSYM(llgo_ffi_current_call) "\n\t" + "movl 0(%eax), %edx\n\t" + "movl 4(%eax), %ecx\n\t" + "addl $12, %esp\n\t" + "jmpl *%edx"); +} + +#elif defined(__aarch64__) + __attribute__((naked)) static void llgo_ffi_env_trampoline(void) { __asm__ volatile( "sub sp, sp, #224\n\t" @@ -145,6 +207,8 @@ __attribute__((naked)) static void llgo_ffi_env_trampoline(void) { "ret"); } +#endif + void llgo_ffi_call_with_env(ffi_cif *cif, void (*fn)(void), void *rvalue, void **avalue, void *env) { struct llgo_ffi_call_context previous = llgo_ffi_call_current; From ac1e562ea4726f1abc5c3195ab2373e51d27a51e Mon Sep 17 00:00:00 2001 From: Li Jie Date: Sun, 2 Aug 2026 19:08:50 +0800 Subject: [PATCH 24/73] ssa: document Windows closure env fallback --- ssa/closure_abi.go | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/ssa/closure_abi.go b/ssa/closure_abi.go index e254acf5a4..7dc4fd00ce 100644 --- a/ssa/closure_abi.go +++ b/ssa/closure_abi.go @@ -21,9 +21,12 @@ const ( func closureEnvABIForTarget(triple string) closureEnvABI { triple = strings.ToLower(triple) arch, _, _ := strings.Cut(triple, "-") - // The current public-libffi final-hop bridge is not implemented for - // Windows. This is a bridge capability, not an LLVM or Win64 restriction: - // x86-64 Win64 can use nest/r10 once that bridge is added. + // LLGo does not currently support Windows, so keep its closure ABI on the + // typed fallback rather than adding untestable target-specific paths here. + // TODO: classify Windows by architecture when the target is supported. + // Upstream libffi's x86 Go ABI matches LLVM nest/R10; AArch64 instead needs + // a validated public-ffi TLS trampoline for swiftself/X20 because Windows + // reserves X18. if strings.Contains(triple, "windows") || strings.Contains(triple, "win32") || strings.Contains(triple, "mingw") { return closureEnvExplicit } From 2c4a8e8747e056de8c219369202805adc67169d1 Mon Sep 17 00:00:00 2001 From: Li Jie Date: Sun, 2 Aug 2026 19:11:45 +0800 Subject: [PATCH 25/73] doc: clarify closure env platform fallbacks --- doc/closure.md | 24 +++++++++++++----------- 1 file changed, 13 insertions(+), 11 deletions(-) diff --git a/doc/closure.md b/doc/closure.md index 863934820a..a150ac0bfc 100644 --- a/doc/closure.md +++ b/doc/closure.md @@ -65,10 +65,10 @@ The physical env parameter is: - `swiftself` on ARM and platforms where AArch64 X18 is reserved; - an ordinary leading parameter on the explicit fallback. -Windows currently uses the explicit fallback because this phase does not add a -Windows final-hop FFI bridge. This is not an LLVM `nest` limitation: for -example, x86-64 Win64 can use its static-chain register once the corresponding -bridge is available and tested. +Windows currently uses the explicit fallback because LLGo does not support the +target. TODO: select its transport by architecture once it is supported. The +x86 libffi Go ABI already matches LLVM `nest`; AArch64 reserves X18 and needs a +validated public-FFI TLS trampoline for `swiftself`/X20. LLVM parameter attributes are preserved when LLGo rewrites large aggregate returns or lowers its C ABI. @@ -80,15 +80,17 @@ returns or lowers its C ABI. - explicit env target: add the env type/value only when `env != nil`; otherwise use the semantic signature. This is the only `env != nil` decision in the reflection/FFI path; -- native hidden env target: x86, RISC-V, and non-Apple/non-Android AArch64 use - libffi's `ffi_call_go` directly when its headers expose `FFI_GO_CLOSURES`, - because its static-chain register is LLGo's `nest` register. ARM also uses - `ffi_call_go`; a short final-hop bridge moves libffi's IP/R12 context to - `swiftself`/R10 without saving argument registers or using TLS. +- native hidden env target: x86, RISC-V, and + non-Apple/non-Android/non-Windows AArch64 use libffi's `ffi_call_go` directly + when its headers expose `FFI_GO_CLOSURES`, because its static-chain register + is LLGo's `nest` register. ARM also uses `ffi_call_go`; a short final-hop + bridge moves libffi's IP/R12 context to `swiftself`/R10 without saving + argument registers or using TLS. - Some x86 system libffi builds, including Apple's SDK libffi, omit the Go ABI. They use stock `ffi_call` plus the TLS final-hop trampoline. Apple/Android - AArch64 use the same fallback because libffi disables its X18 Go ABI there; - their trampoline installs `swiftself`/X20. + AArch64 use the same fallback: Apple libffi disables its X18 Go ABI, while + Android's X18 ABI is incompatible with LLGo. Their trampoline installs + `swiftself`/X20. Although libffi's C implementation of `ffi_call_go` is a thin wrapper, it calls an architecture-private `ffi_call_int(..., closure)` and matching assembly; it From b2d1602e12cc60a3bd96bb1fad9e29aac962fdaf Mon Sep 17 00:00:00 2001 From: Li Jie Date: Sun, 2 Aug 2026 19:49:18 +0800 Subject: [PATCH 26/73] runtime/ffi: enforce target-compatible env final hops --- .github/actions/setup-deps/action.yml | 19 +++- README.md | 2 +- doc/_readme/scripts/install_ubuntu.sh | 2 +- doc/closure.md | 48 ++++++--- runtime/internal/clite/ffi/_wrap/libffi.c | 103 +++++++------------- runtime/internal/clite/ffi/ffi_link.go | 5 +- runtime/internal/ffi/call_llgo_explicit.go | 6 +- runtime/internal/ffi/call_llgo_nest.go | 5 +- runtime/internal/ffi/call_llgo_swiftself.go | 8 +- ssa/closure_abi.go | 21 ++-- ssa/closure_env_test.go | 23 ++++- 11 files changed, 131 insertions(+), 111 deletions(-) diff --git a/.github/actions/setup-deps/action.yml b/.github/actions/setup-deps/action.yml index 35ee24ff7c..4d56839915 100644 --- a/.github/actions/setup-deps/action.yml +++ b/.github/actions/setup-deps/action.yml @@ -55,8 +55,10 @@ runs: fi # Install common dependencies - brew install bdw-gc openssl libffi libuv + brew install pkg-config bdw-gc openssl libffi libuv brew link --overwrite libffi + libffi_pc_path="$(brew --prefix libffi)/lib/pkgconfig" + echo "PKG_CONFIG_PATH=${libffi_pc_path}:${PKG_CONFIG_PATH:-}" >> "$GITHUB_ENV" # Install optional deps for demos. # @@ -97,3 +99,18 @@ runs: python3.12-dev # for github.com/goplus/lib/py ) sudo apt-get install -y "${opt_deps[@]}" + + - name: Verify libffi pkg-config metadata + shell: bash + run: | + pkg-config --modversion libffi + pkg-config --cflags --libs libffi + if [[ "$(uname -s)" == "Darwin" ]]; then + resolved_prefix="$(cd "$(pkg-config --variable=prefix libffi)" && pwd -P)" + homebrew_prefix="$(cd "$(brew --prefix libffi)" && pwd -P)" + echo "resolved libffi prefix: ${resolved_prefix}" + if [[ "${resolved_prefix}" != "${homebrew_prefix}" ]]; then + echo "pkg-config did not resolve Homebrew libffi" >&2 + exit 1 + fi + fi diff --git a/README.md b/README.md index e6be8b1fb4..a8185aec21 100644 --- a/README.md +++ b/README.md @@ -377,7 +377,7 @@ brew link --overwrite llvm@19 lld@19 libffi echo "deb http://apt.llvm.org/$(lsb_release -cs)/ llvm-toolchain-$(lsb_release -cs)-19 main" | sudo tee /etc/apt/sources.list.d/llvm.list wget -O - https://apt.llvm.org/llvm-snapshot.gpg.key | sudo apt-key add - sudo apt-get update -sudo apt-get install -y llvm-19-dev clang-19 libclang-19-dev lld-19 libunwind-19-dev libc++-19-dev pkg-config libgc-dev libssl-dev zlib1g-dev libcjson-dev libsqlite3-dev libuv1-dev +sudo apt-get install -y llvm-19-dev clang-19 libclang-19-dev lld-19 libunwind-19-dev libc++-19-dev pkg-config libgc-dev libssl-dev zlib1g-dev libffi-dev libcjson-dev libsqlite3-dev libuv1-dev sudo apt-get install -y python3.12-dev # optional #curl https://raw.githubusercontent.com/xgo-dev/llgo/refs/heads/main/install.sh | bash ./install.sh diff --git a/doc/_readme/scripts/install_ubuntu.sh b/doc/_readme/scripts/install_ubuntu.sh index d909bca527..62476e355e 100644 --- a/doc/_readme/scripts/install_ubuntu.sh +++ b/doc/_readme/scripts/install_ubuntu.sh @@ -2,7 +2,7 @@ echo "deb http://apt.llvm.org/$(lsb_release -cs)/ llvm-toolchain-$(lsb_release -cs)-19 main" | sudo tee /etc/apt/sources.list.d/llvm.list wget -O - https://apt.llvm.org/llvm-snapshot.gpg.key | sudo apt-key add - sudo apt-get update -sudo apt-get install -y llvm-19-dev clang-19 libclang-19-dev lld-19 libunwind-19-dev libc++-19-dev pkg-config libgc-dev libssl-dev zlib1g-dev libcjson-dev libsqlite3-dev libuv1-dev +sudo apt-get install -y llvm-19-dev clang-19 libclang-19-dev lld-19 libunwind-19-dev libc++-19-dev pkg-config libgc-dev libssl-dev zlib1g-dev libffi-dev libcjson-dev libsqlite3-dev libuv1-dev sudo apt-get install -y python3.12-dev # optional #curl https://raw.githubusercontent.com/xgo-dev/llgo/refs/heads/main/install.sh | bash ./install.sh diff --git a/doc/closure.md b/doc/closure.md index a150ac0bfc..78222f972f 100644 --- a/doc/closure.md +++ b/doc/closure.md @@ -65,10 +65,14 @@ The physical env parameter is: - `swiftself` on ARM and platforms where AArch64 X18 is reserved; - an ordinary leading parameter on the explicit fallback. -Windows currently uses the explicit fallback because LLGo does not support the -target. TODO: select its transport by architecture once it is supported. The -x86 libffi Go ABI already matches LLVM `nest`; AArch64 reserves X18 and needs a -validated public-FFI TLS trampoline for `swiftself`/X20. +Windows follows the architecture-selected ABI even though LLGo does not yet +support the OS: x86 uses `nest`, while ARM/AArch64 use `swiftself`. The x86 +libffi Go ABI already matches LLVM `nest`; the Windows ARM/AArch64 public-FFI +final hop remains a TODO. This keeps compiled closure entries independent of +when runtime support is added. + +WebAssembly remains explicit because it has no compatible hidden-register +transport. Adding one in the future is a deliberate target ABI upgrade. LLVM parameter attributes are preserved when LLGo rewrites large aggregate returns or lowers its C ABI. @@ -80,17 +84,31 @@ returns or lowers its C ABI. - explicit env target: add the env type/value only when `env != nil`; otherwise use the semantic signature. This is the only `env != nil` decision in the reflection/FFI path; -- native hidden env target: x86, RISC-V, and - non-Apple/non-Android/non-Windows AArch64 use libffi's `ffi_call_go` directly - when its headers expose `FFI_GO_CLOSURES`, because its static-chain register - is LLGo's `nest` register. ARM also uses `ffi_call_go`; a short final-hop - bridge moves libffi's IP/R12 context to `swiftself`/R10 without saving - argument registers or using TLS. -- Some x86 system libffi builds, including Apple's SDK libffi, omit the Go ABI. - They use stock `ffi_call` plus the TLS final-hop trampoline. Apple/Android - AArch64 use the same fallback: Apple libffi disables its X18 Go ABI, while - Android's X18 ABI is incompatible with LLGo. Their trampoline installs - `swiftself`/X20. +- native hidden env target: x86, RISC-V, and AArch64 targets where X18 is + available use libffi's `ffi_call_go` directly because its static-chain + register is LLGo's `nest` register. ARM also uses `ffi_call_go`; a short + final-hop bridge moves libffi's IP/R12 context to `swiftself`/R10 without + saving argument registers or using TLS. LLVM lowers ARM32 `nest` as an + ordinary leading argument rather than a hidden static chain, so it cannot + replace this `swiftself` bridge. +- Apple/Android AArch64 use stock `ffi_call` plus the TLS final-hop trampoline: + libffi's X18 Go ABI is unavailable or incompatible there, so the trampoline + installs `swiftself`/X20. In particular, Homebrew libffi does not export + `ffi_call_go` on Apple AArch64, so there is no incoming context register for + an ARM32-style register-only bridge; public `ffi_call` needs TLS to carry + `{fn, env}` to its final target. + +The build obtains both headers and linker flags from `pkg-config libffi`. x86 +requires `FFI_GO_CLOSURES`; a system libffi without that API is rejected rather +than retaining a second x86 FFI final-hop implementation. macOS CI installs +Homebrew libffi and pkg-config explicitly. Apple AArch64 remains on the X20 TLS +trampoline because upstream/Homebrew libffi intentionally disables its X18 Go +ABI there. + +Every architecture that selects a hidden env must select exactly one native +FFI final hop: direct `ffi_call_go`, `ffi_call_go` plus a register bridge, or +public `ffi_call` plus a TLS trampoline. The wrapper rejects missing or +ambiguous selections at compile time. Although libffi's C implementation of `ffi_call_go` is a thin wrapper, it calls an architecture-private `ffi_call_int(..., closure)` and matching assembly; it diff --git a/runtime/internal/clite/ffi/_wrap/libffi.c b/runtime/internal/clite/ffi/_wrap/libffi.c index ffb773a8cb..3ab2d1c159 100644 --- a/runtime/internal/clite/ffi/_wrap/libffi.c +++ b/runtime/internal/clite/ffi/_wrap/libffi.c @@ -7,31 +7,50 @@ void *llgo_ffi_closure_alloc(void **code) { /* * Use libffi's Go ABI directly when its static-chain register is LLGo's nest * register. ARM needs only a final register bridge from libffi's IP/R12 to - * swiftself/R10. Keep the public-ffi_call trampoline where stock libffi does - * not expose its Go ABI: x86 system libffi builds such as Apple's SDK, and - * AArch64 Apple/Android where X18 is reserved. + * swiftself/R10. AArch64 Apple/Android use the public-ffi_call trampoline + * because X18 is reserved and LLGo uses swiftself/X20 instead. + * + * Windows follows the same architecture-selected closure ABI even though LLGo + * does not support the OS yet. x86 can use the direct path below. TODO: add and + * validate the Windows ARM/AArch64 FFI final hop without changing that ABI. */ -#if !defined(_WIN32) && defined(FFI_GO_CLOSURES) && \ +#if defined(__x86_64__) || defined(__i386__) || defined(__riscv) || \ + defined(__riscv__) || defined(__arm__) || defined(__aarch64__) +#define LLGO_FFI_HIDDEN_ENV_TARGET 1 +#endif + +#if defined(FFI_GO_CLOSURES) && \ (defined(__x86_64__) || defined(__i386__) || defined(__riscv) || \ defined(__riscv__) || \ - (defined(__aarch64__) && !defined(__APPLE__) && !defined(__ANDROID__))) + (defined(__aarch64__) && !defined(__APPLE__) && !defined(__ANDROID__) && \ + !defined(_WIN32))) #define LLGO_FFI_CALL_GO_DIRECT 1 #elif !defined(_WIN32) && defined(__arm__) #define LLGO_FFI_CALL_GO_ARM_BRIDGE 1 -#elif !defined(_WIN32) && \ - (((defined(__x86_64__) || defined(__i386__)) && \ - !defined(FFI_GO_CLOSURES)) || \ - (defined(__aarch64__) && \ - (defined(__APPLE__) || defined(__ANDROID__)))) +#elif !defined(_WIN32) && defined(__aarch64__) && \ + (defined(__APPLE__) || defined(__ANDROID__)) #define LLGO_FFI_CALL_PUBLIC_TRAMPOLINE 1 #endif -#if defined(LLGO_FFI_CALL_GO_ARM_BRIDGE) && !defined(FFI_GO_CLOSURES) +#if defined(__APPLE__) && (defined(__x86_64__) || defined(__i386__)) && \ + !defined(FFI_GO_CLOSURES) +#error "LLGo macOS x86 requires pkg-config to resolve Homebrew libffi with Go closures, not Apple SDK libffi" +#elif defined(LLGO_FFI_CALL_GO_ARM_BRIDGE) && !defined(FFI_GO_CLOSURES) #error "LLGo hidden closure environments require libffi Go closures on ARM" -#elif !defined(_WIN32) && !defined(FFI_GO_CLOSURES) && \ - (defined(__riscv) || defined(__riscv__) || \ - (defined(__aarch64__) && !defined(__APPLE__) && !defined(__ANDROID__))) +#elif !defined(FFI_GO_CLOSURES) && \ + (defined(__x86_64__) || defined(__i386__) || defined(__riscv) || \ + defined(__riscv__) || \ + (defined(__aarch64__) && !defined(__APPLE__) && !defined(__ANDROID__) && \ + !defined(_WIN32))) #error "LLGo hidden closure environments require libffi Go closures on this target" +#elif defined(_WIN32) && (defined(__arm__) || defined(__aarch64__)) +#error "LLGo Windows ARM hidden-env FFI final hop is not implemented" +#elif defined(LLGO_FFI_HIDDEN_ENV_TARGET) && \ + (defined(LLGO_FFI_CALL_GO_DIRECT) + \ + defined(LLGO_FFI_CALL_GO_ARM_BRIDGE) + \ + defined(LLGO_FFI_CALL_PUBLIC_TRAMPOLINE) != \ + 1) +#error "LLGo hidden-env target must select exactly one libffi final-hop path" #endif #if defined(LLGO_FFI_CALL_GO_DIRECT) @@ -111,61 +130,7 @@ llgo_ffi_current_call(void) { #define LLGO_ASM_CSYM(name) #name #endif -#if defined(__x86_64__) - -__attribute__((naked)) static void llgo_ffi_env_trampoline(void) { - __asm__ volatile( - "subq $200, %rsp\n\t" - "movq %rdi, 0(%rsp)\n\t" - "movq %rsi, 8(%rsp)\n\t" - "movq %rdx, 16(%rsp)\n\t" - "movq %rcx, 24(%rsp)\n\t" - "movq %r8, 32(%rsp)\n\t" - "movq %r9, 40(%rsp)\n\t" - "movq %rax, 48(%rsp)\n\t" - "movdqu %xmm0, 64(%rsp)\n\t" - "movdqu %xmm1, 80(%rsp)\n\t" - "movdqu %xmm2, 96(%rsp)\n\t" - "movdqu %xmm3, 112(%rsp)\n\t" - "movdqu %xmm4, 128(%rsp)\n\t" - "movdqu %xmm5, 144(%rsp)\n\t" - "movdqu %xmm6, 160(%rsp)\n\t" - "movdqu %xmm7, 176(%rsp)\n\t" - "callq " LLGO_ASM_CSYM(llgo_ffi_current_call) "\n\t" - "movq 0(%rax), %r11\n\t" - "movq 8(%rax), %r10\n\t" - "movdqu 64(%rsp), %xmm0\n\t" - "movdqu 80(%rsp), %xmm1\n\t" - "movdqu 96(%rsp), %xmm2\n\t" - "movdqu 112(%rsp), %xmm3\n\t" - "movdqu 128(%rsp), %xmm4\n\t" - "movdqu 144(%rsp), %xmm5\n\t" - "movdqu 160(%rsp), %xmm6\n\t" - "movdqu 176(%rsp), %xmm7\n\t" - "movq 0(%rsp), %rdi\n\t" - "movq 8(%rsp), %rsi\n\t" - "movq 16(%rsp), %rdx\n\t" - "movq 24(%rsp), %rcx\n\t" - "movq 32(%rsp), %r8\n\t" - "movq 40(%rsp), %r9\n\t" - "movq 48(%rsp), %rax\n\t" - "addq $200, %rsp\n\t" - "jmpq *%r11"); -} - -#elif defined(__i386__) - -__attribute__((naked)) static void llgo_ffi_env_trampoline(void) { - __asm__ volatile( - "subl $12, %esp\n\t" - "calll " LLGO_ASM_CSYM(llgo_ffi_current_call) "\n\t" - "movl 0(%eax), %edx\n\t" - "movl 4(%eax), %ecx\n\t" - "addl $12, %esp\n\t" - "jmpl *%edx"); -} - -#elif defined(__aarch64__) +#if defined(__aarch64__) __attribute__((naked)) static void llgo_ffi_env_trampoline(void) { __asm__ volatile( diff --git a/runtime/internal/clite/ffi/ffi_link.go b/runtime/internal/clite/ffi/ffi_link.go index 2085ae0452..cc6ea4f6ce 100644 --- a/runtime/internal/clite/ffi/ffi_link.go +++ b/runtime/internal/clite/ffi/ffi_link.go @@ -7,7 +7,7 @@ import ( ) const ( - LLGoPackage = "link: $(pkg-config --libs libffi); -lffi" + LLGoPackage = "link: $(pkg-config --libs libffi)" LLGoFiles = "$(pkg-config --cflags libffi): _wrap/libffi.c" ) @@ -42,6 +42,9 @@ void ffi_call(ffi_cif *cif, //go:linkname Call C.ffi_call func Call(cif *Cif, fn unsafe.Pointer, rvalue unsafe.Pointer, avalue *unsafe.Pointer) +// CallWithEnv calls a native hidden-env entry. cif and avalue contain only the +// semantic arguments; env is installed by the architecture-specific final hop. +// //go:linkname CallWithEnv C.llgo_ffi_call_with_env func CallWithEnv(cif *Cif, fn unsafe.Pointer, rvalue unsafe.Pointer, avalue *unsafe.Pointer, env unsafe.Pointer) diff --git a/runtime/internal/ffi/call_llgo_explicit.go b/runtime/internal/ffi/call_llgo_explicit.go index a5e20237d3..b96cc1aca8 100644 --- a/runtime/internal/ffi/call_llgo_explicit.go +++ b/runtime/internal/ffi/call_llgo_explicit.go @@ -7,9 +7,9 @@ import "unsafe" // ClosureEnvExplicit is a compile-time target property. const ClosureEnvExplicit = true -// CallWithEnv calls fn through libffi. On explicit-context targets the signature -// passed by the caller already contains the leading env type; this function -// supplies the corresponding value before reaching this final call helper. +// CallWithEnv calls fn through ordinary libffi on an explicit-context target. +// When env is required, the caller has already prepended its type and value to +// cif and args; the separately supplied env is therefore intentionally unused. func CallWithEnv(cif *Signature, fn, _ unsafe.Pointer, ret unsafe.Pointer, args ...unsafe.Pointer) { Call(cif, fn, ret, args...) } diff --git a/runtime/internal/ffi/call_llgo_nest.go b/runtime/internal/ffi/call_llgo_nest.go index 8bb84870c5..b71fe79fc4 100644 --- a/runtime/internal/ffi/call_llgo_nest.go +++ b/runtime/internal/ffi/call_llgo_nest.go @@ -10,8 +10,9 @@ import ( const ClosureEnvExplicit = false -// CallWithEnv uses the runtime's libffi trampoline to place env in LLVM's nest -// register at the final call without changing the user-visible signature. +// CallWithEnv invokes fn with a semantic CIF that does not contain env. The +// native final hop passes env separately in LLVM's nest register, using +// ffi_call_go directly when libffi selects the same physical register. func CallWithEnv(cif *Signature, fn, env, ret unsafe.Pointer, args ...unsafe.Pointer) { var avalues *unsafe.Pointer if len(args) > 0 { diff --git a/runtime/internal/ffi/call_llgo_swiftself.go b/runtime/internal/ffi/call_llgo_swiftself.go index bf924e250e..3ebc0a3e10 100644 --- a/runtime/internal/ffi/call_llgo_swiftself.go +++ b/runtime/internal/ffi/call_llgo_swiftself.go @@ -10,9 +10,11 @@ import ( const ClosureEnvExplicit = false -// CallWithEnv uses the runtime's libffi trampoline to preserve env across -// argument marshalling and place it in swiftself's register at the final call. -// Nil is written as well so native dynamic calls have one uniform path. +// CallWithEnv invokes fn with a semantic CIF that does not contain env. The +// native final hop passes env separately in LLVM's swiftself register: ARM32 +// bridges libffi's R12 static chain to R10, while AArch64 targets that reserve +// X18 use a TLS trampoline to install X20. Nil is installed as well so native +// dynamic calls keep one uniform path. func CallWithEnv(cif *Signature, fn, env, ret unsafe.Pointer, args ...unsafe.Pointer) { var avalues *unsafe.Pointer if len(args) > 0 { diff --git a/ssa/closure_abi.go b/ssa/closure_abi.go index 7dc4fd00ce..f51d93cdda 100644 --- a/ssa/closure_abi.go +++ b/ssa/closure_abi.go @@ -21,15 +21,9 @@ const ( func closureEnvABIForTarget(triple string) closureEnvABI { triple = strings.ToLower(triple) arch, _, _ := strings.Cut(triple, "-") - // LLGo does not currently support Windows, so keep its closure ABI on the - // typed fallback rather than adding untestable target-specific paths here. - // TODO: classify Windows by architecture when the target is supported. - // Upstream libffi's x86 Go ABI matches LLVM nest/R10; AArch64 instead needs - // a validated public-ffi TLS trampoline for swiftself/X20 because Windows - // reserves X18. - if strings.Contains(triple, "windows") || strings.Contains(triple, "win32") || strings.Contains(triple, "mingw") { - return closureEnvExplicit - } + // Select the long-term machine ABI by physical target even when LLGo does + // not yet support the target OS. FFI final-hop support may follow later + // without changing compiled closure entries. switch { case arch == "arm64", arch == "arm64_32", arch == "aarch64", arch == "aarch64_be": // Keep a stable runtime ABI across LLVM versions on platforms which @@ -58,11 +52,14 @@ func closureEnvABIForTarget(triple string) closureEnvABI { } func aarch64UsesSwiftSelf(triple string) bool { - // Windows was already classified as explicit above. Apple and Android - // reserve X18, so LLGo uses LLVM's swiftself/X20 transport there. + // Apple, Android, and Windows reserve X18, so LLGo uses LLVM's + // swiftself/X20 transport there. return strings.Contains(triple, "apple") || strings.Contains(triple, "darwin") || - strings.Contains(triple, "android") + strings.Contains(triple, "android") || + strings.Contains(triple, "windows") || + strings.Contains(triple, "win32") || + strings.Contains(triple, "mingw") } func (p *Target) closureEnvABI() closureEnvABI { diff --git a/ssa/closure_env_test.go b/ssa/closure_env_test.go index 299fd83061..541be822e6 100644 --- a/ssa/closure_env_test.go +++ b/ssa/closure_env_test.go @@ -52,9 +52,10 @@ func TestClosureEnvABIForTarget(t *testing.T) { {"armv7-unknown-linux-gnueabihf", closureEnvSwiftSelf}, {"aarch64-unknown-linux", closureEnvNest}, {"arm64-apple-macosx", closureEnvSwiftSelf}, - {"x86_64-pc-windows-gnu", closureEnvExplicit}, - {"x86_64-pc-windows-msvc", closureEnvExplicit}, - {"x86_64-w64-mingw32", closureEnvExplicit}, + {"x86_64-pc-windows-gnu", closureEnvNest}, + {"x86_64-pc-windows-msvc", closureEnvNest}, + {"x86_64-w64-mingw32", closureEnvNest}, + {"aarch64-pc-windows-msvc", closureEnvSwiftSelf}, {"mips64-unknown-linux", closureEnvExplicit}, } for _, test := range tests { @@ -343,6 +344,22 @@ func TestClosureObjectCallMatrixAcrossTransports(t *testing.T) { abi: closureEnvSwiftSelf, attr: "swiftself", }, + { + name: "windows-nest", + tgt: &Target{ + GOOS: "windows", GOARCH: "amd64", LLVMTarget: "x86_64-pc-windows-msvc", + }, + abi: closureEnvNest, + attr: "nest", + }, + { + name: "windows-swiftself", + tgt: &Target{ + GOOS: "windows", GOARCH: "arm64", LLVMTarget: "aarch64-pc-windows-msvc", + }, + abi: closureEnvSwiftSelf, + attr: "swiftself", + }, { name: "wasm-explicit", tgt: &Target{GOOS: "wasip1", GOARCH: "wasm"}, From 572a29fca97d1b03c14634037255a43a210d8884 Mon Sep 17 00:00:00 2001 From: Li Jie Date: Sun, 2 Aug 2026 21:34:53 +0800 Subject: [PATCH 27/73] runtime/ffi: finalize hidden-env platform contract --- .github/actions/setup-deps/action.yml | 1 - README.md | 3 ++- doc/_readme/scripts/install_macos.sh | 3 ++- doc/closure.md | 10 +++++++--- runtime/internal/clite/ffi/_wrap/libffi.c | 8 +++++++- ssa/closure_abi.go | 6 +++--- 6 files changed, 21 insertions(+), 10 deletions(-) diff --git a/.github/actions/setup-deps/action.yml b/.github/actions/setup-deps/action.yml index 4d56839915..99cff11ed7 100644 --- a/.github/actions/setup-deps/action.yml +++ b/.github/actions/setup-deps/action.yml @@ -56,7 +56,6 @@ runs: # Install common dependencies brew install pkg-config bdw-gc openssl libffi libuv - brew link --overwrite libffi libffi_pc_path="$(brew --prefix libffi)/lib/pkgconfig" echo "PKG_CONFIG_PATH=${libffi_pc_path}:${PKG_CONFIG_PATH:-}" >> "$GITHUB_ENV" diff --git a/README.md b/README.md index a8185aec21..97d23b2900 100644 --- a/README.md +++ b/README.md @@ -362,7 +362,8 @@ Follow these steps to generate the `llgo` command (its usage is the same as the brew update brew install llvm@19 lld@19 bdw-gc openssl cjson libffi libuv pkg-config brew install python@3.12 # optional -brew link --overwrite llvm@19 lld@19 libffi +export PKG_CONFIG_PATH="$(brew --prefix libffi)/lib/pkgconfig:${PKG_CONFIG_PATH:-}" +brew link --overwrite llvm@19 lld@19 # curl https://raw.githubusercontent.com/xgo-dev/llgo/refs/heads/main/install.sh | bash ./install.sh ``` diff --git a/doc/_readme/scripts/install_macos.sh b/doc/_readme/scripts/install_macos.sh index a2bd676820..a7ebace339 100644 --- a/doc/_readme/scripts/install_macos.sh +++ b/doc/_readme/scripts/install_macos.sh @@ -2,6 +2,7 @@ brew update brew install llvm@19 lld@19 bdw-gc openssl cjson libffi libuv pkg-config brew install python@3.12 # optional -brew link --overwrite llvm@19 lld@19 libffi +export PKG_CONFIG_PATH="$(brew --prefix libffi)/lib/pkgconfig:${PKG_CONFIG_PATH:-}" +brew link --overwrite llvm@19 lld@19 # curl https://raw.githubusercontent.com/xgo-dev/llgo/refs/heads/main/install.sh | bash ./install.sh diff --git a/doc/closure.md b/doc/closure.md index 78222f972f..5dbd9b71d9 100644 --- a/doc/closure.md +++ b/doc/closure.md @@ -22,9 +22,9 @@ This document records the phase-one design from on `env != nil` and emits two exact LLVM call edges: `fn(args...)` and `fn(env, args...)`. - Native hidden env parameters use LLVM `nest` or `swiftself` parameter - attributes. WebAssembly and targets without a validated hidden-register FFI - bridge use an explicit physical env parameter, but only on env-bearing - entries. + attributes. WebAssembly and architectures without a validated LLVM + hidden-register mapping use an explicit physical env parameter, but only on + env-bearing entries. - Direct interface invocation remains a transient `(method entry, receiver)` operation. Its receiver is an ordinary ABI argument; first-class interface method values are lowered through the normal bound-wrapper closure path. @@ -110,6 +110,10 @@ FFI final hop: direct `ffi_call_go`, `ffi_call_go` plus a register bridge, or public `ffi_call` plus a TLS trampoline. The wrapper rejects missing or ambiguous selections at compile time. +Bridge calls are balanced: their targets must return normally through the +final hop so saved registers and, where used, the prior TLS context are +restored. + Although libffi's C implementation of `ffi_call_go` is a thin wrapper, it calls an architecture-private `ffi_call_int(..., closure)` and matching assembly; it cannot be reproduced outside libffi by wrapping public `ffi_call` alone. The diff --git a/runtime/internal/clite/ffi/_wrap/libffi.c b/runtime/internal/clite/ffi/_wrap/libffi.c index 3ab2d1c159..6a15770bf6 100644 --- a/runtime/internal/clite/ffi/_wrap/libffi.c +++ b/runtime/internal/clite/ffi/_wrap/libffi.c @@ -6,7 +6,7 @@ void *llgo_ffi_closure_alloc(void **code) { /* * Use libffi's Go ABI directly when its static-chain register is LLGo's nest - * register. ARM needs only a final register bridge from libffi's IP/R12 to + * register. ARM32 needs only a final register bridge from libffi's IP/R12 to * swiftself/R10. AArch64 Apple/Android use the public-ffi_call trampoline * because X18 is reserved and LLGo uses swiftself/X20 instead. * @@ -70,6 +70,9 @@ struct llgo_ffi_call_context { void *saved_return; }; +/* The target must return normally through this bridge so its callee-saved + * registers and return address can be restored. */ + /* * ffi_call_go enters this function with the context in IP/R12 and all real * arguments already marshalled. Preserve the callee-saved registers used by @@ -117,6 +120,9 @@ struct llgo_ffi_call_context { void *saved_return; }; +/* Targets must return normally through ffi_call. A non-local exit would skip + * both the trampoline's register restore and the prior TLS-context restore. */ + static _Thread_local struct llgo_ffi_call_context llgo_ffi_call_current; __attribute__((noinline, used)) static struct llgo_ffi_call_context * diff --git a/ssa/closure_abi.go b/ssa/closure_abi.go index f51d93cdda..bdb4fbe52c 100644 --- a/ssa/closure_abi.go +++ b/ssa/closure_abi.go @@ -42,9 +42,9 @@ func closureEnvABIForTarget(triple string) closureEnvABI { arch == "i386", arch == "i486", arch == "i586", arch == "i686": return closureEnvNest case arch == "riscv32", arch == "riscv64": - // LLVM lowers the RISC-V nest parameter through t2 (x7). The public - // libffi final-hop bridge installs the environment in the same register; - // the ESP32-C3 suite exercises this transport on riscv32. + // LLVM and libffi both lower the RISC-V static chain through t2 (x7), + // allowing the direct ffi_call_go path. The ESP32-C3 suite exercises + // this transport on riscv32. return closureEnvNest default: return closureEnvExplicit From e30b57223946716e06649ce176df82e4f32b2ce3 Mon Sep 17 00:00:00 2001 From: Li Jie Date: Mon, 3 Aug 2026 05:39:12 +0800 Subject: [PATCH 28/73] chore: restore portable libffi setup --- .github/actions/setup-deps/action.yml | 20 ++----------------- README.md | 3 +-- doc/_readme/scripts/install_macos.sh | 3 +-- doc/closure.md | 17 +++++++--------- .../dcepass/testdata/method_slots/expect.ll | 8 +++----- internal/dcepass/testdata/method_slots/in.ll | 14 ++++++------- runtime/internal/clite/ffi/_wrap/libffi.c | 2 +- runtime/internal/clite/ffi/ffi_link.go | 2 +- 8 files changed, 22 insertions(+), 47 deletions(-) diff --git a/.github/actions/setup-deps/action.yml b/.github/actions/setup-deps/action.yml index 99cff11ed7..35ee24ff7c 100644 --- a/.github/actions/setup-deps/action.yml +++ b/.github/actions/setup-deps/action.yml @@ -55,9 +55,8 @@ runs: fi # Install common dependencies - brew install pkg-config bdw-gc openssl libffi libuv - libffi_pc_path="$(brew --prefix libffi)/lib/pkgconfig" - echo "PKG_CONFIG_PATH=${libffi_pc_path}:${PKG_CONFIG_PATH:-}" >> "$GITHUB_ENV" + brew install bdw-gc openssl libffi libuv + brew link --overwrite libffi # Install optional deps for demos. # @@ -98,18 +97,3 @@ runs: python3.12-dev # for github.com/goplus/lib/py ) sudo apt-get install -y "${opt_deps[@]}" - - - name: Verify libffi pkg-config metadata - shell: bash - run: | - pkg-config --modversion libffi - pkg-config --cflags --libs libffi - if [[ "$(uname -s)" == "Darwin" ]]; then - resolved_prefix="$(cd "$(pkg-config --variable=prefix libffi)" && pwd -P)" - homebrew_prefix="$(cd "$(brew --prefix libffi)" && pwd -P)" - echo "resolved libffi prefix: ${resolved_prefix}" - if [[ "${resolved_prefix}" != "${homebrew_prefix}" ]]; then - echo "pkg-config did not resolve Homebrew libffi" >&2 - exit 1 - fi - fi diff --git a/README.md b/README.md index 97d23b2900..a8185aec21 100644 --- a/README.md +++ b/README.md @@ -362,8 +362,7 @@ Follow these steps to generate the `llgo` command (its usage is the same as the brew update brew install llvm@19 lld@19 bdw-gc openssl cjson libffi libuv pkg-config brew install python@3.12 # optional -export PKG_CONFIG_PATH="$(brew --prefix libffi)/lib/pkgconfig:${PKG_CONFIG_PATH:-}" -brew link --overwrite llvm@19 lld@19 +brew link --overwrite llvm@19 lld@19 libffi # curl https://raw.githubusercontent.com/xgo-dev/llgo/refs/heads/main/install.sh | bash ./install.sh ``` diff --git a/doc/_readme/scripts/install_macos.sh b/doc/_readme/scripts/install_macos.sh index a7ebace339..a2bd676820 100644 --- a/doc/_readme/scripts/install_macos.sh +++ b/doc/_readme/scripts/install_macos.sh @@ -2,7 +2,6 @@ brew update brew install llvm@19 lld@19 bdw-gc openssl cjson libffi libuv pkg-config brew install python@3.12 # optional -export PKG_CONFIG_PATH="$(brew --prefix libffi)/lib/pkgconfig:${PKG_CONFIG_PATH:-}" -brew link --overwrite llvm@19 lld@19 +brew link --overwrite llvm@19 lld@19 libffi # curl https://raw.githubusercontent.com/xgo-dev/llgo/refs/heads/main/install.sh | bash ./install.sh diff --git a/doc/closure.md b/doc/closure.md index 5dbd9b71d9..9ab953cc41 100644 --- a/doc/closure.md +++ b/doc/closure.md @@ -92,18 +92,15 @@ returns or lowers its C ABI. ordinary leading argument rather than a hidden static chain, so it cannot replace this `swiftself` bridge. - Apple/Android AArch64 use stock `ffi_call` plus the TLS final-hop trampoline: - libffi's X18 Go ABI is unavailable or incompatible there, so the trampoline - installs `swiftself`/X20. In particular, Homebrew libffi does not export - `ffi_call_go` on Apple AArch64, so there is no incoming context register for - an ARM32-style register-only bridge; public `ffi_call` needs TLS to carry - `{fn, env}` to its final target. + libffi's Go ABI uses X18 while LLGo's entry ABI uses `swiftself`/X20, so the + public `ffi_call` path needs TLS to carry `{fn, env}` to its final target. The build obtains both headers and linker flags from `pkg-config libffi`. x86 -requires `FFI_GO_CLOSURES`; a system libffi without that API is rejected rather -than retaining a second x86 FFI final-hop implementation. macOS CI installs -Homebrew libffi and pkg-config explicitly. Apple AArch64 remains on the X20 TLS -trampoline because upstream/Homebrew libffi intentionally disables its X18 Go -ABI there. +requires `FFI_GO_CLOSURES`; a libffi implementation without that API is +rejected rather than silently selecting a second x86 FFI final-hop +implementation. No Homebrew-specific libffi path is required. Apple AArch64 +remains on the X20 TLS trampoline because libffi's Go ABI uses X18 while LLGo's +selected entry ABI uses `swiftself`/X20 there. Every architecture that selects a hidden env must select exactly one native FFI final hop: direct `ffi_call_go`, `ffi_call_go` plus a register bridge, or diff --git a/internal/dcepass/testdata/method_slots/expect.ll b/internal/dcepass/testdata/method_slots/expect.ll index b57057c77e..f8aa19371a 100644 --- a/internal/dcepass/testdata/method_slots/expect.ll +++ b/internal/dcepass/testdata/method_slots/expect.ll @@ -11,9 +11,9 @@ source_filename = "dst" %"runtime/abi.FuncType" = type { %"runtime/abi.Type", %runtime.Slice, %runtime.Slice } %Task = type {} -@_llgo_main.Task = constant { %"runtime/abi.StructType", %"runtime/abi.UncommonType", [2 x %"github.com/goplus/llgo/runtime/abi.Method"] } { %"runtime/abi.StructType" { %"runtime/abi.Type" { i64 0, i64 0, i32 1, i8 13, i8 1, i8 1, i8 25, { ptr, ptr } { ptr @memequal0, ptr @_llgo_main.Task }, ptr null, %runtime.String { ptr @0, i64 9 }, ptr @"*_llgo_main.Task" }, %runtime.String zeroinitializer, %runtime.Slice zeroinitializer }, %"runtime/abi.UncommonType" { %runtime.String { ptr @1, i64 4 }, i16 2, i16 2, i32 24 }, [2 x %"github.com/goplus/llgo/runtime/abi.Method"] [%"github.com/goplus/llgo/runtime/abi.Method" { %runtime.String { ptr @2, i64 4 }, ptr @"_llgo_func$run", ptr @"github.com/goplus/llgo/runtime/internal/runtime.unreachableMethod", ptr @"github.com/goplus/llgo/runtime/internal/runtime.unreachableMethod" }, %"github.com/goplus/llgo/runtime/abi.Method" { %runtime.String { ptr @3, i64 3 }, ptr @"_llgo_func$run", ptr @"main.(*Task).Run", ptr @__llgo_stub.main.Task.Run }] }, align 8 +@_llgo_main.Task = constant { %"runtime/abi.StructType", %"runtime/abi.UncommonType", [2 x %"github.com/goplus/llgo/runtime/abi.Method"] } { %"runtime/abi.StructType" { %"runtime/abi.Type" { i64 0, i64 0, i32 1, i8 13, i8 1, i8 1, i8 25, { ptr, ptr } { ptr @memequal0, ptr @_llgo_main.Task }, ptr null, %runtime.String { ptr @0, i64 9 }, ptr @"*_llgo_main.Task" }, %runtime.String zeroinitializer, %runtime.Slice zeroinitializer }, %"runtime/abi.UncommonType" { %runtime.String { ptr @1, i64 4 }, i16 2, i16 2, i32 24 }, [2 x %"github.com/goplus/llgo/runtime/abi.Method"] [%"github.com/goplus/llgo/runtime/abi.Method" { %runtime.String { ptr @2, i64 4 }, ptr @"_llgo_func$run", ptr @"github.com/goplus/llgo/runtime/internal/runtime.unreachableMethod", ptr @"github.com/goplus/llgo/runtime/internal/runtime.unreachableMethod" }, %"github.com/goplus/llgo/runtime/abi.Method" { %runtime.String { ptr @3, i64 3 }, ptr @"_llgo_func$run", ptr @"main.(*Task).Run", ptr @main.Task.Run }] }, align 8 @0 = private constant [9 x i8] c"main.Task", align 1 -@"*_llgo_main.Task" = constant { %"runtime/abi.PtrType", %"runtime/abi.UncommonType", [2 x %"github.com/goplus/llgo/runtime/abi.Method"] } { %"runtime/abi.PtrType" { %"runtime/abi.Type" { i64 8, i64 8, i32 2, i8 11, i8 8, i8 8, i8 54, { ptr, ptr } { ptr @memequalptr, ptr null }, ptr null, %runtime.String { ptr @0, i64 9 }, ptr null }, ptr @_llgo_main.Task }, %"runtime/abi.UncommonType" { %runtime.String { ptr @1, i64 4 }, i16 2, i16 2, i32 24 }, [2 x %"github.com/goplus/llgo/runtime/abi.Method"] [%"github.com/goplus/llgo/runtime/abi.Method" { %runtime.String { ptr @2, i64 4 }, ptr @"_llgo_func$run", ptr @"github.com/goplus/llgo/runtime/internal/runtime.unreachableMethod", ptr @"github.com/goplus/llgo/runtime/internal/runtime.unreachableMethod" }, %"github.com/goplus/llgo/runtime/abi.Method" { %runtime.String { ptr @3, i64 3 }, ptr @"_llgo_func$run", ptr @"main.(*Task).Run", ptr @"__llgo_stub.main.(*Task).Run" }] }, align 8 +@"*_llgo_main.Task" = constant { %"runtime/abi.PtrType", %"runtime/abi.UncommonType", [2 x %"github.com/goplus/llgo/runtime/abi.Method"] } { %"runtime/abi.PtrType" { %"runtime/abi.Type" { i64 8, i64 8, i32 2, i8 11, i8 8, i8 8, i8 54, { ptr, ptr } { ptr @memequalptr, ptr null }, ptr null, %runtime.String { ptr @0, i64 9 }, ptr null }, ptr @_llgo_main.Task }, %"runtime/abi.UncommonType" { %runtime.String { ptr @1, i64 4 }, i16 2, i16 2, i32 24 }, [2 x %"github.com/goplus/llgo/runtime/abi.Method"] [%"github.com/goplus/llgo/runtime/abi.Method" { %runtime.String { ptr @2, i64 4 }, ptr @"_llgo_func$run", ptr @"github.com/goplus/llgo/runtime/internal/runtime.unreachableMethod", ptr @"github.com/goplus/llgo/runtime/internal/runtime.unreachableMethod" }, %"github.com/goplus/llgo/runtime/abi.Method" { %runtime.String { ptr @3, i64 3 }, ptr @"_llgo_func$run", ptr @"main.(*Task).Run", ptr @"main.(*Task).Run" }] }, align 8 @1 = private constant [4 x i8] c"main", align 1 @2 = private constant [4 x i8] c"Drop", align 1 @"_llgo_func$run" = external global %"runtime/abi.FuncType" @@ -25,8 +25,6 @@ declare void @"github.com/goplus/llgo/runtime/internal/runtime.unreachableMethod declare i64 @"main.(*Task).Run"(ptr) -declare i64 @__llgo_stub.main.Task.Run(ptr, %Task) +declare i64 @main.Task.Run(%Task) declare i1 @memequalptr(ptr, ptr, ptr) - -declare i64 @"__llgo_stub.main.(*Task).Run"(ptr, ptr) diff --git a/internal/dcepass/testdata/method_slots/in.ll b/internal/dcepass/testdata/method_slots/in.ll index 9826dc82da..3608b71952 100644 --- a/internal/dcepass/testdata/method_slots/in.ll +++ b/internal/dcepass/testdata/method_slots/in.ll @@ -26,8 +26,8 @@ }, %"runtime/abi.UncommonType" { %"runtime.String" { ptr @task.pkg, i64 4 }, i16 2, i16 2, i32 24 }, [2 x %"github.com/goplus/llgo/runtime/abi.Method"] [ - %"github.com/goplus/llgo/runtime/abi.Method" { %"runtime.String" { ptr @method.drop, i64 4 }, ptr @_llgo_func$run, ptr @"main.(*Task).Drop", ptr @"__llgo_stub.main.Task.Drop" }, - %"github.com/goplus/llgo/runtime/abi.Method" { %"runtime.String" { ptr @method.run, i64 3 }, ptr @_llgo_func$run, ptr @"main.(*Task).Run", ptr @"__llgo_stub.main.Task.Run" } + %"github.com/goplus/llgo/runtime/abi.Method" { %"runtime.String" { ptr @method.drop, i64 4 }, ptr @_llgo_func$run, ptr @"main.(*Task).Drop", ptr @"main.Task.Drop" }, + %"github.com/goplus/llgo/runtime/abi.Method" { %"runtime.String" { ptr @method.run, i64 3 }, ptr @_llgo_func$run, ptr @"main.(*Task).Run", ptr @"main.Task.Run" } ] }, align 8 @@ -38,8 +38,8 @@ }, %"runtime/abi.UncommonType" { %"runtime.String" { ptr @task.pkg, i64 4 }, i16 2, i16 2, i32 24 }, [2 x %"github.com/goplus/llgo/runtime/abi.Method"] [ - %"github.com/goplus/llgo/runtime/abi.Method" { %"runtime.String" { ptr @method.drop, i64 4 }, ptr @_llgo_func$run, ptr @"main.(*Task).Drop", ptr @"__llgo_stub.main.(*Task).Drop" }, - %"github.com/goplus/llgo/runtime/abi.Method" { %"runtime.String" { ptr @method.run, i64 3 }, ptr @_llgo_func$run, ptr @"main.(*Task).Run", ptr @"__llgo_stub.main.(*Task).Run" } + %"github.com/goplus/llgo/runtime/abi.Method" { %"runtime.String" { ptr @method.drop, i64 4 }, ptr @_llgo_func$run, ptr @"main.(*Task).Drop", ptr @"main.(*Task).Drop" }, + %"github.com/goplus/llgo/runtime/abi.Method" { %"runtime.String" { ptr @method.run, i64 3 }, ptr @_llgo_func$run, ptr @"main.(*Task).Run", ptr @"main.(*Task).Run" } ] }, align 8 @@ -76,9 +76,7 @@ declare i1 @memequal0(ptr, ptr, ptr) declare i1 @memequalptr(ptr, ptr, ptr) declare i1 @memequal64(ptr, ptr, ptr) declare i1 @interequal(ptr, ptr, ptr) +declare i64 @"main.Task.Drop"(%Task) +declare i64 @"main.Task.Run"(%Task) declare i64 @"main.(*Task).Drop"(ptr) declare i64 @"main.(*Task).Run"(ptr) -declare i64 @"__llgo_stub.main.Task.Drop"(ptr, %Task) -declare i64 @"__llgo_stub.main.Task.Run"(ptr, %Task) -declare i64 @"__llgo_stub.main.(*Task).Drop"(ptr, ptr) -declare i64 @"__llgo_stub.main.(*Task).Run"(ptr, ptr) diff --git a/runtime/internal/clite/ffi/_wrap/libffi.c b/runtime/internal/clite/ffi/_wrap/libffi.c index 6a15770bf6..f03ee0036f 100644 --- a/runtime/internal/clite/ffi/_wrap/libffi.c +++ b/runtime/internal/clite/ffi/_wrap/libffi.c @@ -34,7 +34,7 @@ void *llgo_ffi_closure_alloc(void **code) { #if defined(__APPLE__) && (defined(__x86_64__) || defined(__i386__)) && \ !defined(FFI_GO_CLOSURES) -#error "LLGo macOS x86 requires pkg-config to resolve Homebrew libffi with Go closures, not Apple SDK libffi" +#error "LLGo macOS x86 requires libffi with FFI_GO_CLOSURES" #elif defined(LLGO_FFI_CALL_GO_ARM_BRIDGE) && !defined(FFI_GO_CLOSURES) #error "LLGo hidden closure environments require libffi Go closures on ARM" #elif !defined(FFI_GO_CLOSURES) && \ diff --git a/runtime/internal/clite/ffi/ffi_link.go b/runtime/internal/clite/ffi/ffi_link.go index cc6ea4f6ce..12fb9e2fe5 100644 --- a/runtime/internal/clite/ffi/ffi_link.go +++ b/runtime/internal/clite/ffi/ffi_link.go @@ -7,7 +7,7 @@ import ( ) const ( - LLGoPackage = "link: $(pkg-config --libs libffi)" + LLGoPackage = "link: $(pkg-config --libs libffi); -lffi" LLGoFiles = "$(pkg-config --cflags libffi): _wrap/libffi.c" ) From 443369e2baf6824668f28ebeaed06387e262b558 Mon Sep 17 00:00:00 2001 From: Li Jie Date: Mon, 3 Aug 2026 06:02:37 +0800 Subject: [PATCH 29/73] runtime/ffi: support system libffi on x86 --- doc/closure.md | 25 ++++---- runtime/internal/clite/ffi/_wrap/libffi.c | 78 +++++++++++++++++++---- 2 files changed, 79 insertions(+), 24 deletions(-) diff --git a/doc/closure.md b/doc/closure.md index 9ab953cc41..50ae7d842f 100644 --- a/doc/closure.md +++ b/doc/closure.md @@ -85,22 +85,23 @@ returns or lowers its C ABI. use the semantic signature. This is the only `env != nil` decision in the reflection/FFI path; - native hidden env target: x86, RISC-V, and AArch64 targets where X18 is - available use libffi's `ffi_call_go` directly because its static-chain - register is LLGo's `nest` register. ARM also uses `ffi_call_go`; a short - final-hop bridge moves libffi's IP/R12 context to `swiftself`/R10 without - saving argument registers or using TLS. LLVM lowers ARM32 `nest` as an - ordinary leading argument rather than a hidden static chain, so it cannot - replace this `swiftself` bridge. + available use libffi's `ffi_call_go` directly when libffi exposes that API, + because its static-chain register is LLGo's `nest` register. ARM also uses + `ffi_call_go`; a short final-hop bridge moves libffi's IP/R12 context to + `swiftself`/R10 without saving argument registers or using TLS. LLVM lowers + ARM32 `nest` as an ordinary leading argument rather than a hidden static + chain, so it cannot replace this `swiftself` bridge. +- x86 libffi builds without `FFI_GO_CLOSURES`, including Apple SDK libffi, use + stock `ffi_call` plus the TLS final-hop trampoline, which installs LLVM's + `nest` register before entering the real target. - Apple/Android AArch64 use stock `ffi_call` plus the TLS final-hop trampoline: libffi's Go ABI uses X18 while LLGo's entry ABI uses `swiftself`/X20, so the public `ffi_call` path needs TLS to carry `{fn, env}` to its final target. -The build obtains both headers and linker flags from `pkg-config libffi`. x86 -requires `FFI_GO_CLOSURES`; a libffi implementation without that API is -rejected rather than silently selecting a second x86 FFI final-hop -implementation. No Homebrew-specific libffi path is required. Apple AArch64 -remains on the X20 TLS trampoline because libffi's Go ABI uses X18 while LLGo's -selected entry ABI uses `swiftself`/X20 there. +The build obtains both headers and linker flags from `pkg-config libffi`; no +Homebrew-specific libffi path is required. Apple AArch64 remains on the X20 TLS +trampoline because libffi's Go ABI uses X18 while LLGo's selected entry ABI +uses `swiftself`/X20 there. Every architecture that selects a hidden env must select exactly one native FFI final hop: direct `ffi_call_go`, `ffi_call_go` plus a register bridge, or diff --git a/runtime/internal/clite/ffi/_wrap/libffi.c b/runtime/internal/clite/ffi/_wrap/libffi.c index f03ee0036f..32bdf00522 100644 --- a/runtime/internal/clite/ffi/_wrap/libffi.c +++ b/runtime/internal/clite/ffi/_wrap/libffi.c @@ -7,8 +7,9 @@ void *llgo_ffi_closure_alloc(void **code) { /* * Use libffi's Go ABI directly when its static-chain register is LLGo's nest * register. ARM32 needs only a final register bridge from libffi's IP/R12 to - * swiftself/R10. AArch64 Apple/Android use the public-ffi_call trampoline - * because X18 is reserved and LLGo uses swiftself/X20 instead. + * swiftself/R10. Use the public-ffi_call trampoline when libffi does not + * expose its Go ABI on x86, and on AArch64 Apple/Android where X18 is reserved + * and LLGo uses swiftself/X20 instead. * * Windows follows the same architecture-selected closure ABI even though LLGo * does not support the OS yet. x86 can use the direct path below. TODO: add and @@ -27,19 +28,18 @@ void *llgo_ffi_closure_alloc(void **code) { #define LLGO_FFI_CALL_GO_DIRECT 1 #elif !defined(_WIN32) && defined(__arm__) #define LLGO_FFI_CALL_GO_ARM_BRIDGE 1 -#elif !defined(_WIN32) && defined(__aarch64__) && \ - (defined(__APPLE__) || defined(__ANDROID__)) +#elif !defined(_WIN32) && \ + (((defined(__x86_64__) || defined(__i386__)) && \ + !defined(FFI_GO_CLOSURES)) || \ + (defined(__aarch64__) && \ + (defined(__APPLE__) || defined(__ANDROID__)))) #define LLGO_FFI_CALL_PUBLIC_TRAMPOLINE 1 #endif -#if defined(__APPLE__) && (defined(__x86_64__) || defined(__i386__)) && \ - !defined(FFI_GO_CLOSURES) -#error "LLGo macOS x86 requires libffi with FFI_GO_CLOSURES" -#elif defined(LLGO_FFI_CALL_GO_ARM_BRIDGE) && !defined(FFI_GO_CLOSURES) +#if defined(LLGO_FFI_CALL_GO_ARM_BRIDGE) && !defined(FFI_GO_CLOSURES) #error "LLGo hidden closure environments require libffi Go closures on ARM" -#elif !defined(FFI_GO_CLOSURES) && \ - (defined(__x86_64__) || defined(__i386__) || defined(__riscv) || \ - defined(__riscv__) || \ +#elif !defined(_WIN32) && !defined(FFI_GO_CLOSURES) && \ + (defined(__riscv) || defined(__riscv__) || \ (defined(__aarch64__) && !defined(__APPLE__) && !defined(__ANDROID__) && \ !defined(_WIN32))) #error "LLGo hidden closure environments require libffi Go closures on this target" @@ -136,7 +136,61 @@ llgo_ffi_current_call(void) { #define LLGO_ASM_CSYM(name) #name #endif -#if defined(__aarch64__) +#if defined(__x86_64__) + +__attribute__((naked)) static void llgo_ffi_env_trampoline(void) { + __asm__ volatile( + "subq $200, %rsp\n\t" + "movq %rdi, 0(%rsp)\n\t" + "movq %rsi, 8(%rsp)\n\t" + "movq %rdx, 16(%rsp)\n\t" + "movq %rcx, 24(%rsp)\n\t" + "movq %r8, 32(%rsp)\n\t" + "movq %r9, 40(%rsp)\n\t" + "movq %rax, 48(%rsp)\n\t" + "movdqu %xmm0, 64(%rsp)\n\t" + "movdqu %xmm1, 80(%rsp)\n\t" + "movdqu %xmm2, 96(%rsp)\n\t" + "movdqu %xmm3, 112(%rsp)\n\t" + "movdqu %xmm4, 128(%rsp)\n\t" + "movdqu %xmm5, 144(%rsp)\n\t" + "movdqu %xmm6, 160(%rsp)\n\t" + "movdqu %xmm7, 176(%rsp)\n\t" + "callq " LLGO_ASM_CSYM(llgo_ffi_current_call) "\n\t" + "movq 0(%rax), %r11\n\t" + "movq 8(%rax), %r10\n\t" + "movdqu 64(%rsp), %xmm0\n\t" + "movdqu 80(%rsp), %xmm1\n\t" + "movdqu 96(%rsp), %xmm2\n\t" + "movdqu 112(%rsp), %xmm3\n\t" + "movdqu 128(%rsp), %xmm4\n\t" + "movdqu 144(%rsp), %xmm5\n\t" + "movdqu 160(%rsp), %xmm6\n\t" + "movdqu 176(%rsp), %xmm7\n\t" + "movq 0(%rsp), %rdi\n\t" + "movq 8(%rsp), %rsi\n\t" + "movq 16(%rsp), %rdx\n\t" + "movq 24(%rsp), %rcx\n\t" + "movq 32(%rsp), %r8\n\t" + "movq 40(%rsp), %r9\n\t" + "movq 48(%rsp), %rax\n\t" + "addq $200, %rsp\n\t" + "jmpq *%r11"); +} + +#elif defined(__i386__) + +__attribute__((naked)) static void llgo_ffi_env_trampoline(void) { + __asm__ volatile( + "subl $12, %esp\n\t" + "calll " LLGO_ASM_CSYM(llgo_ffi_current_call) "\n\t" + "movl 0(%eax), %edx\n\t" + "movl 4(%eax), %ecx\n\t" + "addl $12, %esp\n\t" + "jmpl *%edx"); +} + +#elif defined(__aarch64__) __attribute__((naked)) static void llgo_ffi_env_trampoline(void) { __asm__ volatile( From a87b9bbd0e40c3a0b30e445f1fc5361a9b9e1818 Mon Sep 17 00:00:00 2001 From: Li Jie Date: Mon, 3 Aug 2026 09:31:08 +0800 Subject: [PATCH 30/73] test/goroot: separate not-applicable cases --- test/goroot/README.md | 8 +- test/goroot/notapplicable.yaml | 501 ++++++++++++++++++++++++++++++++ test/goroot/runner_test.go | 92 ++++-- test/goroot/runner_unit_test.go | 57 ++++ test/goroot/xfail.yaml | 496 ------------------------------- 5 files changed, 626 insertions(+), 528 deletions(-) create mode 100644 test/goroot/notapplicable.yaml diff --git a/test/goroot/README.md b/test/goroot/README.md index e954db3daf..e591d81b7b 100644 --- a/test/goroot/README.md +++ b/test/goroot/README.md @@ -18,7 +18,12 @@ Directive modes: `coverage` follows the upstream test runner's directive and compiler flag conventions. Compile-only and diagnostic cases are executed, not omitted from the coverage total. Known failures remain executed and are classified through -`xfail.yaml`; only explicitly host-unsafe cases are skipped. +`xfail.yaml`. Cases that exercise gc-specific or otherwise inapplicable +behavior are classified separately through `notapplicable.yaml`, so the xfail +count continues to represent remaining LLGo compatibility work. Only +explicitly host-unsafe cases are skipped. Each not-applicable entry documents +both the toolchain-specific mechanism under test and why the corresponding +behavior is not an LLGo compatibility goal. Basic usage: @@ -76,3 +81,4 @@ Useful flags: - `-min-swap-free-mib`: minimum free swap in MiB - `-memory-pressure-poll`: system memory and swap sampling interval - `-xfail`: xfail YAML file, relative to repo root by default +- `-not-applicable`: not-applicable YAML file, relative to repo root by default diff --git a/test/goroot/notapplicable.yaml b/test/goroot/notapplicable.yaml new file mode 100644 index 0000000000..53798ae520 --- /dev/null +++ b/test/goroot/notapplicable.yaml @@ -0,0 +1,501 @@ +# GOROOT cases that validate gc-specific implementation details or other behavior +# outside LLGo compatibility goals. They still run, but their failures are not +# counted as remaining compatibility xfails. Every entry names the mechanism +# under test and explains the LLGo design choice that puts it out of scope. +not_applicable: + - version: go1.26 + directive: errorcheck + case: escape_array.go + reason: "not applicable: this case asserts cmd/compile-specific -m escape-analysis diagnostics; LLGo uses go/types plus LLVM and does not reproduce gc compiler diagnostic output; supporting this toolchain-specific behavior is not an LLGo compatibility goal" + - version: go1.26 + directive: errorcheck + case: escape_struct_param2.go + reason: "not applicable: this case asserts cmd/compile-specific -m escape-analysis diagnostics; LLGo uses go/types plus LLVM and does not reproduce gc compiler diagnostic output; supporting this toolchain-specific behavior is not an LLGo compatibility goal" + - version: go1.26 + directive: errorcheck + case: nilptr3.go + reason: "not applicable: this case asserts cmd/compile-specific nil-check elimination diagnostics; LLGo uses go/types plus LLVM and does not reproduce gc compiler diagnostic output; supporting this toolchain-specific behavior is not an LLGo compatibility goal" + - version: go1.26 + directive: errorcheck + case: escape6.go + reason: "not applicable: this case asserts cmd/compile-specific -m escape-analysis diagnostics; LLGo uses go/types plus LLVM and does not reproduce gc compiler diagnostic output; supporting this toolchain-specific behavior is not an LLGo compatibility goal" + - version: go1.26 + directive: errorcheck + case: escape_struct_param1.go + reason: "not applicable: this case asserts cmd/compile-specific -m escape-analysis diagnostics; LLGo uses go/types plus LLVM and does not reproduce gc compiler diagnostic output; supporting this toolchain-specific behavior is not an LLGo compatibility goal" + - version: go1.26 + directive: errorcheck + case: nilcheck.go + reason: "not applicable: this case asserts cmd/compile-specific nil-check elimination diagnostics; LLGo uses go/types plus LLVM and does not reproduce gc compiler diagnostic output; supporting this toolchain-specific behavior is not an LLGo compatibility goal" + - version: go1.26 + directive: errorcheck + case: fixedbugs/issue18331.go + reason: "not applicable: this case validates a gc-only standard-library pragma; LLGo does not use that cmd/compile pragma pipeline; supporting this toolchain-specific behavior is not an LLGo compatibility goal" + - version: go1.26 + directive: errorcheck + case: fixedbugs/issue41635.go + reason: "not applicable: this case asserts cmd/compile-specific -m optimization diagnostics; LLGo uses go/types plus LLVM and does not reproduce gc compiler diagnostic output; supporting this toolchain-specific behavior is not an LLGo compatibility goal" + - version: go1.26 + directive: errorcheck + case: fixedbugs/issue52193.go + reason: "not applicable: this case asserts cmd/compile-specific -m optimization diagnostics; LLGo uses go/types plus LLVM and does not reproduce gc compiler diagnostic output; supporting this toolchain-specific behavior is not an LLGo compatibility goal" + - version: go1.26 + directive: errorcheck + case: escape5.go + reason: "not applicable: this case asserts cmd/compile-specific -m escape-analysis diagnostics; LLGo uses go/types plus LLVM and does not reproduce gc compiler diagnostic output; supporting this toolchain-specific behavior is not an LLGo compatibility goal" + - version: go1.26 + directive: errorcheck + case: escape_slice.go + reason: "not applicable: this case asserts cmd/compile-specific -m escape-analysis diagnostics; LLGo uses go/types plus LLVM and does not reproduce gc compiler diagnostic output; supporting this toolchain-specific behavior is not an LLGo compatibility goal" + - version: go1.26 + directive: errorcheck + case: interface/assertinline.go + reason: "not applicable: this case asserts cmd/compile-specific type-assertion optimization diagnostics; LLGo uses go/types plus LLVM and does not reproduce gc compiler diagnostic output; supporting this toolchain-specific behavior is not an LLGo compatibility goal" + - version: go1.26 + directive: errorcheck + case: escape4.go + reason: "not applicable: this case asserts cmd/compile-specific -m escape-analysis diagnostics; LLGo uses go/types plus LLVM and does not reproduce gc compiler diagnostic output; supporting this toolchain-specific behavior is not an LLGo compatibility goal" + - version: go1.26 + directive: errorcheck + case: escape_selfassign.go + reason: "not applicable: this case asserts cmd/compile-specific -m escape-analysis diagnostics; LLGo uses go/types plus LLVM and does not reproduce gc compiler diagnostic output; supporting this toolchain-specific behavior is not an LLGo compatibility goal" + - version: go1.26 + directive: errorcheck + case: fixedbugs/issue14999.go + reason: "not applicable: this case asserts gc runtime heap-allocation diagnostics; LLGo uses its own runtime and does not expose gc's private compiler diagnostics; supporting this toolchain-specific behavior is not an LLGo compatibility goal" + - version: go1.26 + directive: errorcheck + case: fixedbugs/issue27732a.go + reason: "not applicable: this case asserts cmd/compile-specific small-frame and optimization diagnostics; LLGo uses go/types plus LLVM and does not reproduce gc compiler diagnostic output; supporting this toolchain-specific behavior is not an LLGo compatibility goal" + - version: go1.26 + directive: errorcheck + case: escape2n.go + reason: "not applicable: this case asserts cmd/compile-specific -m escape-analysis diagnostics; LLGo uses go/types plus LLVM and does not reproduce gc compiler diagnostic output; supporting this toolchain-specific behavior is not an LLGo compatibility goal" + - version: go1.26 + directive: errorcheck + case: escape_runtime_atomic.go + reason: "not applicable: this case asserts cmd/compile-specific -m escape-analysis diagnostics; LLGo uses go/types plus LLVM and does not reproduce gc compiler diagnostic output; supporting this toolchain-specific behavior is not an LLGo compatibility goal" + - version: go1.26 + directive: errorcheck + case: abi/result_live.go + reason: "not applicable: this case asserts cmd/compile-specific liveness diagnostics; LLGo uses go/types plus LLVM and does not reproduce gc compiler diagnostic output; supporting this toolchain-specific behavior is not an LLGo compatibility goal" + - version: go1.26 + directive: errorcheck + case: fixedbugs/issue21709.go + reason: "not applicable: this case asserts cmd/compile-specific -m optimization diagnostics; LLGo uses go/types plus LLVM and does not reproduce gc compiler diagnostic output; supporting this toolchain-specific behavior is not an LLGo compatibility goal" + - version: go1.26 + directive: errorcheck + case: fixedbugs/issue23521.go + reason: "not applicable: this case asserts cmd/compile-specific -m optimization diagnostics; LLGo uses go/types plus LLVM and does not reproduce gc compiler diagnostic output; supporting this toolchain-specific behavior is not an LLGo compatibility goal" + - version: go1.26 + directive: errorcheck + case: fixedbugs/issue18419.dir/test.go + reason: "not applicable: this case asserts cmd/compile-specific -m optimization diagnostics; LLGo uses go/types plus LLVM and does not reproduce gc compiler diagnostic output; supporting this toolchain-specific behavior is not an LLGo compatibility goal" + - version: go1.26 + directive: errorcheck + case: fixedbugs/bug388.go + reason: "not applicable: this case asserts gc runtime pseudo-type diagnostics; LLGo uses its own runtime and does not expose gc's private compiler diagnostics; supporting this toolchain-specific behavior is not an LLGo compatibility goal" + - version: go1.26 + directive: errorcheck + case: escape2.go + reason: "not applicable: this case asserts cmd/compile-specific -m escape-analysis diagnostics; LLGo uses go/types plus LLVM and does not reproduce gc compiler diagnostic output; supporting this toolchain-specific behavior is not an LLGo compatibility goal" + - version: go1.26 + directive: errorcheck + case: escape_reflect.go + reason: "not applicable: this case asserts cmd/compile-specific -m escape-analysis diagnostics; LLGo uses go/types plus LLVM and does not reproduce gc compiler diagnostic output; supporting this toolchain-specific behavior is not an LLGo compatibility goal" + - version: go1.26 + directive: errorcheck + case: sliceopt.go + reason: "not applicable: this case asserts cmd/compile-specific append and slice optimization diagnostics; LLGo uses go/types plus LLVM and does not reproduce gc compiler diagnostic output; supporting this toolchain-specific behavior is not an LLGo compatibility goal" + - version: go1.26 + directive: errorcheck + case: writebarrier.go + reason: "not applicable: this case validates gc write-barrier insertion and elimination diagnostics; LLGo's BDWGC and tinygogc runtimes do not use Go GC write barriers, so reproducing those diagnostics is not an LLGo compatibility goal" + - version: go1.26 + directive: errorcheck + case: fixedbugs/issue19743.go + reason: "not applicable: this case asserts cmd/compile-specific -m optimization diagnostics; LLGo uses go/types plus LLVM and does not reproduce gc compiler diagnostic output; supporting this toolchain-specific behavior is not an LLGo compatibility goal" + - version: go1.26 + directive: errorcheck + case: fixedbugs/issue27557.go + reason: "not applicable: this case asserts cmd/compile-specific -m optimization diagnostics; LLGo uses go/types plus LLVM and does not reproduce gc compiler diagnostic output; supporting this toolchain-specific behavior is not an LLGo compatibility goal" + - version: go1.26 + directive: errorcheck + case: fixedbugs/issue10700.dir/test.go + reason: "not applicable: this case asserts cmd/compile-specific -m optimization diagnostics; LLGo uses go/types plus LLVM and does not reproduce gc compiler diagnostic output; supporting this toolchain-specific behavior is not an LLGo compatibility goal" + - version: go1.26 + directive: errorcheck + case: escape_param.go + reason: "not applicable: this case asserts cmd/compile-specific -m escape-analysis diagnostics; LLGo uses go/types plus LLVM and does not reproduce gc compiler diagnostic output; supporting this toolchain-specific behavior is not an LLGo compatibility goal" + - version: go1.26 + directive: errorcheck + case: fixedbugs/issue31573.go + reason: "not applicable: this case asserts cmd/compile-specific -m optimization diagnostics; LLGo uses go/types plus LLVM and does not reproduce gc compiler diagnostic output; supporting this toolchain-specific behavior is not an LLGo compatibility goal" + - version: go1.26 + directive: errorcheck + case: fixedbugs/issue4099.go + reason: "not applicable: this case asserts cmd/compile-specific -m optimization diagnostics; LLGo uses go/types plus LLVM and does not reproduce gc compiler diagnostic output; supporting this toolchain-specific behavior is not an LLGo compatibility goal" + - version: go1.26 + directive: errorcheck + case: fixedbugs/issue7921.go + reason: "not applicable: this case asserts cmd/compile-specific -m optimization diagnostics; LLGo uses go/types plus LLVM and does not reproduce gc compiler diagnostic output; supporting this toolchain-specific behavior is not an LLGo compatibility goal" + - version: go1.26 + directive: errorcheck + case: fixedbugs/notinheap3.go + reason: "not applicable: this case validates gc write-barrier elimination for cgo.Incomplete-based notinheap values; LLGo's runtimes do not use Go GC write barriers, so this gc heap optimization has no LLGo counterpart and is not an LLGo compatibility goal" + - version: go1.26 + directive: errorcheck + case: escape_mutations.go + reason: "not applicable: this case asserts cmd/compile-specific escape-mutation and zerocopy diagnostics; LLGo uses go/types plus LLVM and does not reproduce gc compiler diagnostic output; supporting this toolchain-specific behavior is not an LLGo compatibility goal" + - version: go1.26 + directive: errorcheck + case: fixedbugs/notinheap2.go + reason: "not applicable: this case asserts cmd/compile-specific notinheap allocation diagnostics; LLGo uses go/types plus LLVM and does not reproduce gc compiler diagnostic output; supporting this toolchain-specific behavior is not an LLGo compatibility goal" + - version: go1.26 + directive: errorcheck + case: escape_map.go + reason: "not applicable: this case asserts cmd/compile-specific -m escape-analysis diagnostics; LLGo uses go/types plus LLVM and does not reproduce gc compiler diagnostic output; supporting this toolchain-specific behavior is not an LLGo compatibility goal" + - version: go1.26 + directive: errorcheck + case: runtime.go + reason: "not applicable: this case asserts gc runtime private-symbol compiler diagnostics; LLGo uses its own runtime and does not expose gc's private compiler diagnostics; supporting this toolchain-specific behavior is not an LLGo compatibility goal" + - version: go1.26 + directive: errorcheck + case: fixedbugs/notinheap.go + reason: "not applicable: this case asserts cmd/compile-specific notinheap allocation diagnostics; LLGo uses go/types plus LLVM and does not reproduce gc compiler diagnostic output; supporting this toolchain-specific behavior is not an LLGo compatibility goal" + - version: go1.26 + directive: errorcheck + case: escape_make_non_const.go + reason: "not applicable: this case asserts cmd/compile-specific -m escape-analysis diagnostics; LLGo uses go/types plus LLVM and does not reproduce gc compiler diagnostic output; supporting this toolchain-specific behavior is not an LLGo compatibility goal" + - version: go1.26 + directive: errorcheck + case: fuse.go + reason: "not applicable: this case asserts gc SSA late-fuse diagnostics; LLGo uses LLVM's optimization pipeline instead of gc SSA; supporting this toolchain-specific behavior is not an LLGo compatibility goal" + - version: go1.26 + directive: errorcheck + case: fixedbugs/issue17318.go + reason: "not applicable: this case asserts cmd/compile-specific -m optimization diagnostics; LLGo uses go/types plus LLVM and does not reproduce gc compiler diagnostic output; supporting this toolchain-specific behavior is not an LLGo compatibility goal" + - version: go1.26 + directive: errorcheck + case: fixedbugs/issue30898.go + reason: "not applicable: this case asserts cmd/compile-specific -m optimization diagnostics; LLGo uses go/types plus LLVM and does not reproduce gc compiler diagnostic output; supporting this toolchain-specific behavior is not an LLGo compatibility goal" + - version: go1.26 + directive: errorcheck + case: fixedbugs/issue39292.go + reason: "not applicable: this case asserts cmd/compile-specific -m optimization diagnostics; LLGo uses go/types plus LLVM and does not reproduce gc compiler diagnostic output; supporting this toolchain-specific behavior is not an LLGo compatibility goal" + - version: go1.26 + directive: errorcheck + case: fixedbugs/issue67329.go + reason: "not applicable: this case asserts cmd/compile-specific bounds-check elimination diagnostics; LLGo uses go/types plus LLVM and does not reproduce gc compiler diagnostic output; supporting this toolchain-specific behavior is not an LLGo compatibility goal" + - version: go1.26 + directive: errorcheck + case: devirtualization_with_type_assertions_interleaved.go + reason: "not applicable: this case asserts cmd/compile-specific -m devirtualization diagnostics; LLGo uses go/types plus LLVM and does not reproduce gc compiler diagnostic output; supporting this toolchain-specific behavior is not an LLGo compatibility goal" + - version: go1.26 + directive: errorcheck + case: escape_level.go + reason: "not applicable: this case asserts cmd/compile-specific -m escape-analysis diagnostics; LLGo uses go/types plus LLVM and does not reproduce gc compiler diagnostic output; supporting this toolchain-specific behavior is not an LLGo compatibility goal" + - version: go1.26 + directive: errorcheck + case: fixedbugs/issue12588.go + reason: "not applicable: this case asserts cmd/compile-specific -m optimization diagnostics; LLGo uses go/types plus LLVM and does not reproduce gc compiler diagnostic output; supporting this toolchain-specific behavior is not an LLGo compatibility goal" + - version: go1.26 + directive: errorcheck + case: fixedbugs/issue20780.go + reason: "not applicable: this case asserts cmd/compile-specific stack-frame size diagnostics; LLGo uses go/types plus LLVM and does not reproduce gc compiler diagnostic output; supporting this toolchain-specific behavior is not an LLGo compatibility goal" + - version: go1.26 + directive: errorcheck + case: bounds.go + reason: "not applicable: this case asserts cmd/compile-specific -m bounds-check diagnostics; LLGo uses go/types plus LLVM and does not reproduce gc compiler diagnostic output; supporting this toolchain-specific behavior is not an LLGo compatibility goal" + - version: go1.26 + directive: errorcheck + case: devirtualization.go + reason: "not applicable: this case asserts cmd/compile-specific -m devirtualization diagnostics; LLGo uses go/types plus LLVM and does not reproduce gc compiler diagnostic output; supporting this toolchain-specific behavior is not an LLGo compatibility goal" + - version: go1.26 + directive: errorcheck + case: escape_indir.go + reason: "not applicable: this case asserts cmd/compile-specific -m escape-analysis diagnostics; LLGo uses go/types plus LLVM and does not reproduce gc compiler diagnostic output; supporting this toolchain-specific behavior is not an LLGo compatibility goal" + - version: go1.26 + directive: errorcheck + case: live_uintptrkeepalive.go + reason: "not applicable: this case asserts cmd/compile-specific liveness and standard-package diagnostics; LLGo uses go/types plus LLVM and does not reproduce gc compiler diagnostic output; supporting this toolchain-specific behavior is not an LLGo compatibility goal" + - version: go1.26 + directive: errorcheck + case: uintptrescapes2.go + reason: "not applicable: this case asserts cmd/compile-specific escape and liveness diagnostics; LLGo uses go/types plus LLVM and does not reproduce gc compiler diagnostic output; supporting this toolchain-specific behavior is not an LLGo compatibility goal" + - version: go1.26 + directive: errorcheck + case: fixedbugs/issue19168.go + reason: "not applicable: this case validates gc write-barrier recognition for reflect header pointer stores; LLGo's BDWGC and tinygogc runtimes do not use Go GC write barriers, so reproducing those diagnostics is not an LLGo compatibility goal" + - version: go1.26 + directive: errorcheck + case: fixedbugs/issue75278.go + reason: "not applicable: this case asserts cmd/compile-specific -m optimization diagnostics; LLGo uses go/types plus LLVM and does not reproduce gc compiler diagnostic output; supporting this toolchain-specific behavior is not an LLGo compatibility goal" + - version: go1.26 + directive: errorcheck + case: typeparam/pragma.go + reason: "not applicable: this case asserts cmd/compile-specific pragma optimization diagnostics; LLGo uses go/types plus LLVM and does not reproduce gc compiler diagnostic output; supporting this toolchain-specific behavior is not an LLGo compatibility goal" + - version: go1.26 + directive: errorcheck + case: devirt.go + reason: "not applicable: this case asserts gc SSA devirtualization diagnostics; LLGo uses LLVM's optimization pipeline instead of gc SSA; supporting this toolchain-specific behavior is not an LLGo compatibility goal" + - version: go1.26 + directive: errorcheck + case: escape_iface_data.go + reason: "not applicable: this case asserts cmd/compile-specific escape-debug diagnostics; LLGo uses go/types plus LLVM and does not reproduce gc compiler diagnostic output; supporting this toolchain-specific behavior is not an LLGo compatibility goal" + - version: go1.26 + directive: errorcheck + case: live2.go + reason: "not applicable: this case asserts cmd/compile -live reports while disabling its write-barrier pass; LLGo delegates stack liveness to its LLVM backend and does not expose gc liveness reports, so matching them is not an LLGo compatibility goal" + - version: go1.26 + directive: errorcheck + case: fixedbugs/issue12006.go + reason: "not applicable: this case asserts cmd/compile-specific -m optimization diagnostics; LLGo uses go/types plus LLVM and does not reproduce gc compiler diagnostic output; supporting this toolchain-specific behavior is not an LLGo compatibility goal" + - version: go1.26 + directive: errorcheck + case: fixedbugs/issue42944.go + reason: "not applicable: this case asserts cmd/compile-specific liveness diagnostics; LLGo uses go/types plus LLVM and does not reproduce gc compiler diagnostic output; supporting this toolchain-specific behavior is not an LLGo compatibility goal" + - version: go1.26 + directive: errorcheck + case: bloop.go + reason: "not applicable: this case asserts cmd/compile-specific -m escape-analysis diagnostics; LLGo uses go/types plus LLVM and does not reproduce gc compiler diagnostic output; supporting this toolchain-specific behavior is not an LLGo compatibility goal" + - version: go1.26 + directive: errorcheck + case: defererrcheck.go + reason: "not applicable: this case asserts cmd/compile-specific defer optimization diagnostics; LLGo uses go/types plus LLVM and does not reproduce gc compiler diagnostic output; supporting this toolchain-specific behavior is not an LLGo compatibility goal" + - version: go1.26 + directive: errorcheck + case: escape_iface.go + reason: "not applicable: this case asserts cmd/compile-specific -m escape-analysis diagnostics; LLGo uses go/types plus LLVM and does not reproduce gc compiler diagnostic output; supporting this toolchain-specific behavior is not an LLGo compatibility goal" + - version: go1.26 + directive: errorcheck + case: prove_popcount.go + reason: "not applicable: this case asserts gc SSA prove diagnostics; LLGo uses LLVM's optimization pipeline instead of gc SSA; supporting this toolchain-specific behavior is not an LLGo compatibility goal" + - version: go1.26 + directive: errorcheck + case: typeparam/issue54497.go + reason: "not applicable: this case asserts cmd/compile-specific -m optimization diagnostics; LLGo uses go/types plus LLVM and does not reproduce gc compiler diagnostic output; supporting this toolchain-specific behavior is not an LLGo compatibility goal" + - version: go1.26 + directive: errorcheck + case: escape_hash_maphash.go + reason: "not applicable: this case asserts cmd/compile-specific -m escape-analysis diagnostics; LLGo uses go/types plus LLVM and does not reproduce gc compiler diagnostic output; supporting this toolchain-specific behavior is not an LLGo compatibility goal" + - version: go1.26 + directive: errorcheck + case: prove_invert_loop_with_unused_iterators.go + reason: "not applicable: this case asserts gc SSA prove diagnostics; LLGo uses LLVM's optimization pipeline instead of gc SSA; supporting this toolchain-specific behavior is not an LLGo compatibility goal" + - version: go1.26 + directive: errorcheck + case: fixedbugs/issue13799.go + reason: "not applicable: this case asserts cmd/compile-specific -m optimization diagnostics; LLGo uses go/types plus LLVM and does not reproduce gc compiler diagnostic output; supporting this toolchain-specific behavior is not an LLGo compatibility goal" + - version: go1.26 + directive: errorcheck + case: fixedbugs/issue24651b.go + reason: "not applicable: this case asserts cmd/compile-specific -m optimization diagnostics; LLGo uses go/types plus LLVM and does not reproduce gc compiler diagnostic output; supporting this toolchain-specific behavior is not an LLGo compatibility goal" + - version: go1.26 + directive: errorcheck + case: escape_goto.go + reason: "not applicable: this case asserts cmd/compile-specific -m escape-analysis diagnostics; LLGo uses go/types plus LLVM and does not reproduce gc compiler diagnostic output; supporting this toolchain-specific behavior is not an LLGo compatibility goal" + - version: go1.26 + directive: errorcheck + case: prove_constant_folding.go + reason: "not applicable: this case asserts gc SSA prove diagnostics; LLGo uses LLVM's optimization pipeline instead of gc SSA; supporting this toolchain-specific behavior is not an LLGo compatibility goal" + - version: go1.26 + directive: errorcheck + case: fixedbugs/issue16241_64.go + reason: "not applicable: this case asserts cmd/compile-specific -m optimization diagnostics; LLGo uses go/types plus LLVM and does not reproduce gc compiler diagnostic output; supporting this toolchain-specific behavior is not an LLGo compatibility goal" + - version: go1.26 + directive: errorcheck + case: fixedbugs/issue20250.go + reason: "not applicable: this case asserts cmd/compile-specific liveness diagnostics; LLGo uses go/types plus LLVM and does not reproduce gc compiler diagnostic output; supporting this toolchain-specific behavior is not an LLGo compatibility goal" + - version: go1.26 + directive: errorcheck + case: fixedbugs/issue35518.go + reason: "not applicable: this case asserts cmd/compile-specific -m optimization diagnostics; LLGo uses go/types plus LLVM and does not reproduce gc compiler diagnostic output; supporting this toolchain-specific behavior is not an LLGo compatibility goal" + - version: go1.26 + directive: errorcheck + case: escape_field.go + reason: "not applicable: this case asserts cmd/compile-specific -m escape-analysis diagnostics; LLGo uses go/types plus LLVM and does not reproduce gc compiler diagnostic output; supporting this toolchain-specific behavior is not an LLGo compatibility goal" + - version: go1.26 + directive: errorcheck + case: escape_unsafe.go + reason: "not applicable: this case asserts cmd/compile-specific -m escape-analysis diagnostics; LLGo uses go/types plus LLVM and does not reproduce gc compiler diagnostic output; supporting this toolchain-specific behavior is not an LLGo compatibility goal" + - version: go1.26 + directive: errorcheck + case: intrinsic_atomic.go + reason: "not applicable: this case asserts cmd/compile-specific intrinsic substitution diagnostics; LLGo uses go/types plus LLVM and does not reproduce gc compiler diagnostic output; supporting this toolchain-specific behavior is not an LLGo compatibility goal" + - version: go1.26 + directive: errorcheck + case: prove.go + reason: "not applicable: this case asserts gc SSA prove diagnostics; LLGo uses LLVM's optimization pipeline instead of gc SSA; supporting this toolchain-specific behavior is not an LLGo compatibility goal" + - version: go1.26 + directive: errorcheck + case: fixedbugs/issue13587.go + reason: "not applicable: this case validates gc write-barrier insertion for implicit stores to escaped result parameters; LLGo's BDWGC and tinygogc runtimes do not use Go GC write barriers, so reproducing that diagnostic is not an LLGo compatibility goal" + - version: go1.26 + directive: errorcheck + case: fixedbugs/issue16241.go + reason: "not applicable: this case asserts cmd/compile-specific -m optimization diagnostics; LLGo uses go/types plus LLVM and does not reproduce gc compiler diagnostic output; supporting this toolchain-specific behavior is not an LLGo compatibility goal" + - version: go1.26 + directive: errorcheck + case: escape_closure.go + reason: "not applicable: this case asserts cmd/compile-specific -m escape-analysis diagnostics; LLGo uses go/types plus LLVM and does not reproduce gc compiler diagnostic output; supporting this toolchain-specific behavior is not an LLGo compatibility goal" + - version: go1.26 + directive: errorcheck + case: escape_unique.go + reason: "not applicable: this case asserts cmd/compile-specific -m escape-analysis diagnostics; LLGo uses go/types plus LLVM and does not reproduce gc compiler diagnostic output; supporting this toolchain-specific behavior is not an LLGo compatibility goal" + - version: go1.26 + directive: errorcheck + case: inline_variadic.go + reason: "not applicable: this case asserts cmd/compile-specific -m inlining diagnostics; LLGo uses go/types plus LLVM and does not reproduce gc compiler diagnostic output; supporting this toolchain-specific behavior is not an LLGo compatibility goal" + - version: go1.26 + directive: errorcheck + case: phiopt.go + reason: "not applicable: this case asserts gc SSA phi optimization diagnostics; LLGo uses LLVM's optimization pipeline instead of gc SSA; supporting this toolchain-specific behavior is not an LLGo compatibility goal" + - version: go1.26 + directive: errorcheck + case: tighten.go + reason: "not applicable: this case asserts gc SSA tighten diagnostics; LLGo uses LLVM's optimization pipeline instead of gc SSA; supporting this toolchain-specific behavior is not an LLGo compatibility goal" + - version: go1.26 + directive: errorcheck + case: fixedbugs/issue35073b.go + reason: "not applicable: this case asserts cmd/compile-specific escape and checkptr diagnostics; LLGo uses go/types plus LLVM and does not reproduce gc compiler diagnostic output; supporting this toolchain-specific behavior is not an LLGo compatibility goal" + - version: go1.26 + directive: errorcheck + case: fixedbugs/issue54159.go + reason: "not applicable: this case asserts cmd/compile-specific -m optimization diagnostics; LLGo uses go/types plus LLVM and does not reproduce gc compiler diagnostic output; supporting this toolchain-specific behavior is not an LLGo compatibility goal" + - version: go1.26 + directive: errorcheck + case: internal/runtime/sys/inlinegcpc.go + reason: "not applicable: this case asserts gc runtime inlining diagnostics; LLGo uses its own runtime and does not expose gc's private compiler diagnostics; supporting this toolchain-specific behavior is not an LLGo compatibility goal" + - version: go1.26 + directive: errorcheck + case: escape_calls.go + reason: "not applicable: this case asserts cmd/compile-specific -m escape-analysis diagnostics; LLGo uses go/types plus LLVM and does not reproduce gc compiler diagnostic output; supporting this toolchain-specific behavior is not an LLGo compatibility goal" + - version: go1.26 + directive: errorcheck + case: escape_sync_atomic.go + reason: "not applicable: this case asserts cmd/compile-specific -m escape-analysis diagnostics; LLGo uses go/types plus LLVM and does not reproduce gc compiler diagnostic output; supporting this toolchain-specific behavior is not an LLGo compatibility goal" + - version: go1.26 + directive: errorcheck + case: inline_sync.go + reason: "not applicable: this case asserts cmd/compile-specific -m inlining diagnostics; LLGo uses go/types plus LLVM and does not reproduce gc compiler diagnostic output; supporting this toolchain-specific behavior is not an LLGo compatibility goal" + - version: go1.26 + directive: errorcheck + case: nowritebarrier.go + reason: "not applicable: this case validates gc runtime's private go:nowritebarrier directives; LLGo's BDWGC and tinygogc runtimes do not use Go GC write barriers or those runtime-only pragmas, so supporting them is not an LLGo compatibility goal" + - version: go1.26 + directive: errorcheck + case: tailcall.go + reason: "not applicable: this case asserts cmd/compile-specific tail-call optimization diagnostics; LLGo uses go/types plus LLVM and does not reproduce gc compiler diagnostic output; supporting this toolchain-specific behavior is not an LLGo compatibility goal" + - version: go1.26 + directive: errorcheck + case: fixedbugs/issue15747.go + reason: "not applicable: this case asserts cmd/compile-specific liveness diagnostics; LLGo uses go/types plus LLVM and does not reproduce gc compiler diagnostic output; supporting this toolchain-specific behavior is not an LLGo compatibility goal" + - version: go1.26 + directive: errorcheck + case: fixedbugs/issue34723.go + reason: "not applicable: this case validates gc write-barrier elimination for stores into newly allocated zeroed objects; LLGo's BDWGC and tinygogc runtimes do not use Go GC write barriers, so reproducing that diagnostic is not an LLGo compatibility goal" + - version: go1.26 + directive: errorcheck + case: escape_bloop.go + reason: "not applicable: this case asserts cmd/compile-specific -m escape-analysis diagnostics; LLGo uses go/types plus LLVM and does not reproduce gc compiler diagnostic output; supporting this toolchain-specific behavior is not an LLGo compatibility goal" + - version: go1.26 + directive: errorcheck + case: escape_struct_return.go + reason: "not applicable: this case asserts cmd/compile-specific -m escape-analysis diagnostics; LLGo uses go/types plus LLVM and does not reproduce gc compiler diagnostic output; supporting this toolchain-specific behavior is not an LLGo compatibility goal" + - version: go1.26 + directive: errorcheck + case: inline_big.go + reason: "not applicable: this case asserts cmd/compile-specific -m inlining diagnostics; LLGo uses go/types plus LLVM and does not reproduce gc compiler diagnostic output; supporting this toolchain-specific behavior is not an LLGo compatibility goal" + - version: go1.26 + directive: errorcheck + case: nilptr5.go + reason: "not applicable: this case asserts cmd/compile-specific -d=nil optimization diagnostics; LLGo uses go/types plus LLVM and does not reproduce gc compiler diagnostic output; supporting this toolchain-specific behavior is not an LLGo compatibility goal" + - version: go1.26 + directive: compile + case: typeparam/issue50993.go + reason: "not applicable: -d=checkptr is a cmd/compile backend debug option, not a Go language requirement; LLGo does not reproduce gc backend flags; supporting this toolchain-specific behavior is not an LLGo compatibility goal" + - version: go1.26 + directive: compile + case: fixedbugs/issue26163.go + reason: "not applicable: -d=softfloat controls cmd/compile target lowering; LLGo delegates floating-point lowering to LLVM; supporting this toolchain-specific behavior is not an LLGo compatibility goal" + - version: go1.26 + directive: compile + case: fixedbugs/issue56141.go + reason: "not applicable: -d=libfuzzer selects cmd/compile instrumentation; LLGo relies on LLVM tooling rather than gc's libfuzzer backend mode; supporting this toolchain-specific behavior is not an LLGo compatibility goal" + - version: go1.26 + directive: compile + case: fixedbugs/issue56105.go + reason: "not applicable: -d=libfuzzer selects cmd/compile instrumentation; LLGo relies on LLVM tooling rather than gc's libfuzzer backend mode; supporting this toolchain-specific behavior is not an LLGo compatibility goal" + - version: go1.26 + directive: compile + case: fixedbugs/issue34966.go + reason: "not applicable: -d=checkptr is a cmd/compile backend debug option, not a Go language requirement; LLGo does not reproduce gc backend flags; supporting this toolchain-specific behavior is not an LLGo compatibility goal" + - version: go1.26 + directive: compile + case: fixedbugs/issue58826.go + reason: "not applicable: -dynlink is a cmd/compile backend mode; LLGo uses the LLVM and native linker pipeline instead; supporting this toolchain-specific behavior is not an LLGo compatibility goal" + - version: go1.26 + directive: compile + case: fixedbugs/issue69825.go + reason: "not applicable: -d=libfuzzer selects cmd/compile instrumentation; LLGo relies on LLVM tooling rather than gc's libfuzzer backend mode; supporting this toolchain-specific behavior is not an LLGo compatibility goal" + - version: go1.24 + platform: linux/amd64 + directive: run + case: maymorestack.go + reason: "not applicable: LLGo uses fixed native stacks, so gc's growable-stack maymorestack debug hook has no corresponding behavior; supporting this toolchain-specific behavior is not an LLGo compatibility goal" + - version: go1.25 + platform: linux/amd64 + directive: run + case: maymorestack.go + reason: "not applicable: LLGo uses fixed native stacks, so gc's growable-stack maymorestack debug hook has no corresponding behavior; supporting this toolchain-specific behavior is not an LLGo compatibility goal" + - version: go1.26 + platform: linux/amd64 + directive: run + case: maymorestack.go + reason: "not applicable: LLGo uses fixed native stacks, so gc's growable-stack maymorestack debug hook has no corresponding behavior; supporting this toolchain-specific behavior is not an LLGo compatibility goal" + - version: go1.24 + platform: darwin/arm64 + directive: run + case: maymorestack.go + reason: "not applicable: LLGo uses fixed native stacks, so gc's growable-stack maymorestack debug hook has no corresponding behavior; supporting this toolchain-specific behavior is not an LLGo compatibility goal" + - version: go1.25 + platform: darwin/arm64 + directive: run + case: maymorestack.go + reason: "not applicable: LLGo uses fixed native stacks, so gc's growable-stack maymorestack debug hook has no corresponding behavior; supporting this toolchain-specific behavior is not an LLGo compatibility goal" + - version: go1.26 + platform: darwin/arm64 + directive: run + case: maymorestack.go + reason: "not applicable: LLGo uses fixed native stacks, so gc's growable-stack maymorestack debug hook has no corresponding behavior; supporting this toolchain-specific behavior is not an LLGo compatibility goal" + - version: go1.26 + directive: errorcheckandrundir + case: intrinsic.go + reason: "not applicable: this case asserts gc SSA intrinsic diagnostics; LLGo uses LLVM's optimization pipeline instead of gc SSA; the language-level run stage remains covered separately; supporting this toolchain-specific behavior is not an LLGo compatibility goal" + - version: go1.26 + directive: errorcheckandrundir + case: closure3.go + reason: "not applicable: this case asserts cmd/compile-specific escape and inlining diagnostics; LLGo uses go/types plus LLVM and does not reproduce gc compiler diagnostic output; the language-level run stage remains covered separately; supporting this toolchain-specific behavior is not an LLGo compatibility goal" + - version: go1.26 + directive: errorcheckandrundir + case: linkname.go + reason: "not applicable: this case asserts cmd/compile-specific escape and inlining diagnostics; LLGo uses go/types plus LLVM and does not reproduce gc compiler diagnostic output; the language-level run stage remains covered separately; supporting this toolchain-specific behavior is not an LLGo compatibility goal" + - version: go1.26 + directive: errorcheckandrundir + case: fixedbugs/issue37837.go + reason: "not applicable: this case asserts cmd/compile-specific escape-analysis diagnostics; LLGo uses go/types plus LLVM and does not reproduce gc compiler diagnostic output; the language-level run stage remains covered separately; supporting this toolchain-specific behavior is not an LLGo compatibility goal" + - version: go1.26 + platform: darwin/arm64 + directive: buildrundir + case: asmhdr.go + reason: "not applicable: LLGo uses LLVM and C toolchains, so the Go assembler asmhdr and symabis pipeline is outside its supported build path; supporting this toolchain-specific behavior is not an LLGo compatibility goal" + - version: go1.26 + directive: runindir + case: fixedbugs/issue20014.go + reason: "not applicable: fieldtrack is private cmd/compile and cmd/link metadata; LLGo's LLVM and native linker pipeline does not consume it; supporting this toolchain-specific behavior is not an LLGo compatibility goal" + - version: go1.26 + platform: darwin/arm64 + directive: buildrundir + case: retjmp.go + reason: "not applicable: LLGo does not accept Go assembler, so its return-jump ABI is outside the supported build path; supporting this toolchain-specific behavior is not an LLGo compatibility goal" diff --git a/test/goroot/runner_test.go b/test/goroot/runner_test.go index 9cf94de330..8f32cfb6e8 100644 --- a/test/goroot/runner_test.go +++ b/test/goroot/runner_test.go @@ -33,31 +33,32 @@ import ( ) var ( - flagGOROOT = flag.String("goroot", os.Getenv("LLGO_GOROOT"), "Go toolchain root whose GOROOT/test sources should be used") - flagGoCmd = flag.String("go", os.Getenv("LLGO_GO"), "go binary used as baseline (default: /bin/go)") - flagLLGO = flag.String("llgo", os.Getenv("LLGO_TEST_LLGO"), "llgo binary used for comparisons (default: build from current checkout)") - flagDirs = flag.String("dirs", strings.Join(defaultGoRootTestDirs, ","), "comma-separated GOROOT/test subdirectories to scan") - flagCase = flag.String("case", os.Getenv("LLGO_GOROOT_CASE"), "regexp selecting cases by relative path") - flagLimit = flag.Int("limit", 0, "maximum number of matching cases to run") - flagShardI = flag.Int("shard-index", 0, "0-based shard index used to partition matching cases") - flagShardN = flag.Int("shard-total", 1, "number of shards used to partition matching cases") - flagKeep = flag.Bool("keepwork", false, "keep temporary work directories for debugging") - flagDirMode = flag.String("directive-mode", "legacy", "case discovery mode: legacy, ci, runlike, or coverage") - flagDirective = flag.String("directives", "", "comma-separated directive filter within the selected mode") - flagXFail = flag.String("xfail", filepath.Join("test", "goroot", "xfail.yaml"), "xfail configuration path relative to repo root") - flagBuildTO = flag.Duration("build-timeout", 3*time.Minute, "timeout for each go/llgo build step; 0 disables the timeout") - flagRunTO = flag.Duration("run-timeout", time.Minute, "timeout for the compiled program run step; 0 disables the timeout") - flagSlowBld = flag.Duration("slow-build", 10*time.Second, "log build steps that exceed this duration; 0 disables slow-build logging") - flagSlowRun = flag.Duration("slow-run", 5*time.Second, "log run steps that exceed this duration; 0 disables slow-run logging") - flagProgress = flag.Duration("progress", 0, "log current GOROOT case progress at this interval; 0 disables progress logging") - flagListCases = flag.Bool("list-cases", false, "list selected case counts without building or running llgo") - flagListPaths = flag.Bool("list-case-paths", false, "list selected directive and case paths without building or running llgo") - flagMaxRSSMiB = flag.Int64("max-rss-mib", 4096, "maximum RSS in MiB for each spawned process group; 0 disables the limit") - flagRSSWarnMiB = flag.Int64("rss-warn-mib", 1024, "log commands whose observed peak process-group RSS reaches this value; 0 disables warnings") - flagRSSPoll = flag.Duration("rss-poll", 100*time.Millisecond, "process-group RSS sampling interval") - flagMinMemPct = flag.Int("min-memory-free-percent", 15, "minimum system-wide free memory percentage required to start and continue a command; 0 disables the check") - flagMinSwapMiB = flag.Int64("min-swap-free-mib", 512, "minimum free swap in MiB required to start and continue a command; 0 disables the check") - flagMemPoll = flag.Duration("memory-pressure-poll", time.Second, "system memory pressure sampling interval") + flagGOROOT = flag.String("goroot", os.Getenv("LLGO_GOROOT"), "Go toolchain root whose GOROOT/test sources should be used") + flagGoCmd = flag.String("go", os.Getenv("LLGO_GO"), "go binary used as baseline (default: /bin/go)") + flagLLGO = flag.String("llgo", os.Getenv("LLGO_TEST_LLGO"), "llgo binary used for comparisons (default: build from current checkout)") + flagDirs = flag.String("dirs", strings.Join(defaultGoRootTestDirs, ","), "comma-separated GOROOT/test subdirectories to scan") + flagCase = flag.String("case", os.Getenv("LLGO_GOROOT_CASE"), "regexp selecting cases by relative path") + flagLimit = flag.Int("limit", 0, "maximum number of matching cases to run") + flagShardI = flag.Int("shard-index", 0, "0-based shard index used to partition matching cases") + flagShardN = flag.Int("shard-total", 1, "number of shards used to partition matching cases") + flagKeep = flag.Bool("keepwork", false, "keep temporary work directories for debugging") + flagDirMode = flag.String("directive-mode", "legacy", "case discovery mode: legacy, ci, runlike, or coverage") + flagDirective = flag.String("directives", "", "comma-separated directive filter within the selected mode") + flagXFail = flag.String("xfail", filepath.Join("test", "goroot", "xfail.yaml"), "xfail configuration path relative to repo root") + flagNotApplicable = flag.String("not-applicable", filepath.Join("test", "goroot", "notapplicable.yaml"), "not-applicable configuration path relative to repo root") + flagBuildTO = flag.Duration("build-timeout", 3*time.Minute, "timeout for each go/llgo build step; 0 disables the timeout") + flagRunTO = flag.Duration("run-timeout", time.Minute, "timeout for the compiled program run step; 0 disables the timeout") + flagSlowBld = flag.Duration("slow-build", 10*time.Second, "log build steps that exceed this duration; 0 disables slow-build logging") + flagSlowRun = flag.Duration("slow-run", 5*time.Second, "log run steps that exceed this duration; 0 disables slow-run logging") + flagProgress = flag.Duration("progress", 0, "log current GOROOT case progress at this interval; 0 disables progress logging") + flagListCases = flag.Bool("list-cases", false, "list selected case counts without building or running llgo") + flagListPaths = flag.Bool("list-case-paths", false, "list selected directive and case paths without building or running llgo") + flagMaxRSSMiB = flag.Int64("max-rss-mib", 4096, "maximum RSS in MiB for each spawned process group; 0 disables the limit") + flagRSSWarnMiB = flag.Int64("rss-warn-mib", 1024, "log commands whose observed peak process-group RSS reaches this value; 0 disables warnings") + flagRSSPoll = flag.Duration("rss-poll", 100*time.Millisecond, "process-group RSS sampling interval") + flagMinMemPct = flag.Int("min-memory-free-percent", 15, "minimum system-wide free memory percentage required to start and continue a command; 0 disables the check") + flagMinSwapMiB = flag.Int64("min-swap-free-mib", 512, "minimum free swap in MiB required to start and continue a command; 0 disables the check") + flagMemPoll = flag.Duration("memory-pressure-poll", time.Second, "system memory pressure sampling interval") ) var defaultGoRootTestDirs = []string{ @@ -99,6 +100,10 @@ type xfailConfig struct { Timeouts []timeoutEntry `yaml:"timeouts"` } +type notApplicableConfig struct { + Entries []xfailEntry `yaml:"not_applicable"` +} + type xfailEntry struct { Version string `yaml:"version"` Platform string `yaml:"platform"` @@ -282,6 +287,7 @@ func TestGoRootRunCases(t *testing.T) { } xfails := loadXFailConfig(t, repoRoot, *flagXFail) + notApplicable := loadNotApplicableConfig(t, repoRoot, *flagNotApplicable) caseFilter := compileCaseFilter(t, *flagCase) mode := loadDirectiveMode(t, *flagDirMode) mode = filterDirectiveMode(t, mode, *flagDirective) @@ -345,13 +351,21 @@ func TestGoRootRunCases(t *testing.T) { } match, reason := xfails.Match(envInfo.GOVERSION, envInfo.GOOS+"/"+envInfo.GOARCH, tc) flaky, flakyReason := xfails.MatchFlaky(envInfo.GOVERSION, envInfo.GOOS+"/"+envInfo.GOARCH, tc) + notApply, notApplyReason := notApplicable.Match(envInfo.GOVERSION, envInfo.GOOS+"/"+envInfo.GOARCH, tc) + if match && notApply { + t.Fatalf("case matches both xfail and not-applicable expectations: xfail=%s; not applicable=%s", reason, notApplyReason) + } switch { + case err == nil && notApply: + t.Fatalf("unexpected success for not-applicable case: %s", notApplyReason) case err == nil && match: t.Fatalf("unexpected success for xfail case: %s", reason) case err == nil && flaky: t.Logf("flaky case passed: %s", flakyReason) case err != nil && match: t.Logf("expected failure: %s", reason) + case err != nil && notApply: + t.Logf("expected not-applicable failure: %s", notApplyReason) case err != nil && flaky: t.Logf("known flaky failure: %s", flakyReason) case err != nil: @@ -430,6 +444,20 @@ func buildLLGOBinary(t *testing.T, repoRoot, goCmd string) string { } func loadXFailConfig(t *testing.T, repoRoot, relPath string) xfailConfig { + t.Helper() + var cfg xfailConfig + loadExpectationConfig(t, repoRoot, relPath, &cfg) + return cfg +} + +func loadNotApplicableConfig(t *testing.T, repoRoot, relPath string) notApplicableConfig { + t.Helper() + var cfg notApplicableConfig + loadExpectationConfig(t, repoRoot, relPath, &cfg) + return cfg +} + +func loadExpectationConfig(t *testing.T, repoRoot, relPath string, cfg any) { t.Helper() path := relPath if !filepath.IsAbs(path) { @@ -437,16 +465,14 @@ func loadXFailConfig(t *testing.T, repoRoot, relPath string) xfailConfig { } data, err := os.ReadFile(path) if errors.Is(err, os.ErrNotExist) { - return xfailConfig{} + return } if err != nil { - t.Fatalf("read xfail file %q: %v", path, err) + t.Fatalf("read expectation file %q: %v", path, err) } - var cfg xfailConfig - if err := yaml.Unmarshal(data, &cfg); err != nil { - t.Fatalf("parse xfail file %q: %v", path, err) + if err := yaml.Unmarshal(data, cfg); err != nil { + t.Fatalf("parse expectation file %q: %v", path, err) } - return cfg } func compileCaseFilter(t *testing.T, expr string) *regexp.Regexp { @@ -2039,6 +2065,10 @@ func (cfg xfailConfig) Match(goVersion, platform string, tc testCase) (bool, str return matchEntries(cfg.Entries, goVersion, platform, tc) } +func (cfg notApplicableConfig) Match(goVersion, platform string, tc testCase) (bool, string) { + return matchEntries(cfg.Entries, goVersion, platform, tc) +} + func (cfg xfailConfig) MatchFlaky(goVersion, platform string, tc testCase) (bool, string) { return matchEntries(cfg.Flakes, goVersion, platform, tc) } diff --git a/test/goroot/runner_unit_test.go b/test/goroot/runner_unit_test.go index 08a2126c04..b99b654fed 100644 --- a/test/goroot/runner_unit_test.go +++ b/test/goroot/runner_unit_test.go @@ -102,6 +102,63 @@ func TestXFailMatch(t *testing.T) { } } +func TestNotApplicableMatch(t *testing.T) { + cfg := notApplicableConfig{ + Entries: []xfailEntry{{ + Version: "go1.26", + Directive: "errorcheck", + Case: "writebarrier.go", + Reason: "not applicable: this case checks gc write barriers; LLGo uses a collector without those barriers, so reproducing them is not an LLGo compatibility goal", + }}, + } + tc := testCase{RelPath: "writebarrier.go", Directive: "errorcheck"} + match, reason := cfg.Match("go1.26.5", "linux/amd64", tc) + if !match { + t.Fatal("expected not-applicable match") + } + if reason != "not applicable: this case checks gc write barriers; LLGo uses a collector without those barriers, so reproducing them is not an LLGo compatibility goal" { + t.Fatalf("reason=%q, want not-applicable reason", reason) + } +} + +func TestRepositoryExpectationsAreSeparated(t *testing.T) { + repo := repoRoot(t) + xfails := loadXFailConfig(t, repo, filepath.Join("test", "goroot", "xfail.yaml")) + notApplicable := loadNotApplicableConfig(t, repo, filepath.Join("test", "goroot", "notapplicable.yaml")) + if len(notApplicable.Entries) == 0 { + t.Fatal("not-applicable expectation file is empty") + } + + type selector struct { + version string + platform string + directive string + casePath string + } + xfailSelectors := make(map[selector]struct{}, len(xfails.Entries)) + for _, entry := range xfails.Entries { + if strings.HasPrefix(entry.Reason, "not applicable:") { + t.Fatalf("xfail entry %q has a not-applicable reason", entry.Case) + } + xfailSelectors[selector{entry.Version, entry.Platform, entry.Directive, entry.Case}] = struct{}{} + } + for _, entry := range notApplicable.Entries { + if !strings.HasPrefix(entry.Reason, "not applicable:") { + t.Fatalf("not-applicable entry %q has reason %q without the shared prefix", entry.Case, entry.Reason) + } + if !strings.Contains(entry.Reason, "LLGo") { + t.Fatalf("not-applicable entry %q has reason %q without the LLGo design rationale", entry.Case, entry.Reason) + } + if !strings.Contains(entry.Reason, "compatibility goal") { + t.Fatalf("not-applicable entry %q has reason %q without explaining why support is not planned", entry.Case, entry.Reason) + } + key := selector{entry.Version, entry.Platform, entry.Directive, entry.Case} + if _, ok := xfailSelectors[key]; ok { + t.Fatalf("expectation selector appears in both files: %+v", key) + } + } +} + func TestFlakyMatch(t *testing.T) { cfg := xfailConfig{ Flakes: []xfailEntry{{ diff --git a/test/goroot/xfail.yaml b/test/goroot/xfail.yaml index cee4671e72..761813f9d9 100644 --- a/test/goroot/xfail.yaml +++ b/test/goroot/xfail.yaml @@ -1818,62 +1818,14 @@ flakes: case: fixedbugs/issue25897a.go reason: reflect-generated goroutines under a single-P continuous-GC loop can complete or exceed the 1m run timeout on darwin/arm64 xfails: - - version: go1.26 - directive: errorcheck - case: escape_array.go - reason: gc-specific -m escape-analysis diagnostics are not implemented by llgo - - version: go1.26 - directive: errorcheck - case: escape_struct_param2.go - reason: gc-specific -m escape-analysis diagnostics are not implemented by llgo - - version: go1.26 - directive: errorcheck - case: nilptr3.go - reason: gc-specific nil-check elimination diagnostics are not implemented by llgo - version: go1.26 directive: errorcheck case: fixedbugs/issue23664.go reason: llgo parser recovery emits additional malformed-declaration diagnostics - - version: go1.26 - directive: errorcheck - case: escape6.go - reason: gc-specific -m escape-analysis diagnostics are not implemented by llgo - - version: go1.26 - directive: errorcheck - case: escape_struct_param1.go - reason: gc-specific -m escape-analysis diagnostics are not implemented by llgo - - version: go1.26 - directive: errorcheck - case: nilcheck.go - reason: gc-specific nil-check elimination diagnostics are not implemented by llgo - - version: go1.26 - directive: errorcheck - case: fixedbugs/issue18331.go - reason: gc standard-library pragma validation is not implemented by llgo - - version: go1.26 - directive: errorcheck - case: fixedbugs/issue41635.go - reason: gc-specific -m optimization diagnostics are not implemented by llgo - - version: go1.26 - directive: errorcheck - case: fixedbugs/issue52193.go - reason: gc-specific -m optimization diagnostics are not implemented by llgo - version: go1.26 directive: errorcheck case: fixedbugs/issue33386.go reason: llgo parser recovery emits additional malformed-go/defer diagnostics - - version: go1.26 - directive: errorcheck - case: escape5.go - reason: gc-specific -m escape-analysis diagnostics are not implemented by llgo - - version: go1.26 - directive: errorcheck - case: escape_slice.go - reason: gc-specific -m escape-analysis diagnostics are not implemented by llgo - - version: go1.26 - directive: errorcheck - case: interface/assertinline.go - reason: gc-specific type-assertion optimization diagnostics are not implemented by llgo - version: go1.26 directive: errorcheck case: fixedbugs/bug349.go @@ -1886,22 +1838,6 @@ xfails: directive: errorcheck case: syntax/semi7.go reason: llgo parser recovery emits additional semicolon and else diagnostics - - version: go1.26 - directive: errorcheck - case: escape4.go - reason: gc-specific -m escape-analysis diagnostics are not implemented by llgo - - version: go1.26 - directive: errorcheck - case: escape_selfassign.go - reason: gc-specific -m escape-analysis diagnostics are not implemented by llgo - - version: go1.26 - directive: errorcheck - case: fixedbugs/issue14999.go - reason: gc runtime heap-allocation diagnostics are not implemented by llgo - - version: go1.26 - directive: errorcheck - case: fixedbugs/issue27732a.go - reason: gc-specific small-frame and optimization diagnostics are not implemented by llgo - version: go1.26 directive: errorcheck case: fixedbugs/bug274.go @@ -1914,34 +1850,6 @@ xfails: directive: errorcheck case: fixedbugs/issue4776.go reason: llgo parser uses a different missing-package-clause diagnostic - - version: go1.26 - directive: errorcheck - case: escape2n.go - reason: gc-specific -m escape-analysis diagnostics are not implemented by llgo - - version: go1.26 - directive: errorcheck - case: escape_runtime_atomic.go - reason: gc-specific -m escape-analysis diagnostics are not implemented by llgo - - version: go1.26 - directive: errorcheck - case: abi/result_live.go - reason: gc-specific liveness diagnostics are not implemented by llgo - - version: go1.26 - directive: errorcheck - case: fixedbugs/issue21709.go - reason: gc-specific -m optimization diagnostics are not implemented by llgo - - version: go1.26 - directive: errorcheck - case: fixedbugs/issue23521.go - reason: gc-specific -m optimization diagnostics are not implemented by llgo - - version: go1.26 - directive: errorcheck - case: fixedbugs/issue18419.dir/test.go - reason: gc-specific -m optimization diagnostics are not implemented by llgo - - version: go1.26 - directive: errorcheck - case: fixedbugs/bug388.go - reason: gc runtime pseudo-type diagnostics are not implemented by llgo - version: go1.26 directive: errorcheck case: switch2.go @@ -1954,34 +1862,6 @@ xfails: directive: errorcheck case: syntax/semi5.go reason: llgo parser recovery emits additional semicolon and end-of-file diagnostics - - version: go1.26 - directive: errorcheck - case: escape2.go - reason: gc-specific -m escape-analysis diagnostics are not implemented by llgo - - version: go1.26 - directive: errorcheck - case: escape_reflect.go - reason: gc-specific -m escape-analysis diagnostics are not implemented by llgo - - version: go1.26 - directive: errorcheck - case: sliceopt.go - reason: gc-specific append and slice optimization diagnostics are not implemented by llgo - - version: go1.26 - directive: errorcheck - case: writebarrier.go - reason: "not applicable: llgo's BDWGC and tinygogc runtimes do not use Go GC write barriers" - - version: go1.26 - directive: errorcheck - case: fixedbugs/issue19743.go - reason: gc-specific -m optimization diagnostics are not implemented by llgo - - version: go1.26 - directive: errorcheck - case: fixedbugs/issue27557.go - reason: gc-specific -m optimization diagnostics are not implemented by llgo - - version: go1.26 - directive: errorcheck - case: fixedbugs/issue10700.dir/test.go - reason: gc-specific -m optimization diagnostics are not implemented by llgo - version: go1.26 directive: errorcheck case: fixedbugs/issue13274.go @@ -1994,26 +1874,6 @@ xfails: directive: errorcheck case: syntax/semi4.go reason: llgo parser recovery emits additional semicolon and brace diagnostics - - version: go1.26 - directive: errorcheck - case: escape_param.go - reason: gc-specific -m escape-analysis diagnostics are not implemented by llgo - - version: go1.26 - directive: errorcheck - case: fixedbugs/issue31573.go - reason: gc-specific -m optimization diagnostics are not implemented by llgo - - version: go1.26 - directive: errorcheck - case: fixedbugs/issue4099.go - reason: gc-specific -m optimization diagnostics are not implemented by llgo - - version: go1.26 - directive: errorcheck - case: fixedbugs/issue7921.go - reason: gc-specific -m optimization diagnostics are not implemented by llgo - - version: go1.26 - directive: errorcheck - case: fixedbugs/notinheap3.go - reason: "not applicable: llgo's runtimes do not use Go GC write barriers; notinheap diagnostics are covered separately" - version: go1.26 directive: errorcheck case: fixedbugs/issue13273.go @@ -2022,14 +1882,6 @@ xfails: directive: errorcheck case: syntax/semi3.go reason: llgo parser recovery emits additional semicolon and end-of-file diagnostics - - version: go1.26 - directive: errorcheck - case: escape_mutations.go - reason: gc-specific escape-mutation and zerocopy diagnostics are not implemented by llgo - - version: go1.26 - directive: errorcheck - case: fixedbugs/notinheap2.go - reason: gc-specific notinheap allocation diagnostics are not implemented by llgo - version: go1.26 directive: errorcheck case: fixedbugs/issue13266.go @@ -2042,18 +1894,6 @@ xfails: directive: errorcheck case: syntax/semi2.go reason: llgo parser recovery emits additional semicolon and brace diagnostics - - version: go1.26 - directive: errorcheck - case: escape_map.go - reason: gc-specific -m escape-analysis diagnostics are not implemented by llgo - - version: go1.26 - directive: errorcheck - case: runtime.go - reason: gc runtime private-symbol compiler diagnostics are not implemented by llgo - - version: go1.26 - directive: errorcheck - case: fixedbugs/notinheap.go - reason: gc-specific notinheap allocation diagnostics are not implemented by llgo - version: go1.26 directive: errorcheck case: fixedbugs/issue13248.go @@ -2066,30 +1906,6 @@ xfails: directive: errorcheck case: syntax/semi1.go reason: llgo parser recovery emits additional semicolon and end-of-file diagnostics - - version: go1.26 - directive: errorcheck - case: escape_make_non_const.go - reason: gc-specific -m escape-analysis diagnostics are not implemented by llgo - - version: go1.26 - directive: errorcheck - case: fuse.go - reason: gc-specific SSA late-fuse diagnostics are not implemented by llgo - - version: go1.26 - directive: errorcheck - case: fixedbugs/issue17318.go - reason: gc-specific -m optimization diagnostics are not implemented by llgo - - version: go1.26 - directive: errorcheck - case: fixedbugs/issue30898.go - reason: gc-specific -m optimization diagnostics are not implemented by llgo - - version: go1.26 - directive: errorcheck - case: fixedbugs/issue39292.go - reason: gc-specific -m optimization diagnostics are not implemented by llgo - - version: go1.26 - directive: errorcheck - case: fixedbugs/issue67329.go - reason: gc-specific bounds-check elimination diagnostics are not implemented by llgo - version: go1.26 directive: errorcheck case: fixedbugs/issue20789.go @@ -2098,78 +1914,10 @@ xfails: directive: errorcheck case: syntax/initvar.go reason: llgo parser recovery emits additional invalid-initializer diagnostics - - version: go1.26 - directive: errorcheck - case: devirtualization_with_type_assertions_interleaved.go - reason: gc-specific -m devirtualization diagnostics are not implemented by llgo - - version: go1.26 - directive: errorcheck - case: escape_level.go - reason: gc-specific -m escape-analysis diagnostics are not implemented by llgo - - version: go1.26 - directive: errorcheck - case: fixedbugs/issue12588.go - reason: gc-specific -m optimization diagnostics are not implemented by llgo - - version: go1.26 - directive: errorcheck - case: fixedbugs/issue20780.go - reason: gc-specific stack-frame size diagnostics are not implemented by llgo - - version: go1.26 - directive: errorcheck - case: bounds.go - reason: gc-specific -m bounds-check diagnostics are not implemented by llgo - - version: go1.26 - directive: errorcheck - case: devirtualization.go - reason: gc-specific -m devirtualization diagnostics are not implemented by llgo - - version: go1.26 - directive: errorcheck - case: escape_indir.go - reason: gc-specific -m escape-analysis diagnostics are not implemented by llgo - - version: go1.26 - directive: errorcheck - case: live_uintptrkeepalive.go - reason: gc-specific liveness and standard-package diagnostics are not implemented by llgo - - version: go1.26 - directive: errorcheck - case: uintptrescapes2.go - reason: gc-specific escape and liveness diagnostics are not implemented by llgo - - version: go1.26 - directive: errorcheck - case: fixedbugs/issue19168.go - reason: "not applicable: llgo's BDWGC and tinygogc runtimes do not use Go GC write barriers" - - version: go1.26 - directive: errorcheck - case: fixedbugs/issue75278.go - reason: gc-specific -m optimization diagnostics are not implemented by llgo - - version: go1.26 - directive: errorcheck - case: typeparam/pragma.go - reason: gc-specific pragma optimization diagnostics are not implemented by llgo - version: go1.26 directive: errorcheck case: fixedbugs/bug050.go reason: llgo parser emits an additional malformed-declaration diagnostic - - version: go1.26 - directive: errorcheck - case: devirt.go - reason: gc-specific SSA devirtualization diagnostics are not implemented by llgo - - version: go1.26 - directive: errorcheck - case: escape_iface_data.go - reason: gc-specific escape-debug diagnostics are not implemented by llgo - - version: go1.26 - directive: errorcheck - case: live2.go - reason: "not applicable: llgo's runtimes do not use Go GC write barriers; liveness diagnostics require separate compiler support" - - version: go1.26 - directive: errorcheck - case: fixedbugs/issue12006.go - reason: gc-specific -m optimization diagnostics are not implemented by llgo - - version: go1.26 - directive: errorcheck - case: fixedbugs/issue42944.go - reason: gc-specific liveness diagnostics are not implemented by llgo - version: go1.26 directive: errorcheck case: bombad.go @@ -2186,66 +1934,10 @@ xfails: directive: errorcheck case: fixedbugs/issue22581.go reason: llgo parser recovery emits additional malformed-control-clause diagnostics - - version: go1.26 - directive: errorcheck - case: bloop.go - reason: gc-specific -m escape-analysis diagnostics are not implemented by llgo - - version: go1.26 - directive: errorcheck - case: defererrcheck.go - reason: gc-specific defer optimization diagnostics are not implemented by llgo - - version: go1.26 - directive: errorcheck - case: escape_iface.go - reason: gc-specific -m escape-analysis diagnostics are not implemented by llgo - - version: go1.26 - directive: errorcheck - case: prove_popcount.go - reason: gc-specific SSA prove diagnostics are not implemented by llgo - - version: go1.26 - directive: errorcheck - case: typeparam/issue54497.go - reason: gc-specific -m optimization diagnostics are not implemented by llgo - version: go1.26 directive: errorcheck case: syntax/ddd.go reason: llgo parser recovery emits additional malformed-selector diagnostics - - version: go1.26 - directive: errorcheck - case: escape_hash_maphash.go - reason: gc-specific -m escape-analysis diagnostics are not implemented by llgo - - version: go1.26 - directive: errorcheck - case: prove_invert_loop_with_unused_iterators.go - reason: gc-specific SSA prove diagnostics are not implemented by llgo - - version: go1.26 - directive: errorcheck - case: fixedbugs/issue13799.go - reason: gc-specific -m optimization diagnostics are not implemented by llgo - - version: go1.26 - directive: errorcheck - case: fixedbugs/issue24651b.go - reason: gc-specific -m optimization diagnostics are not implemented by llgo - - version: go1.26 - directive: errorcheck - case: escape_goto.go - reason: gc-specific -m escape-analysis diagnostics are not implemented by llgo - - version: go1.26 - directive: errorcheck - case: prove_constant_folding.go - reason: gc-specific SSA prove diagnostics are not implemented by llgo - - version: go1.26 - directive: errorcheck - case: fixedbugs/issue16241_64.go - reason: gc-specific -m optimization diagnostics are not implemented by llgo - - version: go1.26 - directive: errorcheck - case: fixedbugs/issue20250.go - reason: gc-specific liveness diagnostics are not implemented by llgo - - version: go1.26 - directive: errorcheck - case: fixedbugs/issue35518.go - reason: gc-specific -m optimization diagnostics are not implemented by llgo - version: go1.26 directive: errorcheck case: fixedbugs/bug121.go @@ -2258,66 +1950,10 @@ xfails: directive: errorcheck case: syntax/chan1.go reason: llgo parser recovery emits additional malformed-channel diagnostics - - version: go1.26 - directive: errorcheck - case: escape_field.go - reason: gc-specific -m escape-analysis diagnostics are not implemented by llgo - - version: go1.26 - directive: errorcheck - case: escape_unsafe.go - reason: gc-specific -m escape-analysis diagnostics are not implemented by llgo - - version: go1.26 - directive: errorcheck - case: intrinsic_atomic.go - reason: gc-specific intrinsic substitution diagnostics are not implemented by llgo - - version: go1.26 - directive: errorcheck - case: prove.go - reason: gc-specific SSA prove diagnostics are not implemented by llgo - - version: go1.26 - directive: errorcheck - case: fixedbugs/issue13587.go - reason: "not applicable: llgo's BDWGC and tinygogc runtimes do not use Go GC write barriers" - - version: go1.26 - directive: errorcheck - case: fixedbugs/issue16241.go - reason: gc-specific -m optimization diagnostics are not implemented by llgo - version: go1.26 directive: errorcheck case: fixedbugs/issue18747.go reason: llgo parser recovery emits additional undefined-name diagnostics - - version: go1.26 - directive: errorcheck - case: escape_closure.go - reason: gc-specific -m escape-analysis diagnostics are not implemented by llgo - - version: go1.26 - directive: errorcheck - case: escape_unique.go - reason: gc-specific -m escape-analysis diagnostics are not implemented by llgo - - version: go1.26 - directive: errorcheck - case: inline_variadic.go - reason: gc-specific -m inlining diagnostics are not implemented by llgo - - version: go1.26 - directive: errorcheck - case: phiopt.go - reason: gc-specific SSA phi optimization diagnostics are not implemented by llgo - - version: go1.26 - directive: errorcheck - case: tighten.go - reason: gc-specific SSA tighten diagnostics are not implemented by llgo - - version: go1.26 - directive: errorcheck - case: fixedbugs/issue35073b.go - reason: gc-specific escape and checkptr diagnostics are not implemented by llgo - - version: go1.26 - directive: errorcheck - case: fixedbugs/issue54159.go - reason: gc-specific -m optimization diagnostics are not implemented by llgo - - version: go1.26 - directive: errorcheck - case: internal/runtime/sys/inlinegcpc.go - reason: gc runtime inlining diagnostics are not implemented by llgo - version: go1.26 directive: errorcheck case: fixedbugs/issue11610.go @@ -2326,86 +1962,14 @@ xfails: directive: errorcheck case: fixedbugs/issue22164.go reason: llgo parser recovery emits additional diagnostics for a malformed argument list - - version: go1.26 - directive: errorcheck - case: escape_calls.go - reason: gc-specific -m escape-analysis diagnostics are not implemented by llgo - - version: go1.26 - directive: errorcheck - case: escape_sync_atomic.go - reason: gc-specific -m escape-analysis diagnostics are not implemented by llgo - - version: go1.26 - directive: errorcheck - case: inline_sync.go - reason: gc-specific -m inlining diagnostics are not implemented by llgo - - version: go1.26 - directive: errorcheck - case: nowritebarrier.go - reason: "not applicable: llgo's BDWGC and tinygogc runtimes do not use Go GC write barriers" - - version: go1.26 - directive: errorcheck - case: tailcall.go - reason: gc-specific tail-call optimization diagnostics are not implemented by llgo - - version: go1.26 - directive: errorcheck - case: fixedbugs/issue15747.go - reason: gc-specific liveness diagnostics are not implemented by llgo - - version: go1.26 - directive: errorcheck - case: fixedbugs/issue34723.go - reason: "not applicable: llgo's BDWGC and tinygogc runtimes do not use Go GC write barriers" - version: go1.26 directive: errorcheck case: syntax/vareq1.go reason: llgo parser recovery emits an additional diagnostic after the expected syntax error - - version: go1.26 - directive: errorcheck - case: escape_bloop.go - reason: gc-specific -m escape-analysis diagnostics are not implemented by llgo - - version: go1.26 - directive: errorcheck - case: escape_struct_return.go - reason: gc-specific -m escape-analysis diagnostics are not implemented by llgo - - version: go1.26 - directive: errorcheck - case: inline_big.go - reason: gc-specific -m inlining diagnostics are not implemented by llgo - - version: go1.26 - directive: errorcheck - case: nilptr5.go - reason: gc-specific -d=nil optimization diagnostics are not implemented by llgo - version: go1.26 directive: errorcheck case: syntax/vareq.go reason: llgo parser recovery emits additional diagnostics after the expected syntax error - - version: go1.26 - directive: compile - case: typeparam/issue50993.go - reason: gc-specific -d=checkptr backend option is not implemented by llgo - - version: go1.26 - directive: compile - case: fixedbugs/issue26163.go - reason: gc-specific -d=softfloat backend option is not implemented by llgo - - version: go1.26 - directive: compile - case: fixedbugs/issue56141.go - reason: gc-specific -d=libfuzzer backend option is not implemented by llgo - - version: go1.26 - directive: compile - case: fixedbugs/issue56105.go - reason: gc-specific -d=libfuzzer backend option is not implemented by llgo - - version: go1.26 - directive: compile - case: fixedbugs/issue34966.go - reason: gc-specific -d=checkptr backend option is not implemented by llgo - - version: go1.26 - directive: compile - case: fixedbugs/issue58826.go - reason: gc-specific -dynlink backend mode is not implemented by llgo - - version: go1.26 - directive: compile - case: fixedbugs/issue69825.go - reason: gc-specific -d=libfuzzer backend option is not implemented by llgo - version: go1.24 platform: darwin/arm64 directive: run @@ -2758,21 +2322,6 @@ xfails: directive: run case: fixedbugs/issue75327.go reason: go1.26 goroot run failure on linux/amd64 - - version: go1.24 - platform: linux/amd64 - directive: run - case: maymorestack.go - reason: go1.24 goroot ci-mode run failure on linux/amd64 - - version: go1.25 - platform: linux/amd64 - directive: run - case: maymorestack.go - reason: go1.25 goroot ci-mode run failure on linux/amd64 - - version: go1.26 - platform: linux/amd64 - directive: run - case: maymorestack.go - reason: go1.26 goroot ci-mode run failure on linux/amd64 - version: go1.24 platform: linux/amd64 directive: runoutput @@ -3150,21 +2699,6 @@ xfails: directive: run case: fixedbugs/issue5493.go reason: go1.24 goroot run failure on linux/amd64 - - version: go1.24 - platform: darwin/arm64 - directive: run - case: maymorestack.go - reason: go1.24 goroot ci-mode run failure on darwin/arm64 - - version: go1.25 - platform: darwin/arm64 - directive: run - case: maymorestack.go - reason: go1.25 goroot ci-mode run failure on darwin/arm64 - - version: go1.26 - platform: darwin/arm64 - directive: run - case: maymorestack.go - reason: go1.26 goroot ci-mode run failure on darwin/arm64 - version: go1.26 platform: linux/amd64 directive: run @@ -3482,32 +3016,11 @@ xfails: directive: runoutput case: index0.go reason: current main goroot runoutput failure on linux/amd64 - - version: go1.26 - directive: errorcheckandrundir - case: intrinsic.go - reason: gc-specific SSA intrinsic diagnostics are not implemented by llgo; the run stage still executes - - version: go1.26 - directive: errorcheckandrundir - case: closure3.go - reason: gc-specific escape and inlining diagnostics are not implemented by llgo; the run stage still executes - - version: go1.26 - directive: errorcheckandrundir - case: linkname.go - reason: gc-specific escape and inlining diagnostics are not implemented by llgo; the run stage still executes - - version: go1.26 - directive: errorcheckandrundir - case: fixedbugs/issue37837.go - reason: gc-specific escape-analysis diagnostics are not implemented by llgo; the run stage still executes - version: go1.26 platform: darwin/arm64 directive: rundir case: fixedbugs/issue29919.go reason: runtime CallersFrames reports llgo package names and initialization line metadata differently - - version: go1.26 - platform: darwin/arm64 - directive: buildrundir - case: asmhdr.go - reason: llgo build does not implement the Go assembler asmhdr and symabis pipeline - version: go1.26 directive: rundir case: fixedbugs/issue31636.go @@ -3516,15 +3029,6 @@ xfails: directive: rundir case: fixedbugs/issue9608.go reason: llgo does not eliminate unreachable references to a bodyless function before linking - - version: go1.26 - directive: runindir - case: fixedbugs/issue20014.go - reason: gc-specific fieldtrack linker metadata is not implemented by llgo - - version: go1.26 - platform: darwin/arm64 - directive: buildrundir - case: retjmp.go - reason: llgo does not preserve Go assembler return-jump ABI behavior - version: go1.26 directive: rundir case: fixedbugs/issue24693.go From 2326692f5fa915a31be7277d1e5f4ab8dc9e44bb Mon Sep 17 00:00:00 2001 From: Li Jie Date: Mon, 3 Aug 2026 14:06:19 +0800 Subject: [PATCH 31/73] ci: compare benchmarks on the same runner --- .github/workflows/benchmark.yml | 72 +++++++++++---------------------- benchmark/baseline/README.md | 15 +++++-- benchmark/baseline/run.sh | 71 ++++++++++++++++++++++++++++++++ 3 files changed, 105 insertions(+), 53 deletions(-) create mode 100755 benchmark/baseline/run.sh diff --git a/.github/workflows/benchmark.yml b/.github/workflows/benchmark.yml index cad959e401..94a4c08771 100644 --- a/.github/workflows/benchmark.yml +++ b/.github/workflows/benchmark.yml @@ -32,6 +32,15 @@ jobs: steps: - uses: actions/checkout@v7 + - name: Check out pull request base + if: github.event_name == 'pull_request' + uses: actions/checkout@v7 + with: + repository: ${{ github.event.pull_request.base.repo.full_name }} + ref: ${{ github.event.pull_request.base.sha }} + path: .benchmark/base-source + persist-credentials: false + - name: Install dependencies uses: ./.github/actions/setup-deps with: @@ -40,63 +49,28 @@ jobs: - name: Set up Go uses: ./.github/actions/setup-go - - name: Build LLGo - run: | - set -euo pipefail - mkdir -p .benchmark - go build -p=1 -o .benchmark/llgo ./cmd/llgo - - - name: Measure programs + - name: Measure pull request base + if: github.event_name == 'pull_request' run: | - set -euo pipefail - go run ./benchmark/baseline \ - -llgo "$GITHUB_WORKSPACE/.benchmark/llgo" \ - -out "$GITHUB_WORKSPACE/.benchmark/results" - - - name: Run selected Go benchmarks - run: | - set -euo pipefail - results="$GITHUB_WORKSPACE/.benchmark/results/go.txt" - GOMAXPROCS=1 go test \ - -run '^$' \ - -bench '^(BenchmarkMergeCompilerFlags|BenchmarkMergeLinkerFlags|BenchmarkLookupPCRandom)$' \ - -benchtime=250ms \ - -count=1 \ - -cpu=1 \ - ./internal/clang ./internal/build/funcinfo \ - | tee "$results" - - GOMAXPROCS=1 "$GITHUB_WORKSPACE/.benchmark/llgo" test \ - -run '^$' \ - -bench '^(BenchmarkRuntimeGetG|BenchmarkGlobal(Read|Write)|Benchmark(DirectCall|InterfaceCall|Defer|ChannelBuffered|ChannelHandoff))$' \ - -benchtime=250ms \ - -count=1 \ - ./test/llgoext \ - | tee -a "$results" - - # The current native backend creates one pthread per goroutine and - # intentionally has a bounded lifecycle stress limit. Keep creation - # monitoring deterministic instead of letting testing auto-calibrate - # to millions of host threads. - GOMAXPROCS=1 "$GITHUB_WORKSPACE/.benchmark/llgo" test \ - -run '^$' \ - -bench '^BenchmarkGoroutine$' \ - -benchtime=100x \ - -count=1 \ - ./test/llgoext \ - | tee -a "$results" + benchmark/baseline/run.sh \ + "$GITHUB_WORKSPACE/.benchmark/base-source" \ + "$GITHUB_WORKSPACE/.benchmark/base-llgo" \ + "$GITHUB_WORKSPACE/.benchmark/base-results" - - name: Validate and export benchmark artifact + - name: Measure current revision run: | - go run ./benchmark/baseline \ - -mode export \ - -out .benchmark/results \ - -benchmark-output .benchmark/results/benchmark.txt + benchmark/baseline/run.sh \ + "$GITHUB_WORKSPACE" \ + "$GITHUB_WORKSPACE/.benchmark/llgo" \ + "$GITHUB_WORKSPACE/.benchmark/results" - name: Record benchmark result uses: xgo-dev/setup-benchmark-go-action@v1 with: config: .github/llgo-benchmark.yml benchmark-file: .benchmark/results/benchmark.txt + baseline-benchmark-file: >- + ${{ github.event_name == 'pull_request' && + '.benchmark/base-results/benchmark.txt' || '' }} platform-id: ${{ matrix.id }} platform-label: ${{ matrix.display }} diff --git a/benchmark/baseline/README.md b/benchmark/baseline/README.md index 6f50b78dbc..51021e17f0 100644 --- a/benchmark/baseline/README.md +++ b/benchmark/baseline/README.md @@ -22,10 +22,17 @@ stream adds selected compiler helpers and LLGo-generated core-language operations: direct/interface calls, defer, goroutine creation, channels, `getg`, and global access. -The trusted publisher compares each platform against the latest matching -`main` data and commits the history and generated site to the `pages` branch of -the configured data repository. Every LLGo repository defaults to -`/llgo-benchmark-data`: +For pull requests, each platform job checks out the recorded base commit and +runs the base and current suites sequentially on the same runner. The pull +request comment compares that pair, avoiding differences between runner +machines. Dependency setup is shared, and Go's build cache can be reused by +unchanged packages; main pushes still run the suite only once. If a workflow +does not provide a paired result, the publisher falls back to the latest +matching `main` data. + +The trusted publisher commits the current result history and generated site to +the `pages` branch of the configured data repository. Every LLGo repository +defaults to `/llgo-benchmark-data`: ```text llgo/baseline/series/main/main diff --git a/benchmark/baseline/run.sh b/benchmark/baseline/run.sh new file mode 100755 index 0000000000..3d06adfd0f --- /dev/null +++ b/benchmark/baseline/run.sh @@ -0,0 +1,71 @@ +#!/usr/bin/env bash + +set -euo pipefail + +if [[ $# -ne 3 ]]; then + echo "usage: $0 " >&2 + exit 2 +fi + +source_root="$1" +llgo_output="$2" +result_directory="$3" +harness_root="$(cd "$(dirname "$0")/../.." && pwd)" + +mkdir -p "$(dirname "$llgo_output")" "$result_directory" + +( + cd "$source_root" + LLGO_ROOT="$source_root" go build -p=1 -o "$llgo_output" ./cmd/llgo +) + +( + cd "$harness_root" + LLGO_ROOT="$source_root" go run ./benchmark/baseline \ + -root "$source_root" \ + -llgo "$llgo_output" \ + -out "$result_directory" +) + +go_results="$result_directory/go.txt" +( + cd "$source_root" + GOMAXPROCS=1 LLGO_ROOT="$source_root" go test \ + -run '^$' \ + -bench '^(BenchmarkMergeCompilerFlags|BenchmarkMergeLinkerFlags|BenchmarkLookupPCRandom)$' \ + -benchtime=250ms \ + -count=1 \ + -cpu=1 \ + ./internal/clang ./internal/build/funcinfo +) | tee "$go_results" + +( + cd "$source_root" + GOMAXPROCS=1 LLGO_ROOT="$source_root" "$llgo_output" test \ + -run '^$' \ + -bench '^(BenchmarkRuntimeGetG|BenchmarkGlobal(Read|Write)|Benchmark(DirectCall|InterfaceCall|Defer|ChannelBuffered|ChannelHandoff))$' \ + -benchtime=250ms \ + -count=1 \ + ./test/llgoext +) | tee -a "$go_results" + +# The current native backend creates one pthread per goroutine and intentionally +# has a bounded lifecycle stress limit. Keep creation monitoring deterministic +# instead of letting testing auto-calibrate to millions of host threads. +( + cd "$source_root" + GOMAXPROCS=1 LLGO_ROOT="$source_root" "$llgo_output" test \ + -run '^$' \ + -bench '^BenchmarkGoroutine$' \ + -benchtime=100x \ + -count=1 \ + ./test/llgoext +) | tee -a "$go_results" + +( + cd "$harness_root" + go run ./benchmark/baseline \ + -mode export \ + -out "$result_directory" \ + -benchmark-output "$result_directory/benchmark.txt" +) From 49ba5eefaafa4ef0861823251f47b78f8013eeec Mon Sep 17 00:00:00 2001 From: Li Jie Date: Mon, 3 Aug 2026 16:08:50 +0800 Subject: [PATCH 32/73] ci: stabilize paired benchmark samples --- .github/workflows/benchmark.yml | 21 +++++++++++++++---- benchmark/baseline/README.md | 36 +++++++++++++++++---------------- benchmark/baseline/main.go | 28 +++++++++++++++++-------- benchmark/baseline/main_test.go | 17 +++++++++++----- benchmark/baseline/run.sh | 19 +++++++++-------- 5 files changed, 79 insertions(+), 42 deletions(-) diff --git a/.github/workflows/benchmark.yml b/.github/workflows/benchmark.yml index 94a4c08771..34285de833 100644 --- a/.github/workflows/benchmark.yml +++ b/.github/workflows/benchmark.yml @@ -32,13 +32,13 @@ jobs: steps: - uses: actions/checkout@v7 - - name: Check out pull request base + - name: Check out pull request base benchmark source if: github.event_name == 'pull_request' uses: actions/checkout@v7 with: repository: ${{ github.event.pull_request.base.repo.full_name }} ref: ${{ github.event.pull_request.base.sha }} - path: .benchmark/base-source + path: .benchmark/source persist-credentials: false - name: Install dependencies @@ -53,14 +53,27 @@ jobs: if: github.event_name == 'pull_request' run: | benchmark/baseline/run.sh \ - "$GITHUB_WORKSPACE/.benchmark/base-source" \ + "$GITHUB_WORKSPACE/.benchmark/source" \ "$GITHUB_WORKSPACE/.benchmark/base-llgo" \ "$GITHUB_WORKSPACE/.benchmark/base-results" + - name: Check out pull request head benchmark source + if: github.event_name == 'pull_request' + uses: actions/checkout@v7 + with: + repository: ${{ github.event.pull_request.head.repo.full_name }} + ref: ${{ github.event.pull_request.head.sha }} + path: .benchmark/source + persist-credentials: false + - name: Measure current revision run: | + source_root="$GITHUB_WORKSPACE" + if [[ "$GITHUB_EVENT_NAME" == pull_request ]]; then + source_root="$GITHUB_WORKSPACE/.benchmark/source" + fi benchmark/baseline/run.sh \ - "$GITHUB_WORKSPACE" \ + "$source_root" \ "$GITHUB_WORKSPACE/.benchmark/llgo" \ "$GITHUB_WORKSPACE/.benchmark/results" diff --git a/benchmark/baseline/README.md b/benchmark/baseline/README.md index 51021e17f0..136159341e 100644 --- a/benchmark/baseline/README.md +++ b/benchmark/baseline/README.md @@ -14,21 +14,23 @@ The program workloads reuse: - `benchmark/binary_size/println`: only the built-in `println`; - `benchmark/binary_size/fmtprintf`: `fmt.Printf`. -For each workload, the collector records median warm build time, median process -time, file size, executable-code bytes, allocated non-executable data, and -zero-filled data. On ELF, read-only constants are included in the data bucket; -on Mach-O, `__TEXT` constants are included in the text bucket. The Go benchmark -stream adds selected compiler helpers and LLGo-generated core-language -operations: direct/interface calls, defer, goroutine creation, channels, -`getg`, and global access. +For each workload, the collector performs an unmeasured warm build, then records +median build time, median process time, file size, executable-code bytes, +allocated non-executable data, and zero-filled data. On ELF, read-only constants +are included in the data bucket; on Mach-O, `__TEXT` constants are included in +the text bucket. The Go benchmark stream records three samples of selected +compiler helpers and LLGo-generated core-language operations: direct/interface +calls, defer, goroutine creation, channels, `getg`, and global access. -For pull requests, each platform job checks out the recorded base commit and -runs the base and current suites sequentially on the same runner. The pull -request comment compares that pair, avoiding differences between runner -machines. Dependency setup is shared, and Go's build cache can be reused by -unchanged packages; main pushes still run the suite only once. If a workflow -does not provide a paired result, the publisher falls back to the latest -matching `main` data. +For pull requests, each platform job checks out the recorded base and current +commits into the same source path, then runs both suites sequentially on the same +runner. The pull request comment compares that pair, avoiding differences from +runner machines and embedded source paths. Dependency setup is shared, and Go's +build cache can be reused by unchanged packages; main pushes still run the suite +only once. Very small changes can still be scheduler, frequency, or thermal +noise and should be confirmed by repeated workflow runs. If a workflow does not +provide a paired result, the publisher falls back to the latest matching `main` +data. The trusted publisher commits the current result history and generated site to the `pages` branch of the configured data repository. Every LLGo repository @@ -62,15 +64,15 @@ results=.benchmark/results/go.txt GOMAXPROCS=1 go test \ -run '^$' \ -bench '^(BenchmarkMergeCompilerFlags|BenchmarkMergeLinkerFlags|BenchmarkLookupPCRandom)$' \ - -benchtime=250ms -count=1 -cpu=1 \ + -benchtime=250ms -count=3 -cpu=1 \ ./internal/clang ./internal/build/funcinfo | tee "$results" GOMAXPROCS=1 .benchmark/llgo test \ -run '^$' \ -bench '^(BenchmarkRuntimeGetG|BenchmarkGlobal(Read|Write)|Benchmark(DirectCall|InterfaceCall|Defer|ChannelBuffered|ChannelHandoff))$' \ - -benchtime=250ms -count=1 \ + -benchtime=250ms -count=3 \ ./test/llgoext | tee -a "$results" GOMAXPROCS=1 .benchmark/llgo test \ - -run '^$' -bench '^BenchmarkGoroutine$' -benchtime=100x -count=1 \ + -run '^$' -bench '^BenchmarkGoroutine$' -benchtime=100x -count=3 \ ./test/llgoext | tee -a "$results" ``` diff --git a/benchmark/baseline/main.go b/benchmark/baseline/main.go index 25ebd59dbd..326198b8f7 100644 --- a/benchmark/baseline/main.go +++ b/benchmark/baseline/main.go @@ -74,6 +74,8 @@ var expectedGoBenchmarks = []string{ "BenchmarkRuntimeGetG", } +const goBenchmarkSamples = 3 + type footprint struct { file uint64 text uint64 @@ -221,6 +223,11 @@ func collect(ctx context.Context, root, llgo, out string, buildRuns, runRuns int var sizes, timings []metric for _, item := range workloads { binary := filepath.Join(binDir, item.name) + // Keep first-use toolchain and filesystem caches out of the measured + // median so the first revision is not systematically disadvantaged. + if err := run(ctx, env, io.Discard, llgo, "build", "-o", binary, filepath.Join(root, item.source)); err != nil { + return fmt.Errorf("warm build %s: %w", item.name, err) + } buildDurations := make([]time.Duration, 0, buildRuns) for range buildRuns { start := time.Now() @@ -433,9 +440,9 @@ func validateMetrics(path string, expected map[string]string) error { } func validateGoBenchmarks(r io.Reader) error { - expected := make(map[string]bool, len(expectedGoBenchmarks)) + expected := make(map[string]int, len(expectedGoBenchmarks)) for _, name := range expectedGoBenchmarks { - expected[name] = false + expected[name] = 0 } scanner := bufio.NewScanner(r) for scanner.Scan() { @@ -444,12 +451,12 @@ func validateGoBenchmarks(r io.Reader) error { continue } name := cpuSuffix.ReplaceAllString(fields[0], "") - seen, ok := expected[name] + samples, ok := expected[name] if !ok { return fmt.Errorf("unexpected Go benchmark %q", name) } - if seen { - return fmt.Errorf("duplicate Go benchmark %q", name) + if samples >= goBenchmarkSamples { + return fmt.Errorf("too many samples for Go benchmark %q", name) } if len(fields) < 4 || (len(fields)-2)%2 != 0 { return fmt.Errorf("malformed Go benchmark line %q", scanner.Text()) @@ -474,14 +481,14 @@ func validateGoBenchmarks(r io.Reader) error { if !hasTime { return fmt.Errorf("benchmark %q has no ns/op result", name) } - expected[name] = true + expected[name] = samples + 1 } if err := scanner.Err(); err != nil { return err } var missing []string - for name, seen := range expected { - if !seen { + for name, samples := range expected { + if samples == 0 { missing = append(missing, name) } } @@ -489,5 +496,10 @@ func validateGoBenchmarks(r io.Reader) error { if len(missing) != 0 { return fmt.Errorf("missing Go benchmarks: %s", strings.Join(missing, ", ")) } + for name, samples := range expected { + if samples != goBenchmarkSamples { + return fmt.Errorf("Go benchmark %q has %d samples, want %d", name, samples, goBenchmarkSamples) + } + } return nil } diff --git a/benchmark/baseline/main_test.go b/benchmark/baseline/main_test.go index 51fd781b11..8399325dfe 100644 --- a/benchmark/baseline/main_test.go +++ b/benchmark/baseline/main_test.go @@ -157,8 +157,10 @@ func TestValidateMetricsRejectsInvalidData(t *testing.T) { func TestValidateGoBenchmarks(t *testing.T) { var input strings.Builder for _, name := range expectedGoBenchmarks { - input.WriteString(name) - input.WriteString("-1 100 12.5 ns/op\n") + for range goBenchmarkSamples { + input.WriteString(name) + input.WriteString("-1 100 12.5 ns/op\n") + } } if err := validateGoBenchmarks(strings.NewReader(input.String())); err != nil { t.Fatal(err) @@ -170,7 +172,9 @@ func TestValidateGoBenchmarksRejectsInvalidData(t *testing.T) { var input strings.Builder for _, name := range expectedGoBenchmarks { if name != skip { - input.WriteString(name + "-1 100 12.5 ns/op\n") + for range goBenchmarkSamples { + input.WriteString(name + "-1 100 12.5 ns/op\n") + } } } return input.String() @@ -182,7 +186,8 @@ func TestValidateGoBenchmarksRejectsInvalidData(t *testing.T) { }{ {"missing", valid(expectedGoBenchmarks[0]), "missing Go benchmarks"}, {"unknown", valid("") + "BenchmarkUnknown-1 1 1 ns/op\n", `unexpected Go benchmark "BenchmarkUnknown"`}, - {"duplicate", valid("") + expectedGoBenchmarks[0] + "-1 1 1 ns/op\n", "duplicate Go benchmark"}, + {"too many samples", valid("") + expectedGoBenchmarks[0] + "-1 1 1 ns/op\n", "too many samples"}, + {"too few samples", strings.Replace(valid(""), expectedGoBenchmarks[0]+"-1 100 12.5 ns/op\n", "", 1), "has 2 samples, want 3"}, {"malformed", strings.Replace(valid(""), " 100 12.5 ns/op", " bad", 1), "malformed Go benchmark"}, {"iterations", strings.Replace(valid(""), " 100 ", " bad ", 1), "invalid iteration count"}, {"value", strings.Replace(valid(""), "12.5", "bad", 1), "invalid value"}, @@ -523,7 +528,9 @@ func writeValidArtifact(t *testing.T, dir string) { func makeGoBenchmarkText() string { var input strings.Builder for _, name := range expectedGoBenchmarks { - input.WriteString(name + "-1 100 12.5 ns/op\n") + for range goBenchmarkSamples { + input.WriteString(name + "-1 100 12.5 ns/op\n") + } } return input.String() } diff --git a/benchmark/baseline/run.sh b/benchmark/baseline/run.sh index 3d06adfd0f..978809cd89 100755 --- a/benchmark/baseline/run.sh +++ b/benchmark/baseline/run.sh @@ -7,12 +7,12 @@ if [[ $# -ne 3 ]]; then exit 2 fi -source_root="$1" -llgo_output="$2" -result_directory="$3" harness_root="$(cd "$(dirname "$0")/../.." && pwd)" -mkdir -p "$(dirname "$llgo_output")" "$result_directory" +source_root="$(cd "$1" && pwd)" +mkdir -p "$(dirname "$2")" "$3" +llgo_output="$(cd "$(dirname "$2")" && pwd)/$(basename "$2")" +result_directory="$(cd "$3" && pwd)" ( cd "$source_root" @@ -21,6 +21,8 @@ mkdir -p "$(dirname "$llgo_output")" "$result_directory" ( cd "$harness_root" + # Keep one current-checkout harness for both source revisions. Benchmark + # suite changes must therefore remain executable against the PR base. LLGO_ROOT="$source_root" go run ./benchmark/baseline \ -root "$source_root" \ -llgo "$llgo_output" \ @@ -28,16 +30,17 @@ mkdir -p "$(dirname "$llgo_output")" "$result_directory" ) go_results="$result_directory/go.txt" +: > "$go_results" ( cd "$source_root" GOMAXPROCS=1 LLGO_ROOT="$source_root" go test \ -run '^$' \ -bench '^(BenchmarkMergeCompilerFlags|BenchmarkMergeLinkerFlags|BenchmarkLookupPCRandom)$' \ -benchtime=250ms \ - -count=1 \ + -count=3 \ -cpu=1 \ ./internal/clang ./internal/build/funcinfo -) | tee "$go_results" +) | tee -a "$go_results" ( cd "$source_root" @@ -45,7 +48,7 @@ go_results="$result_directory/go.txt" -run '^$' \ -bench '^(BenchmarkRuntimeGetG|BenchmarkGlobal(Read|Write)|Benchmark(DirectCall|InterfaceCall|Defer|ChannelBuffered|ChannelHandoff))$' \ -benchtime=250ms \ - -count=1 \ + -count=3 \ ./test/llgoext ) | tee -a "$go_results" @@ -58,7 +61,7 @@ go_results="$result_directory/go.txt" -run '^$' \ -bench '^BenchmarkGoroutine$' \ -benchtime=100x \ - -count=1 \ + -count=3 \ ./test/llgoext ) | tee -a "$go_results" From df0bb22bfe8e9f30630ce2e6e51f190855df4d2f Mon Sep 17 00:00:00 2001 From: Li Jie Date: Mon, 3 Aug 2026 16:11:08 +0800 Subject: [PATCH 33/73] ci: collect five microbenchmark samples --- benchmark/baseline/README.md | 8 ++++---- benchmark/baseline/main.go | 2 +- benchmark/baseline/main_test.go | 3 ++- benchmark/baseline/run.sh | 6 +++--- 4 files changed, 10 insertions(+), 9 deletions(-) diff --git a/benchmark/baseline/README.md b/benchmark/baseline/README.md index 136159341e..32073268cf 100644 --- a/benchmark/baseline/README.md +++ b/benchmark/baseline/README.md @@ -18,7 +18,7 @@ For each workload, the collector performs an unmeasured warm build, then records median build time, median process time, file size, executable-code bytes, allocated non-executable data, and zero-filled data. On ELF, read-only constants are included in the data bucket; on Mach-O, `__TEXT` constants are included in -the text bucket. The Go benchmark stream records three samples of selected +the text bucket. The Go benchmark stream records five samples of selected compiler helpers and LLGo-generated core-language operations: direct/interface calls, defer, goroutine creation, channels, `getg`, and global access. @@ -64,15 +64,15 @@ results=.benchmark/results/go.txt GOMAXPROCS=1 go test \ -run '^$' \ -bench '^(BenchmarkMergeCompilerFlags|BenchmarkMergeLinkerFlags|BenchmarkLookupPCRandom)$' \ - -benchtime=250ms -count=3 -cpu=1 \ + -benchtime=250ms -count=5 -cpu=1 \ ./internal/clang ./internal/build/funcinfo | tee "$results" GOMAXPROCS=1 .benchmark/llgo test \ -run '^$' \ -bench '^(BenchmarkRuntimeGetG|BenchmarkGlobal(Read|Write)|Benchmark(DirectCall|InterfaceCall|Defer|ChannelBuffered|ChannelHandoff))$' \ - -benchtime=250ms -count=3 \ + -benchtime=250ms -count=5 \ ./test/llgoext | tee -a "$results" GOMAXPROCS=1 .benchmark/llgo test \ - -run '^$' -bench '^BenchmarkGoroutine$' -benchtime=100x -count=3 \ + -run '^$' -bench '^BenchmarkGoroutine$' -benchtime=100x -count=5 \ ./test/llgoext | tee -a "$results" ``` diff --git a/benchmark/baseline/main.go b/benchmark/baseline/main.go index 326198b8f7..040521319b 100644 --- a/benchmark/baseline/main.go +++ b/benchmark/baseline/main.go @@ -74,7 +74,7 @@ var expectedGoBenchmarks = []string{ "BenchmarkRuntimeGetG", } -const goBenchmarkSamples = 3 +const goBenchmarkSamples = 5 type footprint struct { file uint64 diff --git a/benchmark/baseline/main_test.go b/benchmark/baseline/main_test.go index 8399325dfe..cf18e9a918 100644 --- a/benchmark/baseline/main_test.go +++ b/benchmark/baseline/main_test.go @@ -23,6 +23,7 @@ import ( "debug/macho" "encoding/json" "errors" + "fmt" "io" "math" "os" @@ -187,7 +188,7 @@ func TestValidateGoBenchmarksRejectsInvalidData(t *testing.T) { {"missing", valid(expectedGoBenchmarks[0]), "missing Go benchmarks"}, {"unknown", valid("") + "BenchmarkUnknown-1 1 1 ns/op\n", `unexpected Go benchmark "BenchmarkUnknown"`}, {"too many samples", valid("") + expectedGoBenchmarks[0] + "-1 1 1 ns/op\n", "too many samples"}, - {"too few samples", strings.Replace(valid(""), expectedGoBenchmarks[0]+"-1 100 12.5 ns/op\n", "", 1), "has 2 samples, want 3"}, + {"too few samples", strings.Replace(valid(""), expectedGoBenchmarks[0]+"-1 100 12.5 ns/op\n", "", 1), fmt.Sprintf("has %d samples, want %d", goBenchmarkSamples-1, goBenchmarkSamples)}, {"malformed", strings.Replace(valid(""), " 100 12.5 ns/op", " bad", 1), "malformed Go benchmark"}, {"iterations", strings.Replace(valid(""), " 100 ", " bad ", 1), "invalid iteration count"}, {"value", strings.Replace(valid(""), "12.5", "bad", 1), "invalid value"}, diff --git a/benchmark/baseline/run.sh b/benchmark/baseline/run.sh index 978809cd89..c0ffdf02ec 100755 --- a/benchmark/baseline/run.sh +++ b/benchmark/baseline/run.sh @@ -37,7 +37,7 @@ go_results="$result_directory/go.txt" -run '^$' \ -bench '^(BenchmarkMergeCompilerFlags|BenchmarkMergeLinkerFlags|BenchmarkLookupPCRandom)$' \ -benchtime=250ms \ - -count=3 \ + -count=5 \ -cpu=1 \ ./internal/clang ./internal/build/funcinfo ) | tee -a "$go_results" @@ -48,7 +48,7 @@ go_results="$result_directory/go.txt" -run '^$' \ -bench '^(BenchmarkRuntimeGetG|BenchmarkGlobal(Read|Write)|Benchmark(DirectCall|InterfaceCall|Defer|ChannelBuffered|ChannelHandoff))$' \ -benchtime=250ms \ - -count=3 \ + -count=5 \ ./test/llgoext ) | tee -a "$go_results" @@ -61,7 +61,7 @@ go_results="$result_directory/go.txt" -run '^$' \ -bench '^BenchmarkGoroutine$' \ -benchtime=100x \ - -count=3 \ + -count=5 \ ./test/llgoext ) | tee -a "$go_results" From 3c05bb982f505dd4cc12bf84121f88dc4ae06466 Mon Sep 17 00:00:00 2001 From: Rick Guo Date: Mon, 3 Aug 2026 16:22:43 +0800 Subject: [PATCH 34/73] fix: prefer compiler syntax diagnostics --- internal/packages/load.go | 20 ++++++++++++++++ internal/packages/load_test.go | 28 ++++++++++++++++++++++ test/goroot/xfail.yaml | 44 ---------------------------------- 3 files changed, 48 insertions(+), 44 deletions(-) diff --git a/internal/packages/load.go b/internal/packages/load.go index 3ec632f357..055be834f5 100644 --- a/internal/packages/load.go +++ b/internal/packages/load.go @@ -257,6 +257,20 @@ func loadPackageEx(dedup Deduper, ld *loader, lpkg *loaderPackage) { return // not a source package, don't get syntax trees } + // go list has already captured cmd/compile's authoritative diagnostics in + // this block. For example, an unexpected else stops gc before recovery AST + // errors are reported, so do not append the local parser/type follow-ons. + hasCompilerSyntaxError := false + for _, err := range lpkg.Errors { + if err.Kind != packages.ListError || !strings.HasPrefix(err.Msg, "# ") { + continue + } + if _, diagnostics, ok := strings.Cut(err.Msg, "\n"); ok && strings.Contains(diagnostics, ": syntax error: ") { + hasCompilerSyntaxError = true + break + } + } + appendError := func(err error) { // Convert various error types into the one true Error. var errs []packages.Error @@ -275,6 +289,9 @@ func loadPackageEx(dedup Deduper, ld *loader, lpkg *loaderPackage) { case scanner.ErrorList: // from parser + if hasCompilerSyntaxError { + return + } for _, err := range err { errs = append(errs, packages.Error{ Pos: err.Pos.String(), @@ -285,6 +302,9 @@ func loadPackageEx(dedup Deduper, ld *loader, lpkg *loaderPackage) { case types.Error: // from type checker + if hasCompilerSyntaxError { + return + } lpkg.TypeErrors = append(lpkg.TypeErrors, err) errs = append(errs, packages.Error{ Pos: err.Fset.Position(err.Pos).String(), diff --git a/internal/packages/load_test.go b/internal/packages/load_test.go index a65dfb7955..c6bd6eee9a 100644 --- a/internal/packages/load_test.go +++ b/internal/packages/load_test.go @@ -229,6 +229,34 @@ func TestEmbedDiagnosticHelperBoundaries(t *testing.T) { } func TestLoadExNormalizesFrontendDiagnostics(t *testing.T) { + t.Run("compiler syntax errors are authoritative", func(t *testing.T) { + dir := t.TempDir() + writeLoadTestFile(t, filepath.Join(dir, "go.mod"), "module example.com/syntaxerror\ngo 1.24\n") + writeLoadTestFile(t, filepath.Join(dir, "load.go"), `package syntaxerror +func f() { + if missing {} + else {} +} +`) + cfg := loadTestConfig(dir) + cfg.BuildFlags = []string{"-gcflags=all=-e"} + cfg.ParseFile = func(fset *token.FileSet, filename string, src []byte) (*ast.File, error) { + return parser.ParseFile(fset, filename, src, parser.AllErrors|parser.ParseComments) + } + pkgs, err := LoadExWithGoVersion(nil, nil, cfg, "go1.24", ".") + if err != nil { + t.Fatal(err) + } + if len(pkgs) != 1 { + t.Fatalf("load returned %d packages, want 1", len(pkgs)) + } + pkg := pkgs[0] + assertPackageError(t, pkg, "syntax error:") + for _, secondary := range []string{"expected statement", "found 'EOF'", "undefined: missing"} { + assertPackageErrorAbsent(t, pkg, secondary) + } + }) + t.Run("embed local var", func(t *testing.T) { dir := t.TempDir() writeLoadTestFile(t, filepath.Join(dir, "go.mod"), "module example.com/embedlocal\ngo 1.24\n") diff --git a/test/goroot/xfail.yaml b/test/goroot/xfail.yaml index 761813f9d9..7f3a502743 100644 --- a/test/goroot/xfail.yaml +++ b/test/goroot/xfail.yaml @@ -1818,54 +1818,10 @@ flakes: case: fixedbugs/issue25897a.go reason: reflect-generated goroutines under a single-P continuous-GC loop can complete or exceed the 1m run timeout on darwin/arm64 xfails: - - version: go1.26 - directive: errorcheck - case: fixedbugs/issue23664.go - reason: llgo parser recovery emits additional malformed-declaration diagnostics - - version: go1.26 - directive: errorcheck - case: fixedbugs/issue33386.go - reason: llgo parser recovery emits additional malformed-go/defer diagnostics - - version: go1.26 - directive: errorcheck - case: fixedbugs/bug349.go - reason: llgo parser recovery emits additional return-value diagnostics - - version: go1.26 - directive: errorcheck - case: fixedbugs/issue23587.go - reason: llgo parser recovery emits additional invalid-tilde diagnostics - - version: go1.26 - directive: errorcheck - case: syntax/semi7.go - reason: llgo parser recovery emits additional semicolon and else diagnostics - - version: go1.26 - directive: errorcheck - case: fixedbugs/bug274.go - reason: llgo parser recovery emits additional case and label diagnostics - - version: go1.26 - directive: errorcheck - case: fixedbugs/issue18092.go - reason: llgo parser recovery emits additional malformed-channel diagnostics - version: go1.26 directive: errorcheck case: fixedbugs/issue4776.go reason: llgo parser uses a different missing-package-clause diagnostic - - version: go1.26 - directive: errorcheck - case: switch2.go - reason: llgo parser recovery emits additional malformed-switch diagnostics - - version: go1.26 - directive: errorcheck - case: fixedbugs/issue13319.go - reason: llgo parser recovery emits additional malformed-call diagnostics - - version: go1.26 - directive: errorcheck - case: syntax/semi5.go - reason: llgo parser recovery emits additional semicolon and end-of-file diagnostics - - version: go1.26 - directive: errorcheck - case: fixedbugs/issue13274.go - reason: llgo parser emits an additional end-of-file diagnostic - version: go1.26 directive: errorcheck case: fixedbugs/issue4405.go From 8088399ae64372ef659bd372629ceaaf64cf618a Mon Sep 17 00:00:00 2001 From: Li Jie Date: Wed, 22 Jul 2026 05:42:13 +0800 Subject: [PATCH 35/73] build(debug): run LLVM passes with DWARF --- internal/build/build.go | 10 ++++++---- internal/build/optlevel_test.go | 11 +++++++++++ ssa/package.go | 6 ++++++ 3 files changed, 23 insertions(+), 4 deletions(-) diff --git a/internal/build/build.go b/internal/build/build.go index 411d733568..8352b91d9c 100644 --- a/internal/build/build.go +++ b/internal/build/build.go @@ -591,10 +591,7 @@ func Build(inv Invocation) ([]Package, error) { buildMode := ssaBuildMode cabiOptimize := true - passOpt := true - if emitDebugInfo || mode == ModeGen { - passOpt = false - } + passOpt := shouldRunLLVMPasses(mode) if emitDebugInfo { buildMode |= ssa.GlobalDebug cabiOptimize = false @@ -602,6 +599,7 @@ func Build(inv Invocation) ([]Package, error) { if !IsOptimizeEnabled() { buildMode |= ssa.NaiveForm } + prog.SetDebugInfoOptimized(passOpt && conf.OptLevel != optlevel.O0) progSSA := ssa.NewProgram(initial[0].Fset, buildMode) patches := make(cl.Patches, len(altPkgPaths)) altEntries := registerAltSSAPkgs(progSSA, patches, altPkgs[1:], conf, verbose) @@ -2613,6 +2611,10 @@ func llvmPassPipeline(level optlevel.Level, ltoMode lto.Mode) string { } } +func shouldRunLLVMPasses(mode Mode) bool { + return mode != ModeGen +} + func IsWasiThreadsEnabled() bool { return isEnvOn(llgoWasiThreads, true) } diff --git a/internal/build/optlevel_test.go b/internal/build/optlevel_test.go index ce6d1e7791..857f0a92c5 100644 --- a/internal/build/optlevel_test.go +++ b/internal/build/optlevel_test.go @@ -71,3 +71,14 @@ func TestLLVMPassPipeline(t *testing.T) { } } } + +func TestShouldRunLLVMPasses(t *testing.T) { + for _, mode := range []Mode{ModeBuild, ModeInstall, ModeRun, ModeTest, ModeCmpTest} { + if !shouldRunLLVMPasses(mode) { + t.Errorf("shouldRunLLVMPasses(%v) = false, want true", mode) + } + } + if shouldRunLLVMPasses(ModeGen) { + t.Fatal("shouldRunLLVMPasses(ModeGen) = true, want false") + } +} diff --git a/ssa/package.go b/ssa/package.go index 498bbaf942..d2ee9f0b86 100644 --- a/ssa/package.go +++ b/ssa/package.go @@ -382,6 +382,12 @@ func (p Program) EnableLTOPluginMarkers(enable bool) { p.enableLTOPluginMarker = enable } +// SetDebugInfoOptimized records whether the LLVM IR optimization pipeline runs. +// It only controls DWARF's optimized marker and never selects compiler passes. +func (p Program) SetDebugInfoOptimized(enable bool) { + p.debugInfoOptimized = enable +} + func (p Program) SetNoInterfaceMethod(fullName string) { p.noInterface[fullName] = none{} } From 80a0231b4b31d3a05498e849ab6bd84cb2dec78a Mon Sep 17 00:00:00 2001 From: Li Jie Date: Wed, 22 Jul 2026 23:19:05 +0800 Subject: [PATCH 36/73] fix(debug): ignore DebugRefs during static init --- cl/rewrite_internal_test.go | 79 ++++++++++++++++++++++++++++++++++++- cl/static_init.go | 16 ++++---- 2 files changed, 86 insertions(+), 9 deletions(-) diff --git a/cl/rewrite_internal_test.go b/cl/rewrite_internal_test.go index 235de50269..c90cdcf01e 100644 --- a/cl/rewrite_internal_test.go +++ b/cl/rewrite_internal_test.go @@ -31,6 +31,15 @@ func compileWithRewrites(t *testing.T, src string, rewrites map[string]string) s } func compileWithRewritesTarget(t *testing.T, src string, rewrites map[string]string, target *llssa.Target) string { + return compileWithRewritesModeTarget(t, src, rewrites, + ssa.SanityCheckFunctions|ssa.InstantiateGenerics, target) +} + +func compileWithRewritesMode(t *testing.T, src string, rewrites map[string]string, mode ssa.BuilderMode) string { + return compileWithRewritesModeTarget(t, src, rewrites, mode, nil) +} + +func compileWithRewritesModeTarget(t *testing.T, src string, rewrites map[string]string, mode ssa.BuilderMode, target *llssa.Target) string { t.Helper() fset := token.NewFileSet() file, err := parser.ParseFile(fset, "rewrite.go", src, parser.ParseComments) @@ -38,7 +47,6 @@ func compileWithRewritesTarget(t *testing.T, src string, rewrites map[string]str t.Fatalf("parse failed: %v", err) } importer := gpackages.NewImporter(fset) - mode := ssa.SanityCheckFunctions | ssa.InstantiateGenerics pkg, _, err := ssautil.BuildPackage(&types.Config{Importer: importer}, fset, types.NewPackage(file.Name.Name, file.Name.Name), []*ast.File{file}, mode) if err != nil { @@ -234,6 +242,75 @@ func Use() callbackType { return CallbackTypes[1] } } } +func TestStaticGlobalSliceLiteralInitWithDebugRefs(t *testing.T) { + const src = `package staticinit + +var CallbackTypes = []string{"BeforeCreate", "AfterCreate"} + +func Use() string { return CallbackTypes[1] } +` + ir := compileWithRewritesMode(t, src, nil, + ssa.SanityCheckFunctions|ssa.InstantiateGenerics|ssa.GlobalDebug) + for _, want := range []string{ + `@"staticinit.CallbackTypes$data" = global [2 x %"github.com/goplus/llgo/runtime/internal/runtime.String"]`, + `@staticinit.CallbackTypes = global %"github.com/goplus/llgo/runtime/internal/runtime.Slice" { ptr @"staticinit.CallbackTypes$data", i64 2, i64 2 }`, + `c"BeforeCreate"`, + `c"AfterCreate"`, + } { + if !strings.Contains(ir, want) { + t.Fatalf("missing static slice initializer %q with debug refs:\n%s", want, ir) + } + } + assertNoStoreToGlobal(t, ir, "@staticinit.CallbackTypes") + if strings.Contains(ir, "runtime.AllocZ") { + t.Fatalf("static slice initializer allocates at runtime with debug refs:\n%s", ir) + } +} + +func TestStaticSliceInitRejectsExecutableReferrers(t *testing.T) { + const src = `package foo + +var Values []int + +func useSlice([]int) {} +func usePointer(*int) {} + +func sliceUser() { + backing := [2]int{1, 2} + values := backing[:] + Values = values + useSlice(values) +} + +func elementUser() { + var backing [2]int + elem := &backing[0] + *elem = 1 + usePointer(elem) + Values = backing[:] +} +` + ssapkg := buildSSAPackage(t, src) + global := ssapkg.Members["Values"].(*ssa.Global) + for _, name := range []string{"sliceUser", "elementUser"} { + fn := ssapkg.Func(name) + var globalStore *ssa.Store + for _, block := range fn.Blocks { + for _, instr := range block.Instrs { + if store, ok := instr.(*ssa.Store); ok && store.Addr == global { + globalStore = store + } + } + } + if globalStore == nil { + t.Fatalf("%s: store to Values not found", name) + } + if _, ok := staticSliceInitOf(globalStore); ok { + t.Fatalf("%s: static slice init accepted an executable referrer", name) + } + } +} + func TestStaticGlobalZeroSizedSliceLiteralFallsBack(t *testing.T) { const src = `package staticinit diff --git a/cl/static_init.go b/cl/static_init.go index 9f8fe7ad8d..d89fd45256 100644 --- a/cl/static_init.go +++ b/cl/static_init.go @@ -209,16 +209,16 @@ func staticSliceInitOf(store *ssa.Store) (*staticSliceInit, bool) { values: make(map[int]*ssa.Const), instrs: []ssa.Instruction{alloc, slice, store}, } - sliceRefs := slice.Referrers() - if sliceRefs == nil || len(*sliceRefs) != 1 || (*sliceRefs)[0] != store { + sliceRefs, ok := nonDebugReferrers(slice) + if !ok || len(sliceRefs) != 1 || sliceRefs[0] != store { return nil, false } - refs := alloc.Referrers() - if refs == nil { + refs, ok := nonDebugReferrers(alloc) + if !ok { return nil, false } seenSlice := false - for _, ref := range *refs { + for _, ref := range refs { switch ref := ref.(type) { case *ssa.Slice: if ref != slice || seenSlice { @@ -233,11 +233,11 @@ func staticSliceInitOf(store *ssa.Store) (*staticSliceInit, bool) { if !ok || index >= int(array.Len()) { return nil, false } - indexRefs := ref.Referrers() - if indexRefs == nil || len(*indexRefs) != 1 { + indexRefs, ok := nonDebugReferrers(ref) + if !ok || len(indexRefs) != 1 { return nil, false } - elemStore, ok := (*indexRefs)[0].(*ssa.Store) + elemStore, ok := indexRefs[0].(*ssa.Store) if !ok || elemStore.Addr != ref { return nil, false } From 642f668a608cc83b04753835d423a60959c07903 Mon Sep 17 00:00:00 2001 From: Li Jie Date: Wed, 22 Jul 2026 07:05:54 +0800 Subject: [PATCH 37/73] fix(debug): preserve defer locations under LTO --- cl/compile_test.go | 17 +++++++++++++++++ ssa/di_debug_test.go | 42 ++++++++++++++++++++++++++++++++++++++++++ ssa/eh.go | 10 ++++++++-- 3 files changed, 67 insertions(+), 2 deletions(-) diff --git a/cl/compile_test.go b/cl/compile_test.go index 5eecf6cbd5..bd0c1b810b 100644 --- a/cl/compile_test.go +++ b/cl/compile_test.go @@ -226,6 +226,15 @@ func TestRunAndTestFromTestlto(t *testing.T) { cltest.RunAndTestFromDir(t, "", "./_testlto", ignore, cltest.WithRunConfig(conf)) } +func TestRunAndTestFromTestltoDWARF(t *testing.T) { + t.Setenv("LLGO_BUILD_CACHE", "off") + conf := build.NewDefaultConf(build.ModeRun) + conf.LTO = lto.Full + conf.LinkOptions.DWARF = build.DWARFPreserve + cltest.RunAndTestFromDir(t, "reflectmk_runtime", "./_testlto", nil, + cltest.WithRunConfig(conf), cltest.WithIRCheck(false)) +} + var testltoSymbolChecks = []string{ "globaldce_interface_matrix", "globaldce_interface_slots", @@ -320,6 +329,14 @@ func TestRunAndTestFromTestltoLTOPlugin(t *testing.T) { ) } +func TestRunAndTestFromTestltoLTOPluginDWARF(t *testing.T) { + t.Setenv("LLGO_BUILD_CACHE", "off") + conf := testltoLTOPluginConf(t, build.ModeRun) + conf.LinkOptions.DWARF = build.DWARFPreserve + cltest.RunAndTestFromDir(t, "ltoplugin_switch", "./_testlto", nil, + cltest.WithRunConfig(conf), cltest.WithIRCheck(false)) +} + func TestBuildAndCheckSymbolsFromTestltoLTOPlugin(t *testing.T) { buildConf := testltoLTOPluginConf(t, build.ModeBuild) // See TestBuildAndCheckSymbolsFromTestlto: dynamic main.* exports retain diff --git a/ssa/di_debug_test.go b/ssa/di_debug_test.go index 5732096564..be4cc78ee9 100644 --- a/ssa/di_debug_test.go +++ b/ssa/di_debug_test.go @@ -171,6 +171,48 @@ func TestDIGlobalIgnoresStorageLessFrontendVariable(t *testing.T) { builder.DIGlobal(pyVarExpr(Nil, "attribute"), "module.attribute", token.Position{}) } +func TestDeferInitBuilderInheritsDebugLocation(t *testing.T) { + fset := token.NewFileSet() + file, err := parser.ParseFile(fset, "defer.go", `package p +func f() {} +`, 0) + if err != nil { + t.Fatal(err) + } + typesPkg, err := (&types.Config{}).Check("example.com/p", fset, []*ast.File{file}, nil) + if err != nil { + t.Fatal(err) + } + + prog := NewProgram(&Target{OptLevel: optlevel.O0}) + defer prog.Dispose() + prog.TypeSizes(types.SizesFor("gc", runtime.GOARCH)) + pkg := prog.NewPackage("p", "example.com/p") + pkg.InitDebug("p", "example.com/p", fset) + decl := file.Decls[0].(*ast.FuncDecl) + object := typesPkg.Scope().Lookup("f").(*types.Func) + fn := pkg.NewFunc("example.com/p.f", object.Type().(*types.Signature), InGo) + builder := fn.MakeBody(1) + defer builder.Dispose() + bodyPos := fset.Position(decl.Body.Lbrace) + builder.DebugFunction(fn, object.Scope(), fset.Position(object.Pos()), bodyPos) + builder.DISetCurrentDebugLocation(fn, bodyPos) + builder.Return() + + deferBuilder, next := fn.deferInitBuilder(builder) + defer deferBuilder.Dispose() + loc := deferBuilder.impl.GetCurrentDebugLocation() + if loc.Line != uint(bodyPos.Line) || loc.Col != uint(bodyPos.Column) || loc.Scope != fn.diFunc.ll { + t.Fatalf("defer debug location = %+v, want %s:%d:%d", loc, bodyPos.Filename, bodyPos.Line, bodyPos.Column) + } + deferBuilder.Jump(next) + + pkg.FinalizeDebug() + if err := llvm.VerifyModule(pkg.Module(), llvm.ReturnStatusAction); err != nil { + t.Fatalf("defer debug metadata is invalid: %v\n%s", err, pkg.Module().String()) + } +} + func newDebugRuntimePackage() *types.Package { pkg := types.NewPackage(PkgRuntime, "runtime") unsafePointer := types.Typ[types.UnsafePointer] diff --git a/ssa/eh.go b/ssa/eh.go index 104b8e04af..5d02a7715d 100644 --- a/ssa/eh.go +++ b/ssa/eh.go @@ -136,8 +136,14 @@ func (b Builder) Longjmp(jb, retval Expr) { // ----------------------------------------------------------------------------- -func (p Function) deferInitBuilder() (b Builder, next BasicBlock) { +func (p Function) deferInitBuilder(from Builder) (b Builder, next BasicBlock) { b = p.NewBuilder() + if p.diFunc != nil { + loc := from.impl.GetCurrentDebugLocation() + if !loc.Scope.IsNil() { + b.impl.SetCurrentDebugLocation(loc.Line, loc.Col, loc.Scope, loc.InlinedAt) + } + } next = b.setBlockMoveLast(p.blks[0]) p.blks[0].last = next.last return @@ -197,7 +203,7 @@ func (b Builder) getDefer(kind DoAction) *aDefer { // TODO(xsw): check if in pkg.init var next, panicBlk BasicBlock if kind != DeferAlways { - b, next = self.deferInitBuilder() + b, next = self.deferInitBuilder(b) } blks := self.MakeBlocks(2) From 0aa1d46a5dc758615e7632f1f39727f5c2a1b366 Mon Sep 17 00:00:00 2001 From: Li Jie Date: Wed, 22 Jul 2026 06:30:32 +0800 Subject: [PATCH 38/73] fix(build): keep DebugRefs with reordered return loads --- internal/build/ssa_order_fix.go | 68 +++++----- internal/build/ssa_order_fix_test.go | 141 ++++++++++++++++++++- test/go/dwarf_semantics_acceptance_test.go | 62 +++++++++ 3 files changed, 231 insertions(+), 40 deletions(-) create mode 100644 test/go/dwarf_semantics_acceptance_test.go diff --git a/internal/build/ssa_order_fix.go b/internal/build/ssa_order_fix.go index 57235740c4..08c7df38d8 100644 --- a/internal/build/ssa_order_fix.go +++ b/internal/build/ssa_order_fix.go @@ -302,11 +302,15 @@ func fixSSAOrderBlock(b *ssa.BasicBlock) { continue } - // If the loaded value is used by any instruction between its current - // position and the return (excluding return itself), moving it may place - // its definition after one of those uses and break SSA form. + // DebugRefs are metadata-only and move with the value they describe. Any + // executable use before Return still makes reordering unsafe. + moving := map[ssa.Instruction]struct{}{u: {}} usedBeforeReturn := false for i := loadIdx + 1; i < retIdx; i++ { + if ref, ok := b.Instrs[i].(*ssa.DebugRef); ok && instrUsesValue(ref, u) { + moving[ref] = struct{}{} + continue + } if instrUsesValue(b.Instrs[i], u) { usedBeforeReturn = true break @@ -316,9 +320,7 @@ func fixSSAOrderBlock(b *ssa.BasicBlock) { continue } - // Move the load right after the last call (but before Return). - b.Instrs = moveInstr(b.Instrs, loadIdx, lastCallIdx+1) - // Adjust retIdx for subsequent moves in this block. + b.Instrs = moveInstrsAfter(b.Instrs, moving, b.Instrs[lastCallIdx]) retIdx = indexOfInstr(b.Instrs, ret) } } @@ -391,41 +393,29 @@ func valueDependsOn(v, target ssa.Value, seen map[ssa.Value]struct{}) bool { return false } -// moveInstr moves instrs[from] to position to (like inserting before to), -// preserving relative order of other elements. -func moveInstr(instrs []ssa.Instruction, from, to int) []ssa.Instruction { - if from < 0 || from >= len(instrs) { +// moveInstrsAfter moves selected instructions as a stable group immediately +// after anchor. +func moveInstrsAfter(instrs []ssa.Instruction, moving map[ssa.Instruction]struct{}, anchor ssa.Instruction) []ssa.Instruction { + if len(moving) == 0 || anchor == nil { return instrs } - if to < 0 { - to = 0 - } - if to > len(instrs) { - to = len(instrs) - } - if from == to || from+1 == to { - return instrs - } - - ins := instrs[from] - // Remove. - copy(instrs[from:], instrs[from+1:]) - instrs = instrs[:len(instrs)-1] - - // Recompute insertion index after removal. - if to > from { - to-- - } - if to < 0 { - to = 0 - } - if to > len(instrs) { - to = len(instrs) + moved := make([]ssa.Instruction, 0, len(moving)) + remaining := make([]ssa.Instruction, 0, len(instrs)) + for _, instr := range instrs { + if _, ok := moving[instr]; ok { + moved = append(moved, instr) + continue + } + remaining = append(remaining, instr) + } + for i, instr := range remaining { + if instr == anchor { + ret := make([]ssa.Instruction, 0, len(instrs)) + ret = append(ret, remaining[:i+1]...) + ret = append(ret, moved...) + ret = append(ret, remaining[i+1:]...) + return ret + } } - - // Insert. - instrs = append(instrs, nil) - copy(instrs[to+1:], instrs[to:]) - instrs[to] = ins return instrs } diff --git a/internal/build/ssa_order_fix_test.go b/internal/build/ssa_order_fix_test.go index 7408ae261c..0cd4c1b514 100644 --- a/internal/build/ssa_order_fix_test.go +++ b/internal/build/ssa_order_fix_test.go @@ -11,6 +11,7 @@ import ( "strings" "testing" + "golang.org/x/tools/go/packages" "golang.org/x/tools/go/ssa" "golang.org/x/tools/go/ssa/ssautil" ) @@ -115,7 +116,145 @@ func f() { } } +func TestFixSSAOrderReturnLoadWithDebugRefs(t *testing.T) { + const src = `package p +type value struct { n int } +func (v *value) mutate() bool { v.n = 1; return true } +func f() (value, bool) { + var v value + return v, v.mutate() +}` + base := ssa.SanityCheckFunctions | ssa.InstantiateGenerics + for _, test := range []struct { + name string + mode ssa.BuilderMode + }{ + {name: "default", mode: base}, + {name: "global-debug", mode: base | ssa.GlobalDebug}, + } { + t.Run(test.name, func(t *testing.T) { + fn := buildSSAOrderTestPackageMode(t, src, test.mode) + checkReturnLoadAfterMutation(t, fn, "mutate") + }) + } +} + +func TestFixSSAOrderCryptoX509ParseOID(t *testing.T) { + fset := token.NewFileSet() + loaded, err := packages.Load(&packages.Config{ + Mode: packages.LoadSyntax, + Fset: fset, + }, "crypto/x509") + if err != nil { + t.Fatal(err) + } + if packages.PrintErrors(loaded) != 0 || len(loaded) != 1 { + t.Fatal("failed to load crypto/x509") + } + mode := ssa.SanityCheckFunctions | ssa.InstantiateGenerics | ssa.GlobalDebug + prog, ssaPackages := ssautil.Packages(loaded, mode) + prog.Build() + pkg := ssaPackages[0] + fixSSAOrder(pkg, loaded[0].Syntax) + checkReturnLoadAfterMutation(t, pkg.Func("ParseOID"), "unmarshalOIDText") +} + +func TestMoveInstrsAfter(t *testing.T) { + const src = `package p +func f() { + println(1) + println(2) + println(3) +}` + fn := buildSSAOrderTestPackage(t, src) + instrs := fn.Blocks[0].Instrs + if len(instrs) < 4 { + t.Fatalf("instructions = %d, want at least 4", len(instrs)) + } + + assertOrder := func(t *testing.T, got, want []ssa.Instruction) { + t.Helper() + if len(got) != len(want) { + t.Fatalf("instruction count = %d, want %d", len(got), len(want)) + } + for i := range want { + if got[i] != want[i] { + t.Fatalf("instruction %d = %v, want %v", i, got[i], want[i]) + } + } + } + + t.Run("empty", func(t *testing.T) { + assertOrder(t, moveInstrsAfter(instrs, nil, instrs[1]), instrs) + }) + t.Run("nil-anchor", func(t *testing.T) { + moving := map[ssa.Instruction]struct{}{instrs[0]: {}} + assertOrder(t, moveInstrsAfter(instrs, moving, nil), instrs) + }) + t.Run("missing-anchor", func(t *testing.T) { + moving := map[ssa.Instruction]struct{}{instrs[0]: {}} + assertOrder(t, moveInstrsAfter(instrs, moving, &ssa.Return{}), instrs) + }) + t.Run("stable", func(t *testing.T) { + moving := map[ssa.Instruction]struct{}{ + instrs[0]: {}, + instrs[2]: {}, + } + want := []ssa.Instruction{instrs[1], instrs[0], instrs[2]} + want = append(want, instrs[3:]...) + assertOrder(t, moveInstrsAfter(instrs, moving, instrs[1]), want) + }) +} + +func checkReturnLoadAfterMutation(t *testing.T, fn *ssa.Function, mutation string) { + t.Helper() + var ret *ssa.Return + var mutationCall ssa.CallInstruction + for _, block := range fn.Blocks { + for _, instr := range block.Instrs { + if candidate, ok := instr.(*ssa.Return); ok { + ret = candidate + } + if call, ok := instr.(ssa.CallInstruction); ok { + callee := call.Common().StaticCallee() + if callee != nil && callee.Name() == mutation { + mutationCall = call + } + } + } + } + if ret == nil || len(ret.Results) != 2 || mutationCall == nil { + t.Fatalf("unexpected return instruction: %v", ret) + } + callInstr := mutationCall.(ssa.Instruction) + callIdx := indexOfInstr(callInstr.Block().Instrs, callInstr) + loadIdx := -1 + debugRefIdx := -1 + var resultLoad *ssa.UnOp + for i, instr := range callInstr.Block().Instrs { + if load, ok := instr.(*ssa.UnOp); ok && load.Op == token.MUL { + if alloc, ok := load.X.(*ssa.Alloc); ok && callUsesValue(mutationCall, alloc) { + loadIdx = i + resultLoad = load + } + } + if ref, ok := instr.(*ssa.DebugRef); ok && resultLoad != nil && instrUsesValue(ref, resultLoad) { + debugRefIdx = i + } + } + if callIdx < 0 || loadIdx <= callIdx { + t.Fatalf("return load index = %d, mutation call index = %d; want load after call\n%s", loadIdx, callIdx, fn) + } + if debugRefIdx >= 0 && debugRefIdx <= loadIdx { + t.Fatalf("DebugRef index = %d, load index = %d; want DebugRef after its load\n%s", debugRefIdx, loadIdx, fn) + } +} + func buildSSAOrderTestPackage(t *testing.T, src string) *ssa.Function { + return buildSSAOrderTestPackageMode(t, src, ssa.SanityCheckFunctions|ssa.InstantiateGenerics) +} + +func buildSSAOrderTestPackageMode(t *testing.T, src string, mode ssa.BuilderMode) *ssa.Function { t.Helper() fset := token.NewFileSet() file, err := parser.ParseFile(fset, "p.go", src, 0) @@ -129,7 +268,7 @@ func buildSSAOrderTestPackage(t *testing.T, src string) *ssa.Function { fset, pkg, files, - ssa.SanityCheckFunctions|ssa.InstantiateGenerics, + mode, ) if err != nil { t.Fatalf("BuildPackage: %v", err) diff --git a/test/go/dwarf_semantics_acceptance_test.go b/test/go/dwarf_semantics_acceptance_test.go new file mode 100644 index 0000000000..29a8c34fc8 --- /dev/null +++ b/test/go/dwarf_semantics_acceptance_test.go @@ -0,0 +1,62 @@ +//go:build !llgo + +package gotest + +import ( + "os" + "os/exec" + "path/filepath" + "strings" + "testing" +) + +const dwarfReturnOrderProbe = `package main + +type value struct { + n int +} + +func (v *value) mutate() bool { + v.n = 1 + return true +} + +func result() (value, bool) { + var v value + return v, v.mutate() +} + +func main() { + v, ok := result() + if !ok || v.n != 1 { + panic("return value was loaded before mutation") + } + println("RETURN_ORDER_OK") +} +` + +func TestDWARFReturnOrderSemantics(t *testing.T) { + repoRoot := findStringConversionRepoRoot(t) + source := filepath.Join(t.TempDir(), "main.go") + if err := os.WriteFile(source, []byte(dwarfReturnOrderProbe), 0o600); err != nil { + t.Fatal(err) + } + cmd := exec.Command( + "go", "run", "./cmd/llgo", "run", "-ldflags=-w=false", source, + ) + cmd.Dir = repoRoot + cmd.Env = append(os.Environ(), + "LLGO_ROOT="+repoRoot, + "LLGO_BUILD_CACHE=off", + "GOMAXPROCS=2", + "GOMEMLIMIT=6GiB", + "GOFLAGS=-p=1", + ) + out, err := cmd.CombinedOutput() + if err != nil { + t.Fatalf("LLGo DWARF return-order acceptance failed: %v\n%s", err, out) + } + if !strings.Contains(string(out), "RETURN_ORDER_OK") { + t.Fatalf("LLGo DWARF return-order acceptance did not report success:\n%s", out) + } +} From 557f212d096f382e172a57b0ea3d9ede1f60ff74 Mon Sep 17 00:00:00 2001 From: Li Jie Date: Wed, 22 Jul 2026 19:03:45 +0800 Subject: [PATCH 39/73] fix(build): preserve DebugRefs in select order repair --- internal/build/ssa_order_fix.go | 27 +++++++++++++++ internal/build/ssa_order_fix_test.go | 49 +++++++++++++++++++--------- 2 files changed, 61 insertions(+), 15 deletions(-) diff --git a/internal/build/ssa_order_fix.go b/internal/build/ssa_order_fix.go index 08c7df38d8..1efd9e46b4 100644 --- a/internal/build/ssa_order_fix.go +++ b/internal/build/ssa_order_fix.go @@ -186,6 +186,9 @@ func moveAssignDepsAfterRecv(b *ssa.BasicBlock, roots []ssa.Value, recv ssa.Valu if len(move) == 0 { return false } + // Metadata uses must follow the definitions they describe rather than + // blocking an otherwise safe source-order repair. + includeDebugRefsForMovedValues(b.Instrs, move, recvIdx) if moveWouldBreakSSA(b.Instrs, move, recvIdx) { return false } @@ -205,6 +208,30 @@ func moveAssignDepsAfterRecv(b *ssa.BasicBlock, roots []ssa.Value, recv ssa.Valu return true } +func includeDebugRefsForMovedValues(instrs []ssa.Instruction, move map[int]struct{}, through int) { + moved := make(map[ssa.Value]struct{}, len(move)) + for i := range move { + if v, ok := instrs[i].(ssa.Value); ok && v != nil { + moved[v] = struct{}{} + } + } + for i := 0; i <= through && i < len(instrs); i++ { + if _, moving := move[i]; moving { + continue + } + ref, ok := instrs[i].(*ssa.DebugRef) + if !ok { + continue + } + for v := range moved { + if instrUsesValue(ref, v) { + move[i] = struct{}{} + break + } + } + } +} + func moveWouldBreakSSA(instrs []ssa.Instruction, move map[int]struct{}, recvIdx int) bool { moved := make(map[ssa.Value]struct{}, len(move)) for i := range move { diff --git a/internal/build/ssa_order_fix_test.go b/internal/build/ssa_order_fix_test.go index 0cd4c1b514..33ff26041f 100644 --- a/internal/build/ssa_order_fix_test.go +++ b/internal/build/ssa_order_fix_test.go @@ -29,11 +29,12 @@ func f() { case *fp(&x, 100) = <-fc(c, 1): } }` - fn := buildSSAOrderTestPackage(t, src) - got := instrOrder(fn, "fc(", "<-", "fp(", "*t") - if !inOrder(got, "fc(", "<-", "fp(") { - t.Fatalf("single-case select receive assignment order = %v, want fc/receive before fp", got) - } + testSSAOrderModes(t, src, func(t *testing.T, fn *ssa.Function) { + got := instrOrder(fn, "fc(", "<-", "fp(", "*t") + if !inOrder(got, "fc(", "<-", "fp(") { + t.Fatalf("single-case select receive assignment order = %v, want fc/receive before fp", got) + } + }) } func TestFixSSAOrderPlainRecvAssignKeepsLeftToRight(t *testing.T) { @@ -67,11 +68,12 @@ func f() { case m[fn(13, 100)] = <-fc(c, 1): } }` - fn := buildSSAOrderTestPackage(t, src) - got := instrOrder(fn, "fc(", "<-", "fn(") - if !inOrder(got, "fc(", "<-", "fn(") { - t.Fatalf("single-case select map receive assignment order = %v, want fc/receive before fn", got) - } + testSSAOrderModes(t, src, func(t *testing.T, fn *ssa.Function) { + got := instrOrder(fn, "fc(", "<-", "fn(") + if !inOrder(got, "fc(", "<-", "fn(") { + t.Fatalf("single-case select map receive assignment order = %v, want fc/receive before fn", got) + } + }) } func TestFixSSAOrderSingleCaseSelectTwoValueRecv(t *testing.T) { @@ -88,11 +90,12 @@ func f() { case *fp(&x, 100), ok = <-fc(c, 1): } }` - fn := buildSSAOrderTestPackage(t, src) - got := instrOrder(fn, "fc(", "<-", "fp(", "*t") - if !inOrder(got, "fc(", "<-", "fp(") { - t.Fatalf("single-case select two-value receive assignment order = %v, want fc/receive before fp", got) - } + testSSAOrderModes(t, src, func(t *testing.T, fn *ssa.Function) { + got := instrOrder(fn, "fc(", "<-", "fp(", "*t") + if !inOrder(got, "fc(", "<-", "fp(") { + t.Fatalf("single-case select two-value receive assignment order = %v, want fc/receive before fp", got) + } + }) } func TestFixSSAOrderMultiCaseSelectKeepsLeftToRight(t *testing.T) { @@ -254,6 +257,22 @@ func buildSSAOrderTestPackage(t *testing.T, src string) *ssa.Function { return buildSSAOrderTestPackageMode(t, src, ssa.SanityCheckFunctions|ssa.InstantiateGenerics) } +func testSSAOrderModes(t *testing.T, src string, check func(*testing.T, *ssa.Function)) { + t.Helper() + base := ssa.SanityCheckFunctions | ssa.InstantiateGenerics + for _, test := range []struct { + name string + mode ssa.BuilderMode + }{ + {name: "default", mode: base}, + {name: "global-debug", mode: base | ssa.GlobalDebug}, + } { + t.Run(test.name, func(t *testing.T) { + check(t, buildSSAOrderTestPackageMode(t, src, test.mode)) + }) + } +} + func buildSSAOrderTestPackageMode(t *testing.T, src string, mode ssa.BuilderMode) *ssa.Function { t.Helper() fset := token.NewFileSet() From dbd258806cab5a0ab73d01d9aef32559086be800 Mon Sep 17 00:00:00 2001 From: Li Jie Date: Wed, 22 Jul 2026 23:21:47 +0800 Subject: [PATCH 40/73] test(lto): cover DWARF-preserved string values --- cl/compile_test.go | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/cl/compile_test.go b/cl/compile_test.go index bd0c1b810b..03996d377d 100644 --- a/cl/compile_test.go +++ b/cl/compile_test.go @@ -258,6 +258,13 @@ var testltoLTOPluginTests = []string{ "globaldce_reflect_method_by_name_ltoplugin_switch", } +var testltoLTOPluginDWARFTests = []string{ + "globaldce_reflect_method_by_name_ltoplugin_concat", + "globaldce_reflect_method_by_name_ltoplugin_global_slice", + "globaldce_reflect_method_by_name_ltoplugin_param", + "globaldce_reflect_method_by_name_ltoplugin_slice", +} + func TestBuildAndCheckSymbolsFromTestlto(t *testing.T) { if !buildenv.Dev { t.Skip("globaldce symbol checks require dev build") @@ -401,6 +408,15 @@ func TestBuildAndCheckSymbolsFromTestltoLTOPluginAggregateABI(t *testing.T) { } } +func TestBuildAndCheckSymbolsFromTestltoLTOPluginDWARF(t *testing.T) { + t.Setenv("LLGO_BUILD_CACHE", "off") + buildConf := testltoLTOPluginConf(t, build.ModeBuild) + buildConf.LinkOptions.DWARF = build.DWARFPreserve + cltest.BuildAndCheckSymbolsFromDir(t, "", "./_testlto", testltoLTOPluginDWARFTests, + cltest.WithRunConfig(buildConf), + ) +} + func TestFilterEmulatorOutput(t *testing.T) { tests := []struct { name string From 390453afcaa6ba84d13d3219142f56eb4a9b0121 Mon Sep 17 00:00:00 2001 From: Li Jie Date: Tue, 28 Jul 2026 21:19:50 +0800 Subject: [PATCH 41/73] docs(ssa): clarify DWARF optimized marker --- ssa/package.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/ssa/package.go b/ssa/package.go index d2ee9f0b86..aaf91dbb25 100644 --- a/ssa/package.go +++ b/ssa/package.go @@ -382,8 +382,8 @@ func (p Program) EnableLTOPluginMarkers(enable bool) { p.enableLTOPluginMarker = enable } -// SetDebugInfoOptimized records whether the LLVM IR optimization pipeline runs. -// It only controls DWARF's optimized marker and never selects compiler passes. +// SetDebugInfoOptimized records whether DWARF should mark generated code as +// optimized. It never selects compiler passes. func (p Program) SetDebugInfoOptimized(enable bool) { p.debugInfoOptimized = enable } From d4e975789c26ca2e4a7b57eebf754495292fb48b Mon Sep 17 00:00:00 2001 From: Li Jie Date: Mon, 3 Aug 2026 09:50:13 +0800 Subject: [PATCH 42/73] fix(build): finalize consolidated DebugRef ordering --- internal/build/ssa_order_fix.go | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/internal/build/ssa_order_fix.go b/internal/build/ssa_order_fix.go index 1efd9e46b4..f9d9dc251b 100644 --- a/internal/build/ssa_order_fix.go +++ b/internal/build/ssa_order_fix.go @@ -215,7 +215,7 @@ func includeDebugRefsForMovedValues(instrs []ssa.Instruction, move map[int]struc moved[v] = struct{}{} } } - for i := 0; i <= through && i < len(instrs); i++ { + for i := 0; i < through && i < len(instrs); i++ { if _, moving := move[i]; moving { continue } @@ -421,7 +421,8 @@ func valueDependsOn(v, target ssa.Value, seen map[ssa.Value]struct{}) bool { } // moveInstrsAfter moves selected instructions as a stable group immediately -// after anchor. +// after anchor. It returns instrs unchanged when moving is empty or anchor is +// nil or absent. func moveInstrsAfter(instrs []ssa.Instruction, moving map[ssa.Instruction]struct{}, anchor ssa.Instruction) []ssa.Instruction { if len(moving) == 0 || anchor == nil { return instrs From 276472fead3b8a6a28ec981c938535b347b8b3d2 Mon Sep 17 00:00:00 2001 From: Li Jie Date: Mon, 3 Aug 2026 12:02:39 +0800 Subject: [PATCH 43/73] fix(build): document SSA move precondition --- internal/build/ssa_order_fix.go | 15 ++++++++++----- internal/build/ssa_order_fix_test.go | 4 ++++ test/go/caller_acceptance_test.go | 4 ++-- test/go/dwarf_semantics_acceptance_test.go | 2 +- test/go/fault_unwind_test.go | 2 +- test/go/float_int_conversion_test.go | 2 +- test/go/large_array_return_test.go | 2 +- test/go/newexpr_go126_test.go | 2 +- test/go/runtime_lineinfo_stack_test.go | 4 ++-- test/go/runtime_statement_line_test.go | 2 +- test/go/string_conversion_test.go | 6 +++--- 11 files changed, 27 insertions(+), 18 deletions(-) diff --git a/internal/build/ssa_order_fix.go b/internal/build/ssa_order_fix.go index f9d9dc251b..ccc98a3c8d 100644 --- a/internal/build/ssa_order_fix.go +++ b/internal/build/ssa_order_fix.go @@ -21,9 +21,10 @@ import ( // the first return value as a load before the call, which makes o appear unchanged // to the return value in our backend. // -// This pass moves loads of local allocs used only for the final Return results -// to after any intervening calls that use the same alloc pointer, matching the -// behavior of the Go compiler for the stdlib cases we rely on (e.g. crypto/x509.ParseOID). +// This pass moves loads of local allocs that feed a Return result and have no +// intervening executable use before that Return to after any intervening calls +// that use the same alloc pointer, matching the behavior of the Go compiler for +// the stdlib cases we rely on (e.g. crypto/x509.ParseOID). func fixSSAOrder(pkg *ssa.Package, files []*ast.File) { if pkg == nil { return @@ -421,12 +422,16 @@ func valueDependsOn(v, target ssa.Value, seen map[ssa.Value]struct{}) bool { } // moveInstrsAfter moves selected instructions as a stable group immediately -// after anchor. It returns instrs unchanged when moving is empty or anchor is -// nil or absent. +// after anchor. The anchor must not be in moving; callers use an instruction +// that remains in the block. It returns instrs unchanged when moving is empty, +// anchor is nil or absent, or the precondition is violated. func moveInstrsAfter(instrs []ssa.Instruction, moving map[ssa.Instruction]struct{}, anchor ssa.Instruction) []ssa.Instruction { if len(moving) == 0 || anchor == nil { return instrs } + if _, ok := moving[anchor]; ok { + return instrs + } moved := make([]ssa.Instruction, 0, len(moving)) remaining := make([]ssa.Instruction, 0, len(instrs)) for _, instr := range instrs { diff --git a/internal/build/ssa_order_fix_test.go b/internal/build/ssa_order_fix_test.go index 33ff26041f..9db1b46f1e 100644 --- a/internal/build/ssa_order_fix_test.go +++ b/internal/build/ssa_order_fix_test.go @@ -198,6 +198,10 @@ func f() { moving := map[ssa.Instruction]struct{}{instrs[0]: {}} assertOrder(t, moveInstrsAfter(instrs, moving, &ssa.Return{}), instrs) }) + t.Run("anchor-in-moving", func(t *testing.T) { + moving := map[ssa.Instruction]struct{}{instrs[1]: {}} + assertOrder(t, moveInstrsAfter(instrs, moving, instrs[1]), instrs) + }) t.Run("stable", func(t *testing.T) { moving := map[ssa.Instruction]struct{}{ instrs[0]: {}, diff --git a/test/go/caller_acceptance_test.go b/test/go/caller_acceptance_test.go index f56aa87b1b..dbf3729557 100644 --- a/test/go/caller_acceptance_test.go +++ b/test/go/caller_acceptance_test.go @@ -384,7 +384,7 @@ func runLLGoProbe(t *testing.T, dir string) (string, error) { func runLLGoProbeWithFlags(t *testing.T, dir string, flags ...string) (string, error) { t.Helper() - repoRoot := findStringConversionRepoRoot(t) + repoRoot := findRepoRoot(t) t.Setenv("LLGO_ROOT", repoRoot) args := append([]string{"run", "./cmd/llgo", "run", "-a"}, flags...) cmd := exec.Command("go", append(args, filepath.Join(dir, "main.go"))...) @@ -599,7 +599,7 @@ var ( // its own module). func runLLGoInModule(t *testing.T, dir string, args ...string) (string, error) { t.Helper() - repoRoot := findStringConversionRepoRoot(t) + repoRoot := findRepoRoot(t) t.Setenv("LLGO_ROOT", repoRoot) acceptanceLLGoOnce.Do(func() { tmp, err := os.MkdirTemp("", "llgo-acceptance-bin") diff --git a/test/go/dwarf_semantics_acceptance_test.go b/test/go/dwarf_semantics_acceptance_test.go index 29a8c34fc8..cd417d593d 100644 --- a/test/go/dwarf_semantics_acceptance_test.go +++ b/test/go/dwarf_semantics_acceptance_test.go @@ -36,7 +36,7 @@ func main() { ` func TestDWARFReturnOrderSemantics(t *testing.T) { - repoRoot := findStringConversionRepoRoot(t) + repoRoot := findRepoRoot(t) source := filepath.Join(t.TempDir(), "main.go") if err := os.WriteFile(source, []byte(dwarfReturnOrderProbe), 0o600); err != nil { t.Fatal(err) diff --git a/test/go/fault_unwind_test.go b/test/go/fault_unwind_test.go index 0f6f6a4877..f6dae85141 100644 --- a/test/go/fault_unwind_test.go +++ b/test/go/fault_unwind_test.go @@ -108,7 +108,7 @@ var ( func faultLLGo(t *testing.T) string { t.Helper() - repoRoot := findStringConversionRepoRoot(t) + repoRoot := findRepoRoot(t) t.Setenv("LLGO_ROOT", repoRoot) faultLLGoOnce.Do(func() { tmp, err := os.MkdirTemp("", "llgo-fault-bin") diff --git a/test/go/float_int_conversion_test.go b/test/go/float_int_conversion_test.go index c2ae5498b8..3db49ee309 100644 --- a/test/go/float_int_conversion_test.go +++ b/test/go/float_int_conversion_test.go @@ -106,7 +106,7 @@ func TestFloatToIntegerConversionSemantics(t *testing.T) { if err := os.WriteFile(file, []byte(floatIntConversionProbe), 0644); err != nil { t.Fatal(err) } - repoRoot := findStringConversionRepoRoot(t) + repoRoot := findRepoRoot(t) t.Setenv("LLGO_ROOT", repoRoot) runStringConversionProbe(t, repoRoot, "go", "run", "./cmd/llgo", "run", file) } diff --git a/test/go/large_array_return_test.go b/test/go/large_array_return_test.go index 0cb38c2cc7..2d0363e2a8 100644 --- a/test/go/large_array_return_test.go +++ b/test/go/large_array_return_test.go @@ -61,7 +61,7 @@ var ( func largeArrayLLGo(t *testing.T) string { t.Helper() - root := findStringConversionRepoRoot(t) + root := findRepoRoot(t) t.Setenv("LLGO_ROOT", root) largeArrayLLGoOnce.Do(func() { dir, err := os.MkdirTemp("", "llgo-large-array-bin") diff --git a/test/go/newexpr_go126_test.go b/test/go/newexpr_go126_test.go index e0f9d2a4d6..b03f1873cc 100644 --- a/test/go/newexpr_go126_test.go +++ b/test/go/newexpr_go126_test.go @@ -69,7 +69,7 @@ func TestNewExpressionInitializesAllocatedValue(t *testing.T) { t.Fatal(err) } - repoRoot := findStringConversionRepoRoot(t) + repoRoot := findRepoRoot(t) runStringConversionProbe(t, repoRoot, "go", "run", file) t.Setenv("LLGO_ROOT", repoRoot) runStringConversionProbe(t, repoRoot, "go", "run", "./cmd/llgo", "run", file) diff --git a/test/go/runtime_lineinfo_stack_test.go b/test/go/runtime_lineinfo_stack_test.go index 673276bcd7..46beea2360 100644 --- a/test/go/runtime_lineinfo_stack_test.go +++ b/test/go/runtime_lineinfo_stack_test.go @@ -212,7 +212,7 @@ func TestRuntimeLineInfoAndStack(t *testing.T) { t.Fatal(err) } - repoRoot := findStringConversionRepoRoot(t) + repoRoot := findRepoRoot(t) t.Setenv("LLGO_ROOT", repoRoot) cmd := exec.Command("go", "run", "./cmd/llgo", "run", "-a", file) cmd.Dir = repoRoot @@ -341,7 +341,7 @@ func TestRuntimeFuncInfoConcurrentFirstUse(t *testing.T) { t.Fatal(err) } - repoRoot := findStringConversionRepoRoot(t) + repoRoot := findRepoRoot(t) t.Setenv("LLGO_ROOT", repoRoot) cmd := exec.Command("go", "run", "./cmd/llgo", "run", "-a", file) cmd.Dir = repoRoot diff --git a/test/go/runtime_statement_line_test.go b/test/go/runtime_statement_line_test.go index 9d86021cd2..fd3a79cc00 100644 --- a/test/go/runtime_statement_line_test.go +++ b/test/go/runtime_statement_line_test.go @@ -205,7 +205,7 @@ func TestRuntimeStatementLineInfo(t *testing.T) { t.Fatal(err) } - repoRoot := findStringConversionRepoRoot(t) + repoRoot := findRepoRoot(t) t.Setenv("LLGO_ROOT", repoRoot) cmd := exec.Command("go", "run", "./cmd/llgo", "run", "-a", file) cmd.Dir = repoRoot diff --git a/test/go/string_conversion_test.go b/test/go/string_conversion_test.go index b28115ae9e..0bbd0fb638 100644 --- a/test/go/string_conversion_test.go +++ b/test/go/string_conversion_test.go @@ -98,7 +98,7 @@ func TestStringConversionFromWideIntegers(t *testing.T) { if err := os.WriteFile(file, []byte(stringConversionProbe), 0644); err != nil { t.Fatal(err) } - repoRoot := findStringConversionRepoRoot(t) + repoRoot := findRepoRoot(t) runStringConversionProbe(t, repoRoot, "go", "run", file) t.Setenv("LLGO_ROOT", repoRoot) runStringConversionProbe(t, repoRoot, "go", "run", "./cmd/llgo", "run", file) @@ -110,7 +110,7 @@ func TestEmptyStringToByteRuneSlicesNonNil(t *testing.T) { if err := os.WriteFile(file, []byte(emptyStringConversionProbe), 0644); err != nil { t.Fatal(err) } - repoRoot := findStringConversionRepoRoot(t) + repoRoot := findRepoRoot(t) runStringConversionProbe(t, repoRoot, "go", "run", file) t.Setenv("LLGO_ROOT", repoRoot) runStringConversionProbe(t, repoRoot, "go", "run", "./cmd/llgo", "run", file) @@ -127,7 +127,7 @@ func runStringConversionProbe(t *testing.T, dir, name string, args ...string) { } } -func findStringConversionRepoRoot(t *testing.T) string { +func findRepoRoot(t *testing.T) string { t.Helper() dir, err := os.Getwd() if err != nil { From f33c20864221e4c6cddc0ae3e4e24699f89376f4 Mon Sep 17 00:00:00 2001 From: Li Jie Date: Mon, 3 Aug 2026 14:27:50 +0800 Subject: [PATCH 44/73] refactor(build): share DebugRef move analysis --- internal/build/ssa_order_fix.go | 44 ++++++++++++++++++++++----------- 1 file changed, 30 insertions(+), 14 deletions(-) diff --git a/internal/build/ssa_order_fix.go b/internal/build/ssa_order_fix.go index ccc98a3c8d..c115ee195a 100644 --- a/internal/build/ssa_order_fix.go +++ b/internal/build/ssa_order_fix.go @@ -189,8 +189,9 @@ func moveAssignDepsAfterRecv(b *ssa.BasicBlock, roots []ssa.Value, recv ssa.Valu } // Metadata uses must follow the definitions they describe rather than // blocking an otherwise safe source-order repair. - includeDebugRefsForMovedValues(b.Instrs, move, recvIdx) - if moveWouldBreakSSA(b.Instrs, move, recvIdx) { + moved := movedValuesForIndices(b.Instrs, move) + includeDebugRefsForMovedValues(b.Instrs, move, moved, 0, recvIdx) + if moveWouldBreakSSA(b.Instrs, move, recvIdx, moved) { return false } deps := make([]ssa.Instruction, 0, len(move)) @@ -209,14 +210,30 @@ func moveAssignDepsAfterRecv(b *ssa.BasicBlock, roots []ssa.Value, recv ssa.Valu return true } -func includeDebugRefsForMovedValues(instrs []ssa.Instruction, move map[int]struct{}, through int) { +func movedValuesForIndices(instrs []ssa.Instruction, move map[int]struct{}) map[ssa.Value]struct{} { moved := make(map[ssa.Value]struct{}, len(move)) for i := range move { + if i < 0 || i >= len(instrs) { + continue + } if v, ok := instrs[i].(ssa.Value); ok && v != nil { moved[v] = struct{}{} } } - for i := 0; i < through && i < len(instrs); i++ { + return moved +} + +// includeDebugRefsForMovedValues adds metadata-only uses of moved values to +// move. The moved value set is supplied by the caller so the same set can be +// reused by the subsequent SSA safety check without rescanning move. +func includeDebugRefsForMovedValues(instrs []ssa.Instruction, move map[int]struct{}, moved map[ssa.Value]struct{}, from, through int) { + if from < 0 { + from = 0 + } + if through > len(instrs) { + through = len(instrs) + } + for i := from; i < through; i++ { if _, moving := move[i]; moving { continue } @@ -233,13 +250,7 @@ func includeDebugRefsForMovedValues(instrs []ssa.Instruction, move map[int]struc } } -func moveWouldBreakSSA(instrs []ssa.Instruction, move map[int]struct{}, recvIdx int) bool { - moved := make(map[ssa.Value]struct{}, len(move)) - for i := range move { - if v, ok := instrs[i].(ssa.Value); ok && v != nil { - moved[v] = struct{}{} - } - } +func moveWouldBreakSSA(instrs []ssa.Instruction, move map[int]struct{}, recvIdx int, moved map[ssa.Value]struct{}) bool { for i := 0; i <= recvIdx && i < len(instrs); i++ { if _, moving := move[i]; moving { continue @@ -332,11 +343,16 @@ func fixSSAOrderBlock(b *ssa.BasicBlock) { // DebugRefs are metadata-only and move with the value they describe. Any // executable use before Return still makes reordering unsafe. - moving := map[ssa.Instruction]struct{}{u: {}} + movingIndices := map[int]struct{}{loadIdx: {}} + moved := movedValuesForIndices(b.Instrs, movingIndices) + includeDebugRefsForMovedValues(b.Instrs, movingIndices, moved, loadIdx+1, retIdx) + moving := make(map[ssa.Instruction]struct{}, len(movingIndices)) + for i := range movingIndices { + moving[b.Instrs[i]] = struct{}{} + } usedBeforeReturn := false for i := loadIdx + 1; i < retIdx; i++ { - if ref, ok := b.Instrs[i].(*ssa.DebugRef); ok && instrUsesValue(ref, u) { - moving[ref] = struct{}{} + if _, moving := movingIndices[i]; moving { continue } if instrUsesValue(b.Instrs[i], u) { From 17ac3d313eebc0e71ef4fe728935d748456474f0 Mon Sep 17 00:00:00 2001 From: Li Jie Date: Mon, 3 Aug 2026 17:12:52 +0800 Subject: [PATCH 45/73] test(lto): align DWARF symbol checks with main --- cl/compile_test.go | 33 --------------------------------- 1 file changed, 33 deletions(-) diff --git a/cl/compile_test.go b/cl/compile_test.go index 03996d377d..5eecf6cbd5 100644 --- a/cl/compile_test.go +++ b/cl/compile_test.go @@ -226,15 +226,6 @@ func TestRunAndTestFromTestlto(t *testing.T) { cltest.RunAndTestFromDir(t, "", "./_testlto", ignore, cltest.WithRunConfig(conf)) } -func TestRunAndTestFromTestltoDWARF(t *testing.T) { - t.Setenv("LLGO_BUILD_CACHE", "off") - conf := build.NewDefaultConf(build.ModeRun) - conf.LTO = lto.Full - conf.LinkOptions.DWARF = build.DWARFPreserve - cltest.RunAndTestFromDir(t, "reflectmk_runtime", "./_testlto", nil, - cltest.WithRunConfig(conf), cltest.WithIRCheck(false)) -} - var testltoSymbolChecks = []string{ "globaldce_interface_matrix", "globaldce_interface_slots", @@ -258,13 +249,6 @@ var testltoLTOPluginTests = []string{ "globaldce_reflect_method_by_name_ltoplugin_switch", } -var testltoLTOPluginDWARFTests = []string{ - "globaldce_reflect_method_by_name_ltoplugin_concat", - "globaldce_reflect_method_by_name_ltoplugin_global_slice", - "globaldce_reflect_method_by_name_ltoplugin_param", - "globaldce_reflect_method_by_name_ltoplugin_slice", -} - func TestBuildAndCheckSymbolsFromTestlto(t *testing.T) { if !buildenv.Dev { t.Skip("globaldce symbol checks require dev build") @@ -336,14 +320,6 @@ func TestRunAndTestFromTestltoLTOPlugin(t *testing.T) { ) } -func TestRunAndTestFromTestltoLTOPluginDWARF(t *testing.T) { - t.Setenv("LLGO_BUILD_CACHE", "off") - conf := testltoLTOPluginConf(t, build.ModeRun) - conf.LinkOptions.DWARF = build.DWARFPreserve - cltest.RunAndTestFromDir(t, "ltoplugin_switch", "./_testlto", nil, - cltest.WithRunConfig(conf), cltest.WithIRCheck(false)) -} - func TestBuildAndCheckSymbolsFromTestltoLTOPlugin(t *testing.T) { buildConf := testltoLTOPluginConf(t, build.ModeBuild) // See TestBuildAndCheckSymbolsFromTestlto: dynamic main.* exports retain @@ -408,15 +384,6 @@ func TestBuildAndCheckSymbolsFromTestltoLTOPluginAggregateABI(t *testing.T) { } } -func TestBuildAndCheckSymbolsFromTestltoLTOPluginDWARF(t *testing.T) { - t.Setenv("LLGO_BUILD_CACHE", "off") - buildConf := testltoLTOPluginConf(t, build.ModeBuild) - buildConf.LinkOptions.DWARF = build.DWARFPreserve - cltest.BuildAndCheckSymbolsFromDir(t, "", "./_testlto", testltoLTOPluginDWARFTests, - cltest.WithRunConfig(buildConf), - ) -} - func TestFilterEmulatorOutput(t *testing.T) { tests := []struct { name string From 9642a9efefbb45e650cd97d8a04770570d26f381 Mon Sep 17 00:00:00 2001 From: Li Jie Date: Sat, 1 Aug 2026 21:26:42 +0800 Subject: [PATCH 46/73] cl: fold constant comparisons before lowering --- cl/compile.go | 18 +++++ cl/compile_nil_test.go | 50 ++++++++++++++ internal/build/build_test.go | 24 +++++++ .../testdata/unreachablebodyless/main.go | 66 +++++++++++++++++++ test/goroot/xfail.yaml | 4 -- 5 files changed, 158 insertions(+), 4 deletions(-) create mode 100644 internal/build/testdata/unreachablebodyless/main.go diff --git a/cl/compile.go b/cl/compile.go index d15422e878..c18ac435a9 100644 --- a/cl/compile.go +++ b/cl/compile.go @@ -1309,6 +1309,10 @@ func (p *context) compileInstrOrValue(b llssa.Builder, iv instrOrValue, asValue b.DeferStackDrain() } case *ssa.BinOp: + if value, ok := foldConstComparison(v); ok { + ret = p.prog.BoolVal(value) + break + } if isUntypedNilConst(v.X) && isUntypedNilConst(v.Y) { switch v.Op { case token.EQL: @@ -1684,6 +1688,20 @@ func isUntypedNilConst(v ssa.Value) bool { return ok && basic.Kind() == types.UntypedNil } +func foldConstComparison(v *ssa.BinOp) (bool, bool) { + switch v.Op { + case token.EQL, token.NEQ, token.LSS, token.LEQ, token.GTR, token.GEQ: + default: + return false, false + } + x, xok := v.X.(*ssa.Const) + y, yok := v.Y.(*ssa.Const) + if !xok || !yok || x.Value == nil || y.Value == nil { + return false, false + } + return constant.Compare(x.Value, v.Op, y.Value), true +} + func (p *context) nilOf(typ types.Type) llssa.Expr { return p.prog.Nil(p.type_(typ, llssa.InGo)) } diff --git a/cl/compile_nil_test.go b/cl/compile_nil_test.go index 9309f4b850..f4e7cbb062 100644 --- a/cl/compile_nil_test.go +++ b/cl/compile_nil_test.go @@ -7,6 +7,7 @@ import ( "go/constant" "go/token" "go/types" + "strings" "testing" llssa "github.com/goplus/llgo/ssa" @@ -157,6 +158,55 @@ func iface(v int) any { } } +func TestFoldConstComparison(t *testing.T) { + a := gossa.NewConst(constant.MakeString("a"), types.Typ[types.String]) + b := gossa.NewConst(constant.MakeString("b"), types.Typ[types.String]) + for _, tt := range []struct { + op token.Token + want bool + }{ + {token.EQL, false}, + {token.NEQ, true}, + {token.LSS, true}, + {token.LEQ, true}, + {token.GTR, false}, + {token.GEQ, false}, + } { + if got, ok := foldConstComparison(&gossa.BinOp{Op: tt.op, X: a, Y: b}); !ok || got != tt.want { + t.Errorf("foldConstComparison(%s) = %v, %v; want %v, true", tt.op, got, ok, tt.want) + } + } + if _, ok := foldConstComparison(&gossa.BinOp{Op: token.ADD, X: a, Y: b}); ok { + t.Fatal("non-comparison operation was folded") + } + if _, ok := foldConstComparison(&gossa.BinOp{Op: token.EQL, X: &gossa.Parameter{}, Y: b}); ok { + t.Fatal("non-constant operand was folded") + } + if _, ok := foldConstComparison(&gossa.BinOp{ + Op: token.EQL, + X: gossa.NewConst(nil, types.NewPointer(types.Typ[types.Int])), + Y: gossa.NewConst(nil, types.NewPointer(types.Typ[types.Int])), + }); ok { + t.Fatal("nil comparison was folded through go/constant") + } +} + +func TestCompileFoldsConstStringComparison(t *testing.T) { + _, mod := mustCompileLLPkgFromSrc(t, ` +package foo + +func equal() bool { return "a" == "b" } +func less() bool { return "a" < "b" } +`) + ir := mod.String() + if strings.Contains(ir, "StringEqual") { + t.Fatalf("constant string comparison called the runtime helper:\n%s", ir) + } + if !strings.Contains(ir, "ret i1 false") || !strings.Contains(ir, "ret i1 true") { + t.Fatalf("constant string comparisons were not folded:\n%s", ir) + } +} + func TestCompileGenericNilSwitchAndCompare(t *testing.T) { mustCompileLLPkgFromSrc(t, ` package foo diff --git a/internal/build/build_test.go b/internal/build/build_test.go index 5d67a571b2..74951d5cd1 100644 --- a/internal/build/build_test.go +++ b/internal/build/build_test.go @@ -1448,6 +1448,30 @@ func F() {} pkgs[0].LPkg.Prog.Dispose() } +func TestDoOptimizesUnreachableBodylessCalls(t *testing.T) { + conf := NewDefaultConf(ModeGen) + conf.AllowNoBody = true + pkgs, err := Do([]string{"./testdata/unreachablebodyless/main.go"}, conf) + if err != nil { + t.Fatal(err) + } + if len(pkgs) != 1 || pkgs[0].LPkg == nil { + t.Fatalf("Do returned packages = %+v, want one compiled package", pkgs) + } + defer pkgs[0].LPkg.Prog.Dispose() + mod := pkgs[0].LPkg.Module() + mod.SetDataLayout(pkgs[0].LPkg.Prog.DataLayout()) + mod.SetTarget(pkgs[0].LPkg.Prog.Target().Spec().Triple) + pbo := llvm.NewPassBuilderOptions() + defer pbo.Dispose() + if err := mod.RunPasses("default", pkgs[0].LPkg.Prog.TargetMachine(), pbo); err != nil { + t.Fatalf("optimize generated module: %v", err) + } + if ir := mod.String(); strings.Contains(ir, "call void @main.fail") { + t.Fatalf("unreachable bodyless call remains after optimization:\n%s", ir) + } +} + func TestDoReportsLocalityDirectiveError(t *testing.T) { file := filepath.Join(t.TempDir(), "invalid_locality.go") if err := os.WriteFile(file, []byte(`package invalidlocality diff --git a/internal/build/testdata/unreachablebodyless/main.go b/internal/build/testdata/unreachablebodyless/main.go new file mode 100644 index 0000000000..7d7b270f57 --- /dev/null +++ b/internal/build/testdata/unreachablebodyless/main.go @@ -0,0 +1,66 @@ +package main + +func fail() + +func init() { + if false { + fail() + } + if 0 == 1 { + fail() + } +} + +func init() { + const x = 0 + switch x { + case 1: + fail() + } + switch 1 { + case x: + fail() + } + switch { + case false: + fail() + } + const a = "a" + switch a { + case "b": + fail() + } + const snowman = '☃' + switch snowman { + case '☀': + fail() + } + const zero = float64(0) + const one = float64(1) + switch one { + case -1: + fail() + case zero: + fail() + } + switch 1i { + case 1: + fail() + case -1i: + fail() + } + const no = false + switch no { + case true: + fail() + } + switch 5 { + case 3, 4, 5, 6, 7: + case 0, 1, 2: + fail() + default: + fail() + } +} + +func main() {} diff --git a/test/goroot/xfail.yaml b/test/goroot/xfail.yaml index 8f5ded5305..dd2d2c3f37 100644 --- a/test/goroot/xfail.yaml +++ b/test/goroot/xfail.yaml @@ -3021,10 +3021,6 @@ xfails: directive: rundir case: fixedbugs/issue31636.go reason: llgo initializes independent imported packages in reverse source order - - version: go1.26 - directive: rundir - case: fixedbugs/issue9608.go - reason: llgo does not eliminate unreachable references to a bodyless function before linking - version: go1.26 directive: rundir case: fixedbugs/issue24693.go From 5133432feb3ab1fec727e718e1bbd40d6e104f5b Mon Sep 17 00:00:00 2001 From: Li Jie Date: Sat, 1 Aug 2026 23:43:19 +0800 Subject: [PATCH 47/73] test: isolate constant comparison folding --- cl/compile_nil_test.go | 49 +++++++++++++++++++++++++++++++++++++----- 1 file changed, 44 insertions(+), 5 deletions(-) diff --git a/cl/compile_nil_test.go b/cl/compile_nil_test.go index f4e7cbb062..ce669f692a 100644 --- a/cl/compile_nil_test.go +++ b/cl/compile_nil_test.go @@ -189,21 +189,60 @@ func TestFoldConstComparison(t *testing.T) { }); ok { t.Fatal("nil comparison was folded through go/constant") } + + for _, tt := range []struct { + name string + x, y constant.Value + }{ + {"integer", constant.MakeInt64(0), constant.MakeInt64(1)}, + {"string", constant.MakeString("a"), constant.MakeString("b")}, + {"rune", constant.MakeInt64('☃'), constant.MakeInt64('☀')}, + {"float", constant.MakeFloat64(0), constant.MakeFloat64(1)}, + { + "complex", + constant.MakeFromLiteral("1i", token.IMAG, 0), + constant.MakeFromLiteral("-1i", token.IMAG, 0), + }, + } { + t.Run(tt.name, func(t *testing.T) { + typ := types.Typ[types.UntypedInt] + if tt.name == "string" { + typ = types.Typ[types.UntypedString] + } + if got, ok := foldConstComparison(&gossa.BinOp{ + Op: token.EQL, + X: gossa.NewConst(tt.x, typ), + Y: gossa.NewConst(tt.y, typ), + }); !ok || got { + t.Fatalf("foldConstComparison(%s equality) = %v, %v; want false, true", tt.name, got, ok) + } + }) + } } -func TestCompileFoldsConstStringComparison(t *testing.T) { +func TestCompileFoldsConstComparisons(t *testing.T) { _, mod := mustCompileLLPkgFromSrc(t, ` package foo -func equal() bool { return "a" == "b" } -func less() bool { return "a" < "b" } +func intEqual() bool { return 0 == 1 } +func stringEqual() bool { return "a" == "b" } +func runeEqual() bool { return '☃' == '☀' } +func floatEqual() bool { return 0.0 == 1.0 } +func complexEqual() bool { return 1i == -1i } +func stringLess() bool { return "a" < "b" } `) ir := mod.String() if strings.Contains(ir, "StringEqual") { t.Fatalf("constant string comparison called the runtime helper:\n%s", ir) } - if !strings.Contains(ir, "ret i1 false") || !strings.Contains(ir, "ret i1 true") { - t.Fatalf("constant string comparisons were not folded:\n%s", ir) + for _, name := range []string{"intEqual", "stringEqual", "runeEqual", "floatEqual", "complexEqual"} { + fn := llvmFunction(t, ir, "foo."+name) + if !strings.Contains(fn, "ret i1 false") { + t.Fatalf("%s was not folded to false:\n%s", name, fn) + } + } + if fn := llvmFunction(t, ir, "foo.stringLess"); !strings.Contains(fn, "ret i1 true") { + t.Fatalf("stringLess was not folded to true:\n%s", fn) } } From bc92da09799403d3ec72b41b1cf7e0583e15c993 Mon Sep 17 00:00:00 2001 From: Li Jie Date: Sun, 2 Aug 2026 06:40:32 +0800 Subject: [PATCH 48/73] test: update folded comparison snapshot --- cl/_testrt/builtin/in.go | 30 +++++++++--------------------- 1 file changed, 9 insertions(+), 21 deletions(-) diff --git a/cl/_testrt/builtin/in.go b/cl/_testrt/builtin/in.go index efa6b87f49..19cc37f376 100644 --- a/cl/_testrt/builtin/in.go +++ b/cl/_testrt/builtin/in.go @@ -9,9 +9,7 @@ import ( // CHECK: {{^}}@1 = private unnamed_addr constant [3 x i8] c"def", align 1{{$}} // CHECK: {{^}}@3 = private unnamed_addr constant [4 x i8] c"ABCD", align 1{{$}} // CHECK: {{^}}@4 = private unnamed_addr constant [7 x i8] c"\E4\B8\ADabcd", align 1{{$}} -// CHECK: {{^}}@5 = private unnamed_addr constant [3 x i8] c"abc", align 1{{$}} -// CHECK: {{^}}@6 = private unnamed_addr constant [3 x i8] c"abd", align 1{{$}} -// CHECK: {{^}}@7 = private unnamed_addr constant [2 x i8] c"fn", align 1{{$}} +// CHECK: {{^}}@5 = private unnamed_addr constant [2 x i8] c"fn", align 1{{$}} var a int64 = 1<<63 - 1 var b int64 = -1 << 63 @@ -432,29 +430,19 @@ func demo() { // CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.PrintByte"(i8 32) // CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.PrintString"(%"{{.*}}/runtime/internal/runtime.String" %165) // CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.PrintByte"(i8 10) -// CHECK-NEXT: %166 = call i1 @"{{.*}}/runtime/internal/runtime.StringEqual"(%"{{.*}}/runtime/internal/runtime.String" { ptr @5, i64 3 }, %"{{.*}}/runtime/internal/runtime.String" { ptr @5, i64 3 }) -// CHECK-NEXT: %167 = call i1 @"{{.*}}/runtime/internal/runtime.StringEqual"(%"{{.*}}/runtime/internal/runtime.String" { ptr @5, i64 3 }, %"{{.*}}/runtime/internal/runtime.String" { ptr @6, i64 3 }) -// CHECK-NEXT: %168 = call i1 @"{{.*}}/runtime/internal/runtime.StringEqual"(%"{{.*}}/runtime/internal/runtime.String" { ptr @5, i64 3 }, %"{{.*}}/runtime/internal/runtime.String" { ptr @6, i64 3 }) -// CHECK-NEXT: %169 = xor i1 %168, true -// CHECK-NEXT: %170 = call i1 @"{{.*}}/runtime/internal/runtime.StringLess"(%"{{.*}}/runtime/internal/runtime.String" { ptr @5, i64 3 }, %"{{.*}}/runtime/internal/runtime.String" { ptr @6, i64 3 }) -// CHECK-NEXT: %171 = call i1 @"{{.*}}/runtime/internal/runtime.StringLess"(%"{{.*}}/runtime/internal/runtime.String" { ptr @6, i64 3 }, %"{{.*}}/runtime/internal/runtime.String" { ptr @5, i64 3 }) -// CHECK-NEXT: %172 = xor i1 %171, true -// CHECK-NEXT: %173 = call i1 @"{{.*}}/runtime/internal/runtime.StringLess"(%"{{.*}}/runtime/internal/runtime.String" { ptr @6, i64 3 }, %"{{.*}}/runtime/internal/runtime.String" { ptr @5, i64 3 }) -// CHECK-NEXT: %174 = call i1 @"{{.*}}/runtime/internal/runtime.StringLess"(%"{{.*}}/runtime/internal/runtime.String" { ptr @5, i64 3 }, %"{{.*}}/runtime/internal/runtime.String" { ptr @6, i64 3 }) -// CHECK-NEXT: %175 = xor i1 %174, true -// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.PrintBool"(i1 %166) +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.PrintBool"(i1 true) // CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.PrintByte"(i8 32) -// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.PrintBool"(i1 %167) +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.PrintBool"(i1 false) // CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.PrintByte"(i8 32) -// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.PrintBool"(i1 %169) +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.PrintBool"(i1 true) // CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.PrintByte"(i8 32) -// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.PrintBool"(i1 %170) +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.PrintBool"(i1 true) // CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.PrintByte"(i8 32) -// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.PrintBool"(i1 %172) +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.PrintBool"(i1 true) // CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.PrintByte"(i8 32) -// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.PrintBool"(i1 %173) +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.PrintBool"(i1 false) // CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.PrintByte"(i8 32) -// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.PrintBool"(i1 %175) +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.PrintBool"(i1 false) // CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.PrintByte"(i8 10) // CHECK-NEXT: ret void // CHECK-NEXT: } @@ -496,7 +484,7 @@ func main() { // CHECK-LABEL: define void @"main.main$2"(){{.*}} { // CHECK-NEXT: _llgo_0: - // CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.PrintString"(%"{{.*}}/runtime/internal/runtime.String" { ptr @7, i64 2 }) + // CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.PrintString"(%"{{.*}}/runtime/internal/runtime.String" { ptr @5, i64 2 }) // CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.PrintByte"(i8 10) // CHECK-NEXT: ret void // CHECK-NEXT: } From bf416bc761cb9ebab3cd6266418118bbfe5434a0 Mon Sep 17 00:00:00 2001 From: Li Jie Date: Mon, 3 Aug 2026 14:17:05 +0800 Subject: [PATCH 49/73] ssa: use static defer continuation selectors --- cl/_testgo/cgodefer/cgodefer.go | 28 +++++-- cl/_testgo/cgomacro/cgomacro.go | 28 +++++-- cl/_testgo/cgopython/cgopython.go | 28 +++++-- cl/_testgo/defer5/in.go | 4 +- cl/_testgo/deferloop/in.go | 5 +- cl/_testgo/recoverthenpanic/in.go | 53 +++++++++---- runtime/internal/runtime/z_rt.go | 4 +- ssa/eh.go | 128 ++++++++++++++++++++---------- ssa/eh_defer_test.go | 60 ++++++++++++++ 9 files changed, 249 insertions(+), 89 deletions(-) diff --git a/cl/_testgo/cgodefer/cgodefer.go b/cl/_testgo/cgodefer/cgodefer.go index 5ce8dd6bfe..f9c1d5a7bd 100644 --- a/cl/_testgo/cgodefer/cgodefer.go +++ b/cl/_testgo/cgodefer/cgodefer.go @@ -38,7 +38,7 @@ import "C" // CHECK-NEXT: %13 = getelementptr inbounds %"{{.*}}/runtime/internal/runtime.Defer", ptr %10, i32 0, i32 2 // CHECK-NEXT: store ptr %8, ptr %13, align 8 // CHECK-NEXT: %14 = getelementptr inbounds %"{{.*}}/runtime/internal/runtime.Defer", ptr %10, i32 0, i32 3 -// CHECK-NEXT: store ptr blockaddress(@main.main, %_llgo_2), ptr %14, align 8 +// CHECK-NEXT: store i64 0, ptr %14, align 8 // CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.SetThreadDefer"(ptr %10) // CHECK-NEXT: %15 = getelementptr inbounds %"{{.*}}/runtime/internal/runtime.Defer", ptr %10, i32 0, i32 1 // CHECK-NEXT: %16 = getelementptr inbounds %"{{.*}}/runtime/internal/runtime.Defer", ptr %10, i32 0, i32 3 @@ -53,7 +53,7 @@ import "C" // CHECK-NEXT: ret void // CHECK-EMPTY: // CHECK-NEXT: _llgo_2: ; preds = %_llgo_5, %_llgo_4 -// CHECK-NEXT: store ptr blockaddress(@main.main, %_llgo_3), ptr %16, align 8 +// CHECK-NEXT: store i64 1, ptr %16, align 8 // CHECK-NEXT: %21 = load i64, ptr %15, align 8 // CHECK-NEXT: %22 = load ptr, ptr %18, align 8 // CHECK-NEXT: %23 = icmp ne ptr %22, null @@ -73,13 +73,16 @@ import "C" // CHECK-NEXT: %28 = getelementptr inbounds { ptr, i64, { ptr, ptr } }, ptr %25, i32 0, i32 2 // CHECK-NEXT: store { ptr, ptr } %7, ptr %28, align 8 // CHECK-NEXT: store ptr %25, ptr %18, align 8 -// CHECK-NEXT: store ptr blockaddress(@main.main, %_llgo_6), ptr %17, align 8 +// CHECK-NEXT: store i64 1, ptr %17, align 8 // CHECK-NEXT: br label %_llgo_2 // CHECK-EMPTY: // CHECK-NEXT: _llgo_5: ; preds = %_llgo_0 -// CHECK-NEXT: store ptr blockaddress(@main.main, %_llgo_3), ptr %17, align 8 -// CHECK-NEXT: %29 = load ptr, ptr %16, align 8 -// CHECK-NEXT: indirectbr ptr %29, [label %_llgo_3, label %_llgo_2] +// CHECK-NEXT: store i64 0, ptr %17, align 8 +// CHECK-NEXT: %29 = load i64, ptr %16, align 8 +// CHECK-NEXT: switch i64 %29, label %_llgo_10 [ +// CHECK-NEXT: i64 0, label %_llgo_2 +// CHECK-NEXT: i64 1, label %_llgo_3 +// CHECK-NEXT: ] // CHECK-EMPTY: // CHECK-NEXT: _llgo_6: ; preds = %_llgo_8 // CHECK-NEXT: ret void @@ -101,8 +104,17 @@ import "C" // CHECK-NEXT: %36 = load %"{{.*}}/runtime/internal/runtime.Defer", ptr %10, align 8 // CHECK-NEXT: %37 = extractvalue %"{{.*}}/runtime/internal/runtime.Defer" %36, 2 // CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.SetThreadDefer"(ptr %37) -// CHECK-NEXT: %38 = load ptr, ptr %17, align 8 -// CHECK-NEXT: indirectbr ptr %38, [label %_llgo_3, label %_llgo_6] +// CHECK-NEXT: %38 = load i64, ptr %17, align 8 +// CHECK-NEXT: switch i64 %38, label %_llgo_9 [ +// CHECK-NEXT: i64 0, label %_llgo_3 +// CHECK-NEXT: i64 1, label %_llgo_6 +// CHECK-NEXT: ] +// CHECK-EMPTY: +// CHECK-NEXT: _llgo_9: ; preds = %_llgo_8 +// CHECK-NEXT: unreachable +// CHECK-EMPTY: +// CHECK-NEXT: _llgo_10: ; preds = %_llgo_5 +// CHECK-NEXT: unreachable // CHECK-NEXT: } func main() { // CHECK-LABEL: define { ptr, ptr } @"main.main$1"(ptr {{(nest|swiftself)}} %0){{.*}} { diff --git a/cl/_testgo/cgomacro/cgomacro.go b/cl/_testgo/cgomacro/cgomacro.go index c2c152d37d..6a95c03111 100644 --- a/cl/_testgo/cgomacro/cgomacro.go +++ b/cl/_testgo/cgomacro/cgomacro.go @@ -130,7 +130,7 @@ import ( // CHECK-NEXT: %8 = getelementptr inbounds %"{{.*}}/runtime/internal/runtime.Defer", ptr %5, i32 0, i32 2 // CHECK-NEXT: store ptr %3, ptr %8, align 8 // CHECK-NEXT: %9 = getelementptr inbounds %"{{.*}}/runtime/internal/runtime.Defer", ptr %5, i32 0, i32 3 -// CHECK-NEXT: store ptr blockaddress(@main.main, %_llgo_2), ptr %9, align 8 +// CHECK-NEXT: store i64 0, ptr %9, align 8 // CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.SetThreadDefer"(ptr %5) // CHECK-NEXT: %10 = getelementptr inbounds %"{{.*}}/runtime/internal/runtime.Defer", ptr %5, i32 0, i32 1 // CHECK-NEXT: %11 = getelementptr inbounds %"{{.*}}/runtime/internal/runtime.Defer", ptr %5, i32 0, i32 3 @@ -145,14 +145,17 @@ import ( // CHECK-NEXT: ret void // CHECK-EMPTY: // CHECK-NEXT: _llgo_2: ; preds = %_llgo_5, %_llgo_4 -// CHECK-NEXT: store ptr blockaddress(@main.main, %_llgo_3), ptr %11, align 8 +// CHECK-NEXT: store i64 1, ptr %11, align 8 // CHECK-NEXT: %16 = load i64, ptr %10, align 8 // CHECK-NEXT: %17 = call [0 x i8] @main._Cfunc_Py_Finalize() // CHECK-NEXT: %18 = load %"{{.*}}/runtime/internal/runtime.Defer", ptr %5, align 8 // CHECK-NEXT: %19 = extractvalue %"{{.*}}/runtime/internal/runtime.Defer" %18, 2 // CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.SetThreadDefer"(ptr %19) -// CHECK-NEXT: %20 = load ptr, ptr %12, align 8 -// CHECK-NEXT: indirectbr ptr %20, [label %_llgo_3, label %_llgo_6] +// CHECK-NEXT: %20 = load i64, ptr %12, align 8 +// CHECK-NEXT: switch i64 %20, label %_llgo_7 [ +// CHECK-NEXT: i64 0, label %_llgo_3 +// CHECK-NEXT: i64 1, label %_llgo_6 +// CHECK-NEXT: ] // CHECK-EMPTY: // CHECK-NEXT: _llgo_3: ; preds = %_llgo_5, %_llgo_2 // CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.Rethrow"(ptr %3) @@ -165,16 +168,25 @@ import ( // CHECK-NEXT: %24 = call i32 @"main.main$5"() // CHECK-NEXT: %25 = call i32 @"main.main$6"() // CHECK-NEXT: %26 = call i32 @"main.main$7"() -// CHECK-NEXT: store ptr blockaddress(@main.main, %_llgo_6), ptr %12, align 8 +// CHECK-NEXT: store i64 1, ptr %12, align 8 // CHECK-NEXT: br label %_llgo_2 // CHECK-EMPTY: // CHECK-NEXT: _llgo_5: ; preds = %_llgo_0 -// CHECK-NEXT: store ptr blockaddress(@main.main, %_llgo_3), ptr %12, align 8 -// CHECK-NEXT: %27 = load ptr, ptr %11, align 8 -// CHECK-NEXT: indirectbr ptr %27, [label %_llgo_3, label %_llgo_2] +// CHECK-NEXT: store i64 0, ptr %12, align 8 +// CHECK-NEXT: %27 = load i64, ptr %11, align 8 +// CHECK-NEXT: switch i64 %27, label %_llgo_8 [ +// CHECK-NEXT: i64 0, label %_llgo_2 +// CHECK-NEXT: i64 1, label %_llgo_3 +// CHECK-NEXT: ] // CHECK-EMPTY: // CHECK-NEXT: _llgo_6: ; preds = %_llgo_2 // CHECK-NEXT: ret void +// CHECK-EMPTY: +// CHECK-NEXT: _llgo_7: ; preds = %_llgo_2 +// CHECK-NEXT: unreachable +// CHECK-EMPTY: +// CHECK-NEXT: _llgo_8: ; preds = %_llgo_5 +// CHECK-NEXT: unreachable // CHECK-NEXT: } func main() { C.test_stdout() diff --git a/cl/_testgo/cgopython/cgopython.go b/cl/_testgo/cgopython/cgopython.go index aea2a0f615..977ef31040 100644 --- a/cl/_testgo/cgopython/cgopython.go +++ b/cl/_testgo/cgopython/cgopython.go @@ -63,7 +63,7 @@ import "C" // CHECK-NEXT: %6 = getelementptr inbounds %"{{.*}}/runtime/internal/runtime.Defer", ptr %3, i32 0, i32 2 // CHECK-NEXT: store ptr %1, ptr %6, align 8 // CHECK-NEXT: %7 = getelementptr inbounds %"{{.*}}/runtime/internal/runtime.Defer", ptr %3, i32 0, i32 3 -// CHECK-NEXT: store ptr blockaddress(@main.main, %_llgo_2), ptr %7, align 8 +// CHECK-NEXT: store i64 0, ptr %7, align 8 // CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.SetThreadDefer"(ptr %3) // CHECK-NEXT: %8 = getelementptr inbounds %"{{.*}}/runtime/internal/runtime.Defer", ptr %3, i32 0, i32 1 // CHECK-NEXT: %9 = getelementptr inbounds %"{{.*}}/runtime/internal/runtime.Defer", ptr %3, i32 0, i32 3 @@ -78,14 +78,17 @@ import "C" // CHECK-NEXT: ret void // CHECK-EMPTY: // CHECK-NEXT: _llgo_2: ; preds = %_llgo_5, %_llgo_4 -// CHECK-NEXT: store ptr blockaddress(@main.main, %_llgo_3), ptr %9, align 8 +// CHECK-NEXT: store i64 1, ptr %9, align 8 // CHECK-NEXT: %14 = load i64, ptr %8, align 8 // CHECK-NEXT: %15 = call [0 x i8] @main._Cfunc_Py_Finalize() // CHECK-NEXT: %16 = load %"{{.*}}/runtime/internal/runtime.Defer", ptr %3, align 8 // CHECK-NEXT: %17 = extractvalue %"{{.*}}/runtime/internal/runtime.Defer" %16, 2 // CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.SetThreadDefer"(ptr %17) -// CHECK-NEXT: %18 = load ptr, ptr %10, align 8 -// CHECK-NEXT: indirectbr ptr %18, [label %_llgo_3, label %_llgo_6] +// CHECK-NEXT: %18 = load i64, ptr %10, align 8 +// CHECK-NEXT: switch i64 %18, label %_llgo_7 [ +// CHECK-NEXT: i64 0, label %_llgo_3 +// CHECK-NEXT: i64 1, label %_llgo_6 +// CHECK-NEXT: ] // CHECK-EMPTY: // CHECK-NEXT: _llgo_3: ; preds = %_llgo_5, %_llgo_2 // CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.Rethrow"(ptr %1) @@ -94,16 +97,25 @@ import "C" // CHECK-NEXT: _llgo_4: ; preds = %_llgo_0 // CHECK-NEXT: %19 = call ptr @"{{.*}}/runtime/internal/runtime.CString"(%"{{.*}}/runtime/internal/runtime.String" { ptr @0, i64 23 }) // CHECK-NEXT: %20 = call i32 @main._Cfunc_PyRun_SimpleString(ptr %19) -// CHECK-NEXT: store ptr blockaddress(@main.main, %_llgo_6), ptr %10, align 8 +// CHECK-NEXT: store i64 1, ptr %10, align 8 // CHECK-NEXT: br label %_llgo_2 // CHECK-EMPTY: // CHECK-NEXT: _llgo_5: ; preds = %_llgo_0 -// CHECK-NEXT: store ptr blockaddress(@main.main, %_llgo_3), ptr %10, align 8 -// CHECK-NEXT: %21 = load ptr, ptr %9, align 8 -// CHECK-NEXT: indirectbr ptr %21, [label %_llgo_3, label %_llgo_2] +// CHECK-NEXT: store i64 0, ptr %10, align 8 +// CHECK-NEXT: %21 = load i64, ptr %9, align 8 +// CHECK-NEXT: switch i64 %21, label %_llgo_8 [ +// CHECK-NEXT: i64 0, label %_llgo_2 +// CHECK-NEXT: i64 1, label %_llgo_3 +// CHECK-NEXT: ] // CHECK-EMPTY: // CHECK-NEXT: _llgo_6: ; preds = %_llgo_2 // CHECK-NEXT: ret void +// CHECK-EMPTY: +// CHECK-NEXT: _llgo_7: ; preds = %_llgo_2 +// CHECK-NEXT: unreachable +// CHECK-EMPTY: +// CHECK-NEXT: _llgo_8: ; preds = %_llgo_5 +// CHECK-NEXT: unreachable // CHECK-NEXT: } func main() { C.Py_Initialize() diff --git a/cl/_testgo/defer5/in.go b/cl/_testgo/defer5/in.go index 4bcca285f0..ec59812005 100644 --- a/cl/_testgo/defer5/in.go +++ b/cl/_testgo/defer5/in.go @@ -4,12 +4,12 @@ package main // CHECK-LABEL: define void @main.main(){{.*}} { func main() { // CHECK: GetThreadDefer - // CHECK: blockaddress(@main.main, %_llgo_2) - // CHECK: blockaddress(@main.main, %_llgo_8) + // CHECK: switch i{{(32|64)}} // CHECK: call void @"main.main$1"() // CHECK: call void @"main.main$2"() // CHECK: FreeDeferNode // CHECK: FreeDeferNode + // CHECK: switch i{{(32|64)}} defer println("A") defer func() { if e := recover(); e != nil { diff --git a/cl/_testgo/deferloop/in.go b/cl/_testgo/deferloop/in.go index 7fec91526a..c4c0568599 100644 --- a/cl/_testgo/deferloop/in.go +++ b/cl/_testgo/deferloop/in.go @@ -5,10 +5,11 @@ package main func main() { // CHECK: GetThreadDefer for i := 0; i < 3; i++ { - // CHECK: blockaddress(@main.main, %_llgo_6) + // CHECK: switch i{{(32|64)}} defer println("loop", i) } + // CHECK: switch i{{(32|64)}} + // CHECK: FreeDeferNode // CHECK: PrintString // CHECK: PrintInt - // CHECK: FreeDeferNode } diff --git a/cl/_testgo/recoverthenpanic/in.go b/cl/_testgo/recoverthenpanic/in.go index 6d1364b14f..c6ef4d3eaa 100644 --- a/cl/_testgo/recoverthenpanic/in.go +++ b/cl/_testgo/recoverthenpanic/in.go @@ -20,7 +20,7 @@ package main // CHECK-NEXT: %8 = getelementptr inbounds %"{{.*}}/runtime/internal/runtime.Defer", ptr %5, i32 0, i32 2 // CHECK-NEXT: store ptr %3, ptr %8, align 8 // CHECK-NEXT: %9 = getelementptr inbounds %"{{.*}}/runtime/internal/runtime.Defer", ptr %5, i32 0, i32 3 -// CHECK-NEXT: store ptr blockaddress(@main.End, %_llgo_5), ptr %9, align 8 +// CHECK-NEXT: store i64 0, ptr %9, align 8 // CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.SetThreadDefer"(ptr %5) // CHECK-NEXT: %10 = getelementptr inbounds %"{{.*}}/runtime/internal/runtime.Defer", ptr %5, i32 0, i32 1 // CHECK-NEXT: %11 = getelementptr inbounds %"{{.*}}/runtime/internal/runtime.Defer", ptr %5, i32 0, i32 3 @@ -51,7 +51,7 @@ package main // CHECK-NEXT: _llgo_2: ; preds = %_llgo_1, %_llgo_4 // CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.PrintString"(%"{{.*}}/runtime/internal/runtime.String" { ptr @1, i64 3 }) // CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.PrintByte"(i8 10) -// CHECK-NEXT: store ptr blockaddress(@main.End, %_llgo_8), ptr %12, align 8 +// CHECK-NEXT: store i64 1, ptr %12, align 8 // CHECK-NEXT: br label %_llgo_5 // CHECK-EMPTY: // CHECK-NEXT: _llgo_3: ; preds = %_llgo_6 @@ -61,7 +61,7 @@ package main // CHECK-NEXT: br i1 %2, label %_llgo_1, label %_llgo_2 // CHECK-EMPTY: // CHECK-NEXT: _llgo_5: ; preds = %_llgo_7, %_llgo_2 -// CHECK-NEXT: store ptr blockaddress(@main.End, %_llgo_6), ptr %11, align 8 +// CHECK-NEXT: store i64 1, ptr %11, align 8 // CHECK-NEXT: %23 = load i64, ptr %10, align 8 // CHECK-NEXT: %24 = and i64 %23, 1 // CHECK-NEXT: %25 = icmp ne i64 %24, 0 @@ -72,9 +72,12 @@ package main // CHECK-NEXT: br label %_llgo_3 // CHECK-EMPTY: // CHECK-NEXT: _llgo_7: ; preds = %_llgo_0 -// CHECK-NEXT: store ptr blockaddress(@main.End, %_llgo_6), ptr %12, align 8 -// CHECK-NEXT: %26 = load ptr, ptr %11, align 8 -// CHECK-NEXT: indirectbr ptr %26, [label %_llgo_6, label %_llgo_5] +// CHECK-NEXT: store i64 0, ptr %12, align 8 +// CHECK-NEXT: %26 = load i64, ptr %11, align 8 +// CHECK-NEXT: switch i64 %26, label %_llgo_14 [ +// CHECK-NEXT: i64 0, label %_llgo_5 +// CHECK-NEXT: i64 1, label %_llgo_6 +// CHECK-NEXT: ] // CHECK-EMPTY: // CHECK-NEXT: _llgo_8: ; preds = %_llgo_10 // CHECK-NEXT: ret void @@ -88,8 +91,11 @@ package main // CHECK-NEXT: %29 = load %"{{.*}}/runtime/internal/runtime.Defer", ptr %5, align 8 // CHECK-NEXT: %30 = extractvalue %"{{.*}}/runtime/internal/runtime.Defer" %29, 2 // CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.SetThreadDefer"(ptr %30) -// CHECK-NEXT: %31 = load ptr, ptr %12, align 8 -// CHECK-NEXT: indirectbr ptr %31, [label %_llgo_6, label %_llgo_8] +// CHECK-NEXT: %31 = load i64, ptr %12, align 8 +// CHECK-NEXT: switch i64 %31, label %_llgo_13 [ +// CHECK-NEXT: i64 0, label %_llgo_6 +// CHECK-NEXT: i64 1, label %_llgo_8 +// CHECK-NEXT: ] // CHECK-EMPTY: // CHECK-NEXT: _llgo_11: ; preds = %_llgo_9 // CHECK-NEXT: %32 = load ptr, ptr %13, align 8 @@ -103,6 +109,12 @@ package main // CHECK-EMPTY: // CHECK-NEXT: _llgo_12: ; preds = %_llgo_9 // CHECK-NEXT: br label %_llgo_10 +// CHECK-EMPTY: +// CHECK-NEXT: _llgo_13: ; preds = %_llgo_10 +// CHECK-NEXT: unreachable +// CHECK-EMPTY: +// CHECK-NEXT: _llgo_14: ; preds = %_llgo_7 +// CHECK-NEXT: unreachable // CHECK-NEXT: } func End() { @@ -144,7 +156,7 @@ func main() { // CHECK-NEXT: %5 = getelementptr inbounds %"{{.*}}/runtime/internal/runtime.Defer", ptr %2, i32 0, i32 2 // CHECK-NEXT: store ptr %0, ptr %5, align 8 // CHECK-NEXT: %6 = getelementptr inbounds %"{{.*}}/runtime/internal/runtime.Defer", ptr %2, i32 0, i32 3 -// CHECK-NEXT: store ptr blockaddress(@main.main, %_llgo_2), ptr %6, align 8 +// CHECK-NEXT: store i64 0, ptr %6, align 8 // CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.SetThreadDefer"(ptr %2) // CHECK-NEXT: %7 = getelementptr inbounds %"{{.*}}/runtime/internal/runtime.Defer", ptr %2, i32 0, i32 1 // CHECK-NEXT: %8 = getelementptr inbounds %"{{.*}}/runtime/internal/runtime.Defer", ptr %2, i32 0, i32 3 @@ -159,14 +171,16 @@ func main() { // CHECK-NEXT: ret void // CHECK-EMPTY: // CHECK-NEXT: _llgo_2: ; preds = %_llgo_5 -// CHECK-NEXT: store ptr blockaddress(@main.main, %_llgo_3), ptr %8, align 8 +// CHECK-NEXT: store i64 1, ptr %8, align 8 // CHECK-NEXT: %13 = load i64, ptr %7, align 8 // CHECK-NEXT: call void @main.End() // CHECK-NEXT: %14 = load %"{{.*}}/runtime/internal/runtime.Defer", ptr %2, align 8 // CHECK-NEXT: %15 = extractvalue %"{{.*}}/runtime/internal/runtime.Defer" %14, 2 // CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.SetThreadDefer"(ptr %15) -// CHECK-NEXT: %16 = load ptr, ptr %9, align 8 -// CHECK-NEXT: indirectbr ptr %16, [label %_llgo_3] +// CHECK-NEXT: %16 = load i64, ptr %9, align 8 +// CHECK-NEXT: switch i64 %16, label %_llgo_6 [ +// CHECK-NEXT: i64 0, label %_llgo_3 +// CHECK-NEXT: ] // CHECK-EMPTY: // CHECK-NEXT: _llgo_3: ; preds = %_llgo_5, %_llgo_2 // CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.Rethrow"(ptr %0) @@ -180,7 +194,16 @@ func main() { // CHECK-NEXT: unreachable // CHECK-EMPTY: // CHECK-NEXT: _llgo_5: ; preds = %_llgo_0 -// CHECK-NEXT: store ptr blockaddress(@main.main, %_llgo_3), ptr %9, align 8 -// CHECK-NEXT: %19 = load ptr, ptr %8, align 8 -// CHECK-NEXT: indirectbr ptr %19, [label %_llgo_3, label %_llgo_2] +// CHECK-NEXT: store i64 0, ptr %9, align 8 +// CHECK-NEXT: %19 = load i64, ptr %8, align 8 +// CHECK-NEXT: switch i64 %19, label %_llgo_7 [ +// CHECK-NEXT: i64 0, label %_llgo_2 +// CHECK-NEXT: i64 1, label %_llgo_3 +// CHECK-NEXT: ] +// CHECK-EMPTY: +// CHECK-NEXT: _llgo_6: ; preds = %_llgo_2 +// CHECK-NEXT: unreachable +// CHECK-EMPTY: +// CHECK-NEXT: _llgo_7: ; preds = %_llgo_5 +// CHECK-NEXT: unreachable // CHECK-NEXT: } diff --git a/runtime/internal/runtime/z_rt.go b/runtime/internal/runtime/z_rt.go index 090e3e4cbd..fc707c3abe 100644 --- a/runtime/internal/runtime/z_rt.go +++ b/runtime/internal/runtime/z_rt.go @@ -30,8 +30,8 @@ type Defer struct { Addr unsafe.Pointer // sigjmpbuf Bits uintptr Link *Defer - Reth unsafe.Pointer // block address after Rethrow - Rund unsafe.Pointer // block address after RunDefers + Reth uintptr // continuation selector after Rethrow + Rund uintptr // continuation selector after RunDefers Args unsafe.Pointer // defer func and args links } diff --git a/ssa/eh.go b/ssa/eh.go index 104b8e04af..6d88384444 100644 --- a/ssa/eh.go +++ b/ssa/eh.go @@ -144,21 +144,29 @@ func (p Function) deferInitBuilder() (b Builder, next BasicBlock) { } type aDefer struct { - nextBit int // next defer bit - data Expr // pointer to runtime.Defer - bitsPtr Expr // pointer to defer bits - rethPtr Expr // next block of Rethrow - rundPtr Expr // next block of RunDefers - argsPtr Expr // func and args links - procBlk BasicBlock // deferProc block - panicBlk BasicBlock // panic block (runDefers and rethrow) - rundsNext []BasicBlock // next blocks of RunDefers + nextBit int // next defer bit + data Expr // pointer to runtime.Defer + bitsPtr Expr // pointer to defer bits + rethPtr Expr // Rethrow continuation selector + rundPtr Expr // RunDefers continuation selector + argsPtr Expr // func and args links + procBlk BasicBlock // deferProc block + panicBlk BasicBlock // panic block (runDefers and rethrow) + rundTargets []deferTarget // loopDrainerGenerated marks whether we've already generated the loop-defer // drain loop for the current contiguous run of DeferInLoop statements (when // walking defers in reverse order in endDefer). loopDrainerGenerated bool loopCases []loopDeferCase - stmts []func(bits Expr) + stmts []func(bits Expr, resume deferTarget) +} + +// deferTarget pairs the integer stored in runtime.Defer with its local block. +// Selectors are dense within each dispatch so LLVM can choose the target's +// preferred switch lowering without exposing block addresses. +type deferTarget struct { + index int + block BasicBlock } // loopDeferCase represents a defer statement inside a loop. @@ -176,8 +184,8 @@ const ( // 0: addr sigjmpbuf // 1: bits uintptr // 2: link *Defer - // 3: reth voidptr: block address after Rethrow - // 4: rund voidptr: block address after RunDefers + // 3: reth uintptr: continuation selector after Rethrow + // 4: rund uintptr: continuation selector after RunDefers // 5: func and args links deferSigjmpbuf = iota deferBits @@ -267,7 +275,8 @@ func (b Builder) initDeferState(procBlk, rethrowBlk BasicBlock) (*aDefer, Expr, zero := prog.Val(uintptr(0)) link := b.Call(b.Pkg.rtFunc("GetThreadDefer")) jb := b.AllocaSigjmpBuf() - ptr := b.aggregateAllocU(prog.Defer(), jb.impl, zero.impl, link.impl, procBlk.Addr().impl) + // Reth selector 0 is reserved for procBlk; Rund is zero-initialized. + ptr := b.aggregateAllocU(prog.Defer(), jb.impl, zero.impl, link.impl, zero.impl) deferData := Expr{ptr, prog.DeferPtr()} b.Call(b.Pkg.rtFunc("SetThreadDefer"), deferData) bitsPtr := b.FieldAddr(deferData, deferBits) @@ -282,13 +291,13 @@ func (b Builder) initDeferState(procBlk, rethrowBlk BasicBlock) (*aDefer, Expr, retval := b.Sigsetjmp(jb, czero) self.defer_ = &aDefer{ - data: deferData, - bitsPtr: bitsPtr, - rethPtr: rethPtr, - rundPtr: rundPtr, - argsPtr: argsPtr, - procBlk: procBlk, - rundsNext: []BasicBlock{rethrowBlk}, + data: deferData, + bitsPtr: bitsPtr, + rethPtr: rethPtr, + rundPtr: rundPtr, + argsPtr: argsPtr, + procBlk: procBlk, + rundTargets: []deferTarget{{index: 0, block: rethrowBlk}}, } if len(self.pendingLoopCases) > 0 { self.defer_.loopCases = append(self.defer_.loopCases, self.pendingLoopCases...) @@ -381,7 +390,7 @@ func (b Builder) DeferTo(owner Function, stack Expr, fn Expr, buildCall func(Bui } func (b Builder) appendDeferStmt(self *aDefer, kind DoAction, typ Type, buildCall func(Builder, Expr, ...Expr) Expr, fn Expr, args []Expr, nextbit Expr) { - self.stmts = append(self.stmts, func(bits Expr) { + self.stmts = append(self.stmts, func(bits Expr, resume deferTarget) { switch kind { case DeferInCond: // Leaving a run of loop defers; allow the next loop-defer statement @@ -399,18 +408,18 @@ func (b Builder) appendDeferStmt(self *aDefer, kind DoAction, typ Type, buildCal self.loopDrainerGenerated = false b.callDefer(self, typ, buildCall, fn, args) case DeferInLoop: - b.loopDeferDrainer(self) + b.loopDeferDrainer(self, resume) } }) } func (b Builder) appendLoopDeferDrainer(self *aDefer) { - self.stmts = append(self.stmts, func(Expr) { - b.loopDeferDrainer(self) + self.stmts = append(self.stmts, func(_ Expr, resume deferTarget) { + b.loopDeferDrainer(self, resume) }) } -func (b Builder) loopDeferDrainer(self *aDefer) { +func (b Builder) loopDeferDrainer(self *aDefer, resume deferTarget) { if self.loopDrainerGenerated { return } @@ -420,7 +429,9 @@ func (b Builder) loopDeferDrainer(self *aDefer) { } drainEntry := b.blk - drainEntryAddr := drainEntry.Addr() + if drainEntry != resume.block { + panic("loop defer resume target does not match the drainer entry") + } prog := b.Prog condBlk := b.Func.MakeBlock() @@ -456,7 +467,7 @@ func (b Builder) loopDeferDrainer(self *aDefer) { b.If(match, caseBlks[i], nextBlk) b.SetBlockEx(caseBlks[i], AtEnd, true) - b.Store(self.rethPtr, drainEntryAddr) + b.storeDeferTarget(self.rethPtr, resume) b.callDefer(self, c.typ, c.buildCall, c.fn, c.args) b.Jump(condBlk) } @@ -557,26 +568,43 @@ func (b Builder) RunDefers() { return } blk := b.Func.MakeBlock() - self.rundsNext = append(self.rundsNext, blk) + target := deferTarget{index: len(self.rundTargets), block: blk} + self.rundTargets = append(self.rundTargets, target) - b.Store(self.rundPtr, blk.Addr()) + b.storeDeferTarget(self.rundPtr, target) b.Jump(self.procBlk) b.SetBlockEx(blk, AtEnd, false) b.blk.last = blk.last } +func (b Builder) storeDeferTarget(ptr Expr, target deferTarget) { + b.Store(ptr, b.Prog.Val(uintptr(target.index))) +} + +func (b Builder) jumpDeferTarget(ptr Expr, targets []deferTarget) { + selector := b.Load(ptr) + invalid := b.Func.MakeBlock() + sw := b.impl.CreateSwitch(selector.impl, invalid.first, len(targets)) + for _, target := range targets { + sw.AddCase(b.Prog.Val(uintptr(target.index)).impl, target.block.first) + } + b.SetBlockEx(invalid, AtEnd, false) + b.Unreachable() +} + func (p Function) endDefer(b Builder) { self := p.defer_ if self == nil { return } - nexts := self.rundsNext - if len(nexts) == 0 { + rundTargets := self.rundTargets + if len(rundTargets) == 0 { return } - rethrowBlk := nexts[0] + rethrowTarget := rundTargets[0] + rethrowBlk := rethrowTarget.block procBlk := self.procBlk panicBlk := self.panicBlk rethPtr := self.rethPtr @@ -585,28 +613,40 @@ func (p Function) endDefer(b Builder) { stmts := self.stmts n := len(stmts) - rethsNext := make([]BasicBlock, n+1) + rethChain := make([]deferTarget, n+1) blks := p.MakeBlocks(n - 1) - copy(rethsNext[1:], blks) - rethsNext[0] = rethrowBlk - rethsNext[n] = procBlk + // Reth selector 0 must remain procBlk because initDeferState installs it + // before the final number of deferred statements is known. Selector 1 is + // the terminal rethrow, followed by the intermediate continuation blocks. + rethTargets := make([]deferTarget, n+1) + rethTargets[0] = deferTarget{index: 0, block: procBlk} + if n > 0 { + rethTargets[1] = deferTarget{index: 1, block: rethrowBlk} + for i, blk := range blks { + rethTargets[i+2] = deferTarget{index: i + 2, block: blk} + } + rethChain[0] = rethTargets[1] + copy(rethChain[1:], rethTargets[2:]) + } + rethChain[n] = rethTargets[0] for i := n - 1; i >= 0; i-- { - rethNext := rethsNext[i] - b.SetBlockEx(rethsNext[i+1], AtEnd, true) - b.Store(rethPtr, rethNext.Addr()) - stmts[i](b.Load(bitsPtr)) + rethNext := rethChain[i] + resume := rethChain[i+1] + b.SetBlockEx(resume.block, AtEnd, true) + b.storeDeferTarget(rethPtr, rethNext) + stmts[i](b.Load(bitsPtr), resume) if i != 0 { - b.Jump(rethNext) + b.Jump(rethNext.block) } } link := b.getField(b.Load(self.data), deferLink) b.Call(b.Pkg.rtFunc("SetThreadDefer"), link) - b.IndirectJump(b.Load(rundPtr), nexts) + b.jumpDeferTarget(rundPtr, rundTargets) b.SetBlockEx(panicBlk, AtEnd, false) // panicBlk: exec runDefers and rethrow - b.Store(rundPtr, rethrowBlk.Addr()) - b.IndirectJump(b.Load(rethPtr), rethsNext) + b.storeDeferTarget(rundPtr, rethrowTarget) + b.jumpDeferTarget(rethPtr, rethTargets) } // ----------------------------------------------------------------------------- diff --git a/ssa/eh_defer_test.go b/ssa/eh_defer_test.go index 5f99729b1e..04abbed810 100644 --- a/ssa/eh_defer_test.go +++ b/ssa/eh_defer_test.go @@ -156,3 +156,63 @@ func TestConditionalDeferIR(t *testing.T) { t.Fatalf("expected conditional defer bitmask operations in IR, got:\n%s", ir) } } + +func TestDeferContinuationSelectors(t *testing.T) { + tests := []struct { + name string + target *ssa.Target + switchWidth string + }{ + {name: "linux-amd64", target: &ssa.Target{GOOS: "linux", GOARCH: "amd64"}, switchWidth: "i64"}, + {name: "darwin-arm64", target: &ssa.Target{GOOS: "darwin", GOARCH: "arm64"}, switchWidth: "i64"}, + {name: "wasip1-wasm", target: &ssa.Target{GOOS: "wasip1", GOARCH: "wasm"}, switchWidth: "i32"}, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + prog := ssatest.NewProgram(t, tt.target) + for _, field := range []int{3, 4} { + if got := prog.Field(prog.Defer(), field); got != prog.Uintptr() { + t.Fatalf("runtime.Defer field %d type = %v, want uintptr", field, got) + } + } + pkg := prog.NewPackage("foo", "foo") + + callee := pkg.NewFunc("callee", ssa.NoArgsNoRet, ssa.InGo) + cb := callee.MakeBody(1) + cb.Return() + cb.EndBuild() + + fn := pkg.NewFunc("main", ssa.NoArgsNoRet, ssa.InGo) + b := fn.MakeBody(1) + fn.SetRecover(fn.MakeBlock()) + b.Defer(ssa.DeferAlways, callee.Expr, ssa.Builder.Call) + b.Defer(ssa.DeferAlways, callee.Expr, ssa.Builder.Call) + b.RunDefers() + b.RunDefers() + b.Return() + b.EndBuild() + + ir := pkg.Module().String() + if strings.Contains(ir, "blockaddress") || strings.Contains(ir, "indirectbr") { + t.Fatalf("defer continuations must not expose block addresses:\n%s", ir) + } + if got := strings.Count(ir, "switch "+tt.switchWidth); got != 2 { + t.Fatalf("got %d %s switches, want RunDefers and Rethrow dispatch:\n%s", got, tt.switchWidth, ir) + } + if got := strings.Count(ir, "unreachable"); got < 2 { + t.Fatalf("got %d unreachable defaults, want one per defer dispatch:\n%s", got, ir) + } + + // RunDefers can establish defer state before any defer statement has + // been registered. Its Reth selector still has to dispatch to procBlk. + empty := pkg.NewFunc("empty", ssa.NoArgsNoRet, ssa.InGo) + eb := empty.MakeBody(1) + empty.SetRecover(empty.MakeBlock()) + eb.Return() + eb.SetBlockEx(empty.Block(0), ssa.BeforeLast, true) + eb.RunDefers() + eb.Return() + eb.EndBuild() + }) + } +} From 47d94be50a1da2ae5333cadedd9abcca85bcdaa2 Mon Sep 17 00:00:00 2001 From: Li Jie Date: Mon, 3 Aug 2026 18:22:28 +0800 Subject: [PATCH 50/73] ssa: initialize defer selectors explicitly --- cl/_testgo/cgodefer/cgodefer.go | 1 + cl/_testgo/cgomacro/cgomacro.go | 1 + cl/_testgo/cgopython/cgopython.go | 1 + cl/_testgo/recoverthenpanic/in.go | 2 ++ ssa/eh.go | 8 ++++++-- 5 files changed, 11 insertions(+), 2 deletions(-) diff --git a/cl/_testgo/cgodefer/cgodefer.go b/cl/_testgo/cgodefer/cgodefer.go index f9c1d5a7bd..b9739a724a 100644 --- a/cl/_testgo/cgodefer/cgodefer.go +++ b/cl/_testgo/cgodefer/cgodefer.go @@ -44,6 +44,7 @@ import "C" // CHECK-NEXT: %16 = getelementptr inbounds %"{{.*}}/runtime/internal/runtime.Defer", ptr %10, i32 0, i32 3 // CHECK-NEXT: %17 = getelementptr inbounds %"{{.*}}/runtime/internal/runtime.Defer", ptr %10, i32 0, i32 4 // CHECK-NEXT: %18 = getelementptr inbounds %"{{.*}}/runtime/internal/runtime.Defer", ptr %10, i32 0, i32 5 +// CHECK-NEXT: store i64 0, ptr %17, align 8 // CHECK-NEXT: store ptr null, ptr %18, align 8 // CHECK-NEXT: %19 = call i32 @{{.*}}sigsetjmp(ptr %9, i32 0) // CHECK-NEXT: %20 = icmp eq i32 %19, 0 diff --git a/cl/_testgo/cgomacro/cgomacro.go b/cl/_testgo/cgomacro/cgomacro.go index 6a95c03111..0e8533a480 100644 --- a/cl/_testgo/cgomacro/cgomacro.go +++ b/cl/_testgo/cgomacro/cgomacro.go @@ -136,6 +136,7 @@ import ( // CHECK-NEXT: %11 = getelementptr inbounds %"{{.*}}/runtime/internal/runtime.Defer", ptr %5, i32 0, i32 3 // CHECK-NEXT: %12 = getelementptr inbounds %"{{.*}}/runtime/internal/runtime.Defer", ptr %5, i32 0, i32 4 // CHECK-NEXT: %13 = getelementptr inbounds %"{{.*}}/runtime/internal/runtime.Defer", ptr %5, i32 0, i32 5 +// CHECK-NEXT: store i64 0, ptr %12, align 8 // CHECK-NEXT: store ptr null, ptr %13, align 8 // CHECK-NEXT: %14 = call i32 @{{.*}}sigsetjmp(ptr %4, i32 0) // CHECK-NEXT: %15 = icmp eq i32 %14, 0 diff --git a/cl/_testgo/cgopython/cgopython.go b/cl/_testgo/cgopython/cgopython.go index 977ef31040..a0152704af 100644 --- a/cl/_testgo/cgopython/cgopython.go +++ b/cl/_testgo/cgopython/cgopython.go @@ -69,6 +69,7 @@ import "C" // CHECK-NEXT: %9 = getelementptr inbounds %"{{.*}}/runtime/internal/runtime.Defer", ptr %3, i32 0, i32 3 // CHECK-NEXT: %10 = getelementptr inbounds %"{{.*}}/runtime/internal/runtime.Defer", ptr %3, i32 0, i32 4 // CHECK-NEXT: %11 = getelementptr inbounds %"{{.*}}/runtime/internal/runtime.Defer", ptr %3, i32 0, i32 5 +// CHECK-NEXT: store i64 0, ptr %10, align 8 // CHECK-NEXT: store ptr null, ptr %11, align 8 // CHECK-NEXT: %12 = call i32 @{{.*}}sigsetjmp(ptr %2, i32 0) // CHECK-NEXT: %13 = icmp eq i32 %12, 0 diff --git a/cl/_testgo/recoverthenpanic/in.go b/cl/_testgo/recoverthenpanic/in.go index c6ef4d3eaa..e35f0bcdbf 100644 --- a/cl/_testgo/recoverthenpanic/in.go +++ b/cl/_testgo/recoverthenpanic/in.go @@ -26,6 +26,7 @@ package main // CHECK-NEXT: %11 = getelementptr inbounds %"{{.*}}/runtime/internal/runtime.Defer", ptr %5, i32 0, i32 3 // CHECK-NEXT: %12 = getelementptr inbounds %"{{.*}}/runtime/internal/runtime.Defer", ptr %5, i32 0, i32 4 // CHECK-NEXT: %13 = getelementptr inbounds %"{{.*}}/runtime/internal/runtime.Defer", ptr %5, i32 0, i32 5 +// CHECK-NEXT: store i64 0, ptr %12, align 8 // CHECK-NEXT: store ptr null, ptr %13, align 8 // CHECK-NEXT: %14 = call i32 @{{.*}}sigsetjmp(ptr %4, i32 0) // CHECK-NEXT: %15 = icmp eq i32 %14, 0 @@ -162,6 +163,7 @@ func main() { // CHECK-NEXT: %8 = getelementptr inbounds %"{{.*}}/runtime/internal/runtime.Defer", ptr %2, i32 0, i32 3 // CHECK-NEXT: %9 = getelementptr inbounds %"{{.*}}/runtime/internal/runtime.Defer", ptr %2, i32 0, i32 4 // CHECK-NEXT: %10 = getelementptr inbounds %"{{.*}}/runtime/internal/runtime.Defer", ptr %2, i32 0, i32 5 +// CHECK-NEXT: store i64 0, ptr %9, align 8 // CHECK-NEXT: store ptr null, ptr %10, align 8 // CHECK-NEXT: %11 = call i32 @{{.*}}sigsetjmp(ptr %1, i32 0) // CHECK-NEXT: %12 = icmp eq i32 %11, 0 diff --git a/ssa/eh.go b/ssa/eh.go index 6d88384444..6931732698 100644 --- a/ssa/eh.go +++ b/ssa/eh.go @@ -275,7 +275,7 @@ func (b Builder) initDeferState(procBlk, rethrowBlk BasicBlock) (*aDefer, Expr, zero := prog.Val(uintptr(0)) link := b.Call(b.Pkg.rtFunc("GetThreadDefer")) jb := b.AllocaSigjmpBuf() - // Reth selector 0 is reserved for procBlk; Rund is zero-initialized. + // Reth selector 0 is reserved for procBlk; Rund selector 0 is rethrowBlk. ptr := b.aggregateAllocU(prog.Defer(), jb.impl, zero.impl, link.impl, zero.impl) deferData := Expr{ptr, prog.DeferPtr()} b.Call(b.Pkg.rtFunc("SetThreadDefer"), deferData) @@ -283,6 +283,7 @@ func (b Builder) initDeferState(procBlk, rethrowBlk BasicBlock) (*aDefer, Expr, rethPtr := b.FieldAddr(deferData, deferRethrow) rundPtr := b.FieldAddr(deferData, deferRunDefers) argsPtr := b.FieldAddr(deferData, deferArgs) + b.Store(rundPtr, zero) // Initialize the args list so later guards (e.g. DeferAlways/DeferInLoop) // can safely detect an empty chain without a prior push. b.Store(argsPtr, prog.Nil(prog.VoidPtr())) @@ -614,7 +615,10 @@ func (p Function) endDefer(b Builder) { stmts := self.stmts n := len(stmts) rethChain := make([]deferTarget, n+1) - blks := p.MakeBlocks(n - 1) + var blks []BasicBlock + if n > 1 { + blks = p.MakeBlocks(n - 1) + } // Reth selector 0 must remain procBlk because initDeferState installs it // before the final number of deferred statements is known. Selector 1 is // the terminal rethrow, followed by the intermediate continuation blocks. From 2353dec74d1f59536f29e3e1f0dc17d1d15ba197 Mon Sep 17 00:00:00 2001 From: Li Jie Date: Mon, 3 Aug 2026 19:31:11 +0800 Subject: [PATCH 51/73] test: cover defer selector dispatch end to end --- cl/_testgo/deferiface/in.go | 29 +++++++++++----- internal/build/testdata/wasm-runtime/main.go | 35 ++++++++++++++++++++ test/defer_test.go | 27 +++++++++++++++ 3 files changed, 83 insertions(+), 8 deletions(-) diff --git a/cl/_testgo/deferiface/in.go b/cl/_testgo/deferiface/in.go index bcee22b9ae..996ad051f0 100644 --- a/cl/_testgo/deferiface/in.go +++ b/cl/_testgo/deferiface/in.go @@ -79,12 +79,13 @@ func main() { // CHECK-NEXT: %12 = getelementptr inbounds %"{{.*}}/runtime/internal/runtime.Defer", ptr %9, i32 0, i32 2 // CHECK-NEXT: store ptr %7, ptr %12, align 8 // CHECK-NEXT: %13 = getelementptr inbounds %"{{.*}}/runtime/internal/runtime.Defer", ptr %9, i32 0, i32 3 -// CHECK-NEXT: store ptr blockaddress(@main.run, %_llgo_2), ptr %13, align 8 +// CHECK-NEXT: store i64 0, ptr %13, align 8 // CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.SetThreadDefer"(ptr %9) // CHECK-NEXT: %14 = getelementptr inbounds %"{{.*}}/runtime/internal/runtime.Defer", ptr %9, i32 0, i32 1 // CHECK-NEXT: %15 = getelementptr inbounds %"{{.*}}/runtime/internal/runtime.Defer", ptr %9, i32 0, i32 3 // CHECK-NEXT: %16 = getelementptr inbounds %"{{.*}}/runtime/internal/runtime.Defer", ptr %9, i32 0, i32 4 // CHECK-NEXT: %17 = getelementptr inbounds %"{{.*}}/runtime/internal/runtime.Defer", ptr %9, i32 0, i32 5 +// CHECK-NEXT: store i64 0, ptr %16, align 8 // CHECK-NEXT: store ptr null, ptr %17, align 8 // CHECK-NEXT: %18 = call i32 @{{.*}}sigsetjmp(ptr %8, i32 0) // CHECK-NEXT: %19 = icmp eq i32 %18, 0 @@ -94,7 +95,7 @@ func main() { // CHECK-NEXT: ret void // CHECK-EMPTY: // CHECK-NEXT: _llgo_2: ; preds = %_llgo_5, %_llgo_4 -// CHECK-NEXT: store ptr blockaddress(@main.run, %_llgo_3), ptr %15, align 8 +// CHECK-NEXT: store i64 1, ptr %15, align 8 // CHECK-NEXT: %20 = load i64, ptr %14, align 8 // CHECK-NEXT: %21 = load ptr, ptr %17, align 8 // CHECK-NEXT: %22 = icmp ne ptr %21, null @@ -116,13 +117,16 @@ func main() { // CHECK-NEXT: store ptr %24, ptr %17, align 8 // CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.PrintString"(%"{{.*}}/runtime/internal/runtime.String" { ptr @8, i64 4 }) // CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.PrintByte"(i8 10) -// CHECK-NEXT: store ptr blockaddress(@main.run, %_llgo_6), ptr %16, align 8 +// CHECK-NEXT: store i64 1, ptr %16, align 8 // CHECK-NEXT: br label %_llgo_2 // CHECK-EMPTY: // CHECK-NEXT: _llgo_5: ; preds = %_llgo_0 -// CHECK-NEXT: store ptr blockaddress(@main.run, %_llgo_3), ptr %16, align 8 -// CHECK-NEXT: %28 = load ptr, ptr %15, align 8 -// CHECK-NEXT: indirectbr ptr %28, [label %_llgo_3, label %_llgo_2] +// CHECK-NEXT: store i64 0, ptr %16, align 8 +// CHECK-NEXT: %28 = load i64, ptr %15, align 8 +// CHECK-NEXT: switch i64 %28, label %_llgo_10 [ +// CHECK-NEXT: i64 0, label %_llgo_2 +// CHECK-NEXT: i64 1, label %_llgo_3 +// CHECK-NEXT: ] // CHECK-EMPTY: // CHECK-NEXT: _llgo_6: ; preds = %_llgo_8 // CHECK-NEXT: ret void @@ -143,6 +147,15 @@ func main() { // CHECK-NEXT: %35 = load %"{{.*}}/runtime/internal/runtime.Defer", ptr %9, align 8 // CHECK-NEXT: %36 = extractvalue %"{{.*}}/runtime/internal/runtime.Defer" %35, 2 // CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.SetThreadDefer"(ptr %36) -// CHECK-NEXT: %37 = load ptr, ptr %16, align 8 -// CHECK-NEXT: indirectbr ptr %37, [label %_llgo_3, label %_llgo_6] +// CHECK-NEXT: %37 = load i64, ptr %16, align 8 +// CHECK-NEXT: switch i64 %37, label %_llgo_9 [ +// CHECK-NEXT: i64 0, label %_llgo_3 +// CHECK-NEXT: i64 1, label %_llgo_6 +// CHECK-NEXT: ] +// CHECK-EMPTY: +// CHECK-NEXT: _llgo_9: ; preds = %_llgo_8 +// CHECK-NEXT: unreachable +// CHECK-EMPTY: +// CHECK-NEXT: _llgo_10: ; preds = %_llgo_5 +// CHECK-NEXT: unreachable // CHECK-NEXT: } diff --git a/internal/build/testdata/wasm-runtime/main.go b/internal/build/testdata/wasm-runtime/main.go index af4a422b48..8863f26487 100644 --- a/internal/build/testdata/wasm-runtime/main.go +++ b/internal/build/testdata/wasm-runtime/main.go @@ -3,5 +3,40 @@ package main import "runtime" func main() { + exerciseDeferContinuations() println(runtime.GOOS) } + +func exerciseDeferContinuations() { + if got := normalLoopDefers(); got != 321 { + panic("normal loop defer order") + } + order, recovered := panicWhileDrainingLoopDefers() + if order != 321 || recovered != "wasm-loop-defer-boom" { + panic("panic loop defer order") + } +} + +func normalLoopDefers() (order int) { + for i := 1; i <= 3; i++ { + value := i + defer func() { order = order*10 + value }() + } + return +} + +func panicWhileDrainingLoopDefers() (order int, recovered any) { + defer func() { recovered = recover() }() + func() { + for i := 1; i <= 3; i++ { + value := i + defer func() { + order = order*10 + value + if value == 2 { + panic("wasm-loop-defer-boom") + } + }() + } + }() + return +} diff --git a/test/defer_test.go b/test/defer_test.go index 3a63c7248f..c1dc73d3f3 100644 --- a/test/defer_test.go +++ b/test/defer_test.go @@ -329,6 +329,33 @@ func TestPanicCrossTwoFunctionsRecover(t *testing.T) { } } +func runLoopDeferPanicDuringDrain() (order []int, recovered any) { + defer func() { recovered = recover() }() + func() { + for i := 0; i < 3; i++ { + value := i + defer func() { + order = append(order, value) + if value == 1 { + panic("loop-defer-boom") + } + }() + } + }() + return +} + +func TestPanicWhileDrainingLoopDefers(t *testing.T) { + order, recovered := runLoopDeferPanicDuringDrain() + if recovered != "loop-defer-boom" { + t.Fatalf("unexpected recovered value: got %v, want %q", recovered, "loop-defer-boom") + } + wantOrder := []int{2, 1, 0} + if !reflect.DeepEqual(order, wantOrder) { + t.Fatalf("unexpected loop defer order: got %v, want %v", order, wantOrder) + } +} + // Test for issue #1488: Deferred method literal stub uses undefined value type emitRecorder struct { last func(int) From 96b82b9f715f98f7604de0aa1d10afcfb0256ed9 Mon Sep 17 00:00:00 2001 From: Li Jie Date: Mon, 3 Aug 2026 20:55:30 +0800 Subject: [PATCH 52/73] ssa/wasm: preserve native defer dispatch --- cl/_testgo/cgodefer/cgodefer.go | 29 +++------ cl/_testgo/cgomacro/cgomacro.go | 29 +++------ cl/_testgo/cgopython/cgopython.go | 29 +++------ cl/_testgo/defer5/in.go | 4 +- .../deferdispatch-wasm-target/flags.txt | 3 + cl/_testgo/deferdispatch-wasm-target/in.go | 20 ++++++ cl/_testgo/deferdispatch-wasm/flags.txt | 1 + cl/_testgo/deferdispatch-wasm/in.go | 20 ++++++ cl/_testgo/deferdispatch/in.go | 17 +++++ cl/_testgo/deferiface/in.go | 29 +++------ cl/_testgo/deferloop/in.go | 5 +- cl/_testgo/recoverthenpanic/in.go | 55 +++++----------- internal/llgen/llgenf.go | 34 ++++++++-- internal/llgen/llgenf_test.go | 58 +++++++++++++---- runtime/internal/runtime/z_rt.go | 4 +- ssa/eh.go | 65 +++++++++++-------- ssa/eh_defer_test.go | 37 +++++++---- 17 files changed, 252 insertions(+), 187 deletions(-) create mode 100644 cl/_testgo/deferdispatch-wasm-target/flags.txt create mode 100644 cl/_testgo/deferdispatch-wasm-target/in.go create mode 100644 cl/_testgo/deferdispatch-wasm/flags.txt create mode 100644 cl/_testgo/deferdispatch-wasm/in.go create mode 100644 cl/_testgo/deferdispatch/in.go diff --git a/cl/_testgo/cgodefer/cgodefer.go b/cl/_testgo/cgodefer/cgodefer.go index b9739a724a..5ce8dd6bfe 100644 --- a/cl/_testgo/cgodefer/cgodefer.go +++ b/cl/_testgo/cgodefer/cgodefer.go @@ -38,13 +38,12 @@ import "C" // CHECK-NEXT: %13 = getelementptr inbounds %"{{.*}}/runtime/internal/runtime.Defer", ptr %10, i32 0, i32 2 // CHECK-NEXT: store ptr %8, ptr %13, align 8 // CHECK-NEXT: %14 = getelementptr inbounds %"{{.*}}/runtime/internal/runtime.Defer", ptr %10, i32 0, i32 3 -// CHECK-NEXT: store i64 0, ptr %14, align 8 +// CHECK-NEXT: store ptr blockaddress(@main.main, %_llgo_2), ptr %14, align 8 // CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.SetThreadDefer"(ptr %10) // CHECK-NEXT: %15 = getelementptr inbounds %"{{.*}}/runtime/internal/runtime.Defer", ptr %10, i32 0, i32 1 // CHECK-NEXT: %16 = getelementptr inbounds %"{{.*}}/runtime/internal/runtime.Defer", ptr %10, i32 0, i32 3 // CHECK-NEXT: %17 = getelementptr inbounds %"{{.*}}/runtime/internal/runtime.Defer", ptr %10, i32 0, i32 4 // CHECK-NEXT: %18 = getelementptr inbounds %"{{.*}}/runtime/internal/runtime.Defer", ptr %10, i32 0, i32 5 -// CHECK-NEXT: store i64 0, ptr %17, align 8 // CHECK-NEXT: store ptr null, ptr %18, align 8 // CHECK-NEXT: %19 = call i32 @{{.*}}sigsetjmp(ptr %9, i32 0) // CHECK-NEXT: %20 = icmp eq i32 %19, 0 @@ -54,7 +53,7 @@ import "C" // CHECK-NEXT: ret void // CHECK-EMPTY: // CHECK-NEXT: _llgo_2: ; preds = %_llgo_5, %_llgo_4 -// CHECK-NEXT: store i64 1, ptr %16, align 8 +// CHECK-NEXT: store ptr blockaddress(@main.main, %_llgo_3), ptr %16, align 8 // CHECK-NEXT: %21 = load i64, ptr %15, align 8 // CHECK-NEXT: %22 = load ptr, ptr %18, align 8 // CHECK-NEXT: %23 = icmp ne ptr %22, null @@ -74,16 +73,13 @@ import "C" // CHECK-NEXT: %28 = getelementptr inbounds { ptr, i64, { ptr, ptr } }, ptr %25, i32 0, i32 2 // CHECK-NEXT: store { ptr, ptr } %7, ptr %28, align 8 // CHECK-NEXT: store ptr %25, ptr %18, align 8 -// CHECK-NEXT: store i64 1, ptr %17, align 8 +// CHECK-NEXT: store ptr blockaddress(@main.main, %_llgo_6), ptr %17, align 8 // CHECK-NEXT: br label %_llgo_2 // CHECK-EMPTY: // CHECK-NEXT: _llgo_5: ; preds = %_llgo_0 -// CHECK-NEXT: store i64 0, ptr %17, align 8 -// CHECK-NEXT: %29 = load i64, ptr %16, align 8 -// CHECK-NEXT: switch i64 %29, label %_llgo_10 [ -// CHECK-NEXT: i64 0, label %_llgo_2 -// CHECK-NEXT: i64 1, label %_llgo_3 -// CHECK-NEXT: ] +// CHECK-NEXT: store ptr blockaddress(@main.main, %_llgo_3), ptr %17, align 8 +// CHECK-NEXT: %29 = load ptr, ptr %16, align 8 +// CHECK-NEXT: indirectbr ptr %29, [label %_llgo_3, label %_llgo_2] // CHECK-EMPTY: // CHECK-NEXT: _llgo_6: ; preds = %_llgo_8 // CHECK-NEXT: ret void @@ -105,17 +101,8 @@ import "C" // CHECK-NEXT: %36 = load %"{{.*}}/runtime/internal/runtime.Defer", ptr %10, align 8 // CHECK-NEXT: %37 = extractvalue %"{{.*}}/runtime/internal/runtime.Defer" %36, 2 // CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.SetThreadDefer"(ptr %37) -// CHECK-NEXT: %38 = load i64, ptr %17, align 8 -// CHECK-NEXT: switch i64 %38, label %_llgo_9 [ -// CHECK-NEXT: i64 0, label %_llgo_3 -// CHECK-NEXT: i64 1, label %_llgo_6 -// CHECK-NEXT: ] -// CHECK-EMPTY: -// CHECK-NEXT: _llgo_9: ; preds = %_llgo_8 -// CHECK-NEXT: unreachable -// CHECK-EMPTY: -// CHECK-NEXT: _llgo_10: ; preds = %_llgo_5 -// CHECK-NEXT: unreachable +// CHECK-NEXT: %38 = load ptr, ptr %17, align 8 +// CHECK-NEXT: indirectbr ptr %38, [label %_llgo_3, label %_llgo_6] // CHECK-NEXT: } func main() { // CHECK-LABEL: define { ptr, ptr } @"main.main$1"(ptr {{(nest|swiftself)}} %0){{.*}} { diff --git a/cl/_testgo/cgomacro/cgomacro.go b/cl/_testgo/cgomacro/cgomacro.go index 0e8533a480..c2c152d37d 100644 --- a/cl/_testgo/cgomacro/cgomacro.go +++ b/cl/_testgo/cgomacro/cgomacro.go @@ -130,13 +130,12 @@ import ( // CHECK-NEXT: %8 = getelementptr inbounds %"{{.*}}/runtime/internal/runtime.Defer", ptr %5, i32 0, i32 2 // CHECK-NEXT: store ptr %3, ptr %8, align 8 // CHECK-NEXT: %9 = getelementptr inbounds %"{{.*}}/runtime/internal/runtime.Defer", ptr %5, i32 0, i32 3 -// CHECK-NEXT: store i64 0, ptr %9, align 8 +// CHECK-NEXT: store ptr blockaddress(@main.main, %_llgo_2), ptr %9, align 8 // CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.SetThreadDefer"(ptr %5) // CHECK-NEXT: %10 = getelementptr inbounds %"{{.*}}/runtime/internal/runtime.Defer", ptr %5, i32 0, i32 1 // CHECK-NEXT: %11 = getelementptr inbounds %"{{.*}}/runtime/internal/runtime.Defer", ptr %5, i32 0, i32 3 // CHECK-NEXT: %12 = getelementptr inbounds %"{{.*}}/runtime/internal/runtime.Defer", ptr %5, i32 0, i32 4 // CHECK-NEXT: %13 = getelementptr inbounds %"{{.*}}/runtime/internal/runtime.Defer", ptr %5, i32 0, i32 5 -// CHECK-NEXT: store i64 0, ptr %12, align 8 // CHECK-NEXT: store ptr null, ptr %13, align 8 // CHECK-NEXT: %14 = call i32 @{{.*}}sigsetjmp(ptr %4, i32 0) // CHECK-NEXT: %15 = icmp eq i32 %14, 0 @@ -146,17 +145,14 @@ import ( // CHECK-NEXT: ret void // CHECK-EMPTY: // CHECK-NEXT: _llgo_2: ; preds = %_llgo_5, %_llgo_4 -// CHECK-NEXT: store i64 1, ptr %11, align 8 +// CHECK-NEXT: store ptr blockaddress(@main.main, %_llgo_3), ptr %11, align 8 // CHECK-NEXT: %16 = load i64, ptr %10, align 8 // CHECK-NEXT: %17 = call [0 x i8] @main._Cfunc_Py_Finalize() // CHECK-NEXT: %18 = load %"{{.*}}/runtime/internal/runtime.Defer", ptr %5, align 8 // CHECK-NEXT: %19 = extractvalue %"{{.*}}/runtime/internal/runtime.Defer" %18, 2 // CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.SetThreadDefer"(ptr %19) -// CHECK-NEXT: %20 = load i64, ptr %12, align 8 -// CHECK-NEXT: switch i64 %20, label %_llgo_7 [ -// CHECK-NEXT: i64 0, label %_llgo_3 -// CHECK-NEXT: i64 1, label %_llgo_6 -// CHECK-NEXT: ] +// CHECK-NEXT: %20 = load ptr, ptr %12, align 8 +// CHECK-NEXT: indirectbr ptr %20, [label %_llgo_3, label %_llgo_6] // CHECK-EMPTY: // CHECK-NEXT: _llgo_3: ; preds = %_llgo_5, %_llgo_2 // CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.Rethrow"(ptr %3) @@ -169,25 +165,16 @@ import ( // CHECK-NEXT: %24 = call i32 @"main.main$5"() // CHECK-NEXT: %25 = call i32 @"main.main$6"() // CHECK-NEXT: %26 = call i32 @"main.main$7"() -// CHECK-NEXT: store i64 1, ptr %12, align 8 +// CHECK-NEXT: store ptr blockaddress(@main.main, %_llgo_6), ptr %12, align 8 // CHECK-NEXT: br label %_llgo_2 // CHECK-EMPTY: // CHECK-NEXT: _llgo_5: ; preds = %_llgo_0 -// CHECK-NEXT: store i64 0, ptr %12, align 8 -// CHECK-NEXT: %27 = load i64, ptr %11, align 8 -// CHECK-NEXT: switch i64 %27, label %_llgo_8 [ -// CHECK-NEXT: i64 0, label %_llgo_2 -// CHECK-NEXT: i64 1, label %_llgo_3 -// CHECK-NEXT: ] +// CHECK-NEXT: store ptr blockaddress(@main.main, %_llgo_3), ptr %12, align 8 +// CHECK-NEXT: %27 = load ptr, ptr %11, align 8 +// CHECK-NEXT: indirectbr ptr %27, [label %_llgo_3, label %_llgo_2] // CHECK-EMPTY: // CHECK-NEXT: _llgo_6: ; preds = %_llgo_2 // CHECK-NEXT: ret void -// CHECK-EMPTY: -// CHECK-NEXT: _llgo_7: ; preds = %_llgo_2 -// CHECK-NEXT: unreachable -// CHECK-EMPTY: -// CHECK-NEXT: _llgo_8: ; preds = %_llgo_5 -// CHECK-NEXT: unreachable // CHECK-NEXT: } func main() { C.test_stdout() diff --git a/cl/_testgo/cgopython/cgopython.go b/cl/_testgo/cgopython/cgopython.go index a0152704af..aea2a0f615 100644 --- a/cl/_testgo/cgopython/cgopython.go +++ b/cl/_testgo/cgopython/cgopython.go @@ -63,13 +63,12 @@ import "C" // CHECK-NEXT: %6 = getelementptr inbounds %"{{.*}}/runtime/internal/runtime.Defer", ptr %3, i32 0, i32 2 // CHECK-NEXT: store ptr %1, ptr %6, align 8 // CHECK-NEXT: %7 = getelementptr inbounds %"{{.*}}/runtime/internal/runtime.Defer", ptr %3, i32 0, i32 3 -// CHECK-NEXT: store i64 0, ptr %7, align 8 +// CHECK-NEXT: store ptr blockaddress(@main.main, %_llgo_2), ptr %7, align 8 // CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.SetThreadDefer"(ptr %3) // CHECK-NEXT: %8 = getelementptr inbounds %"{{.*}}/runtime/internal/runtime.Defer", ptr %3, i32 0, i32 1 // CHECK-NEXT: %9 = getelementptr inbounds %"{{.*}}/runtime/internal/runtime.Defer", ptr %3, i32 0, i32 3 // CHECK-NEXT: %10 = getelementptr inbounds %"{{.*}}/runtime/internal/runtime.Defer", ptr %3, i32 0, i32 4 // CHECK-NEXT: %11 = getelementptr inbounds %"{{.*}}/runtime/internal/runtime.Defer", ptr %3, i32 0, i32 5 -// CHECK-NEXT: store i64 0, ptr %10, align 8 // CHECK-NEXT: store ptr null, ptr %11, align 8 // CHECK-NEXT: %12 = call i32 @{{.*}}sigsetjmp(ptr %2, i32 0) // CHECK-NEXT: %13 = icmp eq i32 %12, 0 @@ -79,17 +78,14 @@ import "C" // CHECK-NEXT: ret void // CHECK-EMPTY: // CHECK-NEXT: _llgo_2: ; preds = %_llgo_5, %_llgo_4 -// CHECK-NEXT: store i64 1, ptr %9, align 8 +// CHECK-NEXT: store ptr blockaddress(@main.main, %_llgo_3), ptr %9, align 8 // CHECK-NEXT: %14 = load i64, ptr %8, align 8 // CHECK-NEXT: %15 = call [0 x i8] @main._Cfunc_Py_Finalize() // CHECK-NEXT: %16 = load %"{{.*}}/runtime/internal/runtime.Defer", ptr %3, align 8 // CHECK-NEXT: %17 = extractvalue %"{{.*}}/runtime/internal/runtime.Defer" %16, 2 // CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.SetThreadDefer"(ptr %17) -// CHECK-NEXT: %18 = load i64, ptr %10, align 8 -// CHECK-NEXT: switch i64 %18, label %_llgo_7 [ -// CHECK-NEXT: i64 0, label %_llgo_3 -// CHECK-NEXT: i64 1, label %_llgo_6 -// CHECK-NEXT: ] +// CHECK-NEXT: %18 = load ptr, ptr %10, align 8 +// CHECK-NEXT: indirectbr ptr %18, [label %_llgo_3, label %_llgo_6] // CHECK-EMPTY: // CHECK-NEXT: _llgo_3: ; preds = %_llgo_5, %_llgo_2 // CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.Rethrow"(ptr %1) @@ -98,25 +94,16 @@ import "C" // CHECK-NEXT: _llgo_4: ; preds = %_llgo_0 // CHECK-NEXT: %19 = call ptr @"{{.*}}/runtime/internal/runtime.CString"(%"{{.*}}/runtime/internal/runtime.String" { ptr @0, i64 23 }) // CHECK-NEXT: %20 = call i32 @main._Cfunc_PyRun_SimpleString(ptr %19) -// CHECK-NEXT: store i64 1, ptr %10, align 8 +// CHECK-NEXT: store ptr blockaddress(@main.main, %_llgo_6), ptr %10, align 8 // CHECK-NEXT: br label %_llgo_2 // CHECK-EMPTY: // CHECK-NEXT: _llgo_5: ; preds = %_llgo_0 -// CHECK-NEXT: store i64 0, ptr %10, align 8 -// CHECK-NEXT: %21 = load i64, ptr %9, align 8 -// CHECK-NEXT: switch i64 %21, label %_llgo_8 [ -// CHECK-NEXT: i64 0, label %_llgo_2 -// CHECK-NEXT: i64 1, label %_llgo_3 -// CHECK-NEXT: ] +// CHECK-NEXT: store ptr blockaddress(@main.main, %_llgo_3), ptr %10, align 8 +// CHECK-NEXT: %21 = load ptr, ptr %9, align 8 +// CHECK-NEXT: indirectbr ptr %21, [label %_llgo_3, label %_llgo_2] // CHECK-EMPTY: // CHECK-NEXT: _llgo_6: ; preds = %_llgo_2 // CHECK-NEXT: ret void -// CHECK-EMPTY: -// CHECK-NEXT: _llgo_7: ; preds = %_llgo_2 -// CHECK-NEXT: unreachable -// CHECK-EMPTY: -// CHECK-NEXT: _llgo_8: ; preds = %_llgo_5 -// CHECK-NEXT: unreachable // CHECK-NEXT: } func main() { C.Py_Initialize() diff --git a/cl/_testgo/defer5/in.go b/cl/_testgo/defer5/in.go index ec59812005..4bcca285f0 100644 --- a/cl/_testgo/defer5/in.go +++ b/cl/_testgo/defer5/in.go @@ -4,12 +4,12 @@ package main // CHECK-LABEL: define void @main.main(){{.*}} { func main() { // CHECK: GetThreadDefer - // CHECK: switch i{{(32|64)}} + // CHECK: blockaddress(@main.main, %_llgo_2) + // CHECK: blockaddress(@main.main, %_llgo_8) // CHECK: call void @"main.main$1"() // CHECK: call void @"main.main$2"() // CHECK: FreeDeferNode // CHECK: FreeDeferNode - // CHECK: switch i{{(32|64)}} defer println("A") defer func() { if e := recover(); e != nil { diff --git a/cl/_testgo/deferdispatch-wasm-target/flags.txt b/cl/_testgo/deferdispatch-wasm-target/flags.txt new file mode 100644 index 0000000000..c140566ce8 --- /dev/null +++ b/cl/_testgo/deferdispatch-wasm-target/flags.txt @@ -0,0 +1,3 @@ +# Wasm named targets currently use GOOS/GOARCH for toolchain selection. +GOOS=js GOARCH=wasm +-target=wasm diff --git a/cl/_testgo/deferdispatch-wasm-target/in.go b/cl/_testgo/deferdispatch-wasm-target/in.go new file mode 100644 index 0000000000..ea22c1f291 --- /dev/null +++ b/cl/_testgo/deferdispatch-wasm-target/in.go @@ -0,0 +1,20 @@ +// LITTEST +package main + +func run() { + defer println("first") + defer println("second") +} + +func main() { + run() +} + +// CHECK-LABEL: define void @main.run() +// CHECK-NOT: blockaddress +// CHECK: switch i32 +// CHECK-NOT: blockaddress +// CHECK: switch i32 +// CHECK-NOT: blockaddress +// CHECK-NOT: indirectbr +// CHECK: } diff --git a/cl/_testgo/deferdispatch-wasm/flags.txt b/cl/_testgo/deferdispatch-wasm/flags.txt new file mode 100644 index 0000000000..be36b8150d --- /dev/null +++ b/cl/_testgo/deferdispatch-wasm/flags.txt @@ -0,0 +1 @@ +GOOS=wasip1 GOARCH=wasm diff --git a/cl/_testgo/deferdispatch-wasm/in.go b/cl/_testgo/deferdispatch-wasm/in.go new file mode 100644 index 0000000000..ea22c1f291 --- /dev/null +++ b/cl/_testgo/deferdispatch-wasm/in.go @@ -0,0 +1,20 @@ +// LITTEST +package main + +func run() { + defer println("first") + defer println("second") +} + +func main() { + run() +} + +// CHECK-LABEL: define void @main.run() +// CHECK-NOT: blockaddress +// CHECK: switch i32 +// CHECK-NOT: blockaddress +// CHECK: switch i32 +// CHECK-NOT: blockaddress +// CHECK-NOT: indirectbr +// CHECK: } diff --git a/cl/_testgo/deferdispatch/in.go b/cl/_testgo/deferdispatch/in.go new file mode 100644 index 0000000000..a3a4a2050c --- /dev/null +++ b/cl/_testgo/deferdispatch/in.go @@ -0,0 +1,17 @@ +// LITTEST +package main + +func run() { + defer println("first") + defer println("second") +} + +func main() { + run() +} + +// CHECK-LABEL: define void @main.run() +// CHECK: blockaddress +// CHECK: indirectbr ptr +// CHECK: indirectbr ptr +// CHECK: } diff --git a/cl/_testgo/deferiface/in.go b/cl/_testgo/deferiface/in.go index 996ad051f0..bcee22b9ae 100644 --- a/cl/_testgo/deferiface/in.go +++ b/cl/_testgo/deferiface/in.go @@ -79,13 +79,12 @@ func main() { // CHECK-NEXT: %12 = getelementptr inbounds %"{{.*}}/runtime/internal/runtime.Defer", ptr %9, i32 0, i32 2 // CHECK-NEXT: store ptr %7, ptr %12, align 8 // CHECK-NEXT: %13 = getelementptr inbounds %"{{.*}}/runtime/internal/runtime.Defer", ptr %9, i32 0, i32 3 -// CHECK-NEXT: store i64 0, ptr %13, align 8 +// CHECK-NEXT: store ptr blockaddress(@main.run, %_llgo_2), ptr %13, align 8 // CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.SetThreadDefer"(ptr %9) // CHECK-NEXT: %14 = getelementptr inbounds %"{{.*}}/runtime/internal/runtime.Defer", ptr %9, i32 0, i32 1 // CHECK-NEXT: %15 = getelementptr inbounds %"{{.*}}/runtime/internal/runtime.Defer", ptr %9, i32 0, i32 3 // CHECK-NEXT: %16 = getelementptr inbounds %"{{.*}}/runtime/internal/runtime.Defer", ptr %9, i32 0, i32 4 // CHECK-NEXT: %17 = getelementptr inbounds %"{{.*}}/runtime/internal/runtime.Defer", ptr %9, i32 0, i32 5 -// CHECK-NEXT: store i64 0, ptr %16, align 8 // CHECK-NEXT: store ptr null, ptr %17, align 8 // CHECK-NEXT: %18 = call i32 @{{.*}}sigsetjmp(ptr %8, i32 0) // CHECK-NEXT: %19 = icmp eq i32 %18, 0 @@ -95,7 +94,7 @@ func main() { // CHECK-NEXT: ret void // CHECK-EMPTY: // CHECK-NEXT: _llgo_2: ; preds = %_llgo_5, %_llgo_4 -// CHECK-NEXT: store i64 1, ptr %15, align 8 +// CHECK-NEXT: store ptr blockaddress(@main.run, %_llgo_3), ptr %15, align 8 // CHECK-NEXT: %20 = load i64, ptr %14, align 8 // CHECK-NEXT: %21 = load ptr, ptr %17, align 8 // CHECK-NEXT: %22 = icmp ne ptr %21, null @@ -117,16 +116,13 @@ func main() { // CHECK-NEXT: store ptr %24, ptr %17, align 8 // CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.PrintString"(%"{{.*}}/runtime/internal/runtime.String" { ptr @8, i64 4 }) // CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.PrintByte"(i8 10) -// CHECK-NEXT: store i64 1, ptr %16, align 8 +// CHECK-NEXT: store ptr blockaddress(@main.run, %_llgo_6), ptr %16, align 8 // CHECK-NEXT: br label %_llgo_2 // CHECK-EMPTY: // CHECK-NEXT: _llgo_5: ; preds = %_llgo_0 -// CHECK-NEXT: store i64 0, ptr %16, align 8 -// CHECK-NEXT: %28 = load i64, ptr %15, align 8 -// CHECK-NEXT: switch i64 %28, label %_llgo_10 [ -// CHECK-NEXT: i64 0, label %_llgo_2 -// CHECK-NEXT: i64 1, label %_llgo_3 -// CHECK-NEXT: ] +// CHECK-NEXT: store ptr blockaddress(@main.run, %_llgo_3), ptr %16, align 8 +// CHECK-NEXT: %28 = load ptr, ptr %15, align 8 +// CHECK-NEXT: indirectbr ptr %28, [label %_llgo_3, label %_llgo_2] // CHECK-EMPTY: // CHECK-NEXT: _llgo_6: ; preds = %_llgo_8 // CHECK-NEXT: ret void @@ -147,15 +143,6 @@ func main() { // CHECK-NEXT: %35 = load %"{{.*}}/runtime/internal/runtime.Defer", ptr %9, align 8 // CHECK-NEXT: %36 = extractvalue %"{{.*}}/runtime/internal/runtime.Defer" %35, 2 // CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.SetThreadDefer"(ptr %36) -// CHECK-NEXT: %37 = load i64, ptr %16, align 8 -// CHECK-NEXT: switch i64 %37, label %_llgo_9 [ -// CHECK-NEXT: i64 0, label %_llgo_3 -// CHECK-NEXT: i64 1, label %_llgo_6 -// CHECK-NEXT: ] -// CHECK-EMPTY: -// CHECK-NEXT: _llgo_9: ; preds = %_llgo_8 -// CHECK-NEXT: unreachable -// CHECK-EMPTY: -// CHECK-NEXT: _llgo_10: ; preds = %_llgo_5 -// CHECK-NEXT: unreachable +// CHECK-NEXT: %37 = load ptr, ptr %16, align 8 +// CHECK-NEXT: indirectbr ptr %37, [label %_llgo_3, label %_llgo_6] // CHECK-NEXT: } diff --git a/cl/_testgo/deferloop/in.go b/cl/_testgo/deferloop/in.go index c4c0568599..7fec91526a 100644 --- a/cl/_testgo/deferloop/in.go +++ b/cl/_testgo/deferloop/in.go @@ -5,11 +5,10 @@ package main func main() { // CHECK: GetThreadDefer for i := 0; i < 3; i++ { - // CHECK: switch i{{(32|64)}} + // CHECK: blockaddress(@main.main, %_llgo_6) defer println("loop", i) } - // CHECK: switch i{{(32|64)}} - // CHECK: FreeDeferNode // CHECK: PrintString // CHECK: PrintInt + // CHECK: FreeDeferNode } diff --git a/cl/_testgo/recoverthenpanic/in.go b/cl/_testgo/recoverthenpanic/in.go index e35f0bcdbf..6d1364b14f 100644 --- a/cl/_testgo/recoverthenpanic/in.go +++ b/cl/_testgo/recoverthenpanic/in.go @@ -20,13 +20,12 @@ package main // CHECK-NEXT: %8 = getelementptr inbounds %"{{.*}}/runtime/internal/runtime.Defer", ptr %5, i32 0, i32 2 // CHECK-NEXT: store ptr %3, ptr %8, align 8 // CHECK-NEXT: %9 = getelementptr inbounds %"{{.*}}/runtime/internal/runtime.Defer", ptr %5, i32 0, i32 3 -// CHECK-NEXT: store i64 0, ptr %9, align 8 +// CHECK-NEXT: store ptr blockaddress(@main.End, %_llgo_5), ptr %9, align 8 // CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.SetThreadDefer"(ptr %5) // CHECK-NEXT: %10 = getelementptr inbounds %"{{.*}}/runtime/internal/runtime.Defer", ptr %5, i32 0, i32 1 // CHECK-NEXT: %11 = getelementptr inbounds %"{{.*}}/runtime/internal/runtime.Defer", ptr %5, i32 0, i32 3 // CHECK-NEXT: %12 = getelementptr inbounds %"{{.*}}/runtime/internal/runtime.Defer", ptr %5, i32 0, i32 4 // CHECK-NEXT: %13 = getelementptr inbounds %"{{.*}}/runtime/internal/runtime.Defer", ptr %5, i32 0, i32 5 -// CHECK-NEXT: store i64 0, ptr %12, align 8 // CHECK-NEXT: store ptr null, ptr %13, align 8 // CHECK-NEXT: %14 = call i32 @{{.*}}sigsetjmp(ptr %4, i32 0) // CHECK-NEXT: %15 = icmp eq i32 %14, 0 @@ -52,7 +51,7 @@ package main // CHECK-NEXT: _llgo_2: ; preds = %_llgo_1, %_llgo_4 // CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.PrintString"(%"{{.*}}/runtime/internal/runtime.String" { ptr @1, i64 3 }) // CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.PrintByte"(i8 10) -// CHECK-NEXT: store i64 1, ptr %12, align 8 +// CHECK-NEXT: store ptr blockaddress(@main.End, %_llgo_8), ptr %12, align 8 // CHECK-NEXT: br label %_llgo_5 // CHECK-EMPTY: // CHECK-NEXT: _llgo_3: ; preds = %_llgo_6 @@ -62,7 +61,7 @@ package main // CHECK-NEXT: br i1 %2, label %_llgo_1, label %_llgo_2 // CHECK-EMPTY: // CHECK-NEXT: _llgo_5: ; preds = %_llgo_7, %_llgo_2 -// CHECK-NEXT: store i64 1, ptr %11, align 8 +// CHECK-NEXT: store ptr blockaddress(@main.End, %_llgo_6), ptr %11, align 8 // CHECK-NEXT: %23 = load i64, ptr %10, align 8 // CHECK-NEXT: %24 = and i64 %23, 1 // CHECK-NEXT: %25 = icmp ne i64 %24, 0 @@ -73,12 +72,9 @@ package main // CHECK-NEXT: br label %_llgo_3 // CHECK-EMPTY: // CHECK-NEXT: _llgo_7: ; preds = %_llgo_0 -// CHECK-NEXT: store i64 0, ptr %12, align 8 -// CHECK-NEXT: %26 = load i64, ptr %11, align 8 -// CHECK-NEXT: switch i64 %26, label %_llgo_14 [ -// CHECK-NEXT: i64 0, label %_llgo_5 -// CHECK-NEXT: i64 1, label %_llgo_6 -// CHECK-NEXT: ] +// CHECK-NEXT: store ptr blockaddress(@main.End, %_llgo_6), ptr %12, align 8 +// CHECK-NEXT: %26 = load ptr, ptr %11, align 8 +// CHECK-NEXT: indirectbr ptr %26, [label %_llgo_6, label %_llgo_5] // CHECK-EMPTY: // CHECK-NEXT: _llgo_8: ; preds = %_llgo_10 // CHECK-NEXT: ret void @@ -92,11 +88,8 @@ package main // CHECK-NEXT: %29 = load %"{{.*}}/runtime/internal/runtime.Defer", ptr %5, align 8 // CHECK-NEXT: %30 = extractvalue %"{{.*}}/runtime/internal/runtime.Defer" %29, 2 // CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.SetThreadDefer"(ptr %30) -// CHECK-NEXT: %31 = load i64, ptr %12, align 8 -// CHECK-NEXT: switch i64 %31, label %_llgo_13 [ -// CHECK-NEXT: i64 0, label %_llgo_6 -// CHECK-NEXT: i64 1, label %_llgo_8 -// CHECK-NEXT: ] +// CHECK-NEXT: %31 = load ptr, ptr %12, align 8 +// CHECK-NEXT: indirectbr ptr %31, [label %_llgo_6, label %_llgo_8] // CHECK-EMPTY: // CHECK-NEXT: _llgo_11: ; preds = %_llgo_9 // CHECK-NEXT: %32 = load ptr, ptr %13, align 8 @@ -110,12 +103,6 @@ package main // CHECK-EMPTY: // CHECK-NEXT: _llgo_12: ; preds = %_llgo_9 // CHECK-NEXT: br label %_llgo_10 -// CHECK-EMPTY: -// CHECK-NEXT: _llgo_13: ; preds = %_llgo_10 -// CHECK-NEXT: unreachable -// CHECK-EMPTY: -// CHECK-NEXT: _llgo_14: ; preds = %_llgo_7 -// CHECK-NEXT: unreachable // CHECK-NEXT: } func End() { @@ -157,13 +144,12 @@ func main() { // CHECK-NEXT: %5 = getelementptr inbounds %"{{.*}}/runtime/internal/runtime.Defer", ptr %2, i32 0, i32 2 // CHECK-NEXT: store ptr %0, ptr %5, align 8 // CHECK-NEXT: %6 = getelementptr inbounds %"{{.*}}/runtime/internal/runtime.Defer", ptr %2, i32 0, i32 3 -// CHECK-NEXT: store i64 0, ptr %6, align 8 +// CHECK-NEXT: store ptr blockaddress(@main.main, %_llgo_2), ptr %6, align 8 // CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.SetThreadDefer"(ptr %2) // CHECK-NEXT: %7 = getelementptr inbounds %"{{.*}}/runtime/internal/runtime.Defer", ptr %2, i32 0, i32 1 // CHECK-NEXT: %8 = getelementptr inbounds %"{{.*}}/runtime/internal/runtime.Defer", ptr %2, i32 0, i32 3 // CHECK-NEXT: %9 = getelementptr inbounds %"{{.*}}/runtime/internal/runtime.Defer", ptr %2, i32 0, i32 4 // CHECK-NEXT: %10 = getelementptr inbounds %"{{.*}}/runtime/internal/runtime.Defer", ptr %2, i32 0, i32 5 -// CHECK-NEXT: store i64 0, ptr %9, align 8 // CHECK-NEXT: store ptr null, ptr %10, align 8 // CHECK-NEXT: %11 = call i32 @{{.*}}sigsetjmp(ptr %1, i32 0) // CHECK-NEXT: %12 = icmp eq i32 %11, 0 @@ -173,16 +159,14 @@ func main() { // CHECK-NEXT: ret void // CHECK-EMPTY: // CHECK-NEXT: _llgo_2: ; preds = %_llgo_5 -// CHECK-NEXT: store i64 1, ptr %8, align 8 +// CHECK-NEXT: store ptr blockaddress(@main.main, %_llgo_3), ptr %8, align 8 // CHECK-NEXT: %13 = load i64, ptr %7, align 8 // CHECK-NEXT: call void @main.End() // CHECK-NEXT: %14 = load %"{{.*}}/runtime/internal/runtime.Defer", ptr %2, align 8 // CHECK-NEXT: %15 = extractvalue %"{{.*}}/runtime/internal/runtime.Defer" %14, 2 // CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.SetThreadDefer"(ptr %15) -// CHECK-NEXT: %16 = load i64, ptr %9, align 8 -// CHECK-NEXT: switch i64 %16, label %_llgo_6 [ -// CHECK-NEXT: i64 0, label %_llgo_3 -// CHECK-NEXT: ] +// CHECK-NEXT: %16 = load ptr, ptr %9, align 8 +// CHECK-NEXT: indirectbr ptr %16, [label %_llgo_3] // CHECK-EMPTY: // CHECK-NEXT: _llgo_3: ; preds = %_llgo_5, %_llgo_2 // CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.Rethrow"(ptr %0) @@ -196,16 +180,7 @@ func main() { // CHECK-NEXT: unreachable // CHECK-EMPTY: // CHECK-NEXT: _llgo_5: ; preds = %_llgo_0 -// CHECK-NEXT: store i64 0, ptr %9, align 8 -// CHECK-NEXT: %19 = load i64, ptr %8, align 8 -// CHECK-NEXT: switch i64 %19, label %_llgo_7 [ -// CHECK-NEXT: i64 0, label %_llgo_2 -// CHECK-NEXT: i64 1, label %_llgo_3 -// CHECK-NEXT: ] -// CHECK-EMPTY: -// CHECK-NEXT: _llgo_6: ; preds = %_llgo_2 -// CHECK-NEXT: unreachable -// CHECK-EMPTY: -// CHECK-NEXT: _llgo_7: ; preds = %_llgo_5 -// CHECK-NEXT: unreachable +// CHECK-NEXT: store ptr blockaddress(@main.main, %_llgo_3), ptr %9, align 8 +// CHECK-NEXT: %19 = load ptr, ptr %8, align 8 +// CHECK-NEXT: indirectbr ptr %19, [label %_llgo_3, label %_llgo_2] // CHECK-NEXT: } diff --git a/internal/llgen/llgenf.go b/internal/llgen/llgenf.go index 2629328a05..45baebf0f4 100644 --- a/internal/llgen/llgenf.go +++ b/internal/llgen/llgenf.go @@ -44,7 +44,7 @@ func genFrom(pkgPath string, abiMode build.AbiMode) (build.Package, error) { AbiMode: abiMode, GenLL: true, } - if err := applyGoBuildFlagsFile(conf, filepath.Join(pkgPath, "flags.txt")); err != nil { + if err := applyFlagsFile(conf, filepath.Join(pkgPath, "flags.txt")); err != nil { return nil, err } pkgs, err := build.Do([]string{pkgPath}, conf) @@ -60,7 +60,7 @@ func DoFile(fileOrPkg, outFile string) { check(err) } -func readGoBuildFlags(flagsFile string) ([]string, error) { +func readFlags(flagsFile string) ([]string, error) { data, err := os.ReadFile(flagsFile) if os.IsNotExist(err) { return nil, nil @@ -75,14 +75,38 @@ func readGoBuildFlags(flagsFile string) ([]string, error) { return flags, nil } -func applyGoBuildFlagsFile(conf *build.Config, flagsFile string) error { - flags, err := readGoBuildFlags(flagsFile) +func applyFlagsFile(conf *build.Config, flagsFile string) error { + flags, err := readFlags(flagsFile) if err != nil { return err } - if err := goflags.ApplyBuildFlags(conf, flags); err != nil { + next := *conf + goFlags := make([]string, 0, len(flags)) + for i := 0; i < len(flags); i++ { + flag := flags[i] + switch { + case strings.HasPrefix(flag, "GOOS="): + next.Goos = strings.TrimPrefix(flag, "GOOS=") + case strings.HasPrefix(flag, "GOARCH="): + next.Goarch = strings.TrimPrefix(flag, "GOARCH=") + case flag == "-target" || flag == "--target": + if i+1 == len(flags) { + return fmt.Errorf("apply %s: %s requires a value", flagsFile, flag) + } + i++ + next.Target = flags[i] + case strings.HasPrefix(flag, "-target="): + next.Target = strings.TrimPrefix(flag, "-target=") + case strings.HasPrefix(flag, "--target="): + next.Target = strings.TrimPrefix(flag, "--target=") + default: + goFlags = append(goFlags, flag) + } + } + if err := goflags.ApplyBuildFlags(&next, goFlags); err != nil { return fmt.Errorf("apply %s: %w", flagsFile, err) } + *conf = next return nil } diff --git a/internal/llgen/llgenf_test.go b/internal/llgen/llgenf_test.go index 006e0c5e1e..3dacfd3fb1 100644 --- a/internal/llgen/llgenf_test.go +++ b/internal/llgen/llgenf_test.go @@ -26,22 +26,25 @@ import ( "github.com/goplus/llgo/internal/optlevel" ) -func TestApplyGoBuildFlagsFile(t *testing.T) { +func TestApplyFlagsFile(t *testing.T) { dir := t.TempDir() missing := filepath.Join(dir, "missing.txt") - if err := applyGoBuildFlagsFile(new(build.Config), missing); err != nil { + if err := applyFlagsFile(new(build.Config), missing); err != nil { t.Fatalf("missing flags file: %v", err) } path := filepath.Join(dir, "flags.txt") - data := "--gcflags 'all=-N -l'\n-ldflags=--s --w=false # keep DWARF\n" + data := "GOOS=wasip1 GOARCH=wasm\n-target=wasm\n--gcflags 'all=-N -l'\n-ldflags=--s --w=false # keep DWARF\n" if err := os.WriteFile(path, []byte(data), 0o644); err != nil { t.Fatal(err) } conf := new(build.Config) - if err := applyGoBuildFlagsFile(conf, path); err != nil { + if err := applyFlagsFile(conf, path); err != nil { t.Fatal(err) } + if conf.Goos != "wasip1" || conf.Goarch != "wasm" || conf.Target != "wasm" { + t.Fatalf("target config = %s/%s, target %q", conf.Goos, conf.Goarch, conf.Target) + } if conf.OptLevel != optlevel.O0 { t.Fatalf("OptLevel = %v, want O0", conf.OptLevel) } @@ -50,15 +53,44 @@ func TestApplyGoBuildFlagsFile(t *testing.T) { } } -func TestApplyGoBuildFlagsFileErrorIncludesPath(t *testing.T) { - dir := t.TempDir() - path := filepath.Join(dir, "flags.txt") - data := "-ldflags='unterminated\n" - if err := os.WriteFile(path, []byte(data), 0o644); err != nil { - t.Fatal(err) +func TestApplyFlagsFileErrorIncludesPath(t *testing.T) { + tests := []string{ + "-ldflags='unterminated\n", + "-ldflags=-w=invalid\n", + "-target\n", + } + for _, data := range tests { + t.Run(strings.TrimSpace(data), func(t *testing.T) { + path := filepath.Join(t.TempDir(), "flags.txt") + if err := os.WriteFile(path, []byte(data), 0o644); err != nil { + t.Fatal(err) + } + conf := &build.Config{Target: "original"} + err := applyFlagsFile(conf, path) + if err == nil || !strings.Contains(err.Error(), path) { + t.Fatalf("applyFlagsFile(%q) error = %v, want path", data, err) + } + if conf.Target != "original" { + t.Fatalf("failed application changed target to %q", conf.Target) + } + }) } - err := applyGoBuildFlagsFile(new(build.Config), path) - if err == nil || !strings.Contains(err.Error(), path) { - t.Fatalf("applyGoBuildFlagsFile(%q) error = %v, want path", data, err) +} + +func TestApplyFlagsFileTargetForms(t *testing.T) { + for _, data := range []string{"-target wasi", "--target wasi", "--target=wasi"} { + t.Run(data, func(t *testing.T) { + path := filepath.Join(t.TempDir(), "flags.txt") + if err := os.WriteFile(path, []byte(data), 0o644); err != nil { + t.Fatal(err) + } + conf := new(build.Config) + if err := applyFlagsFile(conf, path); err != nil { + t.Fatal(err) + } + if conf.Target != "wasi" { + t.Fatalf("Target = %q, want wasi", conf.Target) + } + }) } } diff --git a/runtime/internal/runtime/z_rt.go b/runtime/internal/runtime/z_rt.go index fc707c3abe..915905e77a 100644 --- a/runtime/internal/runtime/z_rt.go +++ b/runtime/internal/runtime/z_rt.go @@ -30,8 +30,8 @@ type Defer struct { Addr unsafe.Pointer // sigjmpbuf Bits uintptr Link *Defer - Reth uintptr // continuation selector after Rethrow - Rund uintptr // continuation selector after RunDefers + Reth unsafe.Pointer // native block address or wasm continuation selector + Rund unsafe.Pointer // native block address or wasm continuation selector Args unsafe.Pointer // defer func and args links } diff --git a/ssa/eh.go b/ssa/eh.go index 6931732698..183331ceff 100644 --- a/ssa/eh.go +++ b/ssa/eh.go @@ -147,8 +147,8 @@ type aDefer struct { nextBit int // next defer bit data Expr // pointer to runtime.Defer bitsPtr Expr // pointer to defer bits - rethPtr Expr // Rethrow continuation selector - rundPtr Expr // RunDefers continuation selector + rethPtr Expr // native block address or wasm Rethrow selector + rundPtr Expr // native block address or wasm RunDefers selector argsPtr Expr // func and args links procBlk BasicBlock // deferProc block panicBlk BasicBlock // panic block (runDefers and rethrow) @@ -161,9 +161,9 @@ type aDefer struct { stmts []func(bits Expr, resume deferTarget) } -// deferTarget pairs the integer stored in runtime.Defer with its local block. -// Selectors are dense within each dispatch so LLVM can choose the target's -// preferred switch lowering without exposing block addresses. +// deferTarget pairs a wasm selector with the corresponding local block. +// Native targets store the block address directly; wasm selectors are dense +// within each dispatch so LLVM can lower them efficiently. type deferTarget struct { index int block BasicBlock @@ -184,8 +184,8 @@ const ( // 0: addr sigjmpbuf // 1: bits uintptr // 2: link *Defer - // 3: reth uintptr: continuation selector after Rethrow - // 4: rund uintptr: continuation selector after RunDefers + // 3: reth voidptr: native block address or wasm Rethrow selector + // 4: rund voidptr: native block address or wasm RunDefers selector // 5: func and args links deferSigjmpbuf = iota deferBits @@ -275,15 +275,19 @@ func (b Builder) initDeferState(procBlk, rethrowBlk BasicBlock) (*aDefer, Expr, zero := prog.Val(uintptr(0)) link := b.Call(b.Pkg.rtFunc("GetThreadDefer")) jb := b.AllocaSigjmpBuf() - // Reth selector 0 is reserved for procBlk; Rund selector 0 is rethrowBlk. - ptr := b.aggregateAllocU(prog.Defer(), jb.impl, zero.impl, link.impl, zero.impl) + // Wasm Reth selector 0 is reserved for procBlk; Rund selector 0 is + // rethrowBlk. Native targets store the corresponding block addresses. + initialReth := deferTarget{index: 0, block: procBlk} + ptr := b.aggregateAllocU(prog.Defer(), jb.impl, zero.impl, link.impl, b.deferTargetValue(initialReth).impl) deferData := Expr{ptr, prog.DeferPtr()} b.Call(b.Pkg.rtFunc("SetThreadDefer"), deferData) bitsPtr := b.FieldAddr(deferData, deferBits) rethPtr := b.FieldAddr(deferData, deferRethrow) rundPtr := b.FieldAddr(deferData, deferRunDefers) argsPtr := b.FieldAddr(deferData, deferArgs) - b.Store(rundPtr, zero) + if prog.target.GOARCH == "wasm" { + b.storeDeferTarget(rundPtr, deferTarget{index: 0, block: rethrowBlk}) + } // Initialize the args list so later guards (e.g. DeferAlways/DeferInLoop) // can safely detect an empty chain without a prior push. b.Store(argsPtr, prog.Nil(prog.VoidPtr())) @@ -429,11 +433,6 @@ func (b Builder) loopDeferDrainer(self *aDefer, resume deferTarget) { return } - drainEntry := b.blk - if drainEntry != resume.block { - panic("loop defer resume target does not match the drainer entry") - } - prog := b.Prog condBlk := b.Func.MakeBlock() exitBlk := b.Func.MakeBlock() @@ -580,11 +579,28 @@ func (b Builder) RunDefers() { } func (b Builder) storeDeferTarget(ptr Expr, target deferTarget) { - b.Store(ptr, b.Prog.Val(uintptr(target.index))) + b.Store(ptr, b.deferTargetValue(target)) +} + +func (b Builder) deferTargetValue(target deferTarget) Expr { + if b.Prog.target.GOARCH == "wasm" { + return b.PtrCast(b.Prog.VoidPtr(), b.Prog.Val(uintptr(target.index))) + } + return target.block.Addr() } func (b Builder) jumpDeferTarget(ptr Expr, targets []deferTarget) { - selector := b.Load(ptr) + target := b.Load(ptr) + if b.Prog.target.GOARCH != "wasm" { + blocks := make([]BasicBlock, len(targets)) + for i, target := range targets { + blocks[i] = target.block + } + b.IndirectJump(target, blocks) + return + } + + selector := b.Convert(b.Prog.Uintptr(), target) invalid := b.Func.MakeBlock() sw := b.impl.CreateSwitch(selector.impl, invalid.first, len(targets)) for _, target := range targets { @@ -614,7 +630,6 @@ func (p Function) endDefer(b Builder) { stmts := self.stmts n := len(stmts) - rethChain := make([]deferTarget, n+1) var blks []BasicBlock if n > 1 { blks = p.MakeBlocks(n - 1) @@ -622,21 +637,19 @@ func (p Function) endDefer(b Builder) { // Reth selector 0 must remain procBlk because initDeferState installs it // before the final number of deferred statements is known. Selector 1 is // the terminal rethrow, followed by the intermediate continuation blocks. + // Keep the slice in native continuation order; wasm dispatch uses index. rethTargets := make([]deferTarget, n+1) - rethTargets[0] = deferTarget{index: 0, block: procBlk} if n > 0 { - rethTargets[1] = deferTarget{index: 1, block: rethrowBlk} + rethTargets[0] = deferTarget{index: 1, block: rethrowBlk} for i, blk := range blks { - rethTargets[i+2] = deferTarget{index: i + 2, block: blk} + rethTargets[i+1] = deferTarget{index: i + 2, block: blk} } - rethChain[0] = rethTargets[1] - copy(rethChain[1:], rethTargets[2:]) } - rethChain[n] = rethTargets[0] + rethTargets[n] = deferTarget{index: 0, block: procBlk} for i := n - 1; i >= 0; i-- { - rethNext := rethChain[i] - resume := rethChain[i+1] + rethNext := rethTargets[i] + resume := rethTargets[i+1] b.SetBlockEx(resume.block, AtEnd, true) b.storeDeferTarget(rethPtr, rethNext) stmts[i](b.Load(bitsPtr), resume) diff --git a/ssa/eh_defer_test.go b/ssa/eh_defer_test.go index 04abbed810..88c8364439 100644 --- a/ssa/eh_defer_test.go +++ b/ssa/eh_defer_test.go @@ -157,22 +157,23 @@ func TestConditionalDeferIR(t *testing.T) { } } -func TestDeferContinuationSelectors(t *testing.T) { +func TestDeferContinuationDispatch(t *testing.T) { tests := []struct { name string target *ssa.Target switchWidth string + wasm bool }{ {name: "linux-amd64", target: &ssa.Target{GOOS: "linux", GOARCH: "amd64"}, switchWidth: "i64"}, {name: "darwin-arm64", target: &ssa.Target{GOOS: "darwin", GOARCH: "arm64"}, switchWidth: "i64"}, - {name: "wasip1-wasm", target: &ssa.Target{GOOS: "wasip1", GOARCH: "wasm"}, switchWidth: "i32"}, + {name: "wasip1-wasm", target: &ssa.Target{GOOS: "wasip1", GOARCH: "wasm"}, switchWidth: "i32", wasm: true}, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { prog := ssatest.NewProgram(t, tt.target) for _, field := range []int{3, 4} { - if got := prog.Field(prog.Defer(), field); got != prog.Uintptr() { - t.Fatalf("runtime.Defer field %d type = %v, want uintptr", field, got) + if got := prog.Field(prog.Defer(), field); got != prog.VoidPtr() { + t.Fatalf("runtime.Defer field %d type = %v, want unsafe.Pointer", field, got) } } pkg := prog.NewPackage("foo", "foo") @@ -193,14 +194,26 @@ func TestDeferContinuationSelectors(t *testing.T) { b.EndBuild() ir := pkg.Module().String() - if strings.Contains(ir, "blockaddress") || strings.Contains(ir, "indirectbr") { - t.Fatalf("defer continuations must not expose block addresses:\n%s", ir) - } - if got := strings.Count(ir, "switch "+tt.switchWidth); got != 2 { - t.Fatalf("got %d %s switches, want RunDefers and Rethrow dispatch:\n%s", got, tt.switchWidth, ir) - } - if got := strings.Count(ir, "unreachable"); got < 2 { - t.Fatalf("got %d unreachable defaults, want one per defer dispatch:\n%s", got, ir) + if tt.wasm { + if strings.Contains(ir, "blockaddress") || strings.Contains(ir, "indirectbr") { + t.Fatalf("wasm defer continuations must not expose block addresses:\n%s", ir) + } + if got := strings.Count(ir, "switch "+tt.switchWidth); got != 2 { + t.Fatalf("got %d %s switches, want wasm RunDefers and Rethrow dispatch:\n%s", got, tt.switchWidth, ir) + } + if got := strings.Count(ir, "unreachable"); got < 2 { + t.Fatalf("got %d unreachable defaults, want one per wasm defer dispatch:\n%s", got, ir) + } + } else { + if !strings.Contains(ir, "blockaddress") { + t.Fatalf("native defer continuations must retain block addresses:\n%s", ir) + } + if got := strings.Count(ir, "indirectbr"); got != 2 { + t.Fatalf("got %d indirect branches, want native RunDefers and Rethrow dispatch:\n%s", got, ir) + } + if strings.Contains(ir, "switch "+tt.switchWidth) { + t.Fatalf("native defer continuations must not use selector switches:\n%s", ir) + } } // RunDefers can establish defer state before any defer statement has From bca3c5ce45e36728726e124a729ceb4323c2b2ee Mon Sep 17 00:00:00 2001 From: Li Jie Date: Mon, 3 Aug 2026 21:27:15 +0800 Subject: [PATCH 53/73] build: derive wasm platform from named target --- internal/crosscompile/crosscompile.go | 17 +++++++++++++++-- internal/crosscompile/crosscompile_test.go | 13 +++++++++++++ 2 files changed, 28 insertions(+), 2 deletions(-) diff --git a/internal/crosscompile/crosscompile.go b/internal/crosscompile/crosscompile.go index c017c7e5f4..0798d40e28 100644 --- a/internal/crosscompile/crosscompile.go +++ b/internal/crosscompile/crosscompile.go @@ -718,8 +718,21 @@ func UseTarget(targetName string, level optlevel.Level, ltoMode lto.Mode) (expor // Use extends the original Use function to support target-based configuration // If targetName is provided, it takes precedence over goos/goarch func Use(goos, goarch, targetName string, wasiThreads, forceEspClang bool, level optlevel.Level, ltoMode lto.Mode, goGlobalDCE bool) (export Export, err error) { - if targetName != "" && !strings.HasPrefix(targetName, "wasm") && !strings.HasPrefix(targetName, "wasi") { + if targetName == "" { + return use(goos, goarch, wasiThreads, forceEspClang, level, ltoMode, goGlobalDCE) + } + + config, err := targets.NewDefaultResolver().Resolve(targetName) + if err != nil { + return export, fmt.Errorf("failed to resolve target %s: %w", targetName, err) + } + if config.GOARCH != "wasm" { return UseTarget(targetName, level, ltoMode) } - return use(goos, goarch, wasiThreads, forceEspClang, level, ltoMode, goGlobalDCE) + export, err = use(config.GOOS, config.GOARCH, wasiThreads, forceEspClang, level, ltoMode, goGlobalDCE) + if err == nil { + export.GOOS = config.GOOS + export.GOARCH = config.GOARCH + } + return } diff --git a/internal/crosscompile/crosscompile_test.go b/internal/crosscompile/crosscompile_test.go index ea89a9596a..801533ef4c 100644 --- a/internal/crosscompile/crosscompile_test.go +++ b/internal/crosscompile/crosscompile_test.go @@ -333,6 +333,19 @@ func TestUseWithTarget(t *testing.T) { t.Errorf("Expected CPU generic in CCFLAGS, got %v", export.CCFLAGS) } + // Named WebAssembly targets use the GOOS/GOARCH from their target configuration + // with the standard WebAssembly toolchain setup. + export, err = Use("linux", "amd64", "wasm", false, false, optlevel.O2, lto.Off, false) + if err != nil { + t.Fatalf("Use(wasm) failed: %v", err) + } + if export.GOOS != "js" || export.GOARCH != "wasm" { + t.Fatalf("wasm target platform = %s/%s, want js/wasm", export.GOOS, export.GOARCH) + } + if !hasFlagValue(export.CCFLAGS, "-target", "wasm32-unknown-emscripten") { + t.Fatalf("wasm target CCFLAGS = %v, want emscripten target", export.CCFLAGS) + } + // Test fallback to goos/goarch when no target specified export, err = Use(runtime.GOOS, runtime.GOARCH, "", false, false, optlevel.O2, lto.Thin, false) if err != nil { From 09b8b9521d5421c737a98b2e67d419f335a56c2b Mon Sep 17 00:00:00 2001 From: Li Jie Date: Mon, 3 Aug 2026 21:27:30 +0800 Subject: [PATCH 54/73] test: generate complete defer dispatch checks --- chore/litgen/litgen_test.go | 37 +++++ .../deferdispatch-wasm-target/flags.txt | 2 - cl/_testgo/deferdispatch-wasm-target/in.go | 152 +++++++++++++++++- cl/_testgo/deferdispatch-wasm/in.go | 152 +++++++++++++++++- cl/_testgo/deferdispatch/flags.txt | 1 + cl/_testgo/deferdispatch/in.go | 133 ++++++++++++++- 6 files changed, 454 insertions(+), 23 deletions(-) create mode 100644 cl/_testgo/deferdispatch/flags.txt diff --git a/chore/litgen/litgen_test.go b/chore/litgen/litgen_test.go index 86f5a1a6a6..75d9cd41e7 100644 --- a/chore/litgen/litgen_test.go +++ b/chore/litgen/litgen_test.go @@ -47,3 +47,40 @@ func TestProcessPath_SingleFileUsesContainingDir(t *testing.T) { t.Fatalf("single-file mode did not include the containing package:\n%s", text) } } + +func TestProcessPath_UsesFlagsFileTarget(t *testing.T) { + wd, err := os.Getwd() + if err != nil { + t.Fatal(err) + } + pkgDir, err := os.MkdirTemp(wd, "flags-target-") + if err != nil { + t.Fatal(err) + } + t.Cleanup(func() { + _ = os.RemoveAll(pkgDir) + }) + sourceFile := filepath.Join(pkgDir, "in.go") + if err := os.WriteFile(sourceFile, []byte("// LITTEST\npackage main\n\nfunc main() { defer func() {}() }\n"), 0644); err != nil { + t.Fatal(err) + } + if err := os.WriteFile(filepath.Join(pkgDir, "flags.txt"), []byte("-target=wasm\n"), 0644); err != nil { + t.Fatal(err) + } + + if err := processPath(sourceFile); err != nil { + t.Fatal(err) + } + + data, err := os.ReadFile(sourceFile) + if err != nil { + t.Fatal(err) + } + text := string(data) + if !strings.Contains(text, "// CHECK-NEXT: switch i32") { + t.Fatalf("litgen did not use the wasm target from flags.txt:\n%s", text) + } + if strings.Contains(text, "blockaddress") || strings.Contains(text, "indirectbr") { + t.Fatalf("litgen generated native defer dispatch for a wasm target:\n%s", text) + } +} diff --git a/cl/_testgo/deferdispatch-wasm-target/flags.txt b/cl/_testgo/deferdispatch-wasm-target/flags.txt index c140566ce8..5b6acc668a 100644 --- a/cl/_testgo/deferdispatch-wasm-target/flags.txt +++ b/cl/_testgo/deferdispatch-wasm-target/flags.txt @@ -1,3 +1 @@ -# Wasm named targets currently use GOOS/GOARCH for toolchain selection. -GOOS=js GOARCH=wasm -target=wasm diff --git a/cl/_testgo/deferdispatch-wasm-target/in.go b/cl/_testgo/deferdispatch-wasm-target/in.go index ea22c1f291..fa31f1a8d5 100644 --- a/cl/_testgo/deferdispatch-wasm-target/in.go +++ b/cl/_testgo/deferdispatch-wasm-target/in.go @@ -1,6 +1,9 @@ // LITTEST package main +// CHECK: {{^}}@0 = private unnamed_addr constant [5 x i8] c"first", align 1{{$}} +// CHECK: {{^}}@1 = private unnamed_addr constant [6 x i8] c"second", align 1{{$}} + func run() { defer println("first") defer println("second") @@ -10,11 +13,144 @@ func main() { run() } -// CHECK-LABEL: define void @main.run() -// CHECK-NOT: blockaddress -// CHECK: switch i32 -// CHECK-NOT: blockaddress -// CHECK: switch i32 -// CHECK-NOT: blockaddress -// CHECK-NOT: indirectbr -// CHECK: } +// CHECK-LABEL: define void @main.init(){{.*}} { +// CHECK-NEXT: _llgo_0: +// CHECK-NEXT: %0 = load i1, ptr @"main.init$guard", align 1 +// CHECK-NEXT: br i1 %0, label %_llgo_2, label %_llgo_1 +// CHECK-EMPTY: +// CHECK-NEXT: _llgo_1: ; preds = %_llgo_0 +// CHECK-NEXT: store i1 true, ptr @"main.init$guard", align 1 +// CHECK-NEXT: br label %_llgo_2 +// CHECK-EMPTY: +// CHECK-NEXT: _llgo_2: ; preds = %_llgo_1, %_llgo_0 +// CHECK-NEXT: ret void +// CHECK-NEXT: } + +// CHECK-LABEL: define void @main.main(){{.*}} { +// CHECK-NEXT: _llgo_0: +// CHECK-NEXT: call void @main.run() +// CHECK-NEXT: ret void +// CHECK-NEXT: } + +// CHECK-LABEL: define void @main.run(){{.*}} { +// CHECK-NEXT: _llgo_0: +// CHECK-NEXT: %0 = call ptr @"{{.*}}/runtime/internal/runtime.GetThreadDefer"() +// CHECK-NEXT: %1 = alloca i8, i32 200, align 1 +// CHECK-NEXT: %2 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i32 24) +// CHECK-NEXT: %3 = getelementptr inbounds %"{{.*}}/runtime/internal/runtime.Defer", ptr %2, i32 0, i32 0 +// CHECK-NEXT: store ptr %1, ptr %3, align 4 +// CHECK-NEXT: %4 = getelementptr inbounds %"{{.*}}/runtime/internal/runtime.Defer", ptr %2, i32 0, i32 1 +// CHECK-NEXT: store i32 0, ptr %4, align 4 +// CHECK-NEXT: %5 = getelementptr inbounds %"{{.*}}/runtime/internal/runtime.Defer", ptr %2, i32 0, i32 2 +// CHECK-NEXT: store ptr %0, ptr %5, align 4 +// CHECK-NEXT: %6 = getelementptr inbounds %"{{.*}}/runtime/internal/runtime.Defer", ptr %2, i32 0, i32 3 +// CHECK-NEXT: store ptr null, ptr %6, align 4 +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.SetThreadDefer"(ptr %2) +// CHECK-NEXT: %7 = getelementptr inbounds %"{{.*}}/runtime/internal/runtime.Defer", ptr %2, i32 0, i32 1 +// CHECK-NEXT: %8 = getelementptr inbounds %"{{.*}}/runtime/internal/runtime.Defer", ptr %2, i32 0, i32 3 +// CHECK-NEXT: %9 = getelementptr inbounds %"{{.*}}/runtime/internal/runtime.Defer", ptr %2, i32 0, i32 4 +// CHECK-NEXT: %10 = getelementptr inbounds %"{{.*}}/runtime/internal/runtime.Defer", ptr %2, i32 0, i32 5 +// CHECK-NEXT: store ptr null, ptr %9, align 4 +// CHECK-NEXT: store ptr null, ptr %10, align 4 +// CHECK-NEXT: %11 = call i32 @setjmp(ptr %1) +// CHECK-NEXT: %12 = icmp eq i32 %11, 0 +// CHECK-NEXT: br i1 %12, label %_llgo_4, label %_llgo_5 +// CHECK-EMPTY: +// CHECK-NEXT: _llgo_1: ; preds = %_llgo_3 +// CHECK-NEXT: ret void +// CHECK-EMPTY: +// CHECK-NEXT: _llgo_2: ; preds = %_llgo_5, %_llgo_4 +// CHECK-NEXT: store ptr inttoptr (i32 2 to ptr), ptr %8, align 4 +// CHECK-NEXT: %13 = load i32, ptr %7, align 4 +// CHECK-NEXT: %14 = load ptr, ptr %10, align 4 +// CHECK-NEXT: %15 = icmp ne ptr %14, null +// CHECK-NEXT: br i1 %15, label %_llgo_8, label %_llgo_9 +// CHECK-EMPTY: +// CHECK-NEXT: _llgo_3: ; preds = %_llgo_5, %_llgo_11 +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.Rethrow"(ptr %0) +// CHECK-NEXT: br label %_llgo_1 +// CHECK-EMPTY: +// CHECK-NEXT: _llgo_4: ; preds = %_llgo_0 +// CHECK-NEXT: %16 = load ptr, ptr %10, align 4 +// CHECK-NEXT: %17 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i32 16) +// CHECK-NEXT: %18 = getelementptr inbounds { ptr, i32, %"{{.*}}/runtime/internal/runtime.String" }, ptr %17, i32 0, i32 0 +// CHECK-NEXT: store ptr %16, ptr %18, align 4 +// CHECK-NEXT: %19 = getelementptr inbounds { ptr, i32, %"{{.*}}/runtime/internal/runtime.String" }, ptr %17, i32 0, i32 1 +// CHECK-NEXT: store i32 0, ptr %19, align 4 +// CHECK-NEXT: %20 = getelementptr inbounds { ptr, i32, %"{{.*}}/runtime/internal/runtime.String" }, ptr %17, i32 0, i32 2 +// CHECK-NEXT: store %"{{.*}}/runtime/internal/runtime.String" { ptr @0, i32 5 }, ptr %20, align 4 +// CHECK-NEXT: store ptr %17, ptr %10, align 4 +// CHECK-NEXT: %21 = load ptr, ptr %10, align 4 +// CHECK-NEXT: %22 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i32 16) +// CHECK-NEXT: %23 = getelementptr inbounds { ptr, i32, %"{{.*}}/runtime/internal/runtime.String" }, ptr %22, i32 0, i32 0 +// CHECK-NEXT: store ptr %21, ptr %23, align 4 +// CHECK-NEXT: %24 = getelementptr inbounds { ptr, i32, %"{{.*}}/runtime/internal/runtime.String" }, ptr %22, i32 0, i32 1 +// CHECK-NEXT: store i32 1, ptr %24, align 4 +// CHECK-NEXT: %25 = getelementptr inbounds { ptr, i32, %"{{.*}}/runtime/internal/runtime.String" }, ptr %22, i32 0, i32 2 +// CHECK-NEXT: store %"{{.*}}/runtime/internal/runtime.String" { ptr @1, i32 6 }, ptr %25, align 4 +// CHECK-NEXT: store ptr %22, ptr %10, align 4 +// CHECK-NEXT: store ptr inttoptr (i32 1 to ptr), ptr %9, align 4 +// CHECK-NEXT: br label %_llgo_2 +// CHECK-EMPTY: +// CHECK-NEXT: _llgo_5: ; preds = %_llgo_0 +// CHECK-NEXT: store ptr null, ptr %9, align 4 +// CHECK-NEXT: %26 = load ptr, ptr %8, align 4 +// CHECK-NEXT: %27 = ptrtoint ptr %26 to i32 +// CHECK-NEXT: switch i32 %27, label %_llgo_13 [ +// CHECK-NEXT: i32 1, label %_llgo_3 +// CHECK-NEXT: i32 2, label %_llgo_7 +// CHECK-NEXT: i32 0, label %_llgo_2 +// CHECK-NEXT: ] +// CHECK-EMPTY: +// CHECK-NEXT: _llgo_6: ; preds = %_llgo_11 +// CHECK-NEXT: ret void +// CHECK-EMPTY: +// CHECK-NEXT: _llgo_7: ; preds = %_llgo_5, %_llgo_9 +// CHECK-NEXT: store ptr inttoptr (i32 1 to ptr), ptr %8, align 4 +// CHECK-NEXT: %28 = load i32, ptr %7, align 4 +// CHECK-NEXT: %29 = load ptr, ptr %10, align 4 +// CHECK-NEXT: %30 = icmp ne ptr %29, null +// CHECK-NEXT: br i1 %30, label %_llgo_10, label %_llgo_11 +// CHECK-EMPTY: +// CHECK-NEXT: _llgo_8: ; preds = %_llgo_2 +// CHECK-NEXT: %31 = load ptr, ptr %10, align 4 +// CHECK-NEXT: %32 = load { ptr, i32, %"{{.*}}/runtime/internal/runtime.String" }, ptr %31, align 4 +// CHECK-NEXT: %33 = extractvalue { ptr, i32, %"{{.*}}/runtime/internal/runtime.String" } %32, 0 +// CHECK-NEXT: store ptr %33, ptr %10, align 4 +// CHECK-NEXT: %34 = extractvalue { ptr, i32, %"{{.*}}/runtime/internal/runtime.String" } %32, 2 +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.FreeDeferNode"(ptr %31) +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.PrintString"(%"{{.*}}/runtime/internal/runtime.String" %34) +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.PrintByte"(i8 10) +// CHECK-NEXT: br label %_llgo_9 +// CHECK-EMPTY: +// CHECK-NEXT: _llgo_9: ; preds = %_llgo_8, %_llgo_2 +// CHECK-NEXT: br label %_llgo_7 +// CHECK-EMPTY: +// CHECK-NEXT: _llgo_10: ; preds = %_llgo_7 +// CHECK-NEXT: %35 = load ptr, ptr %10, align 4 +// CHECK-NEXT: %36 = load { ptr, i32, %"{{.*}}/runtime/internal/runtime.String" }, ptr %35, align 4 +// CHECK-NEXT: %37 = extractvalue { ptr, i32, %"{{.*}}/runtime/internal/runtime.String" } %36, 0 +// CHECK-NEXT: store ptr %37, ptr %10, align 4 +// CHECK-NEXT: %38 = extractvalue { ptr, i32, %"{{.*}}/runtime/internal/runtime.String" } %36, 2 +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.FreeDeferNode"(ptr %35) +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.PrintString"(%"{{.*}}/runtime/internal/runtime.String" %38) +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.PrintByte"(i8 10) +// CHECK-NEXT: br label %_llgo_11 +// CHECK-EMPTY: +// CHECK-NEXT: _llgo_11: ; preds = %_llgo_10, %_llgo_7 +// CHECK-NEXT: %39 = load %"{{.*}}/runtime/internal/runtime.Defer", ptr %2, align 4 +// CHECK-NEXT: %40 = extractvalue %"{{.*}}/runtime/internal/runtime.Defer" %39, 2 +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.SetThreadDefer"(ptr %40) +// CHECK-NEXT: %41 = load ptr, ptr %9, align 4 +// CHECK-NEXT: %42 = ptrtoint ptr %41 to i32 +// CHECK-NEXT: switch i32 %42, label %_llgo_12 [ +// CHECK-NEXT: i32 0, label %_llgo_3 +// CHECK-NEXT: i32 1, label %_llgo_6 +// CHECK-NEXT: ] +// CHECK-EMPTY: +// CHECK-NEXT: _llgo_12: ; preds = %_llgo_11 +// CHECK-NEXT: unreachable +// CHECK-EMPTY: +// CHECK-NEXT: _llgo_13: ; preds = %_llgo_5 +// CHECK-NEXT: unreachable +// CHECK-NEXT: } diff --git a/cl/_testgo/deferdispatch-wasm/in.go b/cl/_testgo/deferdispatch-wasm/in.go index ea22c1f291..fa31f1a8d5 100644 --- a/cl/_testgo/deferdispatch-wasm/in.go +++ b/cl/_testgo/deferdispatch-wasm/in.go @@ -1,6 +1,9 @@ // LITTEST package main +// CHECK: {{^}}@0 = private unnamed_addr constant [5 x i8] c"first", align 1{{$}} +// CHECK: {{^}}@1 = private unnamed_addr constant [6 x i8] c"second", align 1{{$}} + func run() { defer println("first") defer println("second") @@ -10,11 +13,144 @@ func main() { run() } -// CHECK-LABEL: define void @main.run() -// CHECK-NOT: blockaddress -// CHECK: switch i32 -// CHECK-NOT: blockaddress -// CHECK: switch i32 -// CHECK-NOT: blockaddress -// CHECK-NOT: indirectbr -// CHECK: } +// CHECK-LABEL: define void @main.init(){{.*}} { +// CHECK-NEXT: _llgo_0: +// CHECK-NEXT: %0 = load i1, ptr @"main.init$guard", align 1 +// CHECK-NEXT: br i1 %0, label %_llgo_2, label %_llgo_1 +// CHECK-EMPTY: +// CHECK-NEXT: _llgo_1: ; preds = %_llgo_0 +// CHECK-NEXT: store i1 true, ptr @"main.init$guard", align 1 +// CHECK-NEXT: br label %_llgo_2 +// CHECK-EMPTY: +// CHECK-NEXT: _llgo_2: ; preds = %_llgo_1, %_llgo_0 +// CHECK-NEXT: ret void +// CHECK-NEXT: } + +// CHECK-LABEL: define void @main.main(){{.*}} { +// CHECK-NEXT: _llgo_0: +// CHECK-NEXT: call void @main.run() +// CHECK-NEXT: ret void +// CHECK-NEXT: } + +// CHECK-LABEL: define void @main.run(){{.*}} { +// CHECK-NEXT: _llgo_0: +// CHECK-NEXT: %0 = call ptr @"{{.*}}/runtime/internal/runtime.GetThreadDefer"() +// CHECK-NEXT: %1 = alloca i8, i32 200, align 1 +// CHECK-NEXT: %2 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i32 24) +// CHECK-NEXT: %3 = getelementptr inbounds %"{{.*}}/runtime/internal/runtime.Defer", ptr %2, i32 0, i32 0 +// CHECK-NEXT: store ptr %1, ptr %3, align 4 +// CHECK-NEXT: %4 = getelementptr inbounds %"{{.*}}/runtime/internal/runtime.Defer", ptr %2, i32 0, i32 1 +// CHECK-NEXT: store i32 0, ptr %4, align 4 +// CHECK-NEXT: %5 = getelementptr inbounds %"{{.*}}/runtime/internal/runtime.Defer", ptr %2, i32 0, i32 2 +// CHECK-NEXT: store ptr %0, ptr %5, align 4 +// CHECK-NEXT: %6 = getelementptr inbounds %"{{.*}}/runtime/internal/runtime.Defer", ptr %2, i32 0, i32 3 +// CHECK-NEXT: store ptr null, ptr %6, align 4 +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.SetThreadDefer"(ptr %2) +// CHECK-NEXT: %7 = getelementptr inbounds %"{{.*}}/runtime/internal/runtime.Defer", ptr %2, i32 0, i32 1 +// CHECK-NEXT: %8 = getelementptr inbounds %"{{.*}}/runtime/internal/runtime.Defer", ptr %2, i32 0, i32 3 +// CHECK-NEXT: %9 = getelementptr inbounds %"{{.*}}/runtime/internal/runtime.Defer", ptr %2, i32 0, i32 4 +// CHECK-NEXT: %10 = getelementptr inbounds %"{{.*}}/runtime/internal/runtime.Defer", ptr %2, i32 0, i32 5 +// CHECK-NEXT: store ptr null, ptr %9, align 4 +// CHECK-NEXT: store ptr null, ptr %10, align 4 +// CHECK-NEXT: %11 = call i32 @setjmp(ptr %1) +// CHECK-NEXT: %12 = icmp eq i32 %11, 0 +// CHECK-NEXT: br i1 %12, label %_llgo_4, label %_llgo_5 +// CHECK-EMPTY: +// CHECK-NEXT: _llgo_1: ; preds = %_llgo_3 +// CHECK-NEXT: ret void +// CHECK-EMPTY: +// CHECK-NEXT: _llgo_2: ; preds = %_llgo_5, %_llgo_4 +// CHECK-NEXT: store ptr inttoptr (i32 2 to ptr), ptr %8, align 4 +// CHECK-NEXT: %13 = load i32, ptr %7, align 4 +// CHECK-NEXT: %14 = load ptr, ptr %10, align 4 +// CHECK-NEXT: %15 = icmp ne ptr %14, null +// CHECK-NEXT: br i1 %15, label %_llgo_8, label %_llgo_9 +// CHECK-EMPTY: +// CHECK-NEXT: _llgo_3: ; preds = %_llgo_5, %_llgo_11 +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.Rethrow"(ptr %0) +// CHECK-NEXT: br label %_llgo_1 +// CHECK-EMPTY: +// CHECK-NEXT: _llgo_4: ; preds = %_llgo_0 +// CHECK-NEXT: %16 = load ptr, ptr %10, align 4 +// CHECK-NEXT: %17 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i32 16) +// CHECK-NEXT: %18 = getelementptr inbounds { ptr, i32, %"{{.*}}/runtime/internal/runtime.String" }, ptr %17, i32 0, i32 0 +// CHECK-NEXT: store ptr %16, ptr %18, align 4 +// CHECK-NEXT: %19 = getelementptr inbounds { ptr, i32, %"{{.*}}/runtime/internal/runtime.String" }, ptr %17, i32 0, i32 1 +// CHECK-NEXT: store i32 0, ptr %19, align 4 +// CHECK-NEXT: %20 = getelementptr inbounds { ptr, i32, %"{{.*}}/runtime/internal/runtime.String" }, ptr %17, i32 0, i32 2 +// CHECK-NEXT: store %"{{.*}}/runtime/internal/runtime.String" { ptr @0, i32 5 }, ptr %20, align 4 +// CHECK-NEXT: store ptr %17, ptr %10, align 4 +// CHECK-NEXT: %21 = load ptr, ptr %10, align 4 +// CHECK-NEXT: %22 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i32 16) +// CHECK-NEXT: %23 = getelementptr inbounds { ptr, i32, %"{{.*}}/runtime/internal/runtime.String" }, ptr %22, i32 0, i32 0 +// CHECK-NEXT: store ptr %21, ptr %23, align 4 +// CHECK-NEXT: %24 = getelementptr inbounds { ptr, i32, %"{{.*}}/runtime/internal/runtime.String" }, ptr %22, i32 0, i32 1 +// CHECK-NEXT: store i32 1, ptr %24, align 4 +// CHECK-NEXT: %25 = getelementptr inbounds { ptr, i32, %"{{.*}}/runtime/internal/runtime.String" }, ptr %22, i32 0, i32 2 +// CHECK-NEXT: store %"{{.*}}/runtime/internal/runtime.String" { ptr @1, i32 6 }, ptr %25, align 4 +// CHECK-NEXT: store ptr %22, ptr %10, align 4 +// CHECK-NEXT: store ptr inttoptr (i32 1 to ptr), ptr %9, align 4 +// CHECK-NEXT: br label %_llgo_2 +// CHECK-EMPTY: +// CHECK-NEXT: _llgo_5: ; preds = %_llgo_0 +// CHECK-NEXT: store ptr null, ptr %9, align 4 +// CHECK-NEXT: %26 = load ptr, ptr %8, align 4 +// CHECK-NEXT: %27 = ptrtoint ptr %26 to i32 +// CHECK-NEXT: switch i32 %27, label %_llgo_13 [ +// CHECK-NEXT: i32 1, label %_llgo_3 +// CHECK-NEXT: i32 2, label %_llgo_7 +// CHECK-NEXT: i32 0, label %_llgo_2 +// CHECK-NEXT: ] +// CHECK-EMPTY: +// CHECK-NEXT: _llgo_6: ; preds = %_llgo_11 +// CHECK-NEXT: ret void +// CHECK-EMPTY: +// CHECK-NEXT: _llgo_7: ; preds = %_llgo_5, %_llgo_9 +// CHECK-NEXT: store ptr inttoptr (i32 1 to ptr), ptr %8, align 4 +// CHECK-NEXT: %28 = load i32, ptr %7, align 4 +// CHECK-NEXT: %29 = load ptr, ptr %10, align 4 +// CHECK-NEXT: %30 = icmp ne ptr %29, null +// CHECK-NEXT: br i1 %30, label %_llgo_10, label %_llgo_11 +// CHECK-EMPTY: +// CHECK-NEXT: _llgo_8: ; preds = %_llgo_2 +// CHECK-NEXT: %31 = load ptr, ptr %10, align 4 +// CHECK-NEXT: %32 = load { ptr, i32, %"{{.*}}/runtime/internal/runtime.String" }, ptr %31, align 4 +// CHECK-NEXT: %33 = extractvalue { ptr, i32, %"{{.*}}/runtime/internal/runtime.String" } %32, 0 +// CHECK-NEXT: store ptr %33, ptr %10, align 4 +// CHECK-NEXT: %34 = extractvalue { ptr, i32, %"{{.*}}/runtime/internal/runtime.String" } %32, 2 +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.FreeDeferNode"(ptr %31) +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.PrintString"(%"{{.*}}/runtime/internal/runtime.String" %34) +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.PrintByte"(i8 10) +// CHECK-NEXT: br label %_llgo_9 +// CHECK-EMPTY: +// CHECK-NEXT: _llgo_9: ; preds = %_llgo_8, %_llgo_2 +// CHECK-NEXT: br label %_llgo_7 +// CHECK-EMPTY: +// CHECK-NEXT: _llgo_10: ; preds = %_llgo_7 +// CHECK-NEXT: %35 = load ptr, ptr %10, align 4 +// CHECK-NEXT: %36 = load { ptr, i32, %"{{.*}}/runtime/internal/runtime.String" }, ptr %35, align 4 +// CHECK-NEXT: %37 = extractvalue { ptr, i32, %"{{.*}}/runtime/internal/runtime.String" } %36, 0 +// CHECK-NEXT: store ptr %37, ptr %10, align 4 +// CHECK-NEXT: %38 = extractvalue { ptr, i32, %"{{.*}}/runtime/internal/runtime.String" } %36, 2 +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.FreeDeferNode"(ptr %35) +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.PrintString"(%"{{.*}}/runtime/internal/runtime.String" %38) +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.PrintByte"(i8 10) +// CHECK-NEXT: br label %_llgo_11 +// CHECK-EMPTY: +// CHECK-NEXT: _llgo_11: ; preds = %_llgo_10, %_llgo_7 +// CHECK-NEXT: %39 = load %"{{.*}}/runtime/internal/runtime.Defer", ptr %2, align 4 +// CHECK-NEXT: %40 = extractvalue %"{{.*}}/runtime/internal/runtime.Defer" %39, 2 +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.SetThreadDefer"(ptr %40) +// CHECK-NEXT: %41 = load ptr, ptr %9, align 4 +// CHECK-NEXT: %42 = ptrtoint ptr %41 to i32 +// CHECK-NEXT: switch i32 %42, label %_llgo_12 [ +// CHECK-NEXT: i32 0, label %_llgo_3 +// CHECK-NEXT: i32 1, label %_llgo_6 +// CHECK-NEXT: ] +// CHECK-EMPTY: +// CHECK-NEXT: _llgo_12: ; preds = %_llgo_11 +// CHECK-NEXT: unreachable +// CHECK-EMPTY: +// CHECK-NEXT: _llgo_13: ; preds = %_llgo_5 +// CHECK-NEXT: unreachable +// CHECK-NEXT: } diff --git a/cl/_testgo/deferdispatch/flags.txt b/cl/_testgo/deferdispatch/flags.txt new file mode 100644 index 0000000000..da594133f1 --- /dev/null +++ b/cl/_testgo/deferdispatch/flags.txt @@ -0,0 +1 @@ +GOOS=linux GOARCH=amd64 diff --git a/cl/_testgo/deferdispatch/in.go b/cl/_testgo/deferdispatch/in.go index a3a4a2050c..985b00eb16 100644 --- a/cl/_testgo/deferdispatch/in.go +++ b/cl/_testgo/deferdispatch/in.go @@ -1,6 +1,9 @@ // LITTEST package main +// CHECK: {{^}}@0 = private unnamed_addr constant [5 x i8] c"first", align 1{{$}} +// CHECK: {{^}}@1 = private unnamed_addr constant [6 x i8] c"second", align 1{{$}} + func run() { defer println("first") defer println("second") @@ -10,8 +13,128 @@ func main() { run() } -// CHECK-LABEL: define void @main.run() -// CHECK: blockaddress -// CHECK: indirectbr ptr -// CHECK: indirectbr ptr -// CHECK: } +// CHECK-LABEL: define void @main.init(){{.*}} { +// CHECK-NEXT: _llgo_0: +// CHECK-NEXT: %0 = load i1, ptr @"main.init$guard", align 1 +// CHECK-NEXT: br i1 %0, label %_llgo_2, label %_llgo_1 +// CHECK-EMPTY: +// CHECK-NEXT: _llgo_1: ; preds = %_llgo_0 +// CHECK-NEXT: store i1 true, ptr @"main.init$guard", align 1 +// CHECK-NEXT: br label %_llgo_2 +// CHECK-EMPTY: +// CHECK-NEXT: _llgo_2: ; preds = %_llgo_1, %_llgo_0 +// CHECK-NEXT: ret void +// CHECK-NEXT: } + +// CHECK-LABEL: define void @main.main(){{.*}} { +// CHECK-NEXT: _llgo_0: +// CHECK-NEXT: call void @main.run() +// CHECK-NEXT: ret void +// CHECK-NEXT: } + +// CHECK-LABEL: define void @main.run(){{.*}} { +// CHECK-NEXT: _llgo_0: +// CHECK-NEXT: %0 = call ptr @"{{.*}}/runtime/internal/runtime.GetThreadDefer"() +// CHECK-NEXT: %1 = alloca i8, i64 200, align 1 +// CHECK-NEXT: %2 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 48) +// CHECK-NEXT: %3 = getelementptr inbounds %"{{.*}}/runtime/internal/runtime.Defer", ptr %2, i32 0, i32 0 +// CHECK-NEXT: store ptr %1, ptr %3, align 8 +// CHECK-NEXT: %4 = getelementptr inbounds %"{{.*}}/runtime/internal/runtime.Defer", ptr %2, i32 0, i32 1 +// CHECK-NEXT: store i64 0, ptr %4, align 8 +// CHECK-NEXT: %5 = getelementptr inbounds %"{{.*}}/runtime/internal/runtime.Defer", ptr %2, i32 0, i32 2 +// CHECK-NEXT: store ptr %0, ptr %5, align 8 +// CHECK-NEXT: %6 = getelementptr inbounds %"{{.*}}/runtime/internal/runtime.Defer", ptr %2, i32 0, i32 3 +// CHECK-NEXT: store ptr blockaddress(@main.run, %_llgo_2), ptr %6, align 8 +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.SetThreadDefer"(ptr %2) +// CHECK-NEXT: %7 = getelementptr inbounds %"{{.*}}/runtime/internal/runtime.Defer", ptr %2, i32 0, i32 1 +// CHECK-NEXT: %8 = getelementptr inbounds %"{{.*}}/runtime/internal/runtime.Defer", ptr %2, i32 0, i32 3 +// CHECK-NEXT: %9 = getelementptr inbounds %"{{.*}}/runtime/internal/runtime.Defer", ptr %2, i32 0, i32 4 +// CHECK-NEXT: %10 = getelementptr inbounds %"{{.*}}/runtime/internal/runtime.Defer", ptr %2, i32 0, i32 5 +// CHECK-NEXT: store ptr null, ptr %10, align 8 +// CHECK-NEXT: %11 = call i32 @__sigsetjmp(ptr %1, i32 0) +// CHECK-NEXT: %12 = icmp eq i32 %11, 0 +// CHECK-NEXT: br i1 %12, label %_llgo_4, label %_llgo_5 +// CHECK-EMPTY: +// CHECK-NEXT: _llgo_1: ; preds = %_llgo_3 +// CHECK-NEXT: ret void +// CHECK-EMPTY: +// CHECK-NEXT: _llgo_2: ; preds = %_llgo_5, %_llgo_4 +// CHECK-NEXT: store ptr blockaddress(@main.run, %_llgo_7), ptr %8, align 8 +// CHECK-NEXT: %13 = load i64, ptr %7, align 8 +// CHECK-NEXT: %14 = load ptr, ptr %10, align 8 +// CHECK-NEXT: %15 = icmp ne ptr %14, null +// CHECK-NEXT: br i1 %15, label %_llgo_8, label %_llgo_9 +// CHECK-EMPTY: +// CHECK-NEXT: _llgo_3: ; preds = %_llgo_5, %_llgo_11 +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.Rethrow"(ptr %0) +// CHECK-NEXT: br label %_llgo_1 +// CHECK-EMPTY: +// CHECK-NEXT: _llgo_4: ; preds = %_llgo_0 +// CHECK-NEXT: %16 = load ptr, ptr %10, align 8 +// CHECK-NEXT: %17 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 32) +// CHECK-NEXT: %18 = getelementptr inbounds { ptr, i64, %"{{.*}}/runtime/internal/runtime.String" }, ptr %17, i32 0, i32 0 +// CHECK-NEXT: store ptr %16, ptr %18, align 8 +// CHECK-NEXT: %19 = getelementptr inbounds { ptr, i64, %"{{.*}}/runtime/internal/runtime.String" }, ptr %17, i32 0, i32 1 +// CHECK-NEXT: store i64 0, ptr %19, align 8 +// CHECK-NEXT: %20 = getelementptr inbounds { ptr, i64, %"{{.*}}/runtime/internal/runtime.String" }, ptr %17, i32 0, i32 2 +// CHECK-NEXT: store %"{{.*}}/runtime/internal/runtime.String" { ptr @0, i64 5 }, ptr %20, align 8 +// CHECK-NEXT: store ptr %17, ptr %10, align 8 +// CHECK-NEXT: %21 = load ptr, ptr %10, align 8 +// CHECK-NEXT: %22 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 32) +// CHECK-NEXT: %23 = getelementptr inbounds { ptr, i64, %"{{.*}}/runtime/internal/runtime.String" }, ptr %22, i32 0, i32 0 +// CHECK-NEXT: store ptr %21, ptr %23, align 8 +// CHECK-NEXT: %24 = getelementptr inbounds { ptr, i64, %"{{.*}}/runtime/internal/runtime.String" }, ptr %22, i32 0, i32 1 +// CHECK-NEXT: store i64 1, ptr %24, align 8 +// CHECK-NEXT: %25 = getelementptr inbounds { ptr, i64, %"{{.*}}/runtime/internal/runtime.String" }, ptr %22, i32 0, i32 2 +// CHECK-NEXT: store %"{{.*}}/runtime/internal/runtime.String" { ptr @1, i64 6 }, ptr %25, align 8 +// CHECK-NEXT: store ptr %22, ptr %10, align 8 +// CHECK-NEXT: store ptr blockaddress(@main.run, %_llgo_6), ptr %9, align 8 +// CHECK-NEXT: br label %_llgo_2 +// CHECK-EMPTY: +// CHECK-NEXT: _llgo_5: ; preds = %_llgo_0 +// CHECK-NEXT: store ptr blockaddress(@main.run, %_llgo_3), ptr %9, align 8 +// CHECK-NEXT: %26 = load ptr, ptr %8, align 8 +// CHECK-NEXT: indirectbr ptr %26, [label %_llgo_3, label %_llgo_7, label %_llgo_2] +// CHECK-EMPTY: +// CHECK-NEXT: _llgo_6: ; preds = %_llgo_11 +// CHECK-NEXT: ret void +// CHECK-EMPTY: +// CHECK-NEXT: _llgo_7: ; preds = %_llgo_5, %_llgo_9 +// CHECK-NEXT: store ptr blockaddress(@main.run, %_llgo_3), ptr %8, align 8 +// CHECK-NEXT: %27 = load i64, ptr %7, align 8 +// CHECK-NEXT: %28 = load ptr, ptr %10, align 8 +// CHECK-NEXT: %29 = icmp ne ptr %28, null +// CHECK-NEXT: br i1 %29, label %_llgo_10, label %_llgo_11 +// CHECK-EMPTY: +// CHECK-NEXT: _llgo_8: ; preds = %_llgo_2 +// CHECK-NEXT: %30 = load ptr, ptr %10, align 8 +// CHECK-NEXT: %31 = load { ptr, i64, %"{{.*}}/runtime/internal/runtime.String" }, ptr %30, align 8 +// CHECK-NEXT: %32 = extractvalue { ptr, i64, %"{{.*}}/runtime/internal/runtime.String" } %31, 0 +// CHECK-NEXT: store ptr %32, ptr %10, align 8 +// CHECK-NEXT: %33 = extractvalue { ptr, i64, %"{{.*}}/runtime/internal/runtime.String" } %31, 2 +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.FreeDeferNode"(ptr %30) +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.PrintString"(%"{{.*}}/runtime/internal/runtime.String" %33) +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.PrintByte"(i8 10) +// CHECK-NEXT: br label %_llgo_9 +// CHECK-EMPTY: +// CHECK-NEXT: _llgo_9: ; preds = %_llgo_8, %_llgo_2 +// CHECK-NEXT: br label %_llgo_7 +// CHECK-EMPTY: +// CHECK-NEXT: _llgo_10: ; preds = %_llgo_7 +// CHECK-NEXT: %34 = load ptr, ptr %10, align 8 +// CHECK-NEXT: %35 = load { ptr, i64, %"{{.*}}/runtime/internal/runtime.String" }, ptr %34, align 8 +// CHECK-NEXT: %36 = extractvalue { ptr, i64, %"{{.*}}/runtime/internal/runtime.String" } %35, 0 +// CHECK-NEXT: store ptr %36, ptr %10, align 8 +// CHECK-NEXT: %37 = extractvalue { ptr, i64, %"{{.*}}/runtime/internal/runtime.String" } %35, 2 +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.FreeDeferNode"(ptr %34) +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.PrintString"(%"{{.*}}/runtime/internal/runtime.String" %37) +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.PrintByte"(i8 10) +// CHECK-NEXT: br label %_llgo_11 +// CHECK-EMPTY: +// CHECK-NEXT: _llgo_11: ; preds = %_llgo_10, %_llgo_7 +// CHECK-NEXT: %38 = load %"{{.*}}/runtime/internal/runtime.Defer", ptr %2, align 8 +// CHECK-NEXT: %39 = extractvalue %"{{.*}}/runtime/internal/runtime.Defer" %38, 2 +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.SetThreadDefer"(ptr %39) +// CHECK-NEXT: %40 = load ptr, ptr %9, align 8 +// CHECK-NEXT: indirectbr ptr %40, [label %_llgo_3, label %_llgo_6] +// CHECK-NEXT: } From 756a51cd7253041f785df8d1dd10de9ca869b902 Mon Sep 17 00:00:00 2001 From: Li Jie Date: Mon, 3 Aug 2026 21:32:23 +0800 Subject: [PATCH 55/73] ssa: clarify defer dispatch invariants --- ssa/eh.go | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/ssa/eh.go b/ssa/eh.go index 183331ceff..59d2723ce5 100644 --- a/ssa/eh.go +++ b/ssa/eh.go @@ -590,17 +590,17 @@ func (b Builder) deferTargetValue(target deferTarget) Expr { } func (b Builder) jumpDeferTarget(ptr Expr, targets []deferTarget) { - target := b.Load(ptr) + loaded := b.Load(ptr) if b.Prog.target.GOARCH != "wasm" { blocks := make([]BasicBlock, len(targets)) for i, target := range targets { blocks[i] = target.block } - b.IndirectJump(target, blocks) + b.IndirectJump(loaded, blocks) return } - selector := b.Convert(b.Prog.Uintptr(), target) + selector := b.Convert(b.Prog.Uintptr(), loaded) invalid := b.Func.MakeBlock() sw := b.impl.CreateSwitch(selector.impl, invalid.first, len(targets)) for _, target := range targets { @@ -616,10 +616,11 @@ func (p Function) endDefer(b Builder) { return } rundTargets := self.rundTargets + // A partially constructed defer state has no dispatch target yet. + // initDeferState seeds selector 0 with the terminal rethrow target. if len(rundTargets) == 0 { return } - rethrowTarget := rundTargets[0] rethrowBlk := rethrowTarget.block procBlk := self.procBlk From 7523cf4b3fe6cea8ede650dc54c15ae81680e2be Mon Sep 17 00:00:00 2001 From: Li Jie Date: Mon, 3 Aug 2026 21:43:45 +0800 Subject: [PATCH 56/73] llgen: derive platform from flags target --- internal/crosscompile/crosscompile.go | 17 ++--------------- internal/crosscompile/crosscompile_test.go | 13 ------------- internal/llgen/llgenf.go | 9 +++++++++ internal/llgen/llgenf_test.go | 5 +++-- 4 files changed, 14 insertions(+), 30 deletions(-) diff --git a/internal/crosscompile/crosscompile.go b/internal/crosscompile/crosscompile.go index 0798d40e28..c017c7e5f4 100644 --- a/internal/crosscompile/crosscompile.go +++ b/internal/crosscompile/crosscompile.go @@ -718,21 +718,8 @@ func UseTarget(targetName string, level optlevel.Level, ltoMode lto.Mode) (expor // Use extends the original Use function to support target-based configuration // If targetName is provided, it takes precedence over goos/goarch func Use(goos, goarch, targetName string, wasiThreads, forceEspClang bool, level optlevel.Level, ltoMode lto.Mode, goGlobalDCE bool) (export Export, err error) { - if targetName == "" { - return use(goos, goarch, wasiThreads, forceEspClang, level, ltoMode, goGlobalDCE) - } - - config, err := targets.NewDefaultResolver().Resolve(targetName) - if err != nil { - return export, fmt.Errorf("failed to resolve target %s: %w", targetName, err) - } - if config.GOARCH != "wasm" { + if targetName != "" && !strings.HasPrefix(targetName, "wasm") && !strings.HasPrefix(targetName, "wasi") { return UseTarget(targetName, level, ltoMode) } - export, err = use(config.GOOS, config.GOARCH, wasiThreads, forceEspClang, level, ltoMode, goGlobalDCE) - if err == nil { - export.GOOS = config.GOOS - export.GOARCH = config.GOARCH - } - return + return use(goos, goarch, wasiThreads, forceEspClang, level, ltoMode, goGlobalDCE) } diff --git a/internal/crosscompile/crosscompile_test.go b/internal/crosscompile/crosscompile_test.go index 801533ef4c..ea89a9596a 100644 --- a/internal/crosscompile/crosscompile_test.go +++ b/internal/crosscompile/crosscompile_test.go @@ -333,19 +333,6 @@ func TestUseWithTarget(t *testing.T) { t.Errorf("Expected CPU generic in CCFLAGS, got %v", export.CCFLAGS) } - // Named WebAssembly targets use the GOOS/GOARCH from their target configuration - // with the standard WebAssembly toolchain setup. - export, err = Use("linux", "amd64", "wasm", false, false, optlevel.O2, lto.Off, false) - if err != nil { - t.Fatalf("Use(wasm) failed: %v", err) - } - if export.GOOS != "js" || export.GOARCH != "wasm" { - t.Fatalf("wasm target platform = %s/%s, want js/wasm", export.GOOS, export.GOARCH) - } - if !hasFlagValue(export.CCFLAGS, "-target", "wasm32-unknown-emscripten") { - t.Fatalf("wasm target CCFLAGS = %v, want emscripten target", export.CCFLAGS) - } - // Test fallback to goos/goarch when no target specified export, err = Use(runtime.GOOS, runtime.GOARCH, "", false, false, optlevel.O2, lto.Thin, false) if err != nil { diff --git a/internal/llgen/llgenf.go b/internal/llgen/llgenf.go index 45baebf0f4..1e45eaf26d 100644 --- a/internal/llgen/llgenf.go +++ b/internal/llgen/llgenf.go @@ -25,6 +25,7 @@ import ( "github.com/goplus/llgo/internal/build" "github.com/goplus/llgo/internal/goflags" + "github.com/goplus/llgo/internal/targets" ) func GenFrom(fileOrPkg string) string { @@ -103,6 +104,14 @@ func applyFlagsFile(conf *build.Config, flagsFile string) error { goFlags = append(goFlags, flag) } } + if next.Target != "" { + target, err := targets.NewDefaultResolver().Resolve(next.Target) + if err != nil { + return fmt.Errorf("apply %s: %w", flagsFile, err) + } + next.Goos = target.GOOS + next.Goarch = target.GOARCH + } if err := goflags.ApplyBuildFlags(&next, goFlags); err != nil { return fmt.Errorf("apply %s: %w", flagsFile, err) } diff --git a/internal/llgen/llgenf_test.go b/internal/llgen/llgenf_test.go index 3dacfd3fb1..8a80433d1e 100644 --- a/internal/llgen/llgenf_test.go +++ b/internal/llgen/llgenf_test.go @@ -34,7 +34,7 @@ func TestApplyFlagsFile(t *testing.T) { } path := filepath.Join(dir, "flags.txt") - data := "GOOS=wasip1 GOARCH=wasm\n-target=wasm\n--gcflags 'all=-N -l'\n-ldflags=--s --w=false # keep DWARF\n" + data := "-target=wasm\n--gcflags 'all=-N -l'\n-ldflags=--s --w=false # keep DWARF\n" if err := os.WriteFile(path, []byte(data), 0o644); err != nil { t.Fatal(err) } @@ -42,7 +42,7 @@ func TestApplyFlagsFile(t *testing.T) { if err := applyFlagsFile(conf, path); err != nil { t.Fatal(err) } - if conf.Goos != "wasip1" || conf.Goarch != "wasm" || conf.Target != "wasm" { + if conf.Goos != "js" || conf.Goarch != "wasm" || conf.Target != "wasm" { t.Fatalf("target config = %s/%s, target %q", conf.Goos, conf.Goarch, conf.Target) } if conf.OptLevel != optlevel.O0 { @@ -58,6 +58,7 @@ func TestApplyFlagsFileErrorIncludesPath(t *testing.T) { "-ldflags='unterminated\n", "-ldflags=-w=invalid\n", "-target\n", + "-target=does-not-exist\n", } for _, data := range tests { t.Run(strings.TrimSpace(data), func(t *testing.T) { From b593d595cfdab797545d4479073fa44b6ba44511 Mon Sep 17 00:00:00 2001 From: Li Jie Date: Sat, 1 Aug 2026 22:22:43 +0800 Subject: [PATCH 57/73] runtime: keep workers alive after main Goexit --- cl/_testgo/goexitmain/expect.txt | 1 + cl/_testgo/goexitmain/in.go | 22 ++++++++++++++++++++++ runtime/internal/runtime/g_tls.go | 5 +++++ runtime/internal/runtime/proc.go | 10 ++++++++++ runtime/internal/runtime/proc_atomic.go | 20 ++++++++++++++++++++ runtime/internal/runtime/proc_baremetal.go | 11 +++++++++++ runtime/internal/runtime/z_default.go | 5 ++++- test/goroot/xfail.yaml | 19 ------------------- 8 files changed, 73 insertions(+), 20 deletions(-) create mode 100644 cl/_testgo/goexitmain/expect.txt create mode 100644 cl/_testgo/goexitmain/in.go diff --git a/cl/_testgo/goexitmain/expect.txt b/cl/_testgo/goexitmain/expect.txt new file mode 100644 index 0000000000..9766475a41 --- /dev/null +++ b/cl/_testgo/goexitmain/expect.txt @@ -0,0 +1 @@ +ok diff --git a/cl/_testgo/goexitmain/in.go b/cl/_testgo/goexitmain/in.go new file mode 100644 index 0000000000..7cc98de048 --- /dev/null +++ b/cl/_testgo/goexitmain/in.go @@ -0,0 +1,22 @@ +package main + +import ( + "fmt" + "os" + "runtime" +) + +func init() { + done := make(chan int, 1) + defer func() { + done <- 0 + }() + go func() { + code := <-done + fmt.Println("ok") + os.Exit(code) + }() + runtime.Goexit() +} + +func main() {} diff --git a/runtime/internal/runtime/g_tls.go b/runtime/internal/runtime/g_tls.go index 7aa00577b4..013fe7f600 100644 --- a/runtime/internal/runtime/g_tls.go +++ b/runtime/internal/runtime/g_tls.go @@ -102,6 +102,11 @@ func destroyG(ptr c.Pointer) { if gp == nil { return } + lastAfterMainExit := releaseG() == 0 && hasMainExited() + if lastAfterMainExit { + fatal("no goroutines (main called runtime.Goexit) - deadlock!") + c.Exit(2) + } if gp.panic_ != nil { c.Free(gp.panic_) } diff --git a/runtime/internal/runtime/proc.go b/runtime/internal/runtime/proc.go index b9e35ef954..22dd1f44be 100644 --- a/runtime/internal/runtime/proc.go +++ b/runtime/internal/runtime/proc.go @@ -45,6 +45,9 @@ var sched struct { goidgen uint64 midgen int64 pidgen int32 + gcount uint64 // live or registered goroutine contexts + + mainExited uint32 // set after the main goroutine finishes Goexit defers } // NewProc creates a new G running fn. @@ -56,6 +59,7 @@ func NewProc(fn goroutineFunc, arg unsafe.Pointer, stackSize uintptr) { gp := newproc1(fn, arg, getg()) if errno := newm(gp.m, stackSize); errno != 0 { ctx := gp.context + releaseG() FreeRoot(arg) FreeRoot(ctx.root) panic("runtime: failed to create new OS thread") @@ -128,6 +132,11 @@ func mexit(mp *m) { pp := mp.p ctx := gp.context root := ctx.root + lastAfterMainExit := releaseG() == 0 && hasMainExited() + if lastAfterMainExit { + fatal("no goroutines (main called runtime.Goexit) - deadlock!") + c.Exit(2) + } casgstatus(gp, _Grunning, _Gdead) setpstatus(pp, _Pdead) @@ -168,6 +177,7 @@ func initRuntimeContext(ctx *runtimeContext, callergp *g, status uint32) *g { } setpstatus(pp, pstatus) pp.m = mp + retainG() return gp } diff --git a/runtime/internal/runtime/proc_atomic.go b/runtime/internal/runtime/proc_atomic.go index eaec33b38f..b383aa6c33 100644 --- a/runtime/internal/runtime/proc_atomic.go +++ b/runtime/internal/runtime/proc_atomic.go @@ -32,6 +32,26 @@ func nextPid(pp *p) int32 { return atomic.Add(&sched.pidgen, int32(1)) - 1 } +func retainG() { + atomic.Add(&sched.gcount, uint64(1)) +} + +func releaseG() uint64 { + return atomic.Sub(&sched.gcount, uint64(1)) +} + +func liveGCount() uint64 { + return atomic.Load(&sched.gcount) +} + +func markMainExited() { + atomic.Store(&sched.mainExited, uint32(1)) +} + +func hasMainExited() bool { + return atomic.Load(&sched.mainExited) != 0 +} + func readgstatus(gp *g) uint32 { return atomic.Load(&gp.atomicstatus) } diff --git a/runtime/internal/runtime/proc_baremetal.go b/runtime/internal/runtime/proc_baremetal.go index e203ec44f1..dc2d5291bb 100644 --- a/runtime/internal/runtime/proc_baremetal.go +++ b/runtime/internal/runtime/proc_baremetal.go @@ -35,6 +35,17 @@ func nextPid(pp *p) int32 { return int32((uintptr(unsafe.Pointer(pp)) >> 2) & 0x7fffffff) } +func retainG() { +} + +func releaseG() uint64 { + return 1 +} + +func hasMainExited() bool { + return false +} + // Each bare-metal G owns its status transitions in the current backend. func readgstatus(gp *g) uint32 { return gp.atomicstatus diff --git a/runtime/internal/runtime/z_default.go b/runtime/internal/runtime/z_default.go index 401f8aaa17..c1de61ff06 100644 --- a/runtime/internal/runtime/z_default.go +++ b/runtime/internal/runtime/z_default.go @@ -36,10 +36,13 @@ func Rethrow(link *Defer) { if link != nil { c.Siglongjmp(link.Addr, 1) } - if gp.isMain { + if gp.isMain && liveGCount() == 1 { fatal("no goroutines (main called runtime.Goexit) - deadlock!") c.Exit(2) } + if gp.isMain { + markMainExited() + } leaveCurrentLocalContext() exitCurrentM() } diff --git a/test/goroot/xfail.yaml b/test/goroot/xfail.yaml index 8f5ded5305..6cb9b3a6b9 100644 --- a/test/goroot/xfail.yaml +++ b/test/goroot/xfail.yaml @@ -2425,10 +2425,6 @@ xfails: directive: run case: fixedbugs/issue57823.go reason: latest main goroot run failure on darwin/arm64 - - platform: darwin/arm64 - directive: run - case: fixedbugs/issue5963.go - reason: latest main goroot run failure on darwin/arm64 - version: go1.25 platform: linux/amd64 directive: run @@ -2519,11 +2515,6 @@ xfails: directive: run case: fixedbugs/issue57823.go reason: go1.25 goroot run failure on linux/amd64 - - version: go1.25 - platform: linux/amd64 - directive: run - case: fixedbugs/issue5963.go - reason: go1.25 goroot run failure on linux/amd64 - version: go1.25 platform: linux/amd64 directive: run @@ -2615,11 +2606,6 @@ xfails: directive: run case: fixedbugs/issue57823.go reason: go1.24 goroot run failure on linux/amd64 - - version: go1.24 - platform: linux/amd64 - directive: run - case: fixedbugs/issue5963.go - reason: go1.24 goroot run failure on linux/amd64 - version: go1.24 platform: linux/amd64 directive: run @@ -2825,11 +2811,6 @@ xfails: directive: run case: fixedbugs/issue57823.go reason: go1.26 goroot run failure on linux/amd64 - - version: go1.26 - platform: linux/amd64 - directive: run - case: fixedbugs/issue5963.go - reason: go1.26 goroot run failure on linux/amd64 - version: go1.24 platform: darwin/arm64 directive: run From 01395458d0c69b74b9d8bf923e342b75fb3b07e2 Mon Sep 17 00:00:00 2001 From: Li Jie Date: Sat, 1 Aug 2026 23:31:32 +0800 Subject: [PATCH 58/73] runtime: make main Goexit lifecycle release atomic --- cl/_testgo/goexitmain/expect.txt | 1 - cl/_testgo/goexitmain/in.go | 22 -------- runtime/internal/runtime/g_global.go | 4 ++ runtime/internal/runtime/g_tls.go | 10 ++-- runtime/internal/runtime/proc.go | 33 ++++++++--- runtime/internal/runtime/proc_atomic.go | 28 ++++++---- runtime/internal/runtime/proc_baremetal.go | 14 +++-- runtime/internal/runtime/z_default.go | 4 -- test/go/goexit_lifecycle_test.go | 65 ++++++++++++++++++++++ 9 files changed, 128 insertions(+), 53 deletions(-) delete mode 100644 cl/_testgo/goexitmain/expect.txt delete mode 100644 cl/_testgo/goexitmain/in.go create mode 100644 test/go/goexit_lifecycle_test.go diff --git a/cl/_testgo/goexitmain/expect.txt b/cl/_testgo/goexitmain/expect.txt deleted file mode 100644 index 9766475a41..0000000000 --- a/cl/_testgo/goexitmain/expect.txt +++ /dev/null @@ -1 +0,0 @@ -ok diff --git a/cl/_testgo/goexitmain/in.go b/cl/_testgo/goexitmain/in.go deleted file mode 100644 index 7cc98de048..0000000000 --- a/cl/_testgo/goexitmain/in.go +++ /dev/null @@ -1,22 +0,0 @@ -package main - -import ( - "fmt" - "os" - "runtime" -) - -func init() { - done := make(chan int, 1) - defer func() { - done <- 0 - }() - go func() { - code := <-done - fmt.Println("ok") - os.Exit(code) - }() - runtime.Goexit() -} - -func main() {} diff --git a/runtime/internal/runtime/g_global.go b/runtime/internal/runtime/g_global.go index d373278a9c..fc5416b6bf 100644 --- a/runtime/internal/runtime/g_global.go +++ b/runtime/internal/runtime/g_global.go @@ -31,3 +31,7 @@ func getg() *g { func setg(gp *g) { currentG = gp } + +func currentGUsesLifecycle() bool { + return false +} diff --git a/runtime/internal/runtime/g_tls.go b/runtime/internal/runtime/g_tls.go index 013fe7f600..9a8bcc5262 100644 --- a/runtime/internal/runtime/g_tls.go +++ b/runtime/internal/runtime/g_tls.go @@ -97,16 +97,16 @@ func setAutoG(gp *g) c.Int { return 0 } +func currentGUsesLifecycle() bool { + return currentGHasLifecycle +} + func destroyG(ptr c.Pointer) { gp := (*g)(ptr) if gp == nil { return } - lastAfterMainExit := releaseG() == 0 && hasMainExited() - if lastAfterMainExit { - fatal("no goroutines (main called runtime.Goexit) - deadlock!") - c.Exit(2) - } + releaseGAndCheckDeadlock() if gp.panic_ != nil { c.Free(gp.panic_) } diff --git a/runtime/internal/runtime/proc.go b/runtime/internal/runtime/proc.go index 22dd1f44be..12dc6169c2 100644 --- a/runtime/internal/runtime/proc.go +++ b/runtime/internal/runtime/proc.go @@ -45,9 +45,11 @@ var sched struct { goidgen uint64 midgen int64 pidgen int32 - gcount uint64 // live or registered goroutine contexts - mainExited uint32 // set after the main goroutine finishes Goexit defers + // gstate packs the live/registered goroutine count with the main-exited + // bit. The goroutine whose release observes count zero can therefore make + // the deadlock decision from one atomic result. + gstate uint64 } // NewProc creates a new G running fn. @@ -132,10 +134,9 @@ func mexit(mp *m) { pp := mp.p ctx := gp.context root := ctx.root - lastAfterMainExit := releaseG() == 0 && hasMainExited() - if lastAfterMainExit { - fatal("no goroutines (main called runtime.Goexit) - deadlock!") - c.Exit(2) + ownedByLifecycle := currentGUsesLifecycle() + if !ownedByLifecycle { + releaseGAndCheckDeadlock() } casgstatus(gp, _Grunning, _Gdead) @@ -147,12 +148,23 @@ func mexit(mp *m) { gp.m = nil setg(nil) - if root != nil { + if !ownedByLifecycle && root != nil { ctx.root = nil FreeRoot(root) } } +// releaseGAndCheckDeadlock is the sole last-goroutine decision. Main marks its +// exit before releasing its own context, so regardless of release ordering the +// final goroutine observes both facts in the packed atomic state. +func releaseGAndCheckDeadlock() { + remaining, mainExited := releaseG() + if remaining == 0 && mainExited { + fatal("no goroutines (main called runtime.Goexit) - deadlock!") + c.Exit(2) + } +} + func initRuntimeContext(ctx *runtimeContext, callergp *g, status uint32) *g { gp := &ctx.g mp := &ctx.m @@ -195,3 +207,10 @@ func GMPForTesting() (goid, parentGoid uint64, mid int64, pid int32, gstatus, ps mp.curg == gp && pp.m == mp && ctx != nil && &ctx.g == gp && &ctx.m == mp && &ctx.p == pp } + +// GStateForTesting reports the packed scheduler state without changing it. +// Execution tests use it to wait until a lifecycle-owned main G has completed +// mexit before allowing the last worker to return. +func GStateForTesting() (count uint64, mainExited bool) { + return gStateForTesting() +} diff --git a/runtime/internal/runtime/proc_atomic.go b/runtime/internal/runtime/proc_atomic.go index b383aa6c33..5db811ab3e 100644 --- a/runtime/internal/runtime/proc_atomic.go +++ b/runtime/internal/runtime/proc_atomic.go @@ -20,6 +20,11 @@ package runtime import "github.com/goplus/llgo/runtime/internal/clite/sync/atomic" +const ( + mainExitedBit = uint64(1) << 63 + gCountMask = mainExitedBit - 1 +) + func nextGoid(gp *g) uint64 { return atomic.Add(&sched.goidgen, uint64(1)) } @@ -33,23 +38,26 @@ func nextPid(pp *p) int32 { } func retainG() { - atomic.Add(&sched.gcount, uint64(1)) -} - -func releaseG() uint64 { - return atomic.Sub(&sched.gcount, uint64(1)) + atomic.Add(&sched.gstate, uint64(1)) } -func liveGCount() uint64 { - return atomic.Load(&sched.gcount) +// releaseG drops one registered context and returns the remaining count and +// main-exited state from the same atomic result. +func releaseG() (remaining uint64, mainExited bool) { + // llgo.atomicSub follows LLVM atomicrmw and returns the value before the + // subtraction, unlike sync/atomic.Add. Convert it to the post-release + // state before deciding whether this was the last context. + state := atomic.Sub(&sched.gstate, uint64(1)) - 1 + return state & gCountMask, state&mainExitedBit != 0 } func markMainExited() { - atomic.Store(&sched.mainExited, uint32(1)) + atomic.Or(&sched.gstate, mainExitedBit) } -func hasMainExited() bool { - return atomic.Load(&sched.mainExited) != 0 +func gStateForTesting() (count uint64, mainExited bool) { + state := atomic.Load(&sched.gstate) + return state & gCountMask, state&mainExitedBit != 0 } func readgstatus(gp *g) uint32 { diff --git a/runtime/internal/runtime/proc_baremetal.go b/runtime/internal/runtime/proc_baremetal.go index dc2d5291bb..39e1d5b3ae 100644 --- a/runtime/internal/runtime/proc_baremetal.go +++ b/runtime/internal/runtime/proc_baremetal.go @@ -38,12 +38,18 @@ func nextPid(pp *p) int32 { func retainG() { } -func releaseG() uint64 { - return 1 +// Bare-metal has no atomic goroutine counter. Returning one remaining +// goroutine intentionally disables native pthread main-Goexit deadlock +// detection for this single-context backend. +func releaseG() (remaining uint64, mainExited bool) { + return 1, false } -func hasMainExited() bool { - return false +// Bare-metal keeps its existing single-context behavior. +func markMainExited() {} + +func gStateForTesting() (count uint64, mainExited bool) { + return 1, false } // Each bare-metal G owns its status transitions in the current backend. diff --git a/runtime/internal/runtime/z_default.go b/runtime/internal/runtime/z_default.go index c1de61ff06..e73aeff206 100644 --- a/runtime/internal/runtime/z_default.go +++ b/runtime/internal/runtime/z_default.go @@ -36,10 +36,6 @@ func Rethrow(link *Defer) { if link != nil { c.Siglongjmp(link.Addr, 1) } - if gp.isMain && liveGCount() == 1 { - fatal("no goroutines (main called runtime.Goexit) - deadlock!") - c.Exit(2) - } if gp.isMain { markMainExited() } diff --git a/test/go/goexit_lifecycle_test.go b/test/go/goexit_lifecycle_test.go new file mode 100644 index 0000000000..bad5b59698 --- /dev/null +++ b/test/go/goexit_lifecycle_test.go @@ -0,0 +1,65 @@ +/* + * Copyright (c) 2026 The XGo Authors (xgo.dev). All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package gotest + +import ( + "strings" + "testing" +) + +const mainGoexitLifecycleProbe = `package main + +import ( + "fmt" + "runtime" + _ "unsafe" +) + +//go:linkname runtimeGStateForTesting github.com/goplus/llgo/runtime/internal/runtime.GStateForTesting +func runtimeGStateForTesting() (count uint64, mainExited bool) + +func init() { + done := make(chan int, 1) + defer func() { done <- 0 }() + go func() { + <-done + for { + count, mainExited := runtimeGStateForTesting() + if count == 1 && mainExited { + break + } + } + fmt.Println("WORKER_RETURNING") + }() + runtime.Goexit() +} + +func main() {} +` + +func TestMainGoexitLifecycleReleasedOnce(t *testing.T) { + _, dir := prepareCallerAcceptanceProbe(t, mainGoexitLifecycleProbe) + out, err := runLLGoProbe(t, dir) + if err == nil { + t.Fatalf("main Goexit probe unexpectedly succeeded:\\n%s", out) + } + worker := strings.Index(out, "WORKER_RETURNING") + deadlock := strings.Index(out, "no goroutines (main called runtime.Goexit) - deadlock!") + if worker < 0 || deadlock < 0 || worker > deadlock { + t.Fatalf("worker must return before the last-goroutine deadlock:\\n%s", out) + } +} From dcff207d2e16353ed1f55841dad54b9788f6acbc Mon Sep 17 00:00:00 2001 From: Li Jie Date: Mon, 3 Aug 2026 23:16:14 +0800 Subject: [PATCH 59/73] build: skip object emission in generation mode --- internal/build/build.go | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/internal/build/build.go b/internal/build/build.go index 411d733568..4e3ae2a499 100644 --- a/internal/build/build.go +++ b/internal/build/build.go @@ -1886,6 +1886,11 @@ func compilePackageModule(ctx *context, aPkg *aPackage, externs []string, verbos } } emitFuncInfoEntrySites(ctx, ret) + // ModeGen callers consume the in-memory LLVM module directly. They do not + // need cgo/link objects or a package archive for a later link step. + if ctx.mode == ModeGen { + return nil + } printCmds := ctx.shouldPrintCommands(verbose) cgoLLFiles, cgoLdflags, err := buildCgo(ctx, aPkg, aPkg.Package.Syntax, externs, printCmds) From b651575d81a9bb1c68ee48f26501efbe97c3c30b Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 4 Aug 2026 00:22:38 +0000 Subject: [PATCH 60/73] build(deps): bump xgo-dev/setup-benchmark-go-action from 1 to 1.0.3 Bumps [xgo-dev/setup-benchmark-go-action](https://github.com/xgo-dev/setup-benchmark-go-action) from 1 to 1.0.3. - [Release notes](https://github.com/xgo-dev/setup-benchmark-go-action/releases) - [Commits](https://github.com/xgo-dev/setup-benchmark-go-action/compare/v1...v1.0.3) --- updated-dependencies: - dependency-name: xgo-dev/setup-benchmark-go-action dependency-version: 1.0.3 dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- .github/workflows/benchmark.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/benchmark.yml b/.github/workflows/benchmark.yml index 34285de833..ee22fa1a34 100644 --- a/.github/workflows/benchmark.yml +++ b/.github/workflows/benchmark.yml @@ -78,7 +78,7 @@ jobs: "$GITHUB_WORKSPACE/.benchmark/results" - name: Record benchmark result - uses: xgo-dev/setup-benchmark-go-action@v1 + uses: xgo-dev/setup-benchmark-go-action@v1.0.3 with: config: .github/llgo-benchmark.yml benchmark-file: .benchmark/results/benchmark.txt From 1928ddff48f53a414b6ec5470a01b9efe6758ec6 Mon Sep 17 00:00:00 2001 From: Li Jie Date: Tue, 4 Aug 2026 11:09:01 +0800 Subject: [PATCH 61/73] fix(build): reject invalid SSA move anchors --- internal/build/ssa_order_fix.go | 4 ++-- internal/build/ssa_order_fix_test.go | 7 ++++++- 2 files changed, 8 insertions(+), 3 deletions(-) diff --git a/internal/build/ssa_order_fix.go b/internal/build/ssa_order_fix.go index c115ee195a..4737ad6fd1 100644 --- a/internal/build/ssa_order_fix.go +++ b/internal/build/ssa_order_fix.go @@ -440,13 +440,13 @@ func valueDependsOn(v, target ssa.Value, seen map[ssa.Value]struct{}) bool { // moveInstrsAfter moves selected instructions as a stable group immediately // after anchor. The anchor must not be in moving; callers use an instruction // that remains in the block. It returns instrs unchanged when moving is empty, -// anchor is nil or absent, or the precondition is violated. +// or anchor is nil or absent. func moveInstrsAfter(instrs []ssa.Instruction, moving map[ssa.Instruction]struct{}, anchor ssa.Instruction) []ssa.Instruction { if len(moving) == 0 || anchor == nil { return instrs } if _, ok := moving[anchor]; ok { - return instrs + panic("moveInstrsAfter: anchor is in moving set") } moved := make([]ssa.Instruction, 0, len(moving)) remaining := make([]ssa.Instruction, 0, len(instrs)) diff --git a/internal/build/ssa_order_fix_test.go b/internal/build/ssa_order_fix_test.go index 9db1b46f1e..3ddbc8ee71 100644 --- a/internal/build/ssa_order_fix_test.go +++ b/internal/build/ssa_order_fix_test.go @@ -199,8 +199,13 @@ func f() { assertOrder(t, moveInstrsAfter(instrs, moving, &ssa.Return{}), instrs) }) t.Run("anchor-in-moving", func(t *testing.T) { + defer func() { + if recover() == nil { + t.Fatal("moveInstrsAfter did not reject an anchor in the moving set") + } + }() moving := map[ssa.Instruction]struct{}{instrs[1]: {}} - assertOrder(t, moveInstrsAfter(instrs, moving, instrs[1]), instrs) + moveInstrsAfter(instrs, moving, instrs[1]) }) t.Run("stable", func(t *testing.T) { moving := map[ssa.Instruction]struct{}{ From 7e290aeead86c9f7d1a53780b6a71b20006f57e6 Mon Sep 17 00:00:00 2001 From: Li Jie Date: Tue, 4 Aug 2026 13:06:31 +0800 Subject: [PATCH 62/73] test: replace legacy out.ll workflow with LIT checks --- chore/gentests/gentests.go | 160 ------------- chore/gentests/gentests_test.go | 35 --- chore/litgen/rewrite.go | 4 +- chore/llgen/llgen.go | 41 ---- chore/llgen/llgen_test.go | 65 ----- cl/_testdata/debug/in.go | 5 + cl/_testdata/debug/out.ll | 1 - cl/_testgo/cgofull/cgofull.go | 5 + cl/_testgo/cgofull/out.ll | 1 - cl/_testgo/chan/in.go | 6 + cl/_testgo/chan/out.ll | 1 - cl/_testgo/cursor/out.ll | 0 cl/_testgo/defer1/in.go | 6 + cl/_testgo/defer1/out.ll | 1 - cl/_testgo/defer2/in.go | 6 + cl/_testgo/defer2/out.ll | 1 - cl/_testgo/defer3/in.go | 6 + cl/_testgo/defer3/out.ll | 1 - cl/_testgo/defer4/in.go | 6 + cl/_testgo/defer4/out.ll | 1 - cl/_testgo/deferclosure/in.go | 6 + cl/_testgo/deferclosure/out.ll | 1 - cl/_testgo/defercomplex/in.go | 6 + cl/_testgo/defercomplex/out.ll | 1 - cl/_testgo/goexit/in.go | 6 + cl/_testgo/goexit/out.ll | 1 - cl/_testgo/indexerr/in.go | 4 + cl/_testgo/indexerr/out.ll | 1 - cl/_testgo/makeslice/in.go | 4 + cl/_testgo/makeslice/out.ll | 1 - cl/_testgo/reader/out.ll | 0 cl/_testgo/reflect/out.ll | 0 cl/_testgo/reflectconv/in.go | 5 + cl/_testgo/reflectconv/out.ll | 1 - cl/_testgo/reflectmk/out.ll | 0 cl/_testgo/rewrite/main.go | 5 + cl/_testgo/rewrite/out.ll | 1 - cl/_testgo/runextest/main.go | 5 + cl/_testgo/runextest/out.ll | 1 - cl/_testgo/runtest/main.go | 5 + cl/_testgo/runtest/out.ll | 1 - cl/_testgo/select/in.go | 5 + cl/_testgo/select/out.ll | 1 - cl/_testgo/syncmap/in.go | 5 + cl/_testgo/syncmap/out.ll | 1 - cl/_testgo/tptypes/out.ll | 0 cl/_testlibc/complex/in.go | 4 + cl/_testlibc/complex/out.ll | 1 - cl/_testlibc/defer/in.go | 5 + cl/_testlibc/defer/out.ll | 1 - cl/_testlibc/once/in.go | 4 + cl/_testlibc/once/out.ll | 1 - cl/_testlibc/setjmp/in.go | 4 + cl/_testlibc/setjmp/out.ll | 1 - cl/_testlibgo/sync/in.go | 4 + cl/_testlibgo/sync/out.ll | 1 - cl/_testlibgo/waitgroup/in.go | 6 + cl/_testlibgo/waitgroup/out.ll | 1 - cl/_testrt/builtin/out.ll | 0 cl/_testrt/linkname/linktarget/out.ll | 55 ----- cl/_testrt/nextblock/in.go | 6 + cl/_testrt/nextblock/out.ll | 1 - cl/cltest/cltest.go | 68 +----- cl/cltest/cltest_test.go | 19 ++ cl/compile_test.go | 11 - internal/build/build.go | 2 +- internal/littest/littest.go | 60 +---- internal/littest/littest_test.go | 333 ++++++-------------------- internal/llgen/llgenf.go | 61 +---- ssa/package.go | 2 +- test/go/defer_ir_regression_test.go | 9 +- 71 files changed, 247 insertions(+), 832 deletions(-) delete mode 100644 chore/gentests/gentests.go delete mode 100644 chore/gentests/gentests_test.go delete mode 100644 chore/llgen/llgen.go delete mode 100644 chore/llgen/llgen_test.go delete mode 100644 cl/_testdata/debug/out.ll delete mode 100644 cl/_testgo/cgofull/out.ll delete mode 100644 cl/_testgo/chan/out.ll delete mode 100644 cl/_testgo/cursor/out.ll delete mode 100644 cl/_testgo/defer1/out.ll delete mode 100644 cl/_testgo/defer2/out.ll delete mode 100644 cl/_testgo/defer3/out.ll delete mode 100644 cl/_testgo/defer4/out.ll delete mode 100644 cl/_testgo/deferclosure/out.ll delete mode 100644 cl/_testgo/defercomplex/out.ll delete mode 100644 cl/_testgo/goexit/out.ll delete mode 100644 cl/_testgo/indexerr/out.ll delete mode 100644 cl/_testgo/makeslice/out.ll delete mode 100644 cl/_testgo/reader/out.ll delete mode 100644 cl/_testgo/reflect/out.ll delete mode 100644 cl/_testgo/reflectconv/out.ll delete mode 100644 cl/_testgo/reflectmk/out.ll delete mode 100644 cl/_testgo/rewrite/out.ll delete mode 100644 cl/_testgo/runextest/out.ll delete mode 100644 cl/_testgo/runtest/out.ll delete mode 100644 cl/_testgo/select/out.ll delete mode 100644 cl/_testgo/syncmap/out.ll delete mode 100644 cl/_testgo/tptypes/out.ll delete mode 100644 cl/_testlibc/complex/out.ll delete mode 100644 cl/_testlibc/defer/out.ll delete mode 100644 cl/_testlibc/once/out.ll delete mode 100644 cl/_testlibc/setjmp/out.ll delete mode 100644 cl/_testlibgo/sync/out.ll delete mode 100644 cl/_testlibgo/waitgroup/out.ll delete mode 100644 cl/_testrt/builtin/out.ll delete mode 100644 cl/_testrt/linkname/linktarget/out.ll delete mode 100644 cl/_testrt/nextblock/out.ll diff --git a/chore/gentests/gentests.go b/chore/gentests/gentests.go deleted file mode 100644 index c306925bf3..0000000000 --- a/chore/gentests/gentests.go +++ /dev/null @@ -1,160 +0,0 @@ -/* - * Copyright (c) 2024 The XGo Authors (xgo.dev). All rights reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package main - -import ( - "fmt" - "os" - "path/filepath" - "strings" - - "github.com/goplus/llgo/cl/cltest" - "github.com/goplus/llgo/internal/build" - "github.com/goplus/llgo/internal/littest" - "github.com/goplus/llgo/internal/llgen" - "github.com/goplus/llgo/internal/lto" - "github.com/goplus/llgo/xtool/env/llvm" - "github.com/goplus/mod" -) - -func main() { - llvm.SetupPath() - dir, _, err := mod.FindGoMod(".") - check(err) - - llgenDir(dir + "/cl/_testlibc") - llgenDir(dir + "/cl/_testlibgo") - llgenDir(dir + "/cl/_testrt") - llgenDir(dir + "/cl/_testgo") - llgenDir(dir + "/cl/_testpy") - llgenDir(dir + "/cl/_testdata") - genMetaDir(dir + "/cl/_testmeta") - - genExpects(dir) -} - -func llgenDir(dir string) { - fis, err := os.ReadDir(dir) - check(err) - for _, fi := range fis { - name := fi.Name() - if !fi.IsDir() || strings.HasPrefix(name, "_") { - continue - } - testDir := dir + "/" + name - skip, err := dirHasLITTESTSource(testDir) - check(err) - if skip { - fmt.Fprintln(os.Stderr, "skip llgen", testDir, "(// LITTEST)") - continue - } - fmt.Fprintln(os.Stderr, "llgen", testDir) - check(os.Chdir(testDir)) - llgen.SmartDoFile(testDir) - } -} - -func genExpects(root string) { - runExpectDir(root, "cl/_testlibc") - runExpectDir(root, "cl/_testlibgo") - runExpectDir(root, "cl/_testrt") - runExpectDir(root, "cl/_testgo") - runExpectDir(root, "cl/_testlto", func(conf *build.Config) { - conf.LTO = lto.Full - }) - runExpectDir(root, "cl/_testpy") - runExpectDir(root, "cl/_testdata") -} - -func genMetaDir(dir string) { - fis, err := os.ReadDir(dir) - check(err) - for _, fi := range fis { - name := fi.Name() - if !fi.IsDir() || strings.HasPrefix(name, "_") { - continue - } - testDir := filepath.Join(dir, name) - if _, err := os.Stat(filepath.Join(testDir, "in.go")); err != nil { - if os.IsNotExist(err) { - continue - } - check(err) - } - relPath, err := filepath.Rel(filepath.Dir(filepath.Dir(dir)), testDir) - check(err) - relPath = filepath.ToSlash(relPath) - fmt.Fprintln(os.Stderr, "meta", relPath) - meta, err := cltest.CaptureMeta("./"+relPath, testDir) - if err != nil { - fmt.Fprintln(os.Stderr, "error:", relPath, err) - continue - } - check(os.WriteFile(filepath.Join(testDir, "meta-expect.txt"), []byte(meta), 0644)) - } -} - -func runExpectDir(root, relDir string, configure ...func(*build.Config)) { - dir := filepath.Join(root, relDir) - fis, err := os.ReadDir(dir) - check(err) - for _, fi := range fis { - name := fi.Name() - if !fi.IsDir() || strings.HasPrefix(name, "_") { - continue - } - relPath := filepath.ToSlash(filepath.Join(relDir, name)) - testDir := filepath.Join(dir, name) - fmt.Fprintln(os.Stderr, "expect", relPath) - pkgPath := "./" + relPath - var output []byte - if len(configure) == 0 { - output, err = cltest.RunAndCapture(pkgPath, testDir) - } else { - conf := build.NewDefaultConf(build.ModeRun) - for _, configure := range configure { - configure(conf) - } - output, err = cltest.RunAndCaptureWithConf(pkgPath, testDir, conf) - } - if err != nil { - fmt.Fprintln(os.Stderr, "error:", relPath, err) - output = []byte{';'} - } - expectFile := filepath.Join(testDir, "expect.txt") - expect, err := os.ReadFile(expectFile) - if err != nil || strings.TrimSpace(string(expect)) == ";" { - fmt.Fprintln(os.Stderr, "skip", relPath, "(expect is ';')") - continue - } - check(os.WriteFile(expectFile, output, 0644)) - } -} - -func check(err error) { - if err != nil { - panic(err) - } -} - -func dirHasLITTESTSource(dir string) (bool, error) { - _, ok, err := littest.FindMarkedSourceFile(dir) - if err != nil { - return false, err - } - return ok, nil -} diff --git a/chore/gentests/gentests_test.go b/chore/gentests/gentests_test.go deleted file mode 100644 index 4a212969fc..0000000000 --- a/chore/gentests/gentests_test.go +++ /dev/null @@ -1,35 +0,0 @@ -package main - -import ( - "os" - "path/filepath" - "testing" -) - -func TestDirHasLITTESTSource(t *testing.T) { - dir := t.TempDir() - if err := os.WriteFile(filepath.Join(dir, "in.go"), []byte("// LITTEST\npackage main\n"), 0644); err != nil { - t.Fatal(err) - } - ok, err := dirHasLITTESTSource(dir) - if err != nil { - t.Fatal(err) - } - if !ok { - t.Fatal("dirHasLITTESTSource = false, want true") - } -} - -func TestDirHasLITTESTSource_IgnoresUnmarkedFiles(t *testing.T) { - dir := t.TempDir() - if err := os.WriteFile(filepath.Join(dir, "in.go"), []byte("package main\n"), 0644); err != nil { - t.Fatal(err) - } - ok, err := dirHasLITTESTSource(dir) - if err != nil { - t.Fatal(err) - } - if ok { - t.Fatal("dirHasLITTESTSource = true, want false") - } -} diff --git a/chore/litgen/rewrite.go b/chore/litgen/rewrite.go index 37585a9a9c..cf86e811f7 100644 --- a/chore/litgen/rewrite.go +++ b/chore/litgen/rewrite.go @@ -120,9 +120,9 @@ func genIR(target string) (ret string, err error) { if r := recover(); r != nil { switch v := r.(type) { case error: - err = fmt.Errorf("llgen failed for %s: %w", target, v) + err = fmt.Errorf("IR generation failed for %s: %w", target, v) case string: - err = fmt.Errorf("llgen failed for %s: %s", target, v) + err = fmt.Errorf("IR generation failed for %s: %s", target, v) default: _, _ = os.Stderr.Write(debug.Stack()) panic(r) diff --git a/chore/llgen/llgen.go b/chore/llgen/llgen.go deleted file mode 100644 index f4050d3128..0000000000 --- a/chore/llgen/llgen.go +++ /dev/null @@ -1,41 +0,0 @@ -/* - * Copyright (c) 2024 The XGo Authors (xgo.dev). All rights reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package main - -import ( - "flag" - "fmt" - "os" - - "github.com/goplus/llgo/internal/build" - "github.com/goplus/llgo/internal/llgen" - "github.com/goplus/llgo/xtool/env/llvm" -) - -var ( - abi = flag.Int("abi", 0, "ABI mode (default 0). 0 = none, 1 = cfunc, 2 = allfunc.") -) - -func main() { - llvm.SetupPath() - flag.Parse() - if len(flag.Args()) != 1 { - fmt.Fprintln(os.Stderr, "Usage: llgen [flags] ") - return - } - llgen.SmartDoFileEx(flag.Args()[0], build.AbiMode(*abi)) -} diff --git a/chore/llgen/llgen_test.go b/chore/llgen/llgen_test.go deleted file mode 100644 index 5972943b09..0000000000 --- a/chore/llgen/llgen_test.go +++ /dev/null @@ -1,65 +0,0 @@ -//go:build !llgo -// +build !llgo - -package main - -import ( - "log" - "os" - "path/filepath" - "strings" - "testing" -) - -func TestMain(t *testing.T) { - // Create test package in current module - testPkg := filepath.Join(".testdata_dont_commit", "hello") - err := os.MkdirAll(testPkg, 0755) - if err != nil { - t.Fatal(err) - } - defer os.RemoveAll(filepath.Join(".testdata_dont_commit")) - - helloFile := filepath.Join(testPkg, "hello.go") - err = os.WriteFile(helloFile, []byte(`package hello - -func Hello() string { - return "Hello, World!" -} -`), 0644) - if err != nil { - t.Fatal(err) - } - - // Save original args and restore them after test - oldArgs := os.Args - defer func() { os.Args = oldArgs }() - - // Get absolute path to test package - absTestPkg, err := filepath.Abs(testPkg) - if err != nil { - t.Fatal(err) - } - - // Set test arguments - os.Args = []string{"llgen", absTestPkg} - - // Run main - main() - - // Check if the output file exists - outputFile := filepath.Join(testPkg, "llgo_autogen.ll") - log.Printf("Generated file: %s", filepath.Join(absTestPkg, "llgo_autogen.ll")) - if _, err = os.Stat(outputFile); err != nil { - t.Fatalf("Generated file should exist: %v", err) - } - - // Read and verify file content - content, err := os.ReadFile(outputFile) - if err != nil { - t.Fatalf("Should be able to read generated file: %v", err) - } - if !strings.Contains(string(content), "define") { - t.Error("Generated file should contain LLVM IR code") - } -} diff --git a/cl/_testdata/debug/in.go b/cl/_testdata/debug/in.go index 5840a92e12..87f22f24b0 100644 --- a/cl/_testdata/debug/in.go +++ b/cl/_testdata/debug/in.go @@ -1,5 +1,10 @@ +// LITTEST package main +// CHECK-DAG: define void @main.FuncWithAllTypeStructParam({{.*}}){{.*}} !dbg !{{[0-9]+}} +// CHECK-DAG: !DICompileUnit({{.*}}producer: "LLGo"{{.*}}emissionKind: FullDebug{{.*}}) +// CHECK-DAG: !DILocalVariable(name: "s"{{.*}}arg: 1{{.*}}) + import "errors" type Base struct { diff --git a/cl/_testdata/debug/out.ll b/cl/_testdata/debug/out.ll deleted file mode 100644 index 1c8a0e7976..0000000000 --- a/cl/_testdata/debug/out.ll +++ /dev/null @@ -1 +0,0 @@ -; \ No newline at end of file diff --git a/cl/_testgo/cgofull/cgofull.go b/cl/_testgo/cgofull/cgofull.go index e5ddb2f382..0ccecc5ceb 100644 --- a/cl/_testgo/cgofull/cgofull.go +++ b/cl/_testgo/cgofull/cgofull.go @@ -1,5 +1,10 @@ +// LITTEST package main +// CHECK-DAG: call {{.*}}_C2func_test_structs{{.*}} +// CHECK-DAG: call {{.*}}cliteErrno{{.*}} +// CHECK-DAG: define i32 @go_callback(i32 %{{.*}}){{.*}} { + /* #cgo windows,!amd64 CFLAGS: -D_WIN32 #cgo !windows CFLAGS: -D_POSIX diff --git a/cl/_testgo/cgofull/out.ll b/cl/_testgo/cgofull/out.ll deleted file mode 100644 index 1c8a0e7976..0000000000 --- a/cl/_testgo/cgofull/out.ll +++ /dev/null @@ -1 +0,0 @@ -; \ No newline at end of file diff --git a/cl/_testgo/chan/in.go b/cl/_testgo/chan/in.go index 4748fabf8e..e76b688bfc 100644 --- a/cl/_testgo/chan/in.go +++ b/cl/_testgo/chan/in.go @@ -1,5 +1,11 @@ +// LITTEST package main +// CHECK-DAG: call ptr @"{{.*}}/runtime/internal/runtime.NewChan"({{.*}}) +// CHECK-DAG: call void @"{{.*}}/runtime/internal/runtime.NewProc"({{.*}}) +// CHECK-DAG: call i1 @"{{.*}}/runtime/internal/runtime.ChanRecv"({{.*}}) +// CHECK-DAG: call void @"{{.*}}/runtime/internal/runtime.ChanClose"({{.*}}) + func main() { ch := make(chan int, 10) var v any = ch diff --git a/cl/_testgo/chan/out.ll b/cl/_testgo/chan/out.ll deleted file mode 100644 index 1c8a0e7976..0000000000 --- a/cl/_testgo/chan/out.ll +++ /dev/null @@ -1 +0,0 @@ -; \ No newline at end of file diff --git a/cl/_testgo/cursor/out.ll b/cl/_testgo/cursor/out.ll deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/cl/_testgo/defer1/in.go b/cl/_testgo/defer1/in.go index 82d34e318c..86d2f621ab 100644 --- a/cl/_testgo/defer1/in.go +++ b/cl/_testgo/defer1/in.go @@ -1,5 +1,11 @@ +// LITTEST package main +// CHECK-DAG: call ptr @"{{.*}}/runtime/internal/runtime.GetThreadDefer"() +// CHECK-DAG: call void @"{{.*}}/runtime/internal/runtime.SetThreadDefer"(ptr %{{.*}}) +// CHECK-DAG: call i32 @{{.*}}setjmp(ptr %{{.*}}{{.*}}) +// CHECK-DAG: call void @"{{.*}}/runtime/internal/runtime.Rethrow"(ptr %{{.*}}) + func f(s string) bool { return len(s) > 2 } diff --git a/cl/_testgo/defer1/out.ll b/cl/_testgo/defer1/out.ll deleted file mode 100644 index 1c8a0e7976..0000000000 --- a/cl/_testgo/defer1/out.ll +++ /dev/null @@ -1 +0,0 @@ -; \ No newline at end of file diff --git a/cl/_testgo/defer2/in.go b/cl/_testgo/defer2/in.go index 779d5b61b2..a37886d57c 100644 --- a/cl/_testgo/defer2/in.go +++ b/cl/_testgo/defer2/in.go @@ -1,5 +1,11 @@ +// LITTEST package main +// CHECK-DAG: call ptr @"{{.*}}/runtime/internal/runtime.GetThreadDefer"() +// CHECK-DAG: call void @"{{.*}}/runtime/internal/runtime.SetThreadDefer"(ptr %{{.*}}) +// CHECK-DAG: call i32 @{{.*}}setjmp(ptr %{{.*}}{{.*}}) +// CHECK-DAG: call void @"{{.*}}/runtime/internal/runtime.Rethrow"(ptr %{{.*}}) + func f(s string) bool { return len(s) > 2 } diff --git a/cl/_testgo/defer2/out.ll b/cl/_testgo/defer2/out.ll deleted file mode 100644 index 1c8a0e7976..0000000000 --- a/cl/_testgo/defer2/out.ll +++ /dev/null @@ -1 +0,0 @@ -; \ No newline at end of file diff --git a/cl/_testgo/defer3/in.go b/cl/_testgo/defer3/in.go index 3679f48f7e..f4172acdc4 100644 --- a/cl/_testgo/defer3/in.go +++ b/cl/_testgo/defer3/in.go @@ -1,5 +1,11 @@ +// LITTEST package main +// CHECK-DAG: call ptr @"{{.*}}/runtime/internal/runtime.GetThreadDefer"() +// CHECK-DAG: call i32 @{{.*}}setjmp(ptr %{{.*}}{{.*}}) +// CHECK-DAG: call void @"{{.*}}/runtime/internal/runtime.Panic"({{.*}}) +// CHECK-DAG: call void @"{{.*}}/runtime/internal/runtime.Rethrow"(ptr %{{.*}}) + func f(s string) bool { return len(s) > 2 } diff --git a/cl/_testgo/defer3/out.ll b/cl/_testgo/defer3/out.ll deleted file mode 100644 index 1c8a0e7976..0000000000 --- a/cl/_testgo/defer3/out.ll +++ /dev/null @@ -1 +0,0 @@ -; \ No newline at end of file diff --git a/cl/_testgo/defer4/in.go b/cl/_testgo/defer4/in.go index fee7dd6341..2fa0df8a2c 100644 --- a/cl/_testgo/defer4/in.go +++ b/cl/_testgo/defer4/in.go @@ -1,5 +1,11 @@ +// LITTEST package main +// CHECK-DAG: call ptr @"{{.*}}/runtime/internal/runtime.GetThreadDefer"() +// CHECK-DAG: call i32 @{{.*}}setjmp(ptr %{{.*}}{{.*}}) +// CHECK-DAG: call %"{{.*}}/runtime/internal/runtime.eface" @"{{.*}}/runtime/internal/runtime.Recover"() +// CHECK-DAG: call void @"{{.*}}/runtime/internal/runtime.Panic"({{.*}}) + func f(s string) bool { return len(s) > 2 } diff --git a/cl/_testgo/defer4/out.ll b/cl/_testgo/defer4/out.ll deleted file mode 100644 index 1c8a0e7976..0000000000 --- a/cl/_testgo/defer4/out.ll +++ /dev/null @@ -1 +0,0 @@ -; \ No newline at end of file diff --git a/cl/_testgo/deferclosure/in.go b/cl/_testgo/deferclosure/in.go index 4428ece8d6..60a3b0cebc 100644 --- a/cl/_testgo/deferclosure/in.go +++ b/cl/_testgo/deferclosure/in.go @@ -1,5 +1,11 @@ +// LITTEST package main +// CHECK-DAG: call ptr @"{{.*}}/runtime/internal/runtime.GetThreadDefer"() +// CHECK-DAG: define void @"main.testDeferClosureValue$1"(ptr {{((nest|swiftself) )?}}%{{.*}}){{.*}} { +// CHECK-DAG: define void @"main.testDeferStructClosure$1"(ptr {{((nest|swiftself) )?}}%{{.*}}, %"{{.*}}/runtime/internal/runtime.String" %{{.*}}){{.*}} { +// CHECK-DAG: call void %{{.*}}(ptr {{((nest|swiftself) )?}}%{{.*}}) + // Test deferred closure and method-value lowering. // Type for holding a function diff --git a/cl/_testgo/deferclosure/out.ll b/cl/_testgo/deferclosure/out.ll deleted file mode 100644 index 1c8a0e7976..0000000000 --- a/cl/_testgo/deferclosure/out.ll +++ /dev/null @@ -1 +0,0 @@ -; \ No newline at end of file diff --git a/cl/_testgo/defercomplex/in.go b/cl/_testgo/defercomplex/in.go index 6341392680..c03d1ce792 100644 --- a/cl/_testgo/defercomplex/in.go +++ b/cl/_testgo/defercomplex/in.go @@ -1,5 +1,11 @@ +// LITTEST package main +// CHECK-DAG: call ptr @"{{.*}}/runtime/internal/runtime.GetThreadDefer"() +// CHECK-DAG: call void @"{{.*}}/runtime/internal/runtime.SetThreadDefer"(ptr %{{.*}}) +// CHECK-DAG: define void @"main.complexOrder$1"(ptr {{((nest|swiftself) )?}}%{{.*}}, %"{{.*}}/runtime/internal/runtime.String" %{{.*}}){{.*}} { +// CHECK-DAG: call %"{{.*}}/runtime/internal/runtime.Slice" @"{{.*}}/runtime/internal/runtime.SliceAppend"({{.*}}) + func main() { for _, label := range complexOrder() { println(label) diff --git a/cl/_testgo/defercomplex/out.ll b/cl/_testgo/defercomplex/out.ll deleted file mode 100644 index 1c8a0e7976..0000000000 --- a/cl/_testgo/defercomplex/out.ll +++ /dev/null @@ -1 +0,0 @@ -; \ No newline at end of file diff --git a/cl/_testgo/goexit/in.go b/cl/_testgo/goexit/in.go index 5e764b4325..480ab3e716 100644 --- a/cl/_testgo/goexit/in.go +++ b/cl/_testgo/goexit/in.go @@ -1,5 +1,11 @@ +// LITTEST package main +// CHECK-DAG: call ptr @"{{.*}}/runtime/internal/runtime.NewChan"({{.*}}) +// CHECK-DAG: call void @"{{.*}}/runtime/internal/runtime.NewProc"({{.*}}) +// CHECK-DAG: call void @runtime.Goexit() +// CHECK-DAG: call %"{{.*}}/runtime/internal/runtime.eface" @"{{.*}}/runtime/internal/runtime.Recover"() + import ( "runtime" ) diff --git a/cl/_testgo/goexit/out.ll b/cl/_testgo/goexit/out.ll deleted file mode 100644 index 1c8a0e7976..0000000000 --- a/cl/_testgo/goexit/out.ll +++ /dev/null @@ -1 +0,0 @@ -; \ No newline at end of file diff --git a/cl/_testgo/indexerr/in.go b/cl/_testgo/indexerr/in.go index 3dc55df08c..bdaf71928d 100644 --- a/cl/_testgo/indexerr/in.go +++ b/cl/_testgo/indexerr/in.go @@ -1,5 +1,9 @@ +// LITTEST package main +// CHECK-DAG: call void @"{{.*}}/runtime/internal/runtime.CheckIndexRange"({{.*}}i1 true{{.*}}) +// CHECK-DAG: call void @"{{.*}}/runtime/internal/runtime.CheckIndexRange"({{.*}}i1 false{{.*}}) + func main() { } diff --git a/cl/_testgo/indexerr/out.ll b/cl/_testgo/indexerr/out.ll deleted file mode 100644 index 1c8a0e7976..0000000000 --- a/cl/_testgo/indexerr/out.ll +++ /dev/null @@ -1 +0,0 @@ -; \ No newline at end of file diff --git a/cl/_testgo/makeslice/in.go b/cl/_testgo/makeslice/in.go index d6602a8c37..bf7a194d6a 100644 --- a/cl/_testgo/makeslice/in.go +++ b/cl/_testgo/makeslice/in.go @@ -1,5 +1,9 @@ +// LITTEST package main +// CHECK-DAG: call %"{{.*}}/runtime/internal/runtime.Slice" @"{{.*}}/runtime/internal/runtime.MakeSlice"({{.*}}) +// CHECK-DAG: call %"{{.*}}/runtime/internal/runtime.eface" @"{{.*}}/runtime/internal/runtime.Recover"() + func main() { } diff --git a/cl/_testgo/makeslice/out.ll b/cl/_testgo/makeslice/out.ll deleted file mode 100644 index 1c8a0e7976..0000000000 --- a/cl/_testgo/makeslice/out.ll +++ /dev/null @@ -1 +0,0 @@ -; \ No newline at end of file diff --git a/cl/_testgo/reader/out.ll b/cl/_testgo/reader/out.ll deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/cl/_testgo/reflect/out.ll b/cl/_testgo/reflect/out.ll deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/cl/_testgo/reflectconv/in.go b/cl/_testgo/reflectconv/in.go index 6927333865..19a30dd3a2 100644 --- a/cl/_testgo/reflectconv/in.go +++ b/cl/_testgo/reflectconv/in.go @@ -1,5 +1,10 @@ +// LITTEST package main +// CHECK-DAG: call i1 @reflect.Value.CanConvert({{.*}}) +// CHECK-DAG: call %reflect.Value @reflect.Value.Convert({{.*}}) +// CHECK-DAG: call void @reflect.Value.Set({{.*}}) + import ( "bytes" "fmt" diff --git a/cl/_testgo/reflectconv/out.ll b/cl/_testgo/reflectconv/out.ll deleted file mode 100644 index 1c8a0e7976..0000000000 --- a/cl/_testgo/reflectconv/out.ll +++ /dev/null @@ -1 +0,0 @@ -; \ No newline at end of file diff --git a/cl/_testgo/reflectmk/out.ll b/cl/_testgo/reflectmk/out.ll deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/cl/_testgo/rewrite/main.go b/cl/_testgo/rewrite/main.go index 4bd616e464..433148a695 100644 --- a/cl/_testgo/rewrite/main.go +++ b/cl/_testgo/rewrite/main.go @@ -1,5 +1,10 @@ +// LITTEST package main +// CHECK-DAG: @main.VarName = global %"{{.*}}/runtime/internal/runtime.String" { ptr @{{.*}}, {{(i32|i64)}} 12 } +// CHECK-DAG: @main.VarPlain = global %"{{.*}}/runtime/internal/runtime.String" zeroinitializer +// CHECK-DAG: call void @"{{.*}}/cl/_testgo/rewrite/dep.PrintVar"() + import ( "fmt" "runtime" diff --git a/cl/_testgo/rewrite/out.ll b/cl/_testgo/rewrite/out.ll deleted file mode 100644 index 1c8a0e7976..0000000000 --- a/cl/_testgo/rewrite/out.ll +++ /dev/null @@ -1 +0,0 @@ -; \ No newline at end of file diff --git a/cl/_testgo/runextest/main.go b/cl/_testgo/runextest/main.go index b3fd473cc5..dbefabd8e1 100644 --- a/cl/_testgo/runextest/main.go +++ b/cl/_testgo/runextest/main.go @@ -1,5 +1,10 @@ +// LITTEST package main +// CHECK-DAG: define {{(i32|i64)}} @main.Zoo(){{.*}} { +// CHECK-DAG: call {{(i32|i64)}} @"{{.*}}/cl/_testgo/runextest/foo.Foo"() +// CHECK-DAG: call {{(i32|i64)}} @"{{.*}}/cl/_testgo/runextest/bar.Bar"() + import ( "github.com/goplus/llgo/cl/_testgo/runextest/bar" "github.com/goplus/llgo/cl/_testgo/runextest/foo" diff --git a/cl/_testgo/runextest/out.ll b/cl/_testgo/runextest/out.ll deleted file mode 100644 index 1c8a0e7976..0000000000 --- a/cl/_testgo/runextest/out.ll +++ /dev/null @@ -1 +0,0 @@ -; \ No newline at end of file diff --git a/cl/_testgo/runtest/main.go b/cl/_testgo/runtest/main.go index 27fb6e7e6e..9ed816ace4 100644 --- a/cl/_testgo/runtest/main.go +++ b/cl/_testgo/runtest/main.go @@ -1,5 +1,10 @@ +// LITTEST package main +// CHECK-DAG: define {{(i32|i64)}} @main.Zoo(){{.*}} { +// CHECK-DAG: call {{(i32|i64)}} @"{{.*}}/cl/_testgo/runtest/foo.Foo"() +// CHECK-DAG: call {{(i32|i64)}} @"{{.*}}/cl/_testgo/runtest/bar.Bar"() + import ( "github.com/goplus/llgo/cl/_testgo/runtest/bar" "github.com/goplus/llgo/cl/_testgo/runtest/foo" diff --git a/cl/_testgo/runtest/out.ll b/cl/_testgo/runtest/out.ll deleted file mode 100644 index 1c8a0e7976..0000000000 --- a/cl/_testgo/runtest/out.ll +++ /dev/null @@ -1 +0,0 @@ -; \ No newline at end of file diff --git a/cl/_testgo/select/in.go b/cl/_testgo/select/in.go index a772e7edce..c3d80220e4 100644 --- a/cl/_testgo/select/in.go +++ b/cl/_testgo/select/in.go @@ -1,5 +1,10 @@ +// LITTEST package main +// CHECK-DAG: call ptr @"{{.*}}/runtime/internal/runtime.NewChan"({{.*}}) +// CHECK-DAG: call void @"{{.*}}/runtime/internal/runtime.NewProc"({{.*}}) +// CHECK-DAG: call { {{(i32|i64)}}, i1 } @"{{.*}}/runtime/internal/runtime.Select"({{.*}}) + func main() { send() recv() diff --git a/cl/_testgo/select/out.ll b/cl/_testgo/select/out.ll deleted file mode 100644 index 1c8a0e7976..0000000000 --- a/cl/_testgo/select/out.ll +++ /dev/null @@ -1 +0,0 @@ -; \ No newline at end of file diff --git a/cl/_testgo/syncmap/in.go b/cl/_testgo/syncmap/in.go index d734860ab5..6e6881405f 100644 --- a/cl/_testgo/syncmap/in.go +++ b/cl/_testgo/syncmap/in.go @@ -1,5 +1,10 @@ +// LITTEST package main +// CHECK-DAG: call {{.*}}sync{{.*}}Map{{.*}}Store{{.*}} +// CHECK-DAG: call {{.*}}sync{{.*}}Map{{.*}}Load{{.*}} +// CHECK-DAG: call {{.*}}sync{{.*}}Map{{.*}}Range{{.*}} + import ( "fmt" "sync" diff --git a/cl/_testgo/syncmap/out.ll b/cl/_testgo/syncmap/out.ll deleted file mode 100644 index 1c8a0e7976..0000000000 --- a/cl/_testgo/syncmap/out.ll +++ /dev/null @@ -1 +0,0 @@ -; \ No newline at end of file diff --git a/cl/_testgo/tptypes/out.ll b/cl/_testgo/tptypes/out.ll deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/cl/_testlibc/complex/in.go b/cl/_testlibc/complex/in.go index e397aad135..35427c1793 100644 --- a/cl/_testlibc/complex/in.go +++ b/cl/_testlibc/complex/in.go @@ -1,5 +1,9 @@ +// LITTEST package main +// CHECK-DAG: call float @cabsf({{.*}}) +// CHECK-DAG: call void @main.f({{.*}}, ptr @main.f) + import ( "github.com/goplus/lib/c" "github.com/goplus/lib/c/math/cmplx" diff --git a/cl/_testlibc/complex/out.ll b/cl/_testlibc/complex/out.ll deleted file mode 100644 index 1c8a0e7976..0000000000 --- a/cl/_testlibc/complex/out.ll +++ /dev/null @@ -1 +0,0 @@ -; \ No newline at end of file diff --git a/cl/_testlibc/defer/in.go b/cl/_testlibc/defer/in.go index ea42c8b144..5910a7c38e 100644 --- a/cl/_testlibc/defer/in.go +++ b/cl/_testlibc/defer/in.go @@ -1,5 +1,10 @@ +// LITTEST package main +// CHECK-DAG: call ptr @"{{.*}}/runtime/internal/runtime.GetThreadDefer"() +// CHECK-DAG: call i32 @{{.*}}setjmp(ptr %{{.*}}{{.*}}) +// CHECK-DAG: call i32 (ptr, ...) @printf({{.*}}) + import "github.com/goplus/lib/c" func f(s string) bool { diff --git a/cl/_testlibc/defer/out.ll b/cl/_testlibc/defer/out.ll deleted file mode 100644 index 1c8a0e7976..0000000000 --- a/cl/_testlibc/defer/out.ll +++ /dev/null @@ -1 +0,0 @@ -; \ No newline at end of file diff --git a/cl/_testlibc/once/in.go b/cl/_testlibc/once/in.go index 19fb8e4d8a..61d9a02e91 100644 --- a/cl/_testlibc/once/in.go +++ b/cl/_testlibc/once/in.go @@ -1,5 +1,9 @@ +// LITTEST package main +// CHECK-DAG: call i32 @pthread_once({{.*}}) +// CHECK-DAG: define void @"main.f$1"(){{.*}} { + import ( "github.com/goplus/lib/c" "github.com/goplus/lib/c/pthread/sync" diff --git a/cl/_testlibc/once/out.ll b/cl/_testlibc/once/out.ll deleted file mode 100644 index 1c8a0e7976..0000000000 --- a/cl/_testlibc/once/out.ll +++ /dev/null @@ -1 +0,0 @@ -; \ No newline at end of file diff --git a/cl/_testlibc/setjmp/in.go b/cl/_testlibc/setjmp/in.go index 898af39bfb..4111e15483 100644 --- a/cl/_testlibc/setjmp/in.go +++ b/cl/_testlibc/setjmp/in.go @@ -1,5 +1,9 @@ +// LITTEST package main +// CHECK-DAG: call i32 @{{.*}}sigsetjmp(ptr %{{.*}}, i32 0) +// CHECK-DAG: call void @{{.*}}siglongjmp(ptr %{{.*}}, i32 1) + import ( "github.com/goplus/lib/c" ) diff --git a/cl/_testlibc/setjmp/out.ll b/cl/_testlibc/setjmp/out.ll deleted file mode 100644 index 1c8a0e7976..0000000000 --- a/cl/_testlibc/setjmp/out.ll +++ /dev/null @@ -1 +0,0 @@ -; \ No newline at end of file diff --git a/cl/_testlibgo/sync/in.go b/cl/_testlibgo/sync/in.go index 1442dbbd35..7365ac3f55 100644 --- a/cl/_testlibgo/sync/in.go +++ b/cl/_testlibgo/sync/in.go @@ -1,5 +1,9 @@ +// LITTEST package main +// CHECK-DAG: call {{.*}}sync{{.*}}Once{{.*}}Do{{.*}} +// CHECK-DAG: define void @"main.f$1"(ptr {{((nest|swiftself) )?}}%{{.*}}){{.*}} { + import ( "sync" ) diff --git a/cl/_testlibgo/sync/out.ll b/cl/_testlibgo/sync/out.ll deleted file mode 100644 index 1c8a0e7976..0000000000 --- a/cl/_testlibgo/sync/out.ll +++ /dev/null @@ -1 +0,0 @@ -; \ No newline at end of file diff --git a/cl/_testlibgo/waitgroup/in.go b/cl/_testlibgo/waitgroup/in.go index 78b65d7ee8..b0fb375a63 100644 --- a/cl/_testlibgo/waitgroup/in.go +++ b/cl/_testlibgo/waitgroup/in.go @@ -1,5 +1,11 @@ +// LITTEST package main +// CHECK-DAG: call {{.*}}sync{{.*}}WaitGroup{{.*}}Add{{.*}} +// CHECK-DAG: call void @"{{.*}}/runtime/internal/runtime.NewProc"({{.*}}) +// CHECK-DAG: call {{.*}}sync{{.*}}WaitGroup{{.*}}Done{{.*}} +// CHECK-DAG: call {{.*}}sync{{.*}}WaitGroup{{.*}}Wait{{.*}} + import ( "sync" ) diff --git a/cl/_testlibgo/waitgroup/out.ll b/cl/_testlibgo/waitgroup/out.ll deleted file mode 100644 index 1c8a0e7976..0000000000 --- a/cl/_testlibgo/waitgroup/out.ll +++ /dev/null @@ -1 +0,0 @@ -; \ No newline at end of file diff --git a/cl/_testrt/builtin/out.ll b/cl/_testrt/builtin/out.ll deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/cl/_testrt/linkname/linktarget/out.ll b/cl/_testrt/linkname/linktarget/out.ll deleted file mode 100644 index 384bde3f60..0000000000 --- a/cl/_testrt/linkname/linktarget/out.ll +++ /dev/null @@ -1,55 +0,0 @@ -; ModuleID = 'github.com/goplus/llgo/cl/internal/linktarget' -source_filename = "github.com/goplus/llgo/cl/internal/linktarget" - -%"github.com/goplus/llgo/internal/runtime.String" = type { ptr, i64 } -%"github.com/goplus/llgo/cl/internal/linktarget.m" = type { %"github.com/goplus/llgo/internal/runtime.String" } - -@"github.com/goplus/llgo/cl/internal/linktarget.init$guard" = global ptr null -@0 = private unnamed_addr constant [14 x i8] c"a: %s, b: %s\0A\00", align 1 - -define void @"github.com/goplus/llgo/cl/internal/linktarget.F"(ptr %0, ptr %1) { -_llgo_0: - %2 = call i32 (ptr, ...) @printf(ptr @0, ptr %0, ptr %1) - ret void -} - -define void @"github.com/goplus/llgo/cl/internal/linktarget.init"() { -_llgo_0: - %0 = load i1, ptr @"github.com/goplus/llgo/cl/internal/linktarget.init$guard", align 1 - br i1 %0, label %_llgo_2, label %_llgo_1 - -_llgo_1: ; preds = %_llgo_0 - store i1 true, ptr @"github.com/goplus/llgo/cl/internal/linktarget.init$guard", align 1 - br label %_llgo_2 - -_llgo_2: ; preds = %_llgo_1, %_llgo_0 - ret void -} - -define %"github.com/goplus/llgo/internal/runtime.String" @"github.com/goplus/llgo/cl/internal/linktarget.m.info"(%"github.com/goplus/llgo/cl/internal/linktarget.m" %0) { -_llgo_0: - %1 = alloca %"github.com/goplus/llgo/cl/internal/linktarget.m", align 8 - %2 = call ptr @"github.com/goplus/llgo/internal/runtime.Zeroinit"(ptr %1, i64 16) - store %"github.com/goplus/llgo/cl/internal/linktarget.m" %0, ptr %2, align 8 - %3 = getelementptr inbounds %"github.com/goplus/llgo/cl/internal/linktarget.m", ptr %2, i32 0, i32 0 - %4 = load %"github.com/goplus/llgo/internal/runtime.String", ptr %3, align 8 - ret %"github.com/goplus/llgo/internal/runtime.String" %4 -} - -define %"github.com/goplus/llgo/internal/runtime.String" @"github.com/goplus/llgo/cl/internal/linktarget.(*m).info"(ptr %0) { -_llgo_0: - %1 = load %"github.com/goplus/llgo/cl/internal/linktarget.m", ptr %0, align 8 - %2 = call %"github.com/goplus/llgo/internal/runtime.String" @"github.com/goplus/llgo/cl/internal/linktarget.m.info"(%"github.com/goplus/llgo/cl/internal/linktarget.m" %1) - ret %"github.com/goplus/llgo/internal/runtime.String" %2 -} - -define void @"github.com/goplus/llgo/cl/internal/linktarget.(*m).setInfo"(ptr %0, %"github.com/goplus/llgo/internal/runtime.String" %1) { -_llgo_0: - %2 = getelementptr inbounds %"github.com/goplus/llgo/cl/internal/linktarget.m", ptr %0, i32 0, i32 0 - store %"github.com/goplus/llgo/internal/runtime.String" %1, ptr %2, align 8 - ret void -} - -declare i32 @printf(ptr, ...) - -declare ptr @"github.com/goplus/llgo/internal/runtime.Zeroinit"(ptr, i64) diff --git a/cl/_testrt/nextblock/in.go b/cl/_testrt/nextblock/in.go index 667ac314e1..c2d2f973e7 100644 --- a/cl/_testrt/nextblock/in.go +++ b/cl/_testrt/nextblock/in.go @@ -1,5 +1,11 @@ +// LITTEST package main +// CHECK-DAG: define void @main.main(){{.*}} { +// CHECK-DAG: call ptr @"{{.*}}/runtime/internal/runtime.GetThreadDefer"() +// CHECK-DAG: call i32 @{{.*}}setjmp(ptr %{{.*}}{{.*}}) +// CHECK-DAG: call void @"{{.*}}/runtime/internal/runtime.Rethrow"(ptr %{{.*}}) + func main() { syms := []int{} for range syms { diff --git a/cl/_testrt/nextblock/out.ll b/cl/_testrt/nextblock/out.ll deleted file mode 100644 index 1c8a0e7976..0000000000 --- a/cl/_testrt/nextblock/out.ll +++ /dev/null @@ -1 +0,0 @@ -; \ No newline at end of file diff --git a/cl/cltest/cltest.go b/cl/cltest/cltest.go index 4a1fc60bef..276e7a695d 100644 --- a/cl/cltest/cltest.go +++ b/cl/cltest/cltest.go @@ -17,7 +17,6 @@ package cltest import ( - "archive/zip" "bytes" "errors" "fmt" @@ -97,7 +96,7 @@ func WithOutputCheck(enabled bool) RunOption { } } -// WithIRCheck enables or disables IR golden checks in RunAndTestFromDir. +// WithIRCheck enables or disables source-embedded IR checks in RunAndTestFromDir. func WithIRCheck(enabled bool) RunOption { return func(opts *runOptions) { opts.checkIR = enabled @@ -128,9 +127,8 @@ func FilterEmulatorOutput(output string) string { return output } -// RunAndTestFromDir executes tests under relDir and validates both runtime -// output and the pre-transform package IR snapshot when the corresponding -// golden files exist. +// RunAndTestFromDir executes tests under relDir and validates runtime output +// goldens and source-embedded IR checks when present. func RunAndTestFromDir(t *testing.T, sel, relDir string, ignore []string, opts ...RunOption) { rootDir, err := os.Getwd() if err != nil { @@ -204,42 +202,6 @@ func BuildAndCheckSymbolsFromDir(t *testing.T, sel, relDir string, names []strin } } -// *.ll => *.lla -func decodeLinkFile(llFile string) (data []byte, err error) { - zipFile := llFile + "a" - zipf, err := zip.OpenReader(zipFile) - if err != nil { - return - } - defer zipf.Close() - f, err := zipf.Open(filepath.Base(llFile)) - if err != nil { - return - } - defer f.Close() - data, err = io.ReadAll(f) - if err == nil { - os.WriteFile(llFile, data, 0644) - } - return -} - -func Pkg(t *testing.T, pkgPath, outFile string) { - b, err := os.ReadFile(outFile) - if err != nil { - if !os.IsNotExist(err) { - t.Fatal("ReadFile failed:", err) - } - if b, err = decodeLinkFile(outFile); err != nil { - t.Fatal("decodeLinkFile failed:", err) - } - } - expected := string(b) - if v := llgen.GenFrom(pkgPath); v != expected { - t.Fatalf("\n==> got:\n%s\n==> expected:\n%s\n", v, expected) - } -} - func testFrom(t *testing.T, pkgDir, sel string) { t.Helper() if sel != "" && !strings.Contains(pkgDir, sel) { @@ -249,22 +211,13 @@ func testFrom(t *testing.T, pkgDir, sel string) { if err != nil { t.Fatal("LoadSpec failed:", err) } - if spec.Mode == littest.ModeSkip { - return - } var v string withFuncInfoDisabled(func() { v = llgen.GenFrom(pkgDir) }) - if spec.Mode == littest.ModeFileCheck { - if err := littest.Check(spec, v); err != nil { - _ = os.WriteFile(pkgDir+"/result.txt", []byte(v), 0644) - t.Fatal(err) - } - return - } - if test.Diff(t, pkgDir+"/result.txt", []byte(v), []byte(spec.Text)) { - t.Fatal("llgen.GenFrom: unexpected result") + if err := littest.Check(spec, v); err != nil { + _ = os.WriteFile(pkgDir+"/result.txt", []byte(v), 0644) + t.Fatal(err) } } @@ -285,8 +238,8 @@ func testRunAndTestFrom(t *testing.T, pkgDir, relPkg, sel string, opts runOption } } if !checkOutput { - // IR-only mode: when expect.txt is not checked, use llgen.GenFrom via - // testFrom to compare this package's generated IR against out.ll. + // IR-only mode: when expect.txt is not checked, use the source-embedded + // FileCheck directives for this package. if opts.checkIR { testFrom(t, pkgDir, sel) } @@ -704,8 +657,7 @@ func symbolTable(bin string) (string, error) { func readIRSpec(pkgDir string) (littest.Spec, bool, error) { spec, err := littest.LoadSpec(pkgDir) if err != nil { - var pathErr *os.PathError - if errors.Is(err, os.ErrNotExist) && errors.As(err, &pathErr) && filepath.Clean(pathErr.Path) == filepath.Join(pkgDir, "out.ll") { + if errors.Is(err, littest.ErrSpecNotFound) { return littest.Spec{}, false, nil } return littest.Spec{}, false, err @@ -802,7 +754,7 @@ func CompileIREx(t *testing.T, src any, fname string, dbg bool, configure func(l func TestCompileEx(t *testing.T, src any, fname, expected string, dbg bool) { t.Helper() v := CompileIREx(t, src, fname, dbg, nil) - if llssa.StripModuleTarget(v) != expected && expected != ";" { // expected == ";" means skipping out.ll + if llssa.StripModuleTarget(v) != expected && expected != ";" { // expected == ";" skips this inline comparison t.Fatalf("\n==> got:\n%s\n==> expected:\n%s\n", v, expected) } } diff --git a/cl/cltest/cltest_test.go b/cl/cltest/cltest_test.go index 636295b984..7f01f49fee 100644 --- a/cl/cltest/cltest_test.go +++ b/cl/cltest/cltest_test.go @@ -61,3 +61,22 @@ func TestReadGoldenReturnsVersionedReadError(t *testing.T) { t.Fatal("readGolden() succeeded for a versioned golden directory") } } + +func TestReadIRSpecRequiresSourceMarker(t *testing.T) { + dir := t.TempDir() + path := filepath.Join(dir, "in.go") + if err := os.WriteFile(path, []byte("package main\n"), 0o644); err != nil { + t.Fatal(err) + } + if _, ok, err := readIRSpec(dir); err != nil || ok { + t.Fatalf("readIRSpec(unmarked) = (_, %v, %v), want (_, false, nil)", ok, err) + } + + if err := os.WriteFile(path, []byte("// LITTEST\npackage main\n// CHECK: define\n"), 0o644); err != nil { + t.Fatal(err) + } + spec, ok, err := readIRSpec(dir) + if err != nil || !ok || spec.Path != path { + t.Fatalf("readIRSpec(marked) = (%q, %v, %v), want (%q, true, nil)", spec.Path, ok, err, path) + } +} diff --git a/cl/compile_test.go b/cl/compile_test.go index 5eecf6cbd5..157eef34b5 100644 --- a/cl/compile_test.go +++ b/cl/compile_test.go @@ -31,7 +31,6 @@ import ( "github.com/goplus/llgo/internal/build" "github.com/goplus/llgo/internal/buildenv" "github.com/goplus/llgo/internal/cabi" - "github.com/goplus/llgo/internal/llgen" "github.com/goplus/llgo/internal/lto" llvmenv "github.com/goplus/llgo/xtool/env/llvm" ) @@ -565,16 +564,6 @@ func TestRunAndTestFromTestdata(t *testing.T) { cltest.RunAndTestFromDir(t, "", "./_testdata", nil) } -func TestCgofullGeneratesC2func(t *testing.T) { - ir := llgen.GenFrom("./_testgo/cgofull") - if !strings.Contains(ir, "_C2func_test_structs") { - t.Fatal("missing _C2func_test_structs in cgofull IR") - } - if !strings.Contains(ir, "cliteErrno") { - t.Fatal("missing cliteErrno call in cgofull IR") - } -} - func TestGoPkgMath(t *testing.T) { conf := build.NewDefaultConf(build.ModeInstall) _, err := build.Do([]string{"math"}, conf) diff --git a/internal/build/build.go b/internal/build/build.go index 4e3ae2a499..f85579a450 100644 --- a/internal/build/build.go +++ b/internal/build/build.go @@ -455,7 +455,7 @@ func Build(inv Invocation) ([]Package, error) { prog := llssa.NewProgram(target) prog.DisableBoundsChecks(conf.DisableBoundsChecks) if conf.Mode != ModeGen { - // ModeGen callers (llgen and the golden suites) read LPkg.String() + // ModeGen callers (IR generation and IR-check suites) read LPkg.String() // after Do returns and dispose the program themselves; every other // mode's outputs are files or a spawned process, so the compile's // LLVM context can be released when Do finishes. In-process diff --git a/internal/littest/littest.go b/internal/littest/littest.go index 0147603631..8f4e4e148e 100644 --- a/internal/littest/littest.go +++ b/internal/littest/littest.go @@ -18,7 +18,6 @@ package littest import ( "bufio" - "bytes" "errors" "fmt" "os" @@ -28,71 +27,28 @@ import ( "github.com/goplus/llgo/internal/filecheck" ) -type Mode int - -const ( - ModeSkip Mode = iota - ModeLiteral - ModeFileCheck -) - type Spec struct { Path string - Text string - Mode Mode } const Marker = "LITTEST" -func LoadSpec(pkgDir string) (Spec, error) { - if spec, ok, err := loadSourceSpec(pkgDir); err != nil { - return Spec{}, err - } else if ok { - return spec, nil - } +// ErrSpecNotFound reports that a package has no source file marked LITTEST. +var ErrSpecNotFound = errors.New("IR check spec not found") - path := filepath.Join(pkgDir, "out.ll") - data, err := os.ReadFile(path) +func LoadSpec(pkgDir string) (Spec, error) { + marked, ok, err := FindMarkedSourceFile(pkgDir) if err != nil { return Spec{}, err } - if bytes.Equal(data, []byte{';'}) { - return Spec{Path: path, Mode: ModeSkip}, nil + if !ok { + return Spec{}, fmt.Errorf("%w: %s", ErrSpecNotFound, pkgDir) } - return Spec{Path: path, Text: string(data), Mode: ModeLiteral}, nil + return Spec{Path: marked}, nil } func Check(spec Spec, actual string) error { - switch spec.Mode { - case ModeSkip: - return nil - case ModeFileCheck: - return filecheck.Match(spec.Path, actual) - case ModeLiteral: - if actual != spec.Text { - return fmt.Errorf("%s: literal LLVM IR mismatch", spec.Path) - } - return nil - default: - return errors.New("unknown lit spec mode") - } -} - -func loadSourceSpec(pkgDir string) (Spec, bool, error) { - marked, ok, err := FindMarkedSourceFile(pkgDir) - if err != nil { - return Spec{}, false, err - } - if !ok { - return Spec{}, false, nil - } - if marked == "" { - return Spec{}, false, nil - } - return Spec{ - Path: marked, - Mode: ModeFileCheck, - }, true, nil + return filecheck.Match(spec.Path, actual) } func FindMarkedSourceFile(dir string) (string, bool, error) { diff --git a/internal/littest/littest_test.go b/internal/littest/littest_test.go index d02d899375..ae8643f44f 100644 --- a/internal/littest/littest_test.go +++ b/internal/littest/littest_test.go @@ -1,167 +1,99 @@ package littest import ( + "errors" "os" "path/filepath" "strings" "testing" ) -func TestLoadSpecPrefersMarkedSourceOverOutLL(t *testing.T) { +func TestLoadSpec(t *testing.T) { dir := t.TempDir() - err := os.WriteFile(filepath.Join(dir, "in.go"), []byte(`// LITTEST + path := filepath.Join(dir, "in.go") + writeTestFile(t, path, `// LITTEST // CHECK: ret void package main func main() {} -`), 0644) - if err != nil { - t.Fatal(err) - } - err = os.WriteFile(filepath.Join(dir, "out.ll"), []byte(`; ModuleID = 'main' -define void @main() { - ret void -} -`), 0644) - if err != nil { - t.Fatal(err) - } +`) spec, err := LoadSpec(dir) if err != nil { t.Fatal(err) } - if spec.Mode != ModeFileCheck { - t.Fatalf("spec.Mode = %v, want %v", spec.Mode, ModeFileCheck) - } - if spec.Path != filepath.Join(dir, "in.go") { - t.Fatalf("spec.Path = %q", spec.Path) + if spec.Path != path { + t.Fatalf("spec.Path = %q, want %q", spec.Path, path) } } func TestLoadSpecReportsMissingDirectory(t *testing.T) { _, err := LoadSpec(filepath.Join(t.TempDir(), "missing")) - if err == nil { - t.Fatal("LoadSpec succeeded unexpectedly") + if err == nil || errors.Is(err, ErrSpecNotFound) { + t.Fatalf("LoadSpec missing directory error = %v", err) } } -func TestLoadSpecRejectsMultipleMarkedSources(t *testing.T) { +func TestLoadSpecReportsMissingMarker(t *testing.T) { dir := t.TempDir() - err := os.WriteFile(filepath.Join(dir, "a.go"), []byte(`// LITTEST -// CHECK: ret void -package main -`), 0644) - if err != nil { - t.Fatal(err) - } - err = os.WriteFile(filepath.Join(dir, "b.go"), []byte(`// LITTEST -// CHECK: unreachable -package main -`), 0644) - if err != nil { - t.Fatal(err) - } - _, err = LoadSpec(dir) - if err == nil { - t.Fatal("LoadSpec succeeded unexpectedly") - } -} - -func TestLoadSpecWorksWithoutOutLLWhenSourceChecksExist(t *testing.T) { - dir := t.TempDir() - err := os.WriteFile(filepath.Join(dir, "in.go"), []byte(`// LITTEST -package main - -// CHECK: ret void -func main() {} -`), 0644) - if err != nil { - t.Fatal(err) - } - spec, err := LoadSpec(dir) - if err != nil { - t.Fatal(err) - } - if spec.Path != filepath.Join(dir, "in.go") { - t.Fatalf("spec.Path = %q", spec.Path) + writeTestFile(t, filepath.Join(dir, "in.go"), "package main\n") + _, err := LoadSpec(dir) + if !errors.Is(err, ErrSpecNotFound) { + t.Fatalf("LoadSpec error = %v, want ErrSpecNotFound", err) } } -func TestCheckReportsMalformedDirective(t *testing.T) { +func TestLoadSpecRejectsMultipleMarkedSources(t *testing.T) { dir := t.TempDir() - path := filepath.Join(dir, "in.go") - err := os.WriteFile(path, []byte(`// LITTEST -// CHECK: {{[invalid -package main -`), 0644) - if err != nil { - t.Fatal(err) - } - spec, err := LoadSpec(dir) - if err != nil { - t.Fatal(err) - } - err = Check(spec, "") - if err == nil { - t.Fatal("Check succeeded unexpectedly") - } - if !strings.Contains(err.Error(), "found start of regex string with no end") { - t.Fatalf("unexpected error: %v", err) + writeTestFile(t, filepath.Join(dir, "a.go"), "// LITTEST\npackage main\n") + writeTestFile(t, filepath.Join(dir, "b.go"), "// LITTEST\npackage main\n") + if _, err := LoadSpec(dir); err == nil { + t.Fatal("LoadSpec succeeded unexpectedly") } } -func TestLoadSpecFallsBackToOutLLWithoutMarker(t *testing.T) { - dir := t.TempDir() - err := os.WriteFile(filepath.Join(dir, "in.go"), []byte(`// CHECK: ret void -package main -`), 0644) - if err != nil { - t.Fatal(err) - } - err = os.WriteFile(filepath.Join(dir, "out.ll"), []byte(`; ModuleID = 'main' -define void @main() { - ret void -} -`), 0644) - if err != nil { - t.Fatal(err) - } - spec, err := LoadSpec(dir) - if err != nil { - t.Fatal(err) - } - if spec.Path != filepath.Join(dir, "out.ll") { - t.Fatalf("spec.Path = %q", spec.Path) - } - if spec.Mode != ModeLiteral { - t.Fatalf("spec.Mode = %v", spec.Mode) +func TestLoadSpecMarkerRules(t *testing.T) { + tests := []struct { + name string + file string + text string + }{ + {name: "not first line", file: "in.go", text: "\n// LITTEST\npackage main\n"}, + {name: "not Go comment", file: "in.go", text: "# LITTEST\npackage main\n"}, + {name: "not Go source", file: "in.c", text: "// LITTEST\n"}, + {name: "test file", file: "in_test.go", text: "// LITTEST\npackage main\n"}, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + dir := t.TempDir() + writeTestFile(t, filepath.Join(dir, tt.file), tt.text) + _, err := LoadSpec(dir) + if !errors.Is(err, ErrSpecNotFound) { + t.Fatalf("LoadSpec error = %v, want ErrSpecNotFound", err) + } + }) } } -func TestLoadSpecReportsMissingOutLL(t *testing.T) { +func TestCheck(t *testing.T) { dir := t.TempDir() - err := os.WriteFile(filepath.Join(dir, "in.go"), []byte("package main\n"), 0644) - if err != nil { + path := filepath.Join(dir, "in.go") + writeTestFile(t, path, "// CHECK: ret void\n") + spec := Spec{Path: path} + if err := Check(spec, " ret void\n"); err != nil { t.Fatal(err) } - _, err = LoadSpec(dir) - if err == nil { - t.Fatal("LoadSpec succeeded unexpectedly") + if err := Check(spec, " unreachable\n"); err == nil { + t.Fatal("Check succeeded unexpectedly") } } -func TestLoadSpecSupportsSkipOutLL(t *testing.T) { +func TestCheckReportsMalformedDirective(t *testing.T) { dir := t.TempDir() - err := os.WriteFile(filepath.Join(dir, "out.ll"), []byte(`;`), 0644) - if err != nil { - t.Fatal(err) - } - spec, err := LoadSpec(dir) - if err != nil { - t.Fatal(err) - } - if spec.Mode != ModeSkip { - t.Fatalf("spec.Mode = %v", spec.Mode) + path := filepath.Join(dir, "in.go") + writeTestFile(t, path, "// CHECK: {{[invalid\n") + err := Check(Spec{Path: path}, "") + if err == nil || !strings.Contains(err.Error(), "found start of regex string with no end") { + t.Fatalf("Check error = %v", err) } } @@ -173,158 +105,31 @@ func TestHasMarker(t *testing.T) { t.Fatalf("HasMarker(missing) = (%v, %v)", ok, err) } - empty := filepath.Join(dir, "empty.go") - err = os.WriteFile(empty, nil, 0644) - if err != nil { - t.Fatal(err) - } - ok, err = HasMarker(empty) - if err != nil || ok { - t.Fatalf("HasMarker(empty) = (%v, %v)", ok, err) - } - - plain := filepath.Join(dir, "plain.go") - err = os.WriteFile(plain, []byte("package main\n"), 0644) - if err != nil { - t.Fatal(err) - } - ok, err = HasMarker(plain) - if err != nil || ok { - t.Fatalf("HasMarker(plain) = (%v, %v)", ok, err) - } -} - -func TestCheck(t *testing.T) { - checkPath := filepath.Join(t.TempDir(), "check.go") - if err := os.WriteFile(checkPath, []byte("// CHECK: ok\n"), 0644); err != nil { - t.Fatal(err) - } - - cases := []struct { + tests := []struct { name string - spec Spec text string - want string + want bool }{ - { - name: "skip", - spec: Spec{Path: "skip", Mode: ModeSkip}, - }, - { - name: "literal match", - spec: Spec{Path: "literal", Text: "ok", Mode: ModeLiteral}, - text: "ok", - }, - { - name: "literal mismatch", - spec: Spec{Path: "literal", Text: "ok", Mode: ModeLiteral}, - text: "bad", - want: "literal LLVM IR mismatch", - }, - { - name: "filecheck match", - spec: Spec{Path: checkPath, Mode: ModeFileCheck}, - text: "ok\n", - }, - { - name: "invalid mode", - spec: Spec{Path: "bad", Mode: Mode(99)}, - want: "unknown lit spec mode", - }, - } - for _, tc := range cases { - t.Run(tc.name, func(t *testing.T) { - err := Check(tc.spec, tc.text) - if tc.want == "" { - if err != nil { - t.Fatal(err) - } - return - } - if err == nil { - t.Fatal("Check succeeded unexpectedly") - } - if !strings.Contains(err.Error(), tc.want) { - t.Fatalf("unexpected error: %v", err) + {name: "empty"}, + {name: "plain", text: "package main\n"}, + {name: "marker", text: "// LITTEST\npackage main\n", want: true}, + {name: "trimmed marker", text: " // LITTEST \npackage main\n", want: true}, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + path := filepath.Join(dir, tt.name+".go") + writeTestFile(t, path, tt.text) + got, err := HasMarker(path) + if err != nil || got != tt.want { + t.Fatalf("HasMarker = (%v, %v), want (%v, nil)", got, err, tt.want) } }) } } -func TestLoadSpecRequiresMarkerOnFirstLine(t *testing.T) { - dir := t.TempDir() - err := os.WriteFile(filepath.Join(dir, "in.go"), []byte(` -// LITTEST -// CHECK: ret void -package main -`), 0644) - if err != nil { +func writeTestFile(t *testing.T, path, text string) { + t.Helper() + if err := os.WriteFile(path, []byte(text), 0o644); err != nil { t.Fatal(err) } - err = os.WriteFile(filepath.Join(dir, "out.ll"), []byte(`; ModuleID = 'main' -define void @main() { - ret void -} -`), 0644) - if err != nil { - t.Fatal(err) - } - spec, err := LoadSpec(dir) - if err != nil { - t.Fatal(err) - } - if spec.Path != filepath.Join(dir, "out.ll") { - t.Fatalf("spec.Path = %q", spec.Path) - } -} - -func TestLoadSpecRequiresSlashSlashMarker(t *testing.T) { - dir := t.TempDir() - err := os.WriteFile(filepath.Join(dir, "in.go"), []byte(`# LITTEST -// CHECK: ret void -package main -`), 0644) - if err != nil { - t.Fatal(err) - } - err = os.WriteFile(filepath.Join(dir, "out.ll"), []byte(`; ModuleID = 'main' -define void @main() { - ret void -} -`), 0644) - if err != nil { - t.Fatal(err) - } - spec, err := LoadSpec(dir) - if err != nil { - t.Fatal(err) - } - if spec.Path != filepath.Join(dir, "out.ll") { - t.Fatalf("spec.Path = %q", spec.Path) - } -} - -func TestLoadSpecIgnoresNonGoFiles(t *testing.T) { - dir := t.TempDir() - err := os.WriteFile(filepath.Join(dir, "in.c"), []byte(`// LITTEST -// CHECK: ret void -`), 0644) - if err != nil { - t.Fatal(err) - } - err = os.WriteFile(filepath.Join(dir, "out.ll"), []byte(`; ModuleID = 'main' -define void @main() { - ret void -} -`), 0644) - if err != nil { - t.Fatal(err) - } - spec, err := LoadSpec(dir) - if err != nil { - t.Fatal(err) - } - if spec.Path != filepath.Join(dir, "out.ll") { - t.Fatalf("spec.Path = %q", spec.Path) - } } diff --git a/internal/llgen/llgenf.go b/internal/llgen/llgenf.go index 1e45eaf26d..62eeddda7c 100644 --- a/internal/llgen/llgenf.go +++ b/internal/llgen/llgenf.go @@ -19,7 +19,6 @@ package llgen import ( "fmt" "os" - "os/exec" "path/filepath" "strings" @@ -29,21 +28,20 @@ import ( ) func GenFrom(fileOrPkg string) string { - pkg, err := genFrom(fileOrPkg, 0) + pkg, err := genFrom(fileOrPkg) check(err) out := pkg.LPkg.String() - // Release the compile's LLVM context: golden suites call GenFrom for + // Release the compile's LLVM context: IR-check suites call GenFrom for // every test dir inside one process, and undisposed contexts // accumulate C++-side memory for the whole run. pkg.LPkg.Prog.Dispose() return out } -func genFrom(pkgPath string, abiMode build.AbiMode) (build.Package, error) { +func genFrom(pkgPath string) (build.Package, error) { conf := &build.Config{ - Mode: build.ModeGen, - AbiMode: abiMode, - GenLL: true, + Mode: build.ModeGen, + GenLL: true, } if err := applyFlagsFile(conf, filepath.Join(pkgPath, "flags.txt")); err != nil { return nil, err @@ -55,12 +53,6 @@ func genFrom(pkgPath string, abiMode build.AbiMode) (build.Package, error) { return pkgs[0], nil } -func DoFile(fileOrPkg, outFile string) { - ret := GenFrom(fileOrPkg) - err := os.WriteFile(outFile, []byte(ret), 0644) - check(err) -} - func readFlags(flagsFile string) ([]string, error) { data, err := os.ReadFile(flagsFile) if os.IsNotExist(err) { @@ -118,46 +110,3 @@ func applyFlagsFile(conf *build.Config, flagsFile string) error { *conf = next return nil } - -func SmartDoFile(pkgPath string) { - SmartDoFileEx(pkgPath, 0) -} - -func SmartDoFileEx(pkgPath string, abiMode build.AbiMode) { - pkg, err := genFrom(pkgPath, abiMode) - check(err) - - const autgenFile = "llgo_autogen.ll" - dir, _ := filepath.Split(pkg.GoFiles[0]) - absDir, _ := filepath.Abs(dir) - absDir = filepath.ToSlash(absDir) - fname := autgenFile - if inCompilerDir(absDir) { - fname = "out.ll" - } - outFile := dir + fname - - b, err := os.ReadFile(outFile) - if err == nil && len(b) == 1 && b[0] == ';' { - return // skip to gen - } - - if err = os.WriteFile(outFile, []byte(pkg.LPkg.String()), 0644); err != nil { - panic(err) - } - if false && fname == autgenFile { - genZip(absDir, "llgo_autogen.lla", autgenFile) - } -} - -func genZip(dir string, outFile, inFile string) { - cmd := exec.Command("zip", outFile, inFile) - cmd.Dir = dir - cmd.Stdout = os.Stdout - cmd.Stderr = os.Stderr - cmd.Run() -} - -func inCompilerDir(dir string) bool { - return strings.Contains(dir, "/cl/_test") -} diff --git a/ssa/package.go b/ssa/package.go index 498bbaf942..8f590a61eb 100644 --- a/ssa/package.go +++ b/ssa/package.go @@ -278,7 +278,7 @@ func is32Bits(arch string) bool { // (and with it every module built in it), the target machine and the // target data. The Program and everything created from it must not be // used afterwards. In-process drivers that compile many packages -// sequentially (llgen goldens, the cltest run harness) call this between +// sequentially (IR checks and the cltest run harness) call this between // compiles; without it each compile's C++-side memory lives until the // process exits. func (p Program) Dispose() { diff --git a/test/go/defer_ir_regression_test.go b/test/go/defer_ir_regression_test.go index 46c17e891a..212ad81328 100644 --- a/test/go/defer_ir_regression_test.go +++ b/test/go/defer_ir_regression_test.go @@ -22,6 +22,8 @@ import ( "path/filepath" "strings" "testing" + + "github.com/goplus/llgo/internal/llgen" ) const recoverThenDeferredPanicProbe = `package main @@ -102,12 +104,7 @@ func llgoIRFromProbe(t *testing.T, name, src string) string { t.Fatal(err) } - runGoCmd(t, root, "run", "./chore/llgen", filepath.ToSlash(dir)) - data, err := os.ReadFile(filepath.Join(dir, "llgo_autogen.ll")) - if err != nil { - t.Fatal(err) - } - return string(data) + return llgen.GenFrom(filepath.ToSlash(dir)) } func assertNoInstructionsAfterUnreachable(t *testing.T, ir string) { From 2381bb9b69bbed0bba4463b79fb858c00c46bafc Mon Sep 17 00:00:00 2001 From: Li Jie Date: Tue, 4 Aug 2026 13:16:47 +0800 Subject: [PATCH 63/73] test(build): cover DebugRef move boundaries --- internal/build/ssa_order_fix_test.go | 28 ++++++++++++++++++++++++++++ 1 file changed, 28 insertions(+) diff --git a/internal/build/ssa_order_fix_test.go b/internal/build/ssa_order_fix_test.go index 3ddbc8ee71..2c416b0e67 100644 --- a/internal/build/ssa_order_fix_test.go +++ b/internal/build/ssa_order_fix_test.go @@ -162,6 +162,34 @@ func TestFixSSAOrderCryptoX509ParseOID(t *testing.T) { checkReturnLoadAfterMutation(t, pkg.Func("ParseOID"), "unmarshalOIDText") } +func TestDebugRefMoveHelpers(t *testing.T) { + movedValue := &ssa.BinOp{} + instrs := []ssa.Instruction{ + movedValue, + &ssa.DebugRef{X: movedValue}, + &ssa.Return{Results: []ssa.Value{movedValue}}, + } + + moved := movedValuesForIndices(instrs, map[int]struct{}{ + -1: {}, + 0: {}, + 2: {}, + len(instrs): {}, + }) + if len(moved) != 1 { + t.Fatalf("moved values = %d, want 1", len(moved)) + } + if _, ok := moved[movedValue]; !ok { + t.Fatal("moved values do not contain the selected SSA value") + } + + move := map[int]struct{}{0: {}} + includeDebugRefsForMovedValues(instrs, move, moved, -1, len(instrs)+1) + if _, ok := move[1]; !ok { + t.Fatal("DebugRef for the moved value was not included") + } +} + func TestMoveInstrsAfter(t *testing.T) { const src = `package p func f() { From d9b118f108988390955188f7b286f6dbc0b77bb1 Mon Sep 17 00:00:00 2001 From: Li Jie Date: Tue, 4 Aug 2026 13:19:19 +0800 Subject: [PATCH 64/73] test: keep existing IR tooling unchanged --- chore/gentests/gentests.go | 160 +++++++++++++ chore/gentests/gentests_test.go | 35 +++ chore/litgen/rewrite.go | 4 +- chore/llgen/llgen.go | 41 ++++ chore/llgen/llgen_test.go | 65 ++++++ cl/cltest/cltest.go | 68 +++++- cl/cltest/cltest_test.go | 19 -- cl/compile_test.go | 11 + internal/build/build.go | 2 +- internal/littest/littest.go | 60 ++++- internal/littest/littest_test.go | 333 ++++++++++++++++++++++------ internal/llgen/llgenf.go | 61 ++++- ssa/package.go | 2 +- test/go/defer_ir_regression_test.go | 9 +- 14 files changed, 752 insertions(+), 118 deletions(-) create mode 100644 chore/gentests/gentests.go create mode 100644 chore/gentests/gentests_test.go create mode 100644 chore/llgen/llgen.go create mode 100644 chore/llgen/llgen_test.go diff --git a/chore/gentests/gentests.go b/chore/gentests/gentests.go new file mode 100644 index 0000000000..c306925bf3 --- /dev/null +++ b/chore/gentests/gentests.go @@ -0,0 +1,160 @@ +/* + * Copyright (c) 2024 The XGo Authors (xgo.dev). All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package main + +import ( + "fmt" + "os" + "path/filepath" + "strings" + + "github.com/goplus/llgo/cl/cltest" + "github.com/goplus/llgo/internal/build" + "github.com/goplus/llgo/internal/littest" + "github.com/goplus/llgo/internal/llgen" + "github.com/goplus/llgo/internal/lto" + "github.com/goplus/llgo/xtool/env/llvm" + "github.com/goplus/mod" +) + +func main() { + llvm.SetupPath() + dir, _, err := mod.FindGoMod(".") + check(err) + + llgenDir(dir + "/cl/_testlibc") + llgenDir(dir + "/cl/_testlibgo") + llgenDir(dir + "/cl/_testrt") + llgenDir(dir + "/cl/_testgo") + llgenDir(dir + "/cl/_testpy") + llgenDir(dir + "/cl/_testdata") + genMetaDir(dir + "/cl/_testmeta") + + genExpects(dir) +} + +func llgenDir(dir string) { + fis, err := os.ReadDir(dir) + check(err) + for _, fi := range fis { + name := fi.Name() + if !fi.IsDir() || strings.HasPrefix(name, "_") { + continue + } + testDir := dir + "/" + name + skip, err := dirHasLITTESTSource(testDir) + check(err) + if skip { + fmt.Fprintln(os.Stderr, "skip llgen", testDir, "(// LITTEST)") + continue + } + fmt.Fprintln(os.Stderr, "llgen", testDir) + check(os.Chdir(testDir)) + llgen.SmartDoFile(testDir) + } +} + +func genExpects(root string) { + runExpectDir(root, "cl/_testlibc") + runExpectDir(root, "cl/_testlibgo") + runExpectDir(root, "cl/_testrt") + runExpectDir(root, "cl/_testgo") + runExpectDir(root, "cl/_testlto", func(conf *build.Config) { + conf.LTO = lto.Full + }) + runExpectDir(root, "cl/_testpy") + runExpectDir(root, "cl/_testdata") +} + +func genMetaDir(dir string) { + fis, err := os.ReadDir(dir) + check(err) + for _, fi := range fis { + name := fi.Name() + if !fi.IsDir() || strings.HasPrefix(name, "_") { + continue + } + testDir := filepath.Join(dir, name) + if _, err := os.Stat(filepath.Join(testDir, "in.go")); err != nil { + if os.IsNotExist(err) { + continue + } + check(err) + } + relPath, err := filepath.Rel(filepath.Dir(filepath.Dir(dir)), testDir) + check(err) + relPath = filepath.ToSlash(relPath) + fmt.Fprintln(os.Stderr, "meta", relPath) + meta, err := cltest.CaptureMeta("./"+relPath, testDir) + if err != nil { + fmt.Fprintln(os.Stderr, "error:", relPath, err) + continue + } + check(os.WriteFile(filepath.Join(testDir, "meta-expect.txt"), []byte(meta), 0644)) + } +} + +func runExpectDir(root, relDir string, configure ...func(*build.Config)) { + dir := filepath.Join(root, relDir) + fis, err := os.ReadDir(dir) + check(err) + for _, fi := range fis { + name := fi.Name() + if !fi.IsDir() || strings.HasPrefix(name, "_") { + continue + } + relPath := filepath.ToSlash(filepath.Join(relDir, name)) + testDir := filepath.Join(dir, name) + fmt.Fprintln(os.Stderr, "expect", relPath) + pkgPath := "./" + relPath + var output []byte + if len(configure) == 0 { + output, err = cltest.RunAndCapture(pkgPath, testDir) + } else { + conf := build.NewDefaultConf(build.ModeRun) + for _, configure := range configure { + configure(conf) + } + output, err = cltest.RunAndCaptureWithConf(pkgPath, testDir, conf) + } + if err != nil { + fmt.Fprintln(os.Stderr, "error:", relPath, err) + output = []byte{';'} + } + expectFile := filepath.Join(testDir, "expect.txt") + expect, err := os.ReadFile(expectFile) + if err != nil || strings.TrimSpace(string(expect)) == ";" { + fmt.Fprintln(os.Stderr, "skip", relPath, "(expect is ';')") + continue + } + check(os.WriteFile(expectFile, output, 0644)) + } +} + +func check(err error) { + if err != nil { + panic(err) + } +} + +func dirHasLITTESTSource(dir string) (bool, error) { + _, ok, err := littest.FindMarkedSourceFile(dir) + if err != nil { + return false, err + } + return ok, nil +} diff --git a/chore/gentests/gentests_test.go b/chore/gentests/gentests_test.go new file mode 100644 index 0000000000..4a212969fc --- /dev/null +++ b/chore/gentests/gentests_test.go @@ -0,0 +1,35 @@ +package main + +import ( + "os" + "path/filepath" + "testing" +) + +func TestDirHasLITTESTSource(t *testing.T) { + dir := t.TempDir() + if err := os.WriteFile(filepath.Join(dir, "in.go"), []byte("// LITTEST\npackage main\n"), 0644); err != nil { + t.Fatal(err) + } + ok, err := dirHasLITTESTSource(dir) + if err != nil { + t.Fatal(err) + } + if !ok { + t.Fatal("dirHasLITTESTSource = false, want true") + } +} + +func TestDirHasLITTESTSource_IgnoresUnmarkedFiles(t *testing.T) { + dir := t.TempDir() + if err := os.WriteFile(filepath.Join(dir, "in.go"), []byte("package main\n"), 0644); err != nil { + t.Fatal(err) + } + ok, err := dirHasLITTESTSource(dir) + if err != nil { + t.Fatal(err) + } + if ok { + t.Fatal("dirHasLITTESTSource = true, want false") + } +} diff --git a/chore/litgen/rewrite.go b/chore/litgen/rewrite.go index cf86e811f7..37585a9a9c 100644 --- a/chore/litgen/rewrite.go +++ b/chore/litgen/rewrite.go @@ -120,9 +120,9 @@ func genIR(target string) (ret string, err error) { if r := recover(); r != nil { switch v := r.(type) { case error: - err = fmt.Errorf("IR generation failed for %s: %w", target, v) + err = fmt.Errorf("llgen failed for %s: %w", target, v) case string: - err = fmt.Errorf("IR generation failed for %s: %s", target, v) + err = fmt.Errorf("llgen failed for %s: %s", target, v) default: _, _ = os.Stderr.Write(debug.Stack()) panic(r) diff --git a/chore/llgen/llgen.go b/chore/llgen/llgen.go new file mode 100644 index 0000000000..f4050d3128 --- /dev/null +++ b/chore/llgen/llgen.go @@ -0,0 +1,41 @@ +/* + * Copyright (c) 2024 The XGo Authors (xgo.dev). All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package main + +import ( + "flag" + "fmt" + "os" + + "github.com/goplus/llgo/internal/build" + "github.com/goplus/llgo/internal/llgen" + "github.com/goplus/llgo/xtool/env/llvm" +) + +var ( + abi = flag.Int("abi", 0, "ABI mode (default 0). 0 = none, 1 = cfunc, 2 = allfunc.") +) + +func main() { + llvm.SetupPath() + flag.Parse() + if len(flag.Args()) != 1 { + fmt.Fprintln(os.Stderr, "Usage: llgen [flags] ") + return + } + llgen.SmartDoFileEx(flag.Args()[0], build.AbiMode(*abi)) +} diff --git a/chore/llgen/llgen_test.go b/chore/llgen/llgen_test.go new file mode 100644 index 0000000000..5972943b09 --- /dev/null +++ b/chore/llgen/llgen_test.go @@ -0,0 +1,65 @@ +//go:build !llgo +// +build !llgo + +package main + +import ( + "log" + "os" + "path/filepath" + "strings" + "testing" +) + +func TestMain(t *testing.T) { + // Create test package in current module + testPkg := filepath.Join(".testdata_dont_commit", "hello") + err := os.MkdirAll(testPkg, 0755) + if err != nil { + t.Fatal(err) + } + defer os.RemoveAll(filepath.Join(".testdata_dont_commit")) + + helloFile := filepath.Join(testPkg, "hello.go") + err = os.WriteFile(helloFile, []byte(`package hello + +func Hello() string { + return "Hello, World!" +} +`), 0644) + if err != nil { + t.Fatal(err) + } + + // Save original args and restore them after test + oldArgs := os.Args + defer func() { os.Args = oldArgs }() + + // Get absolute path to test package + absTestPkg, err := filepath.Abs(testPkg) + if err != nil { + t.Fatal(err) + } + + // Set test arguments + os.Args = []string{"llgen", absTestPkg} + + // Run main + main() + + // Check if the output file exists + outputFile := filepath.Join(testPkg, "llgo_autogen.ll") + log.Printf("Generated file: %s", filepath.Join(absTestPkg, "llgo_autogen.ll")) + if _, err = os.Stat(outputFile); err != nil { + t.Fatalf("Generated file should exist: %v", err) + } + + // Read and verify file content + content, err := os.ReadFile(outputFile) + if err != nil { + t.Fatalf("Should be able to read generated file: %v", err) + } + if !strings.Contains(string(content), "define") { + t.Error("Generated file should contain LLVM IR code") + } +} diff --git a/cl/cltest/cltest.go b/cl/cltest/cltest.go index 276e7a695d..4a1fc60bef 100644 --- a/cl/cltest/cltest.go +++ b/cl/cltest/cltest.go @@ -17,6 +17,7 @@ package cltest import ( + "archive/zip" "bytes" "errors" "fmt" @@ -96,7 +97,7 @@ func WithOutputCheck(enabled bool) RunOption { } } -// WithIRCheck enables or disables source-embedded IR checks in RunAndTestFromDir. +// WithIRCheck enables or disables IR golden checks in RunAndTestFromDir. func WithIRCheck(enabled bool) RunOption { return func(opts *runOptions) { opts.checkIR = enabled @@ -127,8 +128,9 @@ func FilterEmulatorOutput(output string) string { return output } -// RunAndTestFromDir executes tests under relDir and validates runtime output -// goldens and source-embedded IR checks when present. +// RunAndTestFromDir executes tests under relDir and validates both runtime +// output and the pre-transform package IR snapshot when the corresponding +// golden files exist. func RunAndTestFromDir(t *testing.T, sel, relDir string, ignore []string, opts ...RunOption) { rootDir, err := os.Getwd() if err != nil { @@ -202,6 +204,42 @@ func BuildAndCheckSymbolsFromDir(t *testing.T, sel, relDir string, names []strin } } +// *.ll => *.lla +func decodeLinkFile(llFile string) (data []byte, err error) { + zipFile := llFile + "a" + zipf, err := zip.OpenReader(zipFile) + if err != nil { + return + } + defer zipf.Close() + f, err := zipf.Open(filepath.Base(llFile)) + if err != nil { + return + } + defer f.Close() + data, err = io.ReadAll(f) + if err == nil { + os.WriteFile(llFile, data, 0644) + } + return +} + +func Pkg(t *testing.T, pkgPath, outFile string) { + b, err := os.ReadFile(outFile) + if err != nil { + if !os.IsNotExist(err) { + t.Fatal("ReadFile failed:", err) + } + if b, err = decodeLinkFile(outFile); err != nil { + t.Fatal("decodeLinkFile failed:", err) + } + } + expected := string(b) + if v := llgen.GenFrom(pkgPath); v != expected { + t.Fatalf("\n==> got:\n%s\n==> expected:\n%s\n", v, expected) + } +} + func testFrom(t *testing.T, pkgDir, sel string) { t.Helper() if sel != "" && !strings.Contains(pkgDir, sel) { @@ -211,13 +249,22 @@ func testFrom(t *testing.T, pkgDir, sel string) { if err != nil { t.Fatal("LoadSpec failed:", err) } + if spec.Mode == littest.ModeSkip { + return + } var v string withFuncInfoDisabled(func() { v = llgen.GenFrom(pkgDir) }) - if err := littest.Check(spec, v); err != nil { - _ = os.WriteFile(pkgDir+"/result.txt", []byte(v), 0644) - t.Fatal(err) + if spec.Mode == littest.ModeFileCheck { + if err := littest.Check(spec, v); err != nil { + _ = os.WriteFile(pkgDir+"/result.txt", []byte(v), 0644) + t.Fatal(err) + } + return + } + if test.Diff(t, pkgDir+"/result.txt", []byte(v), []byte(spec.Text)) { + t.Fatal("llgen.GenFrom: unexpected result") } } @@ -238,8 +285,8 @@ func testRunAndTestFrom(t *testing.T, pkgDir, relPkg, sel string, opts runOption } } if !checkOutput { - // IR-only mode: when expect.txt is not checked, use the source-embedded - // FileCheck directives for this package. + // IR-only mode: when expect.txt is not checked, use llgen.GenFrom via + // testFrom to compare this package's generated IR against out.ll. if opts.checkIR { testFrom(t, pkgDir, sel) } @@ -657,7 +704,8 @@ func symbolTable(bin string) (string, error) { func readIRSpec(pkgDir string) (littest.Spec, bool, error) { spec, err := littest.LoadSpec(pkgDir) if err != nil { - if errors.Is(err, littest.ErrSpecNotFound) { + var pathErr *os.PathError + if errors.Is(err, os.ErrNotExist) && errors.As(err, &pathErr) && filepath.Clean(pathErr.Path) == filepath.Join(pkgDir, "out.ll") { return littest.Spec{}, false, nil } return littest.Spec{}, false, err @@ -754,7 +802,7 @@ func CompileIREx(t *testing.T, src any, fname string, dbg bool, configure func(l func TestCompileEx(t *testing.T, src any, fname, expected string, dbg bool) { t.Helper() v := CompileIREx(t, src, fname, dbg, nil) - if llssa.StripModuleTarget(v) != expected && expected != ";" { // expected == ";" skips this inline comparison + if llssa.StripModuleTarget(v) != expected && expected != ";" { // expected == ";" means skipping out.ll t.Fatalf("\n==> got:\n%s\n==> expected:\n%s\n", v, expected) } } diff --git a/cl/cltest/cltest_test.go b/cl/cltest/cltest_test.go index 7f01f49fee..636295b984 100644 --- a/cl/cltest/cltest_test.go +++ b/cl/cltest/cltest_test.go @@ -61,22 +61,3 @@ func TestReadGoldenReturnsVersionedReadError(t *testing.T) { t.Fatal("readGolden() succeeded for a versioned golden directory") } } - -func TestReadIRSpecRequiresSourceMarker(t *testing.T) { - dir := t.TempDir() - path := filepath.Join(dir, "in.go") - if err := os.WriteFile(path, []byte("package main\n"), 0o644); err != nil { - t.Fatal(err) - } - if _, ok, err := readIRSpec(dir); err != nil || ok { - t.Fatalf("readIRSpec(unmarked) = (_, %v, %v), want (_, false, nil)", ok, err) - } - - if err := os.WriteFile(path, []byte("// LITTEST\npackage main\n// CHECK: define\n"), 0o644); err != nil { - t.Fatal(err) - } - spec, ok, err := readIRSpec(dir) - if err != nil || !ok || spec.Path != path { - t.Fatalf("readIRSpec(marked) = (%q, %v, %v), want (%q, true, nil)", spec.Path, ok, err, path) - } -} diff --git a/cl/compile_test.go b/cl/compile_test.go index 157eef34b5..5eecf6cbd5 100644 --- a/cl/compile_test.go +++ b/cl/compile_test.go @@ -31,6 +31,7 @@ import ( "github.com/goplus/llgo/internal/build" "github.com/goplus/llgo/internal/buildenv" "github.com/goplus/llgo/internal/cabi" + "github.com/goplus/llgo/internal/llgen" "github.com/goplus/llgo/internal/lto" llvmenv "github.com/goplus/llgo/xtool/env/llvm" ) @@ -564,6 +565,16 @@ func TestRunAndTestFromTestdata(t *testing.T) { cltest.RunAndTestFromDir(t, "", "./_testdata", nil) } +func TestCgofullGeneratesC2func(t *testing.T) { + ir := llgen.GenFrom("./_testgo/cgofull") + if !strings.Contains(ir, "_C2func_test_structs") { + t.Fatal("missing _C2func_test_structs in cgofull IR") + } + if !strings.Contains(ir, "cliteErrno") { + t.Fatal("missing cliteErrno call in cgofull IR") + } +} + func TestGoPkgMath(t *testing.T) { conf := build.NewDefaultConf(build.ModeInstall) _, err := build.Do([]string{"math"}, conf) diff --git a/internal/build/build.go b/internal/build/build.go index f85579a450..4e3ae2a499 100644 --- a/internal/build/build.go +++ b/internal/build/build.go @@ -455,7 +455,7 @@ func Build(inv Invocation) ([]Package, error) { prog := llssa.NewProgram(target) prog.DisableBoundsChecks(conf.DisableBoundsChecks) if conf.Mode != ModeGen { - // ModeGen callers (IR generation and IR-check suites) read LPkg.String() + // ModeGen callers (llgen and the golden suites) read LPkg.String() // after Do returns and dispose the program themselves; every other // mode's outputs are files or a spawned process, so the compile's // LLVM context can be released when Do finishes. In-process diff --git a/internal/littest/littest.go b/internal/littest/littest.go index 8f4e4e148e..0147603631 100644 --- a/internal/littest/littest.go +++ b/internal/littest/littest.go @@ -18,6 +18,7 @@ package littest import ( "bufio" + "bytes" "errors" "fmt" "os" @@ -27,28 +28,71 @@ import ( "github.com/goplus/llgo/internal/filecheck" ) +type Mode int + +const ( + ModeSkip Mode = iota + ModeLiteral + ModeFileCheck +) + type Spec struct { Path string + Text string + Mode Mode } const Marker = "LITTEST" -// ErrSpecNotFound reports that a package has no source file marked LITTEST. -var ErrSpecNotFound = errors.New("IR check spec not found") - func LoadSpec(pkgDir string) (Spec, error) { - marked, ok, err := FindMarkedSourceFile(pkgDir) + if spec, ok, err := loadSourceSpec(pkgDir); err != nil { + return Spec{}, err + } else if ok { + return spec, nil + } + + path := filepath.Join(pkgDir, "out.ll") + data, err := os.ReadFile(path) if err != nil { return Spec{}, err } - if !ok { - return Spec{}, fmt.Errorf("%w: %s", ErrSpecNotFound, pkgDir) + if bytes.Equal(data, []byte{';'}) { + return Spec{Path: path, Mode: ModeSkip}, nil } - return Spec{Path: marked}, nil + return Spec{Path: path, Text: string(data), Mode: ModeLiteral}, nil } func Check(spec Spec, actual string) error { - return filecheck.Match(spec.Path, actual) + switch spec.Mode { + case ModeSkip: + return nil + case ModeFileCheck: + return filecheck.Match(spec.Path, actual) + case ModeLiteral: + if actual != spec.Text { + return fmt.Errorf("%s: literal LLVM IR mismatch", spec.Path) + } + return nil + default: + return errors.New("unknown lit spec mode") + } +} + +func loadSourceSpec(pkgDir string) (Spec, bool, error) { + marked, ok, err := FindMarkedSourceFile(pkgDir) + if err != nil { + return Spec{}, false, err + } + if !ok { + return Spec{}, false, nil + } + if marked == "" { + return Spec{}, false, nil + } + return Spec{ + Path: marked, + Mode: ModeFileCheck, + }, true, nil } func FindMarkedSourceFile(dir string) (string, bool, error) { diff --git a/internal/littest/littest_test.go b/internal/littest/littest_test.go index ae8643f44f..d02d899375 100644 --- a/internal/littest/littest_test.go +++ b/internal/littest/littest_test.go @@ -1,99 +1,167 @@ package littest import ( - "errors" "os" "path/filepath" "strings" "testing" ) -func TestLoadSpec(t *testing.T) { +func TestLoadSpecPrefersMarkedSourceOverOutLL(t *testing.T) { dir := t.TempDir() - path := filepath.Join(dir, "in.go") - writeTestFile(t, path, `// LITTEST + err := os.WriteFile(filepath.Join(dir, "in.go"), []byte(`// LITTEST // CHECK: ret void package main func main() {} -`) +`), 0644) + if err != nil { + t.Fatal(err) + } + err = os.WriteFile(filepath.Join(dir, "out.ll"), []byte(`; ModuleID = 'main' +define void @main() { + ret void +} +`), 0644) + if err != nil { + t.Fatal(err) + } spec, err := LoadSpec(dir) if err != nil { t.Fatal(err) } - if spec.Path != path { - t.Fatalf("spec.Path = %q, want %q", spec.Path, path) + if spec.Mode != ModeFileCheck { + t.Fatalf("spec.Mode = %v, want %v", spec.Mode, ModeFileCheck) + } + if spec.Path != filepath.Join(dir, "in.go") { + t.Fatalf("spec.Path = %q", spec.Path) } } func TestLoadSpecReportsMissingDirectory(t *testing.T) { _, err := LoadSpec(filepath.Join(t.TempDir(), "missing")) - if err == nil || errors.Is(err, ErrSpecNotFound) { - t.Fatalf("LoadSpec missing directory error = %v", err) - } -} - -func TestLoadSpecReportsMissingMarker(t *testing.T) { - dir := t.TempDir() - writeTestFile(t, filepath.Join(dir, "in.go"), "package main\n") - _, err := LoadSpec(dir) - if !errors.Is(err, ErrSpecNotFound) { - t.Fatalf("LoadSpec error = %v, want ErrSpecNotFound", err) + if err == nil { + t.Fatal("LoadSpec succeeded unexpectedly") } } func TestLoadSpecRejectsMultipleMarkedSources(t *testing.T) { dir := t.TempDir() - writeTestFile(t, filepath.Join(dir, "a.go"), "// LITTEST\npackage main\n") - writeTestFile(t, filepath.Join(dir, "b.go"), "// LITTEST\npackage main\n") - if _, err := LoadSpec(dir); err == nil { + err := os.WriteFile(filepath.Join(dir, "a.go"), []byte(`// LITTEST +// CHECK: ret void +package main +`), 0644) + if err != nil { + t.Fatal(err) + } + err = os.WriteFile(filepath.Join(dir, "b.go"), []byte(`// LITTEST +// CHECK: unreachable +package main +`), 0644) + if err != nil { + t.Fatal(err) + } + _, err = LoadSpec(dir) + if err == nil { t.Fatal("LoadSpec succeeded unexpectedly") } } -func TestLoadSpecMarkerRules(t *testing.T) { - tests := []struct { - name string - file string - text string - }{ - {name: "not first line", file: "in.go", text: "\n// LITTEST\npackage main\n"}, - {name: "not Go comment", file: "in.go", text: "# LITTEST\npackage main\n"}, - {name: "not Go source", file: "in.c", text: "// LITTEST\n"}, - {name: "test file", file: "in_test.go", text: "// LITTEST\npackage main\n"}, - } - for _, tt := range tests { - t.Run(tt.name, func(t *testing.T) { - dir := t.TempDir() - writeTestFile(t, filepath.Join(dir, tt.file), tt.text) - _, err := LoadSpec(dir) - if !errors.Is(err, ErrSpecNotFound) { - t.Fatalf("LoadSpec error = %v, want ErrSpecNotFound", err) - } - }) +func TestLoadSpecWorksWithoutOutLLWhenSourceChecksExist(t *testing.T) { + dir := t.TempDir() + err := os.WriteFile(filepath.Join(dir, "in.go"), []byte(`// LITTEST +package main + +// CHECK: ret void +func main() {} +`), 0644) + if err != nil { + t.Fatal(err) + } + spec, err := LoadSpec(dir) + if err != nil { + t.Fatal(err) + } + if spec.Path != filepath.Join(dir, "in.go") { + t.Fatalf("spec.Path = %q", spec.Path) } } -func TestCheck(t *testing.T) { +func TestCheckReportsMalformedDirective(t *testing.T) { dir := t.TempDir() path := filepath.Join(dir, "in.go") - writeTestFile(t, path, "// CHECK: ret void\n") - spec := Spec{Path: path} - if err := Check(spec, " ret void\n"); err != nil { + err := os.WriteFile(path, []byte(`// LITTEST +// CHECK: {{[invalid +package main +`), 0644) + if err != nil { t.Fatal(err) } - if err := Check(spec, " unreachable\n"); err == nil { + spec, err := LoadSpec(dir) + if err != nil { + t.Fatal(err) + } + err = Check(spec, "") + if err == nil { t.Fatal("Check succeeded unexpectedly") } + if !strings.Contains(err.Error(), "found start of regex string with no end") { + t.Fatalf("unexpected error: %v", err) + } } -func TestCheckReportsMalformedDirective(t *testing.T) { +func TestLoadSpecFallsBackToOutLLWithoutMarker(t *testing.T) { dir := t.TempDir() - path := filepath.Join(dir, "in.go") - writeTestFile(t, path, "// CHECK: {{[invalid\n") - err := Check(Spec{Path: path}, "") - if err == nil || !strings.Contains(err.Error(), "found start of regex string with no end") { - t.Fatalf("Check error = %v", err) + err := os.WriteFile(filepath.Join(dir, "in.go"), []byte(`// CHECK: ret void +package main +`), 0644) + if err != nil { + t.Fatal(err) + } + err = os.WriteFile(filepath.Join(dir, "out.ll"), []byte(`; ModuleID = 'main' +define void @main() { + ret void +} +`), 0644) + if err != nil { + t.Fatal(err) + } + spec, err := LoadSpec(dir) + if err != nil { + t.Fatal(err) + } + if spec.Path != filepath.Join(dir, "out.ll") { + t.Fatalf("spec.Path = %q", spec.Path) + } + if spec.Mode != ModeLiteral { + t.Fatalf("spec.Mode = %v", spec.Mode) + } +} + +func TestLoadSpecReportsMissingOutLL(t *testing.T) { + dir := t.TempDir() + err := os.WriteFile(filepath.Join(dir, "in.go"), []byte("package main\n"), 0644) + if err != nil { + t.Fatal(err) + } + _, err = LoadSpec(dir) + if err == nil { + t.Fatal("LoadSpec succeeded unexpectedly") + } +} + +func TestLoadSpecSupportsSkipOutLL(t *testing.T) { + dir := t.TempDir() + err := os.WriteFile(filepath.Join(dir, "out.ll"), []byte(`;`), 0644) + if err != nil { + t.Fatal(err) + } + spec, err := LoadSpec(dir) + if err != nil { + t.Fatal(err) + } + if spec.Mode != ModeSkip { + t.Fatalf("spec.Mode = %v", spec.Mode) } } @@ -105,31 +173,158 @@ func TestHasMarker(t *testing.T) { t.Fatalf("HasMarker(missing) = (%v, %v)", ok, err) } - tests := []struct { + empty := filepath.Join(dir, "empty.go") + err = os.WriteFile(empty, nil, 0644) + if err != nil { + t.Fatal(err) + } + ok, err = HasMarker(empty) + if err != nil || ok { + t.Fatalf("HasMarker(empty) = (%v, %v)", ok, err) + } + + plain := filepath.Join(dir, "plain.go") + err = os.WriteFile(plain, []byte("package main\n"), 0644) + if err != nil { + t.Fatal(err) + } + ok, err = HasMarker(plain) + if err != nil || ok { + t.Fatalf("HasMarker(plain) = (%v, %v)", ok, err) + } +} + +func TestCheck(t *testing.T) { + checkPath := filepath.Join(t.TempDir(), "check.go") + if err := os.WriteFile(checkPath, []byte("// CHECK: ok\n"), 0644); err != nil { + t.Fatal(err) + } + + cases := []struct { name string + spec Spec text string - want bool + want string }{ - {name: "empty"}, - {name: "plain", text: "package main\n"}, - {name: "marker", text: "// LITTEST\npackage main\n", want: true}, - {name: "trimmed marker", text: " // LITTEST \npackage main\n", want: true}, - } - for _, tt := range tests { - t.Run(tt.name, func(t *testing.T) { - path := filepath.Join(dir, tt.name+".go") - writeTestFile(t, path, tt.text) - got, err := HasMarker(path) - if err != nil || got != tt.want { - t.Fatalf("HasMarker = (%v, %v), want (%v, nil)", got, err, tt.want) + { + name: "skip", + spec: Spec{Path: "skip", Mode: ModeSkip}, + }, + { + name: "literal match", + spec: Spec{Path: "literal", Text: "ok", Mode: ModeLiteral}, + text: "ok", + }, + { + name: "literal mismatch", + spec: Spec{Path: "literal", Text: "ok", Mode: ModeLiteral}, + text: "bad", + want: "literal LLVM IR mismatch", + }, + { + name: "filecheck match", + spec: Spec{Path: checkPath, Mode: ModeFileCheck}, + text: "ok\n", + }, + { + name: "invalid mode", + spec: Spec{Path: "bad", Mode: Mode(99)}, + want: "unknown lit spec mode", + }, + } + for _, tc := range cases { + t.Run(tc.name, func(t *testing.T) { + err := Check(tc.spec, tc.text) + if tc.want == "" { + if err != nil { + t.Fatal(err) + } + return + } + if err == nil { + t.Fatal("Check succeeded unexpectedly") + } + if !strings.Contains(err.Error(), tc.want) { + t.Fatalf("unexpected error: %v", err) } }) } } -func writeTestFile(t *testing.T, path, text string) { - t.Helper() - if err := os.WriteFile(path, []byte(text), 0o644); err != nil { +func TestLoadSpecRequiresMarkerOnFirstLine(t *testing.T) { + dir := t.TempDir() + err := os.WriteFile(filepath.Join(dir, "in.go"), []byte(` +// LITTEST +// CHECK: ret void +package main +`), 0644) + if err != nil { t.Fatal(err) } + err = os.WriteFile(filepath.Join(dir, "out.ll"), []byte(`; ModuleID = 'main' +define void @main() { + ret void +} +`), 0644) + if err != nil { + t.Fatal(err) + } + spec, err := LoadSpec(dir) + if err != nil { + t.Fatal(err) + } + if spec.Path != filepath.Join(dir, "out.ll") { + t.Fatalf("spec.Path = %q", spec.Path) + } +} + +func TestLoadSpecRequiresSlashSlashMarker(t *testing.T) { + dir := t.TempDir() + err := os.WriteFile(filepath.Join(dir, "in.go"), []byte(`# LITTEST +// CHECK: ret void +package main +`), 0644) + if err != nil { + t.Fatal(err) + } + err = os.WriteFile(filepath.Join(dir, "out.ll"), []byte(`; ModuleID = 'main' +define void @main() { + ret void +} +`), 0644) + if err != nil { + t.Fatal(err) + } + spec, err := LoadSpec(dir) + if err != nil { + t.Fatal(err) + } + if spec.Path != filepath.Join(dir, "out.ll") { + t.Fatalf("spec.Path = %q", spec.Path) + } +} + +func TestLoadSpecIgnoresNonGoFiles(t *testing.T) { + dir := t.TempDir() + err := os.WriteFile(filepath.Join(dir, "in.c"), []byte(`// LITTEST +// CHECK: ret void +`), 0644) + if err != nil { + t.Fatal(err) + } + err = os.WriteFile(filepath.Join(dir, "out.ll"), []byte(`; ModuleID = 'main' +define void @main() { + ret void +} +`), 0644) + if err != nil { + t.Fatal(err) + } + spec, err := LoadSpec(dir) + if err != nil { + t.Fatal(err) + } + if spec.Path != filepath.Join(dir, "out.ll") { + t.Fatalf("spec.Path = %q", spec.Path) + } } diff --git a/internal/llgen/llgenf.go b/internal/llgen/llgenf.go index 62eeddda7c..1e45eaf26d 100644 --- a/internal/llgen/llgenf.go +++ b/internal/llgen/llgenf.go @@ -19,6 +19,7 @@ package llgen import ( "fmt" "os" + "os/exec" "path/filepath" "strings" @@ -28,20 +29,21 @@ import ( ) func GenFrom(fileOrPkg string) string { - pkg, err := genFrom(fileOrPkg) + pkg, err := genFrom(fileOrPkg, 0) check(err) out := pkg.LPkg.String() - // Release the compile's LLVM context: IR-check suites call GenFrom for + // Release the compile's LLVM context: golden suites call GenFrom for // every test dir inside one process, and undisposed contexts // accumulate C++-side memory for the whole run. pkg.LPkg.Prog.Dispose() return out } -func genFrom(pkgPath string) (build.Package, error) { +func genFrom(pkgPath string, abiMode build.AbiMode) (build.Package, error) { conf := &build.Config{ - Mode: build.ModeGen, - GenLL: true, + Mode: build.ModeGen, + AbiMode: abiMode, + GenLL: true, } if err := applyFlagsFile(conf, filepath.Join(pkgPath, "flags.txt")); err != nil { return nil, err @@ -53,6 +55,12 @@ func genFrom(pkgPath string) (build.Package, error) { return pkgs[0], nil } +func DoFile(fileOrPkg, outFile string) { + ret := GenFrom(fileOrPkg) + err := os.WriteFile(outFile, []byte(ret), 0644) + check(err) +} + func readFlags(flagsFile string) ([]string, error) { data, err := os.ReadFile(flagsFile) if os.IsNotExist(err) { @@ -110,3 +118,46 @@ func applyFlagsFile(conf *build.Config, flagsFile string) error { *conf = next return nil } + +func SmartDoFile(pkgPath string) { + SmartDoFileEx(pkgPath, 0) +} + +func SmartDoFileEx(pkgPath string, abiMode build.AbiMode) { + pkg, err := genFrom(pkgPath, abiMode) + check(err) + + const autgenFile = "llgo_autogen.ll" + dir, _ := filepath.Split(pkg.GoFiles[0]) + absDir, _ := filepath.Abs(dir) + absDir = filepath.ToSlash(absDir) + fname := autgenFile + if inCompilerDir(absDir) { + fname = "out.ll" + } + outFile := dir + fname + + b, err := os.ReadFile(outFile) + if err == nil && len(b) == 1 && b[0] == ';' { + return // skip to gen + } + + if err = os.WriteFile(outFile, []byte(pkg.LPkg.String()), 0644); err != nil { + panic(err) + } + if false && fname == autgenFile { + genZip(absDir, "llgo_autogen.lla", autgenFile) + } +} + +func genZip(dir string, outFile, inFile string) { + cmd := exec.Command("zip", outFile, inFile) + cmd.Dir = dir + cmd.Stdout = os.Stdout + cmd.Stderr = os.Stderr + cmd.Run() +} + +func inCompilerDir(dir string) bool { + return strings.Contains(dir, "/cl/_test") +} diff --git a/ssa/package.go b/ssa/package.go index 8f590a61eb..498bbaf942 100644 --- a/ssa/package.go +++ b/ssa/package.go @@ -278,7 +278,7 @@ func is32Bits(arch string) bool { // (and with it every module built in it), the target machine and the // target data. The Program and everything created from it must not be // used afterwards. In-process drivers that compile many packages -// sequentially (IR checks and the cltest run harness) call this between +// sequentially (llgen goldens, the cltest run harness) call this between // compiles; without it each compile's C++-side memory lives until the // process exits. func (p Program) Dispose() { diff --git a/test/go/defer_ir_regression_test.go b/test/go/defer_ir_regression_test.go index 212ad81328..46c17e891a 100644 --- a/test/go/defer_ir_regression_test.go +++ b/test/go/defer_ir_regression_test.go @@ -22,8 +22,6 @@ import ( "path/filepath" "strings" "testing" - - "github.com/goplus/llgo/internal/llgen" ) const recoverThenDeferredPanicProbe = `package main @@ -104,7 +102,12 @@ func llgoIRFromProbe(t *testing.T, name, src string) string { t.Fatal(err) } - return llgen.GenFrom(filepath.ToSlash(dir)) + runGoCmd(t, root, "run", "./chore/llgen", filepath.ToSlash(dir)) + data, err := os.ReadFile(filepath.Join(dir, "llgo_autogen.ll")) + if err != nil { + t.Fatal(err) + } + return string(data) } func assertNoInstructionsAfterUnreachable(t *testing.T, ir string) { From 275b202668d4476b7c2a6065e127d6f6bd08713f Mon Sep 17 00:00:00 2001 From: Li Jie Date: Tue, 4 Aug 2026 17:57:05 +0800 Subject: [PATCH 65/73] test: expand migrated LIT coverage --- cl/_testdata/debug/in.go | 1355 ++++- cl/_testgo/cgofull/cgofull.go | 550 +- cl/_testgo/chan/in.go | 131 +- cl/_testgo/defer1/in.go | 222 +- cl/_testgo/defer2/in.go | 208 +- cl/_testgo/defer3/in.go | 263 +- cl/_testgo/defer4/in.go | 300 +- cl/_testgo/deferclosure/in.go | 443 +- cl/_testgo/defercomplex/in.go | 712 ++- cl/_testgo/goexit/in.go | 504 +- cl/_testgo/indexerr/in.go | 1052 +++- cl/_testgo/makeslice/in.go | 280 +- cl/_testgo/reflectconv/in.go | 8954 ++++++++++++++++++++++++++++++++- cl/_testgo/rewrite/main.go | 59 +- cl/_testgo/runextest/main.go | 48 +- cl/_testgo/runtest/main.go | 48 +- cl/_testgo/select/in.go | 311 +- cl/_testgo/syncmap/in.go | 76 +- cl/_testlibc/complex/in.go | 54 +- cl/_testlibc/defer/in.go | 201 +- cl/_testlibc/once/in.go | 47 +- cl/_testlibc/setjmp/in.go | 45 +- cl/_testlibgo/sync/in.go | 49 +- cl/_testlibgo/waitgroup/in.go | 241 +- cl/_testrt/nextblock/in.go | 130 +- 25 files changed, 16188 insertions(+), 95 deletions(-) diff --git a/cl/_testdata/debug/in.go b/cl/_testdata/debug/in.go index 87f22f24b0..b91d822089 100644 --- a/cl/_testdata/debug/in.go +++ b/cl/_testdata/debug/in.go @@ -1,12 +1,30 @@ // LITTEST package main -// CHECK-DAG: define void @main.FuncWithAllTypeStructParam({{.*}}){{.*}} !dbg !{{[0-9]+}} -// CHECK-DAG: !DICompileUnit({{.*}}producer: "LLGo"{{.*}}emissionKind: FullDebug{{.*}}) -// CHECK-DAG: !DILocalVariable(name: "s"{{.*}}arg: 1{{.*}}) - import "errors" +// CHECK: {{^}}@{{[0-9]+}} = private unnamed_addr constant [4 x i8] c"done", align 1{{$}} +// CHECK: {{^}}@{{[0-9]+}} = private unnamed_addr constant [5 x i8] c"world", align 1{{$}} +// CHECK: {{^}}@{{[0-9]+}} = private unnamed_addr constant [10 x i8] c"some error", align 1{{$}} +// CHECK: {{^}}@{{[0-9]+}} = private unnamed_addr constant [6 x i8] c"i is 0", align 1{{$}} +// CHECK: {{^}}@{{[0-9]+}} = private unnamed_addr constant [2 x i8] c"i:", align 1{{$}} +// CHECK: {{^}}@{{[0-9]+}} = private unnamed_addr constant [2 x i8] c"a:", align 1{{$}} +// CHECK: {{^}}@{{[0-9]+}} = private unnamed_addr constant [6 x i8] c"i is 1", align 1{{$}} +// CHECK: {{^}}@{{[0-9]+}} = private unnamed_addr constant [4 x i8] c"i is", align 1{{$}} +// CHECK: {{^}}@{{[0-9]+}} = private unnamed_addr constant [2 x i8] c"b:", align 1{{$}} +// CHECK: {{^}}@{{[0-9]+}} = private unnamed_addr constant [6 x i8] c"i is 2", align 1{{$}} +// CHECK: {{^}}@{{[0-9]+}} = private unnamed_addr constant [2 x i8] c"c:", align 1{{$}} +// CHECK: {{^}}@{{[0-9]+}} = private unnamed_addr constant [2 x i8] c"d:", align 1{{$}} +// CHECK: {{^}}@{{[0-9]+}} = private unnamed_addr constant [1 x i8] c"a", align 1{{$}} +// CHECK: {{^}}@{{[0-9]+}} = private unnamed_addr constant [1 x i8] c"b", align 1{{$}} +// CHECK: {{^}}@{{[0-9]+}} = private unnamed_addr constant [10 x i8] c"Test error", align 1{{$}} +// CHECK: {{^}}@{{[0-9]+}} = private unnamed_addr constant [5 x i8] c"hello", align 1{{$}} +// CHECK: {{^}}@{{[0-9]+}} = private unnamed_addr constant [10 x i8] c"globalInt:", align 1{{$}} +// CHECK: {{^}}@{{[0-9]+}} = private unnamed_addr constant [2 x i8] c"s:", align 1{{$}} +// CHECK: {{^}}@{{[0-9]+}} = private unnamed_addr constant [27 x i8] c"called function with struct", align 1{{$}} +// CHECK: {{^}}@{{[0-9]+}} = private unnamed_addr constant [3 x i8] c"fn:", align 1{{$}} +// CHECK: {{^}}@{{[0-9]+}} = private unnamed_addr constant [8 x i8] c"fn error", align 1{{$}} + type Base struct { name string } @@ -572,3 +590,1332 @@ func main() { var globalInt int = 301 var globalStruct StructWithAllTypeFields var globalStructPtr *StructWithAllTypeFields + +// CHECK-LABEL: define void @main.FuncStructParams(%main.TinyStruct %0, %main.SmallStruct %1, %main.MidStruct %2, %main.BigStruct %3){{.*}} { +// CHECK-NEXT: _llgo_0: +// CHECK-NEXT: %4 = alloca %main.TinyStruct, align 8 +// CHECK-NEXT: call void @llvm.memset.p0.i64(ptr %4, i8 0, i64 8, i1 false) +// CHECK-NEXT: #dbg_declare(ptr %4, !{{[0-9]+}}, !DIExpression(), !{{[0-9]+}}) +// CHECK-NEXT: store %main.TinyStruct %0, ptr %4, align 8 +// CHECK-NEXT: %5 = alloca %main.SmallStruct, align 8 +// CHECK-NEXT: call void @llvm.memset.p0.i64(ptr %5, i8 0, i64 16, i1 false) +// CHECK-NEXT: #dbg_declare(ptr %5, !{{[0-9]+}}, !DIExpression(), !{{[0-9]+}}) +// CHECK-NEXT: store %main.SmallStruct %1, ptr %5, align 8 +// CHECK-NEXT: %6 = alloca %main.MidStruct, align 8 +// CHECK-NEXT: call void @llvm.memset.p0.i64(ptr %6, i8 0, i64 24, i1 false) +// CHECK-NEXT: #dbg_declare(ptr %6, !{{[0-9]+}}, !DIExpression(), !{{[0-9]+}}) +// CHECK-NEXT: store %main.MidStruct %2, ptr %6, align 8 +// CHECK-NEXT: %7 = alloca %main.BigStruct, align 8 +// CHECK-NEXT: call void @llvm.memset.p0.i64(ptr %7, i8 0, i64 80, i1 false) +// CHECK-NEXT: #dbg_declare(ptr %7, !{{[0-9]+}}, !DIExpression(), !{{[0-9]+}}) +// CHECK-NEXT: store %main.BigStruct %3, ptr %7, align 8 +// CHECK-NEXT: #dbg_declare(ptr %4, !{{[0-9]+}}, !DIExpression(), !{{[0-9]+}}) +// CHECK-NEXT: %8 = getelementptr inbounds %main.TinyStruct, ptr %4, i32 0, i32 0 +// CHECK-NEXT: %9 = load i64, ptr %8, align 8 +// CHECK-NEXT: #dbg_declare(ptr %5, !{{[0-9]+}}, !DIExpression(), !{{[0-9]+}}) +// CHECK-NEXT: %10 = getelementptr inbounds %main.SmallStruct, ptr %5, i32 0, i32 0 +// CHECK-NEXT: %11 = load i64, ptr %10, align 8 +// CHECK-NEXT: #dbg_declare(ptr %5, !{{[0-9]+}}, !DIExpression(), !{{[0-9]+}}) +// CHECK-NEXT: %12 = getelementptr inbounds %main.SmallStruct, ptr %5, i32 0, i32 1 +// CHECK-NEXT: %13 = load i64, ptr %12, align 8 +// CHECK-NEXT: #dbg_declare(ptr %6, !{{[0-9]+}}, !DIExpression(), !{{[0-9]+}}) +// CHECK-NEXT: %14 = getelementptr inbounds %main.MidStruct, ptr %6, i32 0, i32 0 +// CHECK-NEXT: %15 = load i64, ptr %14, align 8 +// CHECK-NEXT: #dbg_declare(ptr %6, !{{[0-9]+}}, !DIExpression(), !{{[0-9]+}}) +// CHECK-NEXT: %16 = getelementptr inbounds %main.MidStruct, ptr %6, i32 0, i32 1 +// CHECK-NEXT: %17 = load i64, ptr %16, align 8 +// CHECK-NEXT: #dbg_declare(ptr %6, !{{[0-9]+}}, !DIExpression(), !{{[0-9]+}}) +// CHECK-NEXT: %18 = getelementptr inbounds %main.MidStruct, ptr %6, i32 0, i32 2 +// CHECK-NEXT: %19 = load i64, ptr %18, align 8 +// CHECK-NEXT: #dbg_declare(ptr %7, !{{[0-9]+}}, !DIExpression(), !{{[0-9]+}}) +// CHECK-NEXT: %20 = getelementptr inbounds %main.BigStruct, ptr %7, i32 0, i32 0 +// CHECK-NEXT: %21 = load i64, ptr %20, align 8 +// CHECK-NEXT: #dbg_declare(ptr %7, !{{[0-9]+}}, !DIExpression(), !{{[0-9]+}}) +// CHECK-NEXT: %22 = getelementptr inbounds %main.BigStruct, ptr %7, i32 0, i32 1 +// CHECK-NEXT: %23 = load i64, ptr %22, align 8 +// CHECK-NEXT: #dbg_declare(ptr %7, !{{[0-9]+}}, !DIExpression(), !{{[0-9]+}}) +// CHECK-NEXT: %24 = getelementptr inbounds %main.BigStruct, ptr %7, i32 0, i32 2 +// CHECK-NEXT: %25 = load i64, ptr %24, align 8 +// CHECK-NEXT: #dbg_declare(ptr %7, !{{[0-9]+}}, !DIExpression(), !{{[0-9]+}}) +// CHECK-NEXT: %26 = getelementptr inbounds %main.BigStruct, ptr %7, i32 0, i32 3 +// CHECK-NEXT: %27 = load i64, ptr %26, align 8 +// CHECK-NEXT: #dbg_declare(ptr %7, !{{[0-9]+}}, !DIExpression(), !{{[0-9]+}}) +// CHECK-NEXT: %28 = getelementptr inbounds %main.BigStruct, ptr %7, i32 0, i32 4 +// CHECK-NEXT: %29 = load i64, ptr %28, align 8 +// CHECK-NEXT: #dbg_declare(ptr %7, !{{[0-9]+}}, !DIExpression(), !{{[0-9]+}}) +// CHECK-NEXT: %30 = getelementptr inbounds %main.BigStruct, ptr %7, i32 0, i32 5 +// CHECK-NEXT: %31 = load i64, ptr %30, align 8 +// CHECK-NEXT: #dbg_declare(ptr %7, !{{[0-9]+}}, !DIExpression(), !{{[0-9]+}}) +// CHECK-NEXT: %32 = getelementptr inbounds %main.BigStruct, ptr %7, i32 0, i32 6 +// CHECK-NEXT: %33 = load i64, ptr %32, align 8 +// CHECK-NEXT: #dbg_declare(ptr %7, !{{[0-9]+}}, !DIExpression(), !{{[0-9]+}}) +// CHECK-NEXT: %34 = getelementptr inbounds %main.BigStruct, ptr %7, i32 0, i32 7 +// CHECK-NEXT: %35 = load i64, ptr %34, align 8 +// CHECK-NEXT: #dbg_declare(ptr %7, !{{[0-9]+}}, !DIExpression(), !{{[0-9]+}}) +// CHECK-NEXT: %36 = getelementptr inbounds %main.BigStruct, ptr %7, i32 0, i32 8 +// CHECK-NEXT: %37 = load i64, ptr %36, align 8 +// CHECK-NEXT: #dbg_declare(ptr %7, !{{[0-9]+}}, !DIExpression(), !{{[0-9]+}}) +// CHECK-NEXT: %38 = getelementptr inbounds %main.BigStruct, ptr %7, i32 0, i32 9 +// CHECK-NEXT: %39 = load i64, ptr %38, align 8 +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.PrintInt"(i64 %9) +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.PrintByte"(i8 32) +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.PrintInt"(i64 %11) +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.PrintByte"(i8 32) +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.PrintInt"(i64 %13) +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.PrintByte"(i8 32) +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.PrintInt"(i64 %15) +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.PrintByte"(i8 32) +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.PrintInt"(i64 %17) +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.PrintByte"(i8 32) +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.PrintInt"(i64 %19) +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.PrintByte"(i8 32) +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.PrintInt"(i64 %21) +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.PrintByte"(i8 32) +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.PrintInt"(i64 %23) +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.PrintByte"(i8 32) +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.PrintInt"(i64 %25) +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.PrintByte"(i8 32) +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.PrintInt"(i64 %27) +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.PrintByte"(i8 32) +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.PrintInt"(i64 %29) +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.PrintByte"(i8 32) +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.PrintInt"(i64 %31) +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.PrintByte"(i8 32) +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.PrintInt"(i64 %33) +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.PrintByte"(i8 32) +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.PrintInt"(i64 %35) +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.PrintByte"(i8 32) +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.PrintInt"(i64 %37) +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.PrintByte"(i8 32) +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.PrintInt"(i64 %39) +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.PrintByte"(i8 10) +// CHECK-NEXT: #dbg_declare(ptr %4, !{{[0-9]+}}, !DIExpression(), !{{[0-9]+}}) +// CHECK-NEXT: %40 = getelementptr inbounds %main.TinyStruct, ptr %4, i32 0, i32 0 +// CHECK-NEXT: store i64 10, ptr %40, align 8 +// CHECK-NEXT: #dbg_declare(ptr %5, !{{[0-9]+}}, !DIExpression(), !{{[0-9]+}}) +// CHECK-NEXT: %41 = getelementptr inbounds %main.SmallStruct, ptr %5, i32 0, i32 0 +// CHECK-NEXT: store i64 20, ptr %41, align 8 +// CHECK-NEXT: #dbg_declare(ptr %5, !{{[0-9]+}}, !DIExpression(), !{{[0-9]+}}) +// CHECK-NEXT: %42 = getelementptr inbounds %main.SmallStruct, ptr %5, i32 0, i32 1 +// CHECK-NEXT: store i64 21, ptr %42, align 8 +// CHECK-NEXT: #dbg_declare(ptr %6, !{{[0-9]+}}, !DIExpression(), !{{[0-9]+}}) +// CHECK-NEXT: %43 = getelementptr inbounds %main.MidStruct, ptr %6, i32 0, i32 0 +// CHECK-NEXT: store i64 40, ptr %43, align 8 +// CHECK-NEXT: #dbg_declare(ptr %6, !{{[0-9]+}}, !DIExpression(), !{{[0-9]+}}) +// CHECK-NEXT: %44 = getelementptr inbounds %main.MidStruct, ptr %6, i32 0, i32 1 +// CHECK-NEXT: store i64 41, ptr %44, align 8 +// CHECK-NEXT: #dbg_declare(ptr %6, !{{[0-9]+}}, !DIExpression(), !{{[0-9]+}}) +// CHECK-NEXT: %45 = getelementptr inbounds %main.MidStruct, ptr %6, i32 0, i32 2 +// CHECK-NEXT: store i64 42, ptr %45, align 8 +// CHECK-NEXT: #dbg_declare(ptr %7, !{{[0-9]+}}, !DIExpression(), !{{[0-9]+}}) +// CHECK-NEXT: %46 = getelementptr inbounds %main.BigStruct, ptr %7, i32 0, i32 0 +// CHECK-NEXT: store i64 70, ptr %46, align 8 +// CHECK-NEXT: #dbg_declare(ptr %7, !{{[0-9]+}}, !DIExpression(), !{{[0-9]+}}) +// CHECK-NEXT: %47 = getelementptr inbounds %main.BigStruct, ptr %7, i32 0, i32 1 +// CHECK-NEXT: store i64 71, ptr %47, align 8 +// CHECK-NEXT: #dbg_declare(ptr %7, !{{[0-9]+}}, !DIExpression(), !{{[0-9]+}}) +// CHECK-NEXT: %48 = getelementptr inbounds %main.BigStruct, ptr %7, i32 0, i32 2 +// CHECK-NEXT: store i64 72, ptr %48, align 8 +// CHECK-NEXT: #dbg_declare(ptr %7, !{{[0-9]+}}, !DIExpression(), !{{[0-9]+}}) +// CHECK-NEXT: %49 = getelementptr inbounds %main.BigStruct, ptr %7, i32 0, i32 3 +// CHECK-NEXT: store i64 73, ptr %49, align 8 +// CHECK-NEXT: #dbg_declare(ptr %7, !{{[0-9]+}}, !DIExpression(), !{{[0-9]+}}) +// CHECK-NEXT: %50 = getelementptr inbounds %main.BigStruct, ptr %7, i32 0, i32 4 +// CHECK-NEXT: store i64 74, ptr %50, align 8 +// CHECK-NEXT: #dbg_declare(ptr %7, !{{[0-9]+}}, !DIExpression(), !{{[0-9]+}}) +// CHECK-NEXT: %51 = getelementptr inbounds %main.BigStruct, ptr %7, i32 0, i32 5 +// CHECK-NEXT: store i64 75, ptr %51, align 8 +// CHECK-NEXT: #dbg_declare(ptr %7, !{{[0-9]+}}, !DIExpression(), !{{[0-9]+}}) +// CHECK-NEXT: %52 = getelementptr inbounds %main.BigStruct, ptr %7, i32 0, i32 6 +// CHECK-NEXT: store i64 76, ptr %52, align 8 +// CHECK-NEXT: #dbg_declare(ptr %7, !{{[0-9]+}}, !DIExpression(), !{{[0-9]+}}) +// CHECK-NEXT: %53 = getelementptr inbounds %main.BigStruct, ptr %7, i32 0, i32 7 +// CHECK-NEXT: store i64 77, ptr %53, align 8 +// CHECK-NEXT: #dbg_declare(ptr %7, !{{[0-9]+}}, !DIExpression(), !{{[0-9]+}}) +// CHECK-NEXT: %54 = getelementptr inbounds %main.BigStruct, ptr %7, i32 0, i32 8 +// CHECK-NEXT: store i64 78, ptr %54, align 8 +// CHECK-NEXT: #dbg_declare(ptr %7, !{{[0-9]+}}, !DIExpression(), !{{[0-9]+}}) +// CHECK-NEXT: %55 = getelementptr inbounds %main.BigStruct, ptr %7, i32 0, i32 9 +// CHECK-NEXT: store i64 79, ptr %55, align 8 +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.PrintString"(%"{{.*}}/runtime/internal/runtime.String" { ptr @{{[0-9]+}}, i64 4 }) +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.PrintByte"(i8 10) +// CHECK-NEXT: ret void +// CHECK-NEXT: } + +// CHECK-LABEL: define void @main.FuncStructPtrParams(ptr %0, ptr %1, ptr %2, ptr %3){{.*}} { +// CHECK-NEXT: _llgo_0: +// CHECK-NEXT: #dbg_value(ptr %0, !{{[0-9]+}}, !DIExpression(), !{{[0-9]+}}) +// CHECK-NEXT: #dbg_value(ptr %1, !{{[0-9]+}}, !DIExpression(), !{{[0-9]+}}) +// CHECK-NEXT: #dbg_value(ptr %2, !{{[0-9]+}}, !DIExpression(), !{{[0-9]+}}) +// CHECK-NEXT: #dbg_value(ptr %3, !{{[0-9]+}}, !DIExpression(), !{{[0-9]+}}) +// CHECK-NEXT: #dbg_value(ptr %0, !{{[0-9]+}}, !DIExpression(), !{{[0-9]+}}) +// CHECK-NEXT: #dbg_value(ptr %1, !{{[0-9]+}}, !DIExpression(), !{{[0-9]+}}) +// CHECK-NEXT: #dbg_value(ptr %2, !{{[0-9]+}}, !DIExpression(), !{{[0-9]+}}) +// CHECK-NEXT: #dbg_value(ptr %3, !{{[0-9]+}}, !DIExpression(), !{{[0-9]+}}) +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.PrintPointer"(ptr %0) +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.PrintByte"(i8 32) +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.PrintPointer"(ptr %1) +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.PrintByte"(i8 32) +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.PrintPointer"(ptr %2) +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.PrintByte"(i8 32) +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.PrintPointer"(ptr %3) +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.PrintByte"(i8 10) +// CHECK-NEXT: #dbg_value(ptr %0, !{{[0-9]+}}, !DIExpression(), !{{[0-9]+}}) +// CHECK-NEXT: %4 = getelementptr inbounds %main.TinyStruct, ptr %0, i32 0, i32 0 +// CHECK-NEXT: store i64 10, ptr %4, align 8 +// CHECK-NEXT: #dbg_value(ptr %1, !{{[0-9]+}}, !DIExpression(), !{{[0-9]+}}) +// CHECK-NEXT: %5 = getelementptr inbounds %main.SmallStruct, ptr %1, i32 0, i32 0 +// CHECK-NEXT: store i64 20, ptr %5, align 8 +// CHECK-NEXT: #dbg_value(ptr %1, !{{[0-9]+}}, !DIExpression(), !{{[0-9]+}}) +// CHECK-NEXT: %6 = getelementptr inbounds %main.SmallStruct, ptr %1, i32 0, i32 1 +// CHECK-NEXT: store i64 21, ptr %6, align 8 +// CHECK-NEXT: #dbg_value(ptr %2, !{{[0-9]+}}, !DIExpression(), !{{[0-9]+}}) +// CHECK-NEXT: %7 = getelementptr inbounds %main.MidStruct, ptr %2, i32 0, i32 0 +// CHECK-NEXT: store i64 40, ptr %7, align 8 +// CHECK-NEXT: #dbg_value(ptr %2, !{{[0-9]+}}, !DIExpression(), !{{[0-9]+}}) +// CHECK-NEXT: %8 = getelementptr inbounds %main.MidStruct, ptr %2, i32 0, i32 1 +// CHECK-NEXT: store i64 41, ptr %8, align 8 +// CHECK-NEXT: #dbg_value(ptr %2, !{{[0-9]+}}, !DIExpression(), !{{[0-9]+}}) +// CHECK-NEXT: %9 = getelementptr inbounds %main.MidStruct, ptr %2, i32 0, i32 2 +// CHECK-NEXT: store i64 42, ptr %9, align 8 +// CHECK-NEXT: #dbg_value(ptr %3, !{{[0-9]+}}, !DIExpression(), !{{[0-9]+}}) +// CHECK-NEXT: %10 = getelementptr inbounds %main.BigStruct, ptr %3, i32 0, i32 0 +// CHECK-NEXT: store i64 70, ptr %10, align 8 +// CHECK-NEXT: #dbg_value(ptr %3, !{{[0-9]+}}, !DIExpression(), !{{[0-9]+}}) +// CHECK-NEXT: %11 = getelementptr inbounds %main.BigStruct, ptr %3, i32 0, i32 1 +// CHECK-NEXT: store i64 71, ptr %11, align 8 +// CHECK-NEXT: #dbg_value(ptr %3, !{{[0-9]+}}, !DIExpression(), !{{[0-9]+}}) +// CHECK-NEXT: %12 = getelementptr inbounds %main.BigStruct, ptr %3, i32 0, i32 2 +// CHECK-NEXT: store i64 72, ptr %12, align 8 +// CHECK-NEXT: #dbg_value(ptr %3, !{{[0-9]+}}, !DIExpression(), !{{[0-9]+}}) +// CHECK-NEXT: %13 = getelementptr inbounds %main.BigStruct, ptr %3, i32 0, i32 3 +// CHECK-NEXT: store i64 73, ptr %13, align 8 +// CHECK-NEXT: #dbg_value(ptr %3, !{{[0-9]+}}, !DIExpression(), !{{[0-9]+}}) +// CHECK-NEXT: %14 = getelementptr inbounds %main.BigStruct, ptr %3, i32 0, i32 4 +// CHECK-NEXT: store i64 74, ptr %14, align 8 +// CHECK-NEXT: #dbg_value(ptr %3, !{{[0-9]+}}, !DIExpression(), !{{[0-9]+}}) +// CHECK-NEXT: %15 = getelementptr inbounds %main.BigStruct, ptr %3, i32 0, i32 5 +// CHECK-NEXT: store i64 75, ptr %15, align 8 +// CHECK-NEXT: #dbg_value(ptr %3, !{{[0-9]+}}, !DIExpression(), !{{[0-9]+}}) +// CHECK-NEXT: %16 = getelementptr inbounds %main.BigStruct, ptr %3, i32 0, i32 6 +// CHECK-NEXT: store i64 76, ptr %16, align 8 +// CHECK-NEXT: #dbg_value(ptr %3, !{{[0-9]+}}, !DIExpression(), !{{[0-9]+}}) +// CHECK-NEXT: %17 = getelementptr inbounds %main.BigStruct, ptr %3, i32 0, i32 7 +// CHECK-NEXT: store i64 77, ptr %17, align 8 +// CHECK-NEXT: #dbg_value(ptr %3, !{{[0-9]+}}, !DIExpression(), !{{[0-9]+}}) +// CHECK-NEXT: %18 = getelementptr inbounds %main.BigStruct, ptr %3, i32 0, i32 8 +// CHECK-NEXT: store i64 78, ptr %18, align 8 +// CHECK-NEXT: #dbg_value(ptr %3, !{{[0-9]+}}, !DIExpression(), !{{[0-9]+}}) +// CHECK-NEXT: %19 = getelementptr inbounds %main.BigStruct, ptr %3, i32 0, i32 9 +// CHECK-NEXT: store i64 79, ptr %19, align 8 +// CHECK-NEXT: #dbg_value(ptr %0, !{{[0-9]+}}, !DIExpression(), !{{[0-9]+}}) +// CHECK-NEXT: %20 = getelementptr inbounds %main.TinyStruct, ptr %0, i32 0, i32 0 +// CHECK-NEXT: %21 = load i64, ptr %20, align 8 +// CHECK-NEXT: #dbg_value(ptr %1, !{{[0-9]+}}, !DIExpression(), !{{[0-9]+}}) +// CHECK-NEXT: %22 = getelementptr inbounds %main.SmallStruct, ptr %1, i32 0, i32 0 +// CHECK-NEXT: %23 = load i64, ptr %22, align 8 +// CHECK-NEXT: #dbg_value(ptr %1, !{{[0-9]+}}, !DIExpression(), !{{[0-9]+}}) +// CHECK-NEXT: %24 = getelementptr inbounds %main.SmallStruct, ptr %1, i32 0, i32 1 +// CHECK-NEXT: %25 = load i64, ptr %24, align 8 +// CHECK-NEXT: #dbg_value(ptr %2, !{{[0-9]+}}, !DIExpression(), !{{[0-9]+}}) +// CHECK-NEXT: %26 = getelementptr inbounds %main.MidStruct, ptr %2, i32 0, i32 0 +// CHECK-NEXT: %27 = load i64, ptr %26, align 8 +// CHECK-NEXT: #dbg_value(ptr %2, !{{[0-9]+}}, !DIExpression(), !{{[0-9]+}}) +// CHECK-NEXT: %28 = getelementptr inbounds %main.MidStruct, ptr %2, i32 0, i32 1 +// CHECK-NEXT: %29 = load i64, ptr %28, align 8 +// CHECK-NEXT: #dbg_value(ptr %2, !{{[0-9]+}}, !DIExpression(), !{{[0-9]+}}) +// CHECK-NEXT: %30 = getelementptr inbounds %main.MidStruct, ptr %2, i32 0, i32 2 +// CHECK-NEXT: %31 = load i64, ptr %30, align 8 +// CHECK-NEXT: #dbg_value(ptr %3, !{{[0-9]+}}, !DIExpression(), !{{[0-9]+}}) +// CHECK-NEXT: %32 = getelementptr inbounds %main.BigStruct, ptr %3, i32 0, i32 0 +// CHECK-NEXT: %33 = load i64, ptr %32, align 8 +// CHECK-NEXT: #dbg_value(ptr %3, !{{[0-9]+}}, !DIExpression(), !{{[0-9]+}}) +// CHECK-NEXT: %34 = getelementptr inbounds %main.BigStruct, ptr %3, i32 0, i32 1 +// CHECK-NEXT: %35 = load i64, ptr %34, align 8 +// CHECK-NEXT: #dbg_value(ptr %3, !{{[0-9]+}}, !DIExpression(), !{{[0-9]+}}) +// CHECK-NEXT: %36 = getelementptr inbounds %main.BigStruct, ptr %3, i32 0, i32 2 +// CHECK-NEXT: %37 = load i64, ptr %36, align 8 +// CHECK-NEXT: #dbg_value(ptr %3, !{{[0-9]+}}, !DIExpression(), !{{[0-9]+}}) +// CHECK-NEXT: %38 = getelementptr inbounds %main.BigStruct, ptr %3, i32 0, i32 3 +// CHECK-NEXT: %39 = load i64, ptr %38, align 8 +// CHECK-NEXT: #dbg_value(ptr %3, !{{[0-9]+}}, !DIExpression(), !{{[0-9]+}}) +// CHECK-NEXT: %40 = getelementptr inbounds %main.BigStruct, ptr %3, i32 0, i32 4 +// CHECK-NEXT: %41 = load i64, ptr %40, align 8 +// CHECK-NEXT: #dbg_value(ptr %3, !{{[0-9]+}}, !DIExpression(), !{{[0-9]+}}) +// CHECK-NEXT: %42 = getelementptr inbounds %main.BigStruct, ptr %3, i32 0, i32 5 +// CHECK-NEXT: %43 = load i64, ptr %42, align 8 +// CHECK-NEXT: #dbg_value(ptr %3, !{{[0-9]+}}, !DIExpression(), !{{[0-9]+}}) +// CHECK-NEXT: %44 = getelementptr inbounds %main.BigStruct, ptr %3, i32 0, i32 6 +// CHECK-NEXT: %45 = load i64, ptr %44, align 8 +// CHECK-NEXT: #dbg_value(ptr %3, !{{[0-9]+}}, !DIExpression(), !{{[0-9]+}}) +// CHECK-NEXT: %46 = getelementptr inbounds %main.BigStruct, ptr %3, i32 0, i32 7 +// CHECK-NEXT: %47 = load i64, ptr %46, align 8 +// CHECK-NEXT: #dbg_value(ptr %3, !{{[0-9]+}}, !DIExpression(), !{{[0-9]+}}) +// CHECK-NEXT: %48 = getelementptr inbounds %main.BigStruct, ptr %3, i32 0, i32 8 +// CHECK-NEXT: %49 = load i64, ptr %48, align 8 +// CHECK-NEXT: #dbg_value(ptr %3, !{{[0-9]+}}, !DIExpression(), !{{[0-9]+}}) +// CHECK-NEXT: %50 = getelementptr inbounds %main.BigStruct, ptr %3, i32 0, i32 9 +// CHECK-NEXT: %51 = load i64, ptr %50, align 8 +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.PrintInt"(i64 %21) +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.PrintByte"(i8 32) +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.PrintInt"(i64 %23) +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.PrintByte"(i8 32) +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.PrintInt"(i64 %25) +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.PrintByte"(i8 32) +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.PrintInt"(i64 %27) +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.PrintByte"(i8 32) +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.PrintInt"(i64 %29) +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.PrintByte"(i8 32) +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.PrintInt"(i64 %31) +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.PrintByte"(i8 32) +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.PrintInt"(i64 %33) +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.PrintByte"(i8 32) +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.PrintInt"(i64 %35) +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.PrintByte"(i8 32) +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.PrintInt"(i64 %37) +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.PrintByte"(i8 32) +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.PrintInt"(i64 %39) +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.PrintByte"(i8 32) +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.PrintInt"(i64 %41) +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.PrintByte"(i8 32) +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.PrintInt"(i64 %43) +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.PrintByte"(i8 32) +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.PrintInt"(i64 %45) +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.PrintByte"(i8 32) +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.PrintInt"(i64 %47) +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.PrintByte"(i8 32) +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.PrintInt"(i64 %49) +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.PrintByte"(i8 32) +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.PrintInt"(i64 %51) +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.PrintByte"(i8 10) +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.PrintString"(%"{{.*}}/runtime/internal/runtime.String" { ptr @{{[0-9]+}}, i64 4 }) +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.PrintByte"(i8 10) +// CHECK-NEXT: ret void +// CHECK-NEXT: } + +// CHECK-LABEL: define { i64, %"{{.*}}/runtime/internal/runtime.iface" } @main.FuncWithAllTypeParams(i8 %0, i16 %1, i32 %2, i64 %3, i64 %4, i8 %5, i16 %6, i32 %7, i64 %8, i64 %9, float %10, double %11, i1 %12, { float, float } %13, { double, double } %14, %"{{.*}}/runtime/internal/runtime.Slice" %15, [3 x i64] %16, [3 x %main.E] %17, %"{{.*}}/runtime/internal/runtime.String" %18, %main.E %19, %main.StructWithAllTypeFields %20, ptr %21, ptr %22, %"{{.*}}/runtime/internal/runtime.iface" %23, ptr %24, ptr %25, %"{{.*}}/runtime/internal/runtime.iface" %26, { ptr, ptr } %27){{.*}} { +// CHECK-NEXT: _llgo_0: +// CHECK-NEXT: #dbg_value(i8 %0, !{{[0-9]+}}, !DIExpression(), !{{[0-9]+}}) +// CHECK-NEXT: #dbg_value(i16 %1, !{{[0-9]+}}, !DIExpression(), !{{[0-9]+}}) +// CHECK-NEXT: #dbg_value(i32 %2, !{{[0-9]+}}, !DIExpression(), !{{[0-9]+}}) +// CHECK-NEXT: #dbg_value(i64 %3, !{{[0-9]+}}, !DIExpression(), !{{[0-9]+}}) +// CHECK-NEXT: #dbg_value(i64 %4, !{{[0-9]+}}, !DIExpression(), !{{[0-9]+}}) +// CHECK-NEXT: #dbg_value(i8 %5, !{{[0-9]+}}, !DIExpression(), !{{[0-9]+}}) +// CHECK-NEXT: #dbg_value(i16 %6, !{{[0-9]+}}, !DIExpression(), !{{[0-9]+}}) +// CHECK-NEXT: #dbg_value(i32 %7, !{{[0-9]+}}, !DIExpression(), !{{[0-9]+}}) +// CHECK-NEXT: #dbg_value(i64 %8, !{{[0-9]+}}, !DIExpression(), !{{[0-9]+}}) +// CHECK-NEXT: #dbg_value(i64 %9, !{{[0-9]+}}, !DIExpression(), !{{[0-9]+}}) +// CHECK-NEXT: #dbg_value(float %10, !{{[0-9]+}}, !DIExpression(), !{{[0-9]+}}) +// CHECK-NEXT: #dbg_value(double %11, !{{[0-9]+}}, !DIExpression(), !{{[0-9]+}}) +// CHECK-NEXT: #dbg_value(i1 %12, !{{[0-9]+}}, !DIExpression(), !{{[0-9]+}}) +// CHECK-NEXT: %28 = alloca { float, float }, align 8 +// CHECK-NEXT: store { float, float } %13, ptr %28, align 4 +// CHECK-NEXT: %29 = load { float, float }, ptr %28, align 4 +// CHECK-NEXT: #dbg_value(ptr %28, !{{[0-9]+}}, !DIExpression(DW_OP_deref), !{{[0-9]+}}) +// CHECK-NEXT: %30 = alloca { double, double }, align 8 +// CHECK-NEXT: store { double, double } %14, ptr %30, align 8 +// CHECK-NEXT: %31 = load { double, double }, ptr %30, align 8 +// CHECK-NEXT: #dbg_value(ptr %30, !{{[0-9]+}}, !DIExpression(DW_OP_deref), !{{[0-9]+}}) +// CHECK-NEXT: %32 = alloca { ptr, i64, i64 }, align 8 +// CHECK-NEXT: store %"{{.*}}/runtime/internal/runtime.Slice" %15, ptr %32, align 8 +// CHECK-NEXT: %33 = load %"{{.*}}/runtime/internal/runtime.Slice", ptr %32, align 8 +// CHECK-NEXT: #dbg_value(ptr %32, !{{[0-9]+}}, !DIExpression(DW_OP_deref), !{{[0-9]+}}) +// CHECK-NEXT: %34 = alloca %"{{.*}}/runtime/internal/runtime.String", align 8 +// CHECK-NEXT: store %"{{.*}}/runtime/internal/runtime.String" %18, ptr %34, align 8 +// CHECK-NEXT: %35 = load %"{{.*}}/runtime/internal/runtime.String", ptr %34, align 8 +// CHECK-NEXT: #dbg_value(ptr %34, !{{[0-9]+}}, !DIExpression(DW_OP_deref), !{{[0-9]+}}) +// CHECK-NEXT: #dbg_value(ptr %21, !{{[0-9]+}}, !DIExpression(), !{{[0-9]+}}) +// CHECK-NEXT: #dbg_value(ptr %22, !{{[0-9]+}}, !DIExpression(), !{{[0-9]+}}) +// CHECK-NEXT: %36 = alloca %"{{.*}}/runtime/internal/runtime.iface", align 8 +// CHECK-NEXT: store %"{{.*}}/runtime/internal/runtime.iface" %23, ptr %36, align 8 +// CHECK-NEXT: %37 = load %"{{.*}}/runtime/internal/runtime.iface", ptr %36, align 8 +// CHECK-NEXT: #dbg_value(ptr %36, !{{[0-9]+}}, !DIExpression(DW_OP_deref), !{{[0-9]+}}) +// CHECK-NEXT: %38 = alloca { i64, i8, i8, i16, i32, ptr, ptr, i64, ptr }, align 8 +// CHECK-NEXT: store ptr %24, ptr %38, align 8 +// CHECK-NEXT: %39 = load ptr, ptr %38, align 8 +// CHECK-NEXT: #dbg_value(ptr %38, !{{[0-9]+}}, !DIExpression(DW_OP_deref), !{{[0-9]+}}) +// CHECK-NEXT: %40 = alloca ptr, align 8 +// CHECK-NEXT: store ptr %25, ptr %40, align 8 +// CHECK-NEXT: %41 = load ptr, ptr %40, align 8 +// CHECK-NEXT: #dbg_value(ptr %40, !{{[0-9]+}}, !DIExpression(DW_OP_deref), !{{[0-9]+}}) +// CHECK-NEXT: %42 = alloca %"{{.*}}/runtime/internal/runtime.iface", align 8 +// CHECK-NEXT: store %"{{.*}}/runtime/internal/runtime.iface" %26, ptr %42, align 8 +// CHECK-NEXT: %43 = load %"{{.*}}/runtime/internal/runtime.iface", ptr %42, align 8 +// CHECK-NEXT: #dbg_value(ptr %42, !{{[0-9]+}}, !DIExpression(DW_OP_deref), !{{[0-9]+}}) +// CHECK-NEXT: %44 = alloca { ptr, ptr }, align 8 +// CHECK-NEXT: store { ptr, ptr } %27, ptr %44, align 8 +// CHECK-NEXT: %45 = load { ptr, ptr }, ptr %44, align 8 +// CHECK-NEXT: #dbg_value(ptr %44, !{{[0-9]+}}, !DIExpression(DW_OP_deref), !{{[0-9]+}}) +// CHECK-NEXT: %46 = call ptr @"{{.*}}/runtime/internal/runtime.AllocZ"(i64 24) +// CHECK-NEXT: #dbg_declare(ptr %46, !{{[0-9]+}}, !DIExpression(), !{{[0-9]+}}) +// CHECK-NEXT: store [3 x i64] %16, ptr %46, align 8 +// CHECK-NEXT: %47 = call ptr @"{{.*}}/runtime/internal/runtime.AllocZ"(i64 24) +// CHECK-NEXT: #dbg_declare(ptr %47, !{{[0-9]+}}, !DIExpression(), !{{[0-9]+}}) +// CHECK-NEXT: store [3 x %main.E] %17, ptr %47, align 8 +// CHECK-NEXT: %48 = call ptr @"{{.*}}/runtime/internal/runtime.AllocZ"(i64 8) +// CHECK-NEXT: #dbg_declare(ptr %48, !{{[0-9]+}}, !DIExpression(), !{{[0-9]+}}) +// CHECK-NEXT: store %main.E %19, ptr %48, align 8 +// CHECK-NEXT: %49 = call ptr @"{{.*}}/runtime/internal/runtime.AllocZ"(i64 288) +// CHECK-NEXT: #dbg_declare(ptr %49, !{{[0-9]+}}, !DIExpression(), !{{[0-9]+}}) +// CHECK-NEXT: store %main.StructWithAllTypeFields %20, ptr %49, align 8 +// CHECK-NEXT: #dbg_value(i8 %0, !{{[0-9]+}}, !DIExpression(), !{{[0-9]+}}) +// CHECK-NEXT: #dbg_value(i16 %1, !{{[0-9]+}}, !DIExpression(), !{{[0-9]+}}) +// CHECK-NEXT: #dbg_value(i32 %2, !{{[0-9]+}}, !DIExpression(), !{{[0-9]+}}) +// CHECK-NEXT: #dbg_value(i64 %3, !{{[0-9]+}}, !DIExpression(), !{{[0-9]+}}) +// CHECK-NEXT: #dbg_value(i64 %4, !{{[0-9]+}}, !DIExpression(), !{{[0-9]+}}) +// CHECK-NEXT: #dbg_value(i8 %5, !{{[0-9]+}}, !DIExpression(), !{{[0-9]+}}) +// CHECK-NEXT: #dbg_value(i16 %6, !{{[0-9]+}}, !DIExpression(), !{{[0-9]+}}) +// CHECK-NEXT: #dbg_value(i32 %7, !{{[0-9]+}}, !DIExpression(), !{{[0-9]+}}) +// CHECK-NEXT: #dbg_value(i64 %8, !{{[0-9]+}}, !DIExpression(), !{{[0-9]+}}) +// CHECK-NEXT: #dbg_value(i64 %9, !{{[0-9]+}}, !DIExpression(), !{{[0-9]+}}) +// CHECK-NEXT: #dbg_value(float %10, !{{[0-9]+}}, !DIExpression(), !{{[0-9]+}}) +// CHECK-NEXT: #dbg_value(double %11, !{{[0-9]+}}, !DIExpression(), !{{[0-9]+}}) +// CHECK-NEXT: #dbg_value(i1 %12, !{{[0-9]+}}, !DIExpression(), !{{[0-9]+}}) +// CHECK-NEXT: %50 = alloca { float, float }, align 8 +// CHECK-NEXT: store { float, float } %13, ptr %50, align 4 +// CHECK-NEXT: %51 = load { float, float }, ptr %50, align 4 +// CHECK-NEXT: #dbg_value(ptr %50, !{{[0-9]+}}, !DIExpression(DW_OP_deref), !{{[0-9]+}}) +// CHECK-NEXT: %52 = alloca { double, double }, align 8 +// CHECK-NEXT: store { double, double } %14, ptr %52, align 8 +// CHECK-NEXT: %53 = load { double, double }, ptr %52, align 8 +// CHECK-NEXT: #dbg_value(ptr %52, !{{[0-9]+}}, !DIExpression(DW_OP_deref), !{{[0-9]+}}) +// CHECK-NEXT: %54 = alloca { ptr, i64, i64 }, align 8 +// CHECK-NEXT: store %"{{.*}}/runtime/internal/runtime.Slice" %15, ptr %54, align 8 +// CHECK-NEXT: %55 = load %"{{.*}}/runtime/internal/runtime.Slice", ptr %54, align 8 +// CHECK-NEXT: #dbg_value(ptr %54, !{{[0-9]+}}, !DIExpression(DW_OP_deref), !{{[0-9]+}}) +// CHECK-NEXT: #dbg_declare(ptr %46, !{{[0-9]+}}, !DIExpression(), !{{[0-9]+}}) +// CHECK-NEXT: %56 = call %"{{.*}}/runtime/internal/runtime.Slice" @"{{.*}}/runtime/internal/runtime.NewSlice2"(ptr %46, i64 8, i64 3, i64 0, i64 3, i1 true, i1 true, i1 true) +// CHECK-NEXT: %57 = alloca %"{{.*}}/runtime/internal/runtime.String", align 8 +// CHECK-NEXT: store %"{{.*}}/runtime/internal/runtime.String" %18, ptr %57, align 8 +// CHECK-NEXT: %58 = load %"{{.*}}/runtime/internal/runtime.String", ptr %57, align 8 +// CHECK-NEXT: #dbg_value(ptr %57, !{{[0-9]+}}, !DIExpression(DW_OP_deref), !{{[0-9]+}}) +// CHECK-NEXT: #dbg_declare(ptr %48, !{{[0-9]+}}, !DIExpression(), !{{[0-9]+}}) +// CHECK-NEXT: #dbg_declare(ptr %49, !{{[0-9]+}}, !DIExpression(), !{{[0-9]+}}) +// CHECK-NEXT: #dbg_value(ptr %21, !{{[0-9]+}}, !DIExpression(), !{{[0-9]+}}) +// CHECK-NEXT: #dbg_value(ptr %22, !{{[0-9]+}}, !DIExpression(), !{{[0-9]+}}) +// CHECK-NEXT: %59 = alloca %"{{.*}}/runtime/internal/runtime.iface", align 8 +// CHECK-NEXT: store %"{{.*}}/runtime/internal/runtime.iface" %23, ptr %59, align 8 +// CHECK-NEXT: %60 = load %"{{.*}}/runtime/internal/runtime.iface", ptr %59, align 8 +// CHECK-NEXT: #dbg_value(ptr %59, !{{[0-9]+}}, !DIExpression(DW_OP_deref), !{{[0-9]+}}) +// CHECK-NEXT: %61 = alloca { i64, i8, i8, i16, i32, ptr, ptr, i64, ptr }, align 8 +// CHECK-NEXT: store ptr %24, ptr %61, align 8 +// CHECK-NEXT: %62 = load ptr, ptr %61, align 8 +// CHECK-NEXT: #dbg_value(ptr %61, !{{[0-9]+}}, !DIExpression(DW_OP_deref), !{{[0-9]+}}) +// CHECK-NEXT: %63 = alloca ptr, align 8 +// CHECK-NEXT: store ptr %25, ptr %63, align 8 +// CHECK-NEXT: %64 = load ptr, ptr %63, align 8 +// CHECK-NEXT: #dbg_value(ptr %63, !{{[0-9]+}}, !DIExpression(DW_OP_deref), !{{[0-9]+}}) +// CHECK-NEXT: %65 = alloca %"{{.*}}/runtime/internal/runtime.iface", align 8 +// CHECK-NEXT: store %"{{.*}}/runtime/internal/runtime.iface" %26, ptr %65, align 8 +// CHECK-NEXT: %66 = load %"{{.*}}/runtime/internal/runtime.iface", ptr %65, align 8 +// CHECK-NEXT: #dbg_value(ptr %65, !{{[0-9]+}}, !DIExpression(DW_OP_deref), !{{[0-9]+}}) +// CHECK-NEXT: %67 = alloca { ptr, ptr }, align 8 +// CHECK-NEXT: store { ptr, ptr } %27, ptr %67, align 8 +// CHECK-NEXT: %68 = load { ptr, ptr }, ptr %67, align 8 +// CHECK-NEXT: #dbg_value(ptr %67, !{{[0-9]+}}, !DIExpression(DW_OP_deref), !{{[0-9]+}}) +// CHECK-NEXT: %69 = sext i8 %0 to i64 +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.PrintInt"(i64 %69) +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.PrintByte"(i8 32) +// CHECK-NEXT: %70 = sext i16 %1 to i64 +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.PrintInt"(i64 %70) +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.PrintByte"(i8 32) +// CHECK-NEXT: %71 = sext i32 %2 to i64 +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.PrintInt"(i64 %71) +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.PrintByte"(i8 32) +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.PrintInt"(i64 %3) +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.PrintByte"(i8 32) +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.PrintInt"(i64 %4) +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.PrintByte"(i8 32) +// CHECK-NEXT: %72 = zext i8 %5 to i64 +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.PrintUint"(i64 %72) +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.PrintByte"(i8 32) +// CHECK-NEXT: %73 = zext i16 %6 to i64 +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.PrintUint"(i64 %73) +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.PrintByte"(i8 32) +// CHECK-NEXT: %74 = zext i32 %7 to i64 +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.PrintUint"(i64 %74) +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.PrintByte"(i8 32) +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.PrintUint"(i64 %8) +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.PrintByte"(i8 32) +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.PrintUint"(i64 %9) +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.PrintByte"(i8 32) +// CHECK-NEXT: %75 = fpext float %10 to double +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.PrintFloat"(double %75) +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.PrintByte"(i8 32) +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.PrintFloat"(double %11) +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.PrintByte"(i8 32) +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.PrintBool"(i1 %12) +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.PrintByte"(i8 32) +// CHECK-NEXT: %76 = extractvalue { float, float } %13, 0 +// CHECK-NEXT: %77 = extractvalue { float, float } %13, 1 +// CHECK-NEXT: %78 = fpext float %76 to double +// CHECK-NEXT: %79 = fpext float %77 to double +// CHECK-NEXT: %80 = insertvalue { double, double } undef, double %78, 0 +// CHECK-NEXT: %81 = insertvalue { double, double } %80, double %79, 1 +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.PrintComplex"({ double, double } %81) +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.PrintByte"(i8 32) +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.PrintComplex"({ double, double } %14) +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.PrintByte"(i8 32) +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.PrintSlice"(%"{{.*}}/runtime/internal/runtime.Slice" %15) +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.PrintByte"(i8 32) +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.PrintSlice"(%"{{.*}}/runtime/internal/runtime.Slice" %56) +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.PrintByte"(i8 32) +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.PrintString"(%"{{.*}}/runtime/internal/runtime.String" %18) +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.PrintByte"(i8 32) +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.PrintPointer"(ptr %48) +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.PrintByte"(i8 32) +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.PrintPointer"(ptr %49) +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.PrintByte"(i8 32) +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.PrintPointer"(ptr %21) +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.PrintByte"(i8 32) +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.PrintPointer"(ptr %22) +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.PrintByte"(i8 32) +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.PrintIface"(%"{{.*}}/runtime/internal/runtime.iface" %23) +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.PrintByte"(i8 32) +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.PrintPointer"(ptr %24) +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.PrintByte"(i8 32) +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.PrintPointer"(ptr %25) +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.PrintByte"(i8 32) +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.PrintIface"(%"{{.*}}/runtime/internal/runtime.iface" %26) +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.PrintByte"(i8 32) +// CHECK-NEXT: %82 = extractvalue { ptr, ptr } %27, 0 +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.PrintPointer"(ptr %82) +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.PrintByte"(i8 10) +// CHECK-NEXT: #dbg_value(i8 9, !{{[0-9]+}}, !DIExpression(), !{{[0-9]+}}) +// CHECK-NEXT: #dbg_value(i16 10, !{{[0-9]+}}, !DIExpression(), !{{[0-9]+}}) +// CHECK-NEXT: #dbg_value(i32 11, !{{[0-9]+}}, !DIExpression(), !{{[0-9]+}}) +// CHECK-NEXT: #dbg_value(i64 12, !{{[0-9]+}}, !DIExpression(), !{{[0-9]+}}) +// CHECK-NEXT: #dbg_value(i64 13, !{{[0-9]+}}, !DIExpression(), !{{[0-9]+}}) +// CHECK-NEXT: #dbg_value(i8 14, !{{[0-9]+}}, !DIExpression(), !{{[0-9]+}}) +// CHECK-NEXT: #dbg_value(i16 15, !{{[0-9]+}}, !DIExpression(), !{{[0-9]+}}) +// CHECK-NEXT: #dbg_value(i32 16, !{{[0-9]+}}, !DIExpression(), !{{[0-9]+}}) +// CHECK-NEXT: #dbg_value(i64 17, !{{[0-9]+}}, !DIExpression(), !{{[0-9]+}}) +// CHECK-NEXT: #dbg_value(i64 18, !{{[0-9]+}}, !DIExpression(), !{{[0-9]+}}) +// CHECK-NEXT: #dbg_value(float 1.900000e+01, !{{[0-9]+}}, !DIExpression(), !{{[0-9]+}}) +// CHECK-NEXT: #dbg_value(double 2.000000e+01, !{{[0-9]+}}, !DIExpression(), !{{[0-9]+}}) +// CHECK-NEXT: #dbg_value(i1 false, !{{[0-9]+}}, !DIExpression(), !{{[0-9]+}}) +// CHECK-NEXT: %83 = alloca { float, float }, align 8 +// CHECK-NEXT: store { float, float } { float 2.100000e+01, float 2.200000e+01 }, ptr %83, align 4 +// CHECK-NEXT: %84 = load { float, float }, ptr %83, align 4 +// CHECK-NEXT: #dbg_value(ptr %83, !{{[0-9]+}}, !DIExpression(DW_OP_deref), !{{[0-9]+}}) +// CHECK-NEXT: %85 = alloca { double, double }, align 8 +// CHECK-NEXT: store { double, double } { double 2.300000e+01, double 2.400000e+01 }, ptr %85, align 8 +// CHECK-NEXT: %86 = load { double, double }, ptr %85, align 8 +// CHECK-NEXT: #dbg_value(ptr %85, !{{[0-9]+}}, !DIExpression(DW_OP_deref), !{{[0-9]+}}) +// CHECK-NEXT: %87 = alloca { ptr, i64, i64 }, align 8 +// CHECK-NEXT: store %"{{.*}}/runtime/internal/runtime.Slice" %15, ptr %87, align 8 +// CHECK-NEXT: %88 = load %"{{.*}}/runtime/internal/runtime.Slice", ptr %87, align 8 +// CHECK-NEXT: #dbg_value(ptr %87, !{{[0-9]+}}, !DIExpression(DW_OP_deref), !{{[0-9]+}}) +// CHECK-NEXT: %89 = call ptr @"{{.*}}/runtime/internal/runtime.AllocZ"(i64 24) +// CHECK-NEXT: %90 = getelementptr inbounds i64, ptr %89, i64 0 +// CHECK-NEXT: store i64 31, ptr %90, align 8 +// CHECK-NEXT: %91 = getelementptr inbounds i64, ptr %89, i64 1 +// CHECK-NEXT: store i64 32, ptr %91, align 8 +// CHECK-NEXT: %92 = getelementptr inbounds i64, ptr %89, i64 2 +// CHECK-NEXT: store i64 33, ptr %92, align 8 +// CHECK-NEXT: %93 = insertvalue %"{{.*}}/runtime/internal/runtime.Slice" undef, ptr %89, 0 +// CHECK-NEXT: %94 = insertvalue %"{{.*}}/runtime/internal/runtime.Slice" %93, i64 3, 1 +// CHECK-NEXT: %95 = insertvalue %"{{.*}}/runtime/internal/runtime.Slice" %94, i64 3, 2 +// CHECK-NEXT: #dbg_declare(ptr %46, !{{[0-9]+}}, !DIExpression(), !{{[0-9]+}}) +// CHECK-NEXT: %96 = getelementptr inbounds i64, ptr %46, i64 0 +// CHECK-NEXT: %97 = getelementptr inbounds i64, ptr %46, i64 1 +// CHECK-NEXT: %98 = getelementptr inbounds i64, ptr %46, i64 2 +// CHECK-NEXT: store i64 34, ptr %96, align 8 +// CHECK-NEXT: store i64 35, ptr %97, align 8 +// CHECK-NEXT: store i64 36, ptr %98, align 8 +// CHECK-NEXT: #dbg_declare(ptr %47, !{{[0-9]+}}, !DIExpression(), !{{[0-9]+}}) +// CHECK-NEXT: %99 = getelementptr inbounds %main.E, ptr %47, i64 0 +// CHECK-NEXT: %100 = getelementptr inbounds %main.E, ptr %99, i32 0, i32 0 +// CHECK-NEXT: %101 = getelementptr inbounds %main.E, ptr %47, i64 1 +// CHECK-NEXT: %102 = getelementptr inbounds %main.E, ptr %101, i32 0, i32 0 +// CHECK-NEXT: %103 = getelementptr inbounds %main.E, ptr %47, i64 2 +// CHECK-NEXT: %104 = getelementptr inbounds %main.E, ptr %103, i32 0, i32 0 +// CHECK-NEXT: store i64 37, ptr %100, align 8 +// CHECK-NEXT: store i64 38, ptr %102, align 8 +// CHECK-NEXT: store i64 39, ptr %104, align 8 +// CHECK-NEXT: %105 = alloca %"{{.*}}/runtime/internal/runtime.String", align 8 +// CHECK-NEXT: store %"{{.*}}/runtime/internal/runtime.String" { ptr @{{[0-9]+}}, i64 5 }, ptr %105, align 8 +// CHECK-NEXT: %106 = load %"{{.*}}/runtime/internal/runtime.String", ptr %105, align 8 +// CHECK-NEXT: #dbg_value(ptr %105, !{{[0-9]+}}, !DIExpression(DW_OP_deref), !{{[0-9]+}}) +// CHECK-NEXT: #dbg_declare(ptr %48, !{{[0-9]+}}, !DIExpression(), !{{[0-9]+}}) +// CHECK-NEXT: %107 = getelementptr inbounds %main.E, ptr %48, i32 0, i32 0 +// CHECK-NEXT: store i64 40, ptr %107, align 8 +// CHECK-NEXT: #dbg_value(i8 9, !{{[0-9]+}}, !DIExpression(), !{{[0-9]+}}) +// CHECK-NEXT: #dbg_value(i16 10, !{{[0-9]+}}, !DIExpression(), !{{[0-9]+}}) +// CHECK-NEXT: #dbg_value(i32 11, !{{[0-9]+}}, !DIExpression(), !{{[0-9]+}}) +// CHECK-NEXT: #dbg_value(i64 12, !{{[0-9]+}}, !DIExpression(), !{{[0-9]+}}) +// CHECK-NEXT: #dbg_value(i64 13, !{{[0-9]+}}, !DIExpression(), !{{[0-9]+}}) +// CHECK-NEXT: #dbg_value(i8 14, !{{[0-9]+}}, !DIExpression(), !{{[0-9]+}}) +// CHECK-NEXT: #dbg_value(i16 15, !{{[0-9]+}}, !DIExpression(), !{{[0-9]+}}) +// CHECK-NEXT: #dbg_value(i32 16, !{{[0-9]+}}, !DIExpression(), !{{[0-9]+}}) +// CHECK-NEXT: #dbg_value(i64 17, !{{[0-9]+}}, !DIExpression(), !{{[0-9]+}}) +// CHECK-NEXT: #dbg_value(i64 18, !{{[0-9]+}}, !DIExpression(), !{{[0-9]+}}) +// CHECK-NEXT: #dbg_value(float 1.900000e+01, !{{[0-9]+}}, !DIExpression(), !{{[0-9]+}}) +// CHECK-NEXT: #dbg_value(double 2.000000e+01, !{{[0-9]+}}, !DIExpression(), !{{[0-9]+}}) +// CHECK-NEXT: #dbg_value(i1 false, !{{[0-9]+}}, !DIExpression(), !{{[0-9]+}}) +// CHECK-NEXT: %108 = alloca { float, float }, align 8 +// CHECK-NEXT: store { float, float } { float 2.100000e+01, float 2.200000e+01 }, ptr %108, align 4 +// CHECK-NEXT: %109 = load { float, float }, ptr %108, align 4 +// CHECK-NEXT: #dbg_value(ptr %108, !{{[0-9]+}}, !DIExpression(DW_OP_deref), !{{[0-9]+}}) +// CHECK-NEXT: %110 = alloca { double, double }, align 8 +// CHECK-NEXT: store { double, double } { double 2.300000e+01, double 2.400000e+01 }, ptr %110, align 8 +// CHECK-NEXT: %111 = load { double, double }, ptr %110, align 8 +// CHECK-NEXT: #dbg_value(ptr %110, !{{[0-9]+}}, !DIExpression(DW_OP_deref), !{{[0-9]+}}) +// CHECK-NEXT: %112 = alloca { ptr, i64, i64 }, align 8 +// CHECK-NEXT: store %"{{.*}}/runtime/internal/runtime.Slice" %95, ptr %112, align 8 +// CHECK-NEXT: %113 = load %"{{.*}}/runtime/internal/runtime.Slice", ptr %112, align 8 +// CHECK-NEXT: #dbg_value(ptr %112, !{{[0-9]+}}, !DIExpression(DW_OP_deref), !{{[0-9]+}}) +// CHECK-NEXT: #dbg_declare(ptr %46, !{{[0-9]+}}, !DIExpression(), !{{[0-9]+}}) +// CHECK-NEXT: %114 = call %"{{.*}}/runtime/internal/runtime.Slice" @"{{.*}}/runtime/internal/runtime.NewSlice2"(ptr %46, i64 8, i64 3, i64 0, i64 3, i1 true, i1 true, i1 true) +// CHECK-NEXT: #dbg_declare(ptr %47, !{{[0-9]+}}, !DIExpression(), !{{[0-9]+}}) +// CHECK-NEXT: %115 = alloca %"{{.*}}/runtime/internal/runtime.String", align 8 +// CHECK-NEXT: store %"{{.*}}/runtime/internal/runtime.String" { ptr @{{[0-9]+}}, i64 5 }, ptr %115, align 8 +// CHECK-NEXT: %116 = load %"{{.*}}/runtime/internal/runtime.String", ptr %115, align 8 +// CHECK-NEXT: #dbg_value(ptr %115, !{{[0-9]+}}, !DIExpression(DW_OP_deref), !{{[0-9]+}}) +// CHECK-NEXT: #dbg_declare(ptr %48, !{{[0-9]+}}, !DIExpression(), !{{[0-9]+}}) +// CHECK-NEXT: #dbg_declare(ptr %49, !{{[0-9]+}}, !DIExpression(), !{{[0-9]+}}) +// CHECK-NEXT: #dbg_value(ptr %21, !{{[0-9]+}}, !DIExpression(), !{{[0-9]+}}) +// CHECK-NEXT: #dbg_value(ptr %22, !{{[0-9]+}}, !DIExpression(), !{{[0-9]+}}) +// CHECK-NEXT: %117 = alloca %"{{.*}}/runtime/internal/runtime.iface", align 8 +// CHECK-NEXT: store %"{{.*}}/runtime/internal/runtime.iface" %23, ptr %117, align 8 +// CHECK-NEXT: %118 = load %"{{.*}}/runtime/internal/runtime.iface", ptr %117, align 8 +// CHECK-NEXT: #dbg_value(ptr %117, !{{[0-9]+}}, !DIExpression(DW_OP_deref), !{{[0-9]+}}) +// CHECK-NEXT: %119 = alloca { i64, i8, i8, i16, i32, ptr, ptr, i64, ptr }, align 8 +// CHECK-NEXT: store ptr %24, ptr %119, align 8 +// CHECK-NEXT: %120 = load ptr, ptr %119, align 8 +// CHECK-NEXT: #dbg_value(ptr %119, !{{[0-9]+}}, !DIExpression(DW_OP_deref), !{{[0-9]+}}) +// CHECK-NEXT: %121 = alloca ptr, align 8 +// CHECK-NEXT: store ptr %25, ptr %121, align 8 +// CHECK-NEXT: %122 = load ptr, ptr %121, align 8 +// CHECK-NEXT: #dbg_value(ptr %121, !{{[0-9]+}}, !DIExpression(DW_OP_deref), !{{[0-9]+}}) +// CHECK-NEXT: %123 = alloca %"{{.*}}/runtime/internal/runtime.iface", align 8 +// CHECK-NEXT: store %"{{.*}}/runtime/internal/runtime.iface" %26, ptr %123, align 8 +// CHECK-NEXT: %124 = load %"{{.*}}/runtime/internal/runtime.iface", ptr %123, align 8 +// CHECK-NEXT: #dbg_value(ptr %123, !{{[0-9]+}}, !DIExpression(DW_OP_deref), !{{[0-9]+}}) +// CHECK-NEXT: %125 = alloca { ptr, ptr }, align 8 +// CHECK-NEXT: store { ptr, ptr } %27, ptr %125, align 8 +// CHECK-NEXT: %126 = load { ptr, ptr }, ptr %125, align 8 +// CHECK-NEXT: #dbg_value(ptr %125, !{{[0-9]+}}, !DIExpression(DW_OP_deref), !{{[0-9]+}}) +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.PrintInt"(i64 9) +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.PrintByte"(i8 32) +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.PrintInt"(i64 10) +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.PrintByte"(i8 32) +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.PrintInt"(i64 11) +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.PrintByte"(i8 32) +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.PrintInt"(i64 12) +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.PrintByte"(i8 32) +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.PrintInt"(i64 13) +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.PrintByte"(i8 32) +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.PrintUint"(i64 14) +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.PrintByte"(i8 32) +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.PrintUint"(i64 15) +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.PrintByte"(i8 32) +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.PrintUint"(i64 16) +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.PrintByte"(i8 32) +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.PrintUint"(i64 17) +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.PrintByte"(i8 32) +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.PrintUint"(i64 18) +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.PrintByte"(i8 32) +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.PrintFloat"(double 1.900000e+01) +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.PrintByte"(i8 32) +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.PrintFloat"(double 2.000000e+01) +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.PrintByte"(i8 32) +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.PrintBool"(i1 false) +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.PrintByte"(i8 32) +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.PrintComplex"({ double, double } { double 2.100000e+01, double 2.200000e+01 }) +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.PrintByte"(i8 32) +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.PrintComplex"({ double, double } { double 2.300000e+01, double 2.400000e+01 }) +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.PrintByte"(i8 32) +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.PrintSlice"(%"{{.*}}/runtime/internal/runtime.Slice" %95) +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.PrintByte"(i8 32) +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.PrintSlice"(%"{{.*}}/runtime/internal/runtime.Slice" %114) +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.PrintByte"(i8 32) +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.PrintPointer"(ptr %47) +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.PrintByte"(i8 32) +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.PrintString"(%"{{.*}}/runtime/internal/runtime.String" { ptr @{{[0-9]+}}, i64 5 }) +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.PrintByte"(i8 32) +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.PrintPointer"(ptr %48) +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.PrintByte"(i8 32) +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.PrintPointer"(ptr %49) +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.PrintByte"(i8 32) +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.PrintPointer"(ptr %21) +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.PrintByte"(i8 32) +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.PrintPointer"(ptr %22) +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.PrintByte"(i8 32) +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.PrintIface"(%"{{.*}}/runtime/internal/runtime.iface" %23) +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.PrintByte"(i8 32) +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.PrintPointer"(ptr %24) +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.PrintByte"(i8 32) +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.PrintPointer"(ptr %25) +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.PrintByte"(i8 32) +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.PrintIface"(%"{{.*}}/runtime/internal/runtime.iface" %26) +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.PrintByte"(i8 32) +// CHECK-NEXT: %127 = extractvalue { ptr, ptr } %27, 0 +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.PrintPointer"(ptr %127) +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.PrintByte"(i8 10) +// CHECK-NEXT: %128 = call %"{{.*}}/runtime/internal/runtime.iface" @errors.New(%"{{.*}}/runtime/internal/runtime.String" { ptr @{{[0-9]+}}, i64 10 }) +// CHECK-NEXT: %129 = insertvalue { i64, %"{{.*}}/runtime/internal/runtime.iface" } { i64 1, %"{{.*}}/runtime/internal/runtime.iface" undef }, %"{{.*}}/runtime/internal/runtime.iface" %128, 1 +// CHECK-NEXT: ret { i64, %"{{.*}}/runtime/internal/runtime.iface" } %129 +// CHECK-NEXT: } + +// CHECK-LABEL: define void @main.FuncWithAllTypeStructParam(%main.StructWithAllTypeFields %0){{.*}} !dbg !{{[0-9]+}} { +// CHECK-NEXT: _llgo_0: +// CHECK-NEXT: %1 = call ptr @"{{.*}}/runtime/internal/runtime.AllocZ"(i64 288) +// CHECK-NEXT: #dbg_declare(ptr %1, !{{[0-9]+}}, !DIExpression(), !{{[0-9]+}}) +// CHECK-NEXT: store %main.StructWithAllTypeFields %0, ptr %1, align 8 +// CHECK-NEXT: #dbg_declare(ptr %1, !{{[0-9]+}}, !DIExpression(), !{{[0-9]+}}) +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.PrintPointer"(ptr %1) +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.PrintByte"(i8 10) +// CHECK-NEXT: #dbg_declare(ptr %1, !{{[0-9]+}}, !DIExpression(), !{{[0-9]+}}) +// CHECK-NEXT: %2 = getelementptr inbounds %main.StructWithAllTypeFields, ptr %1, i32 0, i32 0 +// CHECK-NEXT: store i8 8, ptr %2, align 1 +// CHECK-NEXT: #dbg_declare(ptr %1, !{{[0-9]+}}, !DIExpression(), !{{[0-9]+}}) +// CHECK-NEXT: %3 = getelementptr inbounds %main.StructWithAllTypeFields, ptr %1, i32 0, i32 18 +// CHECK-NEXT: %4 = load %"{{.*}}/runtime/internal/runtime.String", ptr %3, align 8 +// CHECK-NEXT: %5 = extractvalue %"{{.*}}/runtime/internal/runtime.String" %4, 1 +// CHECK-NEXT: #dbg_declare(ptr %1, !{{[0-9]+}}, !DIExpression(), !{{[0-9]+}}) +// CHECK-NEXT: %6 = getelementptr inbounds %main.StructWithAllTypeFields, ptr %1, i32 0, i32 0 +// CHECK-NEXT: %7 = load i8, ptr %6, align 1 +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.PrintInt"(i64 %5) +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.PrintByte"(i8 32) +// CHECK-NEXT: %8 = sext i8 %7 to i64 +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.PrintInt"(i64 %8) +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.PrintByte"(i8 10) +// CHECK-NEXT: ret void +// CHECK-NEXT: } + +// CHECK-LABEL: define void @main.ScopeFor(){{.*}} { +// CHECK-NEXT: _llgo_0: +// CHECK-NEXT: #dbg_value(i64 1, !{{[0-9]+}}, !DIExpression(), !{{[0-9]+}}) +// CHECK-NEXT: #dbg_value(i64 0, !{{[0-9]+}}, !DIExpression(), !{{[0-9]+}}) +// CHECK-NEXT: br label %_llgo_1 +// CHECK-EMPTY: +// CHECK-NEXT: _llgo_1: ; preds = %_llgo_4, %_llgo_0 +// CHECK-NEXT: %0 = phi i64 [ 0, %_llgo_0 ], [ %3, %_llgo_4 ] +// CHECK-NEXT: #dbg_value(i64 %0, !{{[0-9]+}}, !DIExpression(), !{{[0-9]+}}) +// CHECK-NEXT: %1 = icmp slt i64 %0, 10 +// CHECK-NEXT: br i1 %1, label %_llgo_2, label %_llgo_3 +// CHECK-EMPTY: +// CHECK-NEXT: _llgo_2: ; preds = %_llgo_1 +// CHECK-NEXT: #dbg_value(i64 %0, !{{[0-9]+}}, !DIExpression(), !{{[0-9]+}}) +// CHECK-NEXT: %2 = icmp eq i64 %0, 0 +// CHECK-NEXT: br i1 %2, label %_llgo_5, label %_llgo_7 +// CHECK-EMPTY: +// CHECK-NEXT: _llgo_3: ; preds = %_llgo_1 +// CHECK-NEXT: #dbg_value(i64 1, !{{[0-9]+}}, !DIExpression(), !{{[0-9]+}}) +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.PrintString"(%"{{.*}}/runtime/internal/runtime.String" { ptr @{{[0-9]+}}, i64 2 }) +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.PrintByte"(i8 32) +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.PrintInt"(i64 1) +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.PrintByte"(i8 10) +// CHECK-NEXT: ret void +// CHECK-EMPTY: +// CHECK-NEXT: _llgo_4: ; preds = %_llgo_8, %_llgo_6, %_llgo_5 +// CHECK-NEXT: %3 = add i64 %0, 1 +// CHECK-NEXT: #dbg_value(i64 %3, !{{[0-9]+}}, !DIExpression(), !{{[0-9]+}}) +// CHECK-NEXT: br label %_llgo_1 +// CHECK-EMPTY: +// CHECK-NEXT: _llgo_5: ; preds = %_llgo_2 +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.PrintString"(%"{{.*}}/runtime/internal/runtime.String" { ptr @{{[0-9]+}}, i64 6 }) +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.PrintByte"(i8 10) +// CHECK-NEXT: #dbg_value(i64 %0, !{{[0-9]+}}, !DIExpression(), !{{[0-9]+}}) +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.PrintString"(%"{{.*}}/runtime/internal/runtime.String" { ptr @{{[0-9]+}}, i64 2 }) +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.PrintByte"(i8 32) +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.PrintInt"(i64 %0) +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.PrintByte"(i8 10) +// CHECK-NEXT: br label %_llgo_4 +// CHECK-EMPTY: +// CHECK-NEXT: _llgo_6: ; preds = %_llgo_7 +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.PrintString"(%"{{.*}}/runtime/internal/runtime.String" { ptr @{{[0-9]+}}, i64 6 }) +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.PrintByte"(i8 10) +// CHECK-NEXT: #dbg_value(i64 %0, !{{[0-9]+}}, !DIExpression(), !{{[0-9]+}}) +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.PrintString"(%"{{.*}}/runtime/internal/runtime.String" { ptr @{{[0-9]+}}, i64 2 }) +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.PrintByte"(i8 32) +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.PrintInt"(i64 %0) +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.PrintByte"(i8 10) +// CHECK-NEXT: br label %_llgo_4 +// CHECK-EMPTY: +// CHECK-NEXT: _llgo_7: ; preds = %_llgo_2 +// CHECK-NEXT: %4 = icmp eq i64 %0, 1 +// CHECK-NEXT: br i1 %4, label %_llgo_6, label %_llgo_8 +// CHECK-EMPTY: +// CHECK-NEXT: _llgo_8: ; preds = %_llgo_7 +// CHECK-NEXT: #dbg_value(i64 %0, !{{[0-9]+}}, !DIExpression(), !{{[0-9]+}}) +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.PrintString"(%"{{.*}}/runtime/internal/runtime.String" { ptr @{{[0-9]+}}, i64 4 }) +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.PrintByte"(i8 32) +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.PrintInt"(i64 %0) +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.PrintByte"(i8 10) +// CHECK-NEXT: br label %_llgo_4 +// CHECK-NEXT: } + +// CHECK-LABEL: define void @main.ScopeIf(i64 %0){{.*}} { +// CHECK-NEXT: _llgo_0: +// CHECK-NEXT: #dbg_value(i64 %0, !{{[0-9]+}}, !DIExpression(), !{{[0-9]+}}) +// CHECK-NEXT: #dbg_value(i64 1, !{{[0-9]+}}, !DIExpression(), !{{[0-9]+}}) +// CHECK-NEXT: #dbg_value(i64 %0, !{{[0-9]+}}, !DIExpression(), !{{[0-9]+}}) +// CHECK-NEXT: %1 = icmp eq i64 %0, 1 +// CHECK-NEXT: br i1 %1, label %_llgo_1, label %_llgo_3 +// CHECK-EMPTY: +// CHECK-NEXT: _llgo_1: ; preds = %_llgo_0 +// CHECK-NEXT: #dbg_value(i64 2, !{{[0-9]+}}, !DIExpression(), !{{[0-9]+}}) +// CHECK-NEXT: #dbg_value(i64 3, !{{[0-9]+}}, !DIExpression(), !{{[0-9]+}}) +// CHECK-NEXT: #dbg_value(i64 1, !{{[0-9]+}}, !DIExpression(), !{{[0-9]+}}) +// CHECK-NEXT: #dbg_value(i64 2, !{{[0-9]+}}, !DIExpression(), !{{[0-9]+}}) +// CHECK-NEXT: #dbg_value(i64 3, !{{[0-9]+}}, !DIExpression(), !{{[0-9]+}}) +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.PrintInt"(i64 1) +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.PrintByte"(i8 32) +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.PrintInt"(i64 2) +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.PrintByte"(i8 32) +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.PrintInt"(i64 3) +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.PrintByte"(i8 10) +// CHECK-NEXT: br label %_llgo_2 +// CHECK-EMPTY: +// CHECK-NEXT: _llgo_2: ; preds = %_llgo_3, %_llgo_1 +// CHECK-NEXT: #dbg_value(i64 1, !{{[0-9]+}}, !DIExpression(), !{{[0-9]+}}) +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.PrintString"(%"{{.*}}/runtime/internal/runtime.String" { ptr @{{[0-9]+}}, i64 2 }) +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.PrintByte"(i8 32) +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.PrintInt"(i64 1) +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.PrintByte"(i8 10) +// CHECK-NEXT: ret void +// CHECK-EMPTY: +// CHECK-NEXT: _llgo_3: ; preds = %_llgo_0 +// CHECK-NEXT: #dbg_value(i64 3, !{{[0-9]+}}, !DIExpression(), !{{[0-9]+}}) +// CHECK-NEXT: #dbg_value(i64 4, !{{[0-9]+}}, !DIExpression(), !{{[0-9]+}}) +// CHECK-NEXT: #dbg_value(i64 1, !{{[0-9]+}}, !DIExpression(), !{{[0-9]+}}) +// CHECK-NEXT: #dbg_value(i64 3, !{{[0-9]+}}, !DIExpression(), !{{[0-9]+}}) +// CHECK-NEXT: #dbg_value(i64 4, !{{[0-9]+}}, !DIExpression(), !{{[0-9]+}}) +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.PrintInt"(i64 1) +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.PrintByte"(i8 32) +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.PrintInt"(i64 3) +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.PrintByte"(i8 32) +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.PrintInt"(i64 4) +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.PrintByte"(i8 10) +// CHECK-NEXT: br label %_llgo_2 +// CHECK-NEXT: } + +// CHECK-LABEL: define void @main.ScopeSwitch(i64 %0){{.*}} { +// CHECK-NEXT: _llgo_0: +// CHECK-NEXT: #dbg_value(i64 %0, !{{[0-9]+}}, !DIExpression(), !{{[0-9]+}}) +// CHECK-NEXT: #dbg_value(i64 0, !{{[0-9]+}}, !DIExpression(), !{{[0-9]+}}) +// CHECK-NEXT: #dbg_value(i64 %0, !{{[0-9]+}}, !DIExpression(), !{{[0-9]+}}) +// CHECK-NEXT: %1 = icmp eq i64 %0, 1 +// CHECK-NEXT: br i1 %1, label %_llgo_2, label %_llgo_4 +// CHECK-EMPTY: +// CHECK-NEXT: _llgo_1: ; preds = %_llgo_5, %_llgo_3, %_llgo_2 +// CHECK-NEXT: #dbg_value(i64 0, !{{[0-9]+}}, !DIExpression(), !{{[0-9]+}}) +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.PrintString"(%"{{.*}}/runtime/internal/runtime.String" { ptr @{{[0-9]+}}, i64 2 }) +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.PrintByte"(i8 32) +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.PrintInt"(i64 0) +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.PrintByte"(i8 10) +// CHECK-NEXT: ret void +// CHECK-EMPTY: +// CHECK-NEXT: _llgo_2: ; preds = %_llgo_0 +// CHECK-NEXT: #dbg_value(i64 1, !{{[0-9]+}}, !DIExpression(), !{{[0-9]+}}) +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.PrintString"(%"{{.*}}/runtime/internal/runtime.String" { ptr @{{[0-9]+}}, i64 6 }) +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.PrintByte"(i8 10) +// CHECK-NEXT: #dbg_value(i64 %0, !{{[0-9]+}}, !DIExpression(), !{{[0-9]+}}) +// CHECK-NEXT: #dbg_value(i64 0, !{{[0-9]+}}, !DIExpression(), !{{[0-9]+}}) +// CHECK-NEXT: #dbg_value(i64 1, !{{[0-9]+}}, !DIExpression(), !{{[0-9]+}}) +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.PrintString"(%"{{.*}}/runtime/internal/runtime.String" { ptr @{{[0-9]+}}, i64 2 }) +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.PrintByte"(i8 32) +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.PrintInt"(i64 %0) +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.PrintByte"(i8 32) +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.PrintString"(%"{{.*}}/runtime/internal/runtime.String" { ptr @{{[0-9]+}}, i64 2 }) +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.PrintByte"(i8 32) +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.PrintInt"(i64 0) +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.PrintByte"(i8 32) +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.PrintString"(%"{{.*}}/runtime/internal/runtime.String" { ptr @{{[0-9]+}}, i64 2 }) +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.PrintByte"(i8 32) +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.PrintInt"(i64 1) +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.PrintByte"(i8 10) +// CHECK-NEXT: br label %_llgo_1 +// CHECK-EMPTY: +// CHECK-NEXT: _llgo_3: ; preds = %_llgo_4 +// CHECK-NEXT: #dbg_value(i64 2, !{{[0-9]+}}, !DIExpression(), !{{[0-9]+}}) +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.PrintString"(%"{{.*}}/runtime/internal/runtime.String" { ptr @{{[0-9]+}}, i64 6 }) +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.PrintByte"(i8 10) +// CHECK-NEXT: #dbg_value(i64 %0, !{{[0-9]+}}, !DIExpression(), !{{[0-9]+}}) +// CHECK-NEXT: #dbg_value(i64 0, !{{[0-9]+}}, !DIExpression(), !{{[0-9]+}}) +// CHECK-NEXT: #dbg_value(i64 2, !{{[0-9]+}}, !DIExpression(), !{{[0-9]+}}) +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.PrintString"(%"{{.*}}/runtime/internal/runtime.String" { ptr @{{[0-9]+}}, i64 2 }) +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.PrintByte"(i8 32) +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.PrintInt"(i64 %0) +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.PrintByte"(i8 32) +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.PrintString"(%"{{.*}}/runtime/internal/runtime.String" { ptr @{{[0-9]+}}, i64 2 }) +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.PrintByte"(i8 32) +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.PrintInt"(i64 0) +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.PrintByte"(i8 32) +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.PrintString"(%"{{.*}}/runtime/internal/runtime.String" { ptr @{{[0-9]+}}, i64 2 }) +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.PrintByte"(i8 32) +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.PrintInt"(i64 2) +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.PrintByte"(i8 10) +// CHECK-NEXT: br label %_llgo_1 +// CHECK-EMPTY: +// CHECK-NEXT: _llgo_4: ; preds = %_llgo_0 +// CHECK-NEXT: %2 = icmp eq i64 %0, 2 +// CHECK-NEXT: br i1 %2, label %_llgo_3, label %_llgo_5 +// CHECK-EMPTY: +// CHECK-NEXT: _llgo_5: ; preds = %_llgo_4 +// CHECK-NEXT: #dbg_value(i64 3, !{{[0-9]+}}, !DIExpression(), !{{[0-9]+}}) +// CHECK-NEXT: #dbg_value(i64 %0, !{{[0-9]+}}, !DIExpression(), !{{[0-9]+}}) +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.PrintString"(%"{{.*}}/runtime/internal/runtime.String" { ptr @{{[0-9]+}}, i64 4 }) +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.PrintByte"(i8 32) +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.PrintInt"(i64 %0) +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.PrintByte"(i8 10) +// CHECK-NEXT: #dbg_value(i64 %0, !{{[0-9]+}}, !DIExpression(), !{{[0-9]+}}) +// CHECK-NEXT: #dbg_value(i64 0, !{{[0-9]+}}, !DIExpression(), !{{[0-9]+}}) +// CHECK-NEXT: #dbg_value(i64 3, !{{[0-9]+}}, !DIExpression(), !{{[0-9]+}}) +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.PrintString"(%"{{.*}}/runtime/internal/runtime.String" { ptr @{{[0-9]+}}, i64 2 }) +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.PrintByte"(i8 32) +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.PrintInt"(i64 %0) +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.PrintByte"(i8 32) +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.PrintString"(%"{{.*}}/runtime/internal/runtime.String" { ptr @{{[0-9]+}}, i64 2 }) +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.PrintByte"(i8 32) +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.PrintInt"(i64 0) +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.PrintByte"(i8 32) +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.PrintString"(%"{{.*}}/runtime/internal/runtime.String" { ptr @{{[0-9]+}}, i64 2 }) +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.PrintByte"(i8 32) +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.PrintInt"(i64 3) +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.PrintByte"(i8 10) +// CHECK-NEXT: br label %_llgo_1 +// CHECK-NEXT: } + +// CHECK-LABEL: define i64 @"main.(*Struct).Foo"(ptr %0, %"{{.*}}/runtime/internal/runtime.Slice" %1, %"{{.*}}/runtime/internal/runtime.String" %2){{.*}} { +// CHECK-NEXT: _llgo_0: +// CHECK-NEXT: #dbg_value(ptr %0, !{{[0-9]+}}, !DIExpression(), !{{[0-9]+}}) +// CHECK-NEXT: %3 = alloca { ptr, i64, i64 }, align 8 +// CHECK-NEXT: store %"{{.*}}/runtime/internal/runtime.Slice" %1, ptr %3, align 8 +// CHECK-NEXT: %4 = load %"{{.*}}/runtime/internal/runtime.Slice", ptr %3, align 8 +// CHECK-NEXT: #dbg_value(ptr %3, !{{[0-9]+}}, !DIExpression(DW_OP_deref), !{{[0-9]+}}) +// CHECK-NEXT: %5 = alloca %"{{.*}}/runtime/internal/runtime.String", align 8 +// CHECK-NEXT: store %"{{.*}}/runtime/internal/runtime.String" %2, ptr %5, align 8 +// CHECK-NEXT: %6 = load %"{{.*}}/runtime/internal/runtime.String", ptr %5, align 8 +// CHECK-NEXT: #dbg_value(ptr %5, !{{[0-9]+}}, !DIExpression(DW_OP_deref), !{{[0-9]+}}) +// CHECK-NEXT: ret i64 1 +// CHECK-NEXT: } + +// CHECK-LABEL: define void @main.init(){{.*}} { +// CHECK-NEXT: _llgo_0: +// CHECK-NEXT: %0 = load i1, ptr @"main.init$guard", align 1 +// CHECK-NEXT: br i1 %0, label %_llgo_2, label %_llgo_1 +// CHECK-EMPTY: +// CHECK-NEXT: _llgo_1: ; preds = %_llgo_0 +// CHECK-NEXT: store i1 true, ptr @"main.init$guard", align 1 +// CHECK-NEXT: call void @errors.init() +// CHECK-NEXT: br label %_llgo_2 +// CHECK-EMPTY: +// CHECK-NEXT: _llgo_2: ; preds = %_llgo_1, %_llgo_0 +// CHECK-NEXT: ret void +// CHECK-NEXT: } + +// CHECK-LABEL: define void @main.main(){{.*}} { +// CHECK-NEXT: _llgo_0: +// CHECK-NEXT: %0 = alloca %main.TinyStruct, align 8 +// CHECK-NEXT: call void @llvm.memset.p0.i64(ptr %0, i8 0, i64 8, i1 false) +// CHECK-NEXT: %1 = getelementptr inbounds %main.TinyStruct, ptr %0, i32 0, i32 0 +// CHECK-NEXT: store i64 1, ptr %1, align 8 +// CHECK-NEXT: %2 = load %main.TinyStruct, ptr %0, align 8 +// CHECK-NEXT: %3 = alloca %main.SmallStruct, align 8 +// CHECK-NEXT: call void @llvm.memset.p0.i64(ptr %3, i8 0, i64 16, i1 false) +// CHECK-NEXT: %4 = getelementptr inbounds %main.SmallStruct, ptr %3, i32 0, i32 0 +// CHECK-NEXT: %5 = getelementptr inbounds %main.SmallStruct, ptr %3, i32 0, i32 1 +// CHECK-NEXT: store i64 2, ptr %4, align 8 +// CHECK-NEXT: store i64 3, ptr %5, align 8 +// CHECK-NEXT: %6 = load %main.SmallStruct, ptr %3, align 8 +// CHECK-NEXT: %7 = alloca %main.MidStruct, align 8 +// CHECK-NEXT: call void @llvm.memset.p0.i64(ptr %7, i8 0, i64 24, i1 false) +// CHECK-NEXT: %8 = getelementptr inbounds %main.MidStruct, ptr %7, i32 0, i32 0 +// CHECK-NEXT: %9 = getelementptr inbounds %main.MidStruct, ptr %7, i32 0, i32 1 +// CHECK-NEXT: %10 = getelementptr inbounds %main.MidStruct, ptr %7, i32 0, i32 2 +// CHECK-NEXT: store i64 4, ptr %8, align 8 +// CHECK-NEXT: store i64 5, ptr %9, align 8 +// CHECK-NEXT: store i64 6, ptr %10, align 8 +// CHECK-NEXT: %11 = load %main.MidStruct, ptr %7, align 8 +// CHECK-NEXT: %12 = alloca %main.BigStruct, align 8 +// CHECK-NEXT: call void @llvm.memset.p0.i64(ptr %12, i8 0, i64 80, i1 false) +// CHECK-NEXT: %13 = getelementptr inbounds %main.BigStruct, ptr %12, i32 0, i32 0 +// CHECK-NEXT: %14 = getelementptr inbounds %main.BigStruct, ptr %12, i32 0, i32 1 +// CHECK-NEXT: %15 = getelementptr inbounds %main.BigStruct, ptr %12, i32 0, i32 2 +// CHECK-NEXT: %16 = getelementptr inbounds %main.BigStruct, ptr %12, i32 0, i32 3 +// CHECK-NEXT: %17 = getelementptr inbounds %main.BigStruct, ptr %12, i32 0, i32 4 +// CHECK-NEXT: %18 = getelementptr inbounds %main.BigStruct, ptr %12, i32 0, i32 5 +// CHECK-NEXT: %19 = getelementptr inbounds %main.BigStruct, ptr %12, i32 0, i32 6 +// CHECK-NEXT: %20 = getelementptr inbounds %main.BigStruct, ptr %12, i32 0, i32 7 +// CHECK-NEXT: %21 = getelementptr inbounds %main.BigStruct, ptr %12, i32 0, i32 8 +// CHECK-NEXT: %22 = getelementptr inbounds %main.BigStruct, ptr %12, i32 0, i32 9 +// CHECK-NEXT: store i64 7, ptr %13, align 8 +// CHECK-NEXT: store i64 8, ptr %14, align 8 +// CHECK-NEXT: store i64 9, ptr %15, align 8 +// CHECK-NEXT: store i64 10, ptr %16, align 8 +// CHECK-NEXT: store i64 11, ptr %17, align 8 +// CHECK-NEXT: store i64 12, ptr %18, align 8 +// CHECK-NEXT: store i64 13, ptr %19, align 8 +// CHECK-NEXT: store i64 14, ptr %20, align 8 +// CHECK-NEXT: store i64 15, ptr %21, align 8 +// CHECK-NEXT: store i64 16, ptr %22, align 8 +// CHECK-NEXT: %23 = load %main.BigStruct, ptr %12, align 8 +// CHECK-NEXT: call void @main.FuncStructParams(%main.TinyStruct %2, %main.SmallStruct %6, %main.MidStruct %11, %main.BigStruct %23) +// CHECK-NEXT: %24 = call ptr @"{{.*}}/runtime/internal/runtime.AllocZ"(i64 8) +// CHECK-NEXT: %25 = getelementptr inbounds %main.TinyStruct, ptr %24, i32 0, i32 0 +// CHECK-NEXT: store i64 1, ptr %25, align 8 +// CHECK-NEXT: %26 = call ptr @"{{.*}}/runtime/internal/runtime.AllocZ"(i64 16) +// CHECK-NEXT: %27 = getelementptr inbounds %main.SmallStruct, ptr %26, i32 0, i32 0 +// CHECK-NEXT: %28 = getelementptr inbounds %main.SmallStruct, ptr %26, i32 0, i32 1 +// CHECK-NEXT: store i64 2, ptr %27, align 8 +// CHECK-NEXT: store i64 3, ptr %28, align 8 +// CHECK-NEXT: %29 = call ptr @"{{.*}}/runtime/internal/runtime.AllocZ"(i64 24) +// CHECK-NEXT: %30 = getelementptr inbounds %main.MidStruct, ptr %29, i32 0, i32 0 +// CHECK-NEXT: %31 = getelementptr inbounds %main.MidStruct, ptr %29, i32 0, i32 1 +// CHECK-NEXT: %32 = getelementptr inbounds %main.MidStruct, ptr %29, i32 0, i32 2 +// CHECK-NEXT: store i64 4, ptr %30, align 8 +// CHECK-NEXT: store i64 5, ptr %31, align 8 +// CHECK-NEXT: store i64 6, ptr %32, align 8 +// CHECK-NEXT: %33 = call ptr @"{{.*}}/runtime/internal/runtime.AllocZ"(i64 80) +// CHECK-NEXT: %34 = getelementptr inbounds %main.BigStruct, ptr %33, i32 0, i32 0 +// CHECK-NEXT: %35 = getelementptr inbounds %main.BigStruct, ptr %33, i32 0, i32 1 +// CHECK-NEXT: %36 = getelementptr inbounds %main.BigStruct, ptr %33, i32 0, i32 2 +// CHECK-NEXT: %37 = getelementptr inbounds %main.BigStruct, ptr %33, i32 0, i32 3 +// CHECK-NEXT: %38 = getelementptr inbounds %main.BigStruct, ptr %33, i32 0, i32 4 +// CHECK-NEXT: %39 = getelementptr inbounds %main.BigStruct, ptr %33, i32 0, i32 5 +// CHECK-NEXT: %40 = getelementptr inbounds %main.BigStruct, ptr %33, i32 0, i32 6 +// CHECK-NEXT: %41 = getelementptr inbounds %main.BigStruct, ptr %33, i32 0, i32 7 +// CHECK-NEXT: %42 = getelementptr inbounds %main.BigStruct, ptr %33, i32 0, i32 8 +// CHECK-NEXT: %43 = getelementptr inbounds %main.BigStruct, ptr %33, i32 0, i32 9 +// CHECK-NEXT: store i64 7, ptr %34, align 8 +// CHECK-NEXT: store i64 8, ptr %35, align 8 +// CHECK-NEXT: store i64 9, ptr %36, align 8 +// CHECK-NEXT: store i64 10, ptr %37, align 8 +// CHECK-NEXT: store i64 11, ptr %38, align 8 +// CHECK-NEXT: store i64 12, ptr %39, align 8 +// CHECK-NEXT: store i64 13, ptr %40, align 8 +// CHECK-NEXT: store i64 14, ptr %41, align 8 +// CHECK-NEXT: store i64 15, ptr %42, align 8 +// CHECK-NEXT: store i64 16, ptr %43, align 8 +// CHECK-NEXT: call void @main.FuncStructPtrParams(ptr %24, ptr %26, ptr %29, ptr %33) +// CHECK-NEXT: %44 = call ptr @"{{.*}}/runtime/internal/runtime.AllocZ"(i64 8) +// CHECK-NEXT: #dbg_declare(ptr %44, !{{[0-9]+}}, !DIExpression(), !{{[0-9]+}}) +// CHECK-NEXT: store i64 100, ptr %44, align 8 +// CHECK-NEXT: #dbg_value(i64 100, !{{[0-9]+}}, !DIExpression(), !{{[0-9]+}}) +// CHECK-NEXT: %45 = call ptr @"{{.*}}/runtime/internal/runtime.AllocZ"(i64 288) +// CHECK-NEXT: #dbg_declare(ptr %45, !{{[0-9]+}}, !DIExpression(), !{{[0-9]+}}) +// CHECK-NEXT: #dbg_declare(ptr %45, !{{[0-9]+}}, !DIExpression(), !{{[0-9]+}}) +// CHECK-NEXT: %46 = getelementptr inbounds %main.StructWithAllTypeFields, ptr %45, i32 0, i32 0 +// CHECK-NEXT: %47 = getelementptr inbounds %main.StructWithAllTypeFields, ptr %45, i32 0, i32 1 +// CHECK-NEXT: %48 = getelementptr inbounds %main.StructWithAllTypeFields, ptr %45, i32 0, i32 2 +// CHECK-NEXT: %49 = getelementptr inbounds %main.StructWithAllTypeFields, ptr %45, i32 0, i32 3 +// CHECK-NEXT: %50 = getelementptr inbounds %main.StructWithAllTypeFields, ptr %45, i32 0, i32 4 +// CHECK-NEXT: %51 = getelementptr inbounds %main.StructWithAllTypeFields, ptr %45, i32 0, i32 5 +// CHECK-NEXT: %52 = getelementptr inbounds %main.StructWithAllTypeFields, ptr %45, i32 0, i32 6 +// CHECK-NEXT: %53 = getelementptr inbounds %main.StructWithAllTypeFields, ptr %45, i32 0, i32 7 +// CHECK-NEXT: %54 = getelementptr inbounds %main.StructWithAllTypeFields, ptr %45, i32 0, i32 8 +// CHECK-NEXT: %55 = getelementptr inbounds %main.StructWithAllTypeFields, ptr %45, i32 0, i32 9 +// CHECK-NEXT: %56 = getelementptr inbounds %main.StructWithAllTypeFields, ptr %45, i32 0, i32 10 +// CHECK-NEXT: %57 = getelementptr inbounds %main.StructWithAllTypeFields, ptr %45, i32 0, i32 11 +// CHECK-NEXT: %58 = getelementptr inbounds %main.StructWithAllTypeFields, ptr %45, i32 0, i32 12 +// CHECK-NEXT: %59 = getelementptr inbounds %main.StructWithAllTypeFields, ptr %45, i32 0, i32 13 +// CHECK-NEXT: %60 = getelementptr inbounds %main.StructWithAllTypeFields, ptr %45, i32 0, i32 14 +// CHECK-NEXT: %61 = getelementptr inbounds %main.StructWithAllTypeFields, ptr %45, i32 0, i32 15 +// CHECK-NEXT: %62 = call ptr @"{{.*}}/runtime/internal/runtime.AllocZ"(i64 24) +// CHECK-NEXT: %63 = getelementptr inbounds i64, ptr %62, i64 0 +// CHECK-NEXT: store i64 21, ptr %63, align 8 +// CHECK-NEXT: %64 = getelementptr inbounds i64, ptr %62, i64 1 +// CHECK-NEXT: store i64 22, ptr %64, align 8 +// CHECK-NEXT: %65 = getelementptr inbounds i64, ptr %62, i64 2 +// CHECK-NEXT: store i64 23, ptr %65, align 8 +// CHECK-NEXT: %66 = insertvalue %"{{.*}}/runtime/internal/runtime.Slice" undef, ptr %62, 0 +// CHECK-NEXT: %67 = insertvalue %"{{.*}}/runtime/internal/runtime.Slice" %66, i64 3, 1 +// CHECK-NEXT: %68 = insertvalue %"{{.*}}/runtime/internal/runtime.Slice" %67, i64 3, 2 +// CHECK-NEXT: %69 = getelementptr inbounds %main.StructWithAllTypeFields, ptr %45, i32 0, i32 16 +// CHECK-NEXT: %70 = icmp eq ptr %69, null +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.AssertNilDeref"(i1 %70) +// CHECK-NEXT: %71 = getelementptr inbounds i64, ptr %69, i64 0 +// CHECK-NEXT: %72 = icmp eq ptr %69, null +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.AssertNilDeref"(i1 %72) +// CHECK-NEXT: %73 = getelementptr inbounds i64, ptr %69, i64 1 +// CHECK-NEXT: %74 = icmp eq ptr %69, null +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.AssertNilDeref"(i1 %74) +// CHECK-NEXT: %75 = getelementptr inbounds i64, ptr %69, i64 2 +// CHECK-NEXT: %76 = getelementptr inbounds %main.StructWithAllTypeFields, ptr %45, i32 0, i32 17 +// CHECK-NEXT: %77 = icmp eq ptr %76, null +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.AssertNilDeref"(i1 %77) +// CHECK-NEXT: %78 = getelementptr inbounds %main.E, ptr %76, i64 0 +// CHECK-NEXT: %79 = getelementptr inbounds %main.E, ptr %78, i32 0, i32 0 +// CHECK-NEXT: %80 = icmp eq ptr %76, null +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.AssertNilDeref"(i1 %80) +// CHECK-NEXT: %81 = getelementptr inbounds %main.E, ptr %76, i64 1 +// CHECK-NEXT: %82 = getelementptr inbounds %main.E, ptr %81, i32 0, i32 0 +// CHECK-NEXT: %83 = icmp eq ptr %76, null +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.AssertNilDeref"(i1 %83) +// CHECK-NEXT: %84 = getelementptr inbounds %main.E, ptr %76, i64 2 +// CHECK-NEXT: %85 = getelementptr inbounds %main.E, ptr %84, i32 0, i32 0 +// CHECK-NEXT: %86 = getelementptr inbounds %main.StructWithAllTypeFields, ptr %45, i32 0, i32 18 +// CHECK-NEXT: %87 = getelementptr inbounds %main.StructWithAllTypeFields, ptr %45, i32 0, i32 19 +// CHECK-NEXT: %88 = getelementptr inbounds %main.E, ptr %87, i32 0, i32 0 +// CHECK-NEXT: %89 = getelementptr inbounds %main.StructWithAllTypeFields, ptr %45, i32 0, i32 20 +// CHECK-NEXT: %90 = call ptr @"{{.*}}/runtime/internal/runtime.AllocZ"(i64 288) +// CHECK-NEXT: %91 = getelementptr inbounds %main.StructWithAllTypeFields, ptr %90, i32 0, i32 1 +// CHECK-NEXT: store i16 100, ptr %91, align 2 +// CHECK-NEXT: %92 = getelementptr inbounds %main.StructWithAllTypeFields, ptr %45, i32 0, i32 21 +// CHECK-NEXT: #dbg_declare(ptr %44, !{{[0-9]+}}, !DIExpression(), !{{[0-9]+}}) +// CHECK-NEXT: %93 = getelementptr inbounds %main.StructWithAllTypeFields, ptr %45, i32 0, i32 22 +// CHECK-NEXT: %94 = getelementptr inbounds %main.StructWithAllTypeFields, ptr %45, i32 0, i32 23 +// CHECK-NEXT: %95 = call ptr @"{{.*}}/runtime/internal/runtime.MakeMap"(ptr @"map[_llgo_string]_llgo_uint64", i64 2) +// CHECK-NEXT: %96 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 16) +// CHECK-NEXT: store %"{{.*}}/runtime/internal/runtime.String" { ptr @{{[0-9]+}}, i64 1 }, ptr %96, align 8 +// CHECK-NEXT: %97 = call ptr @"{{.*}}/runtime/internal/runtime.MapAssign"(ptr @"map[_llgo_string]_llgo_uint64", ptr %95, ptr %96) +// CHECK-NEXT: store i64 31, ptr %97, align 8 +// CHECK-NEXT: %98 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 16) +// CHECK-NEXT: store %"{{.*}}/runtime/internal/runtime.String" { ptr @{{[0-9]+}}, i64 1 }, ptr %98, align 8 +// CHECK-NEXT: %99 = call ptr @"{{.*}}/runtime/internal/runtime.MapAssign"(ptr @"map[_llgo_string]_llgo_uint64", ptr %95, ptr %98) +// CHECK-NEXT: store i64 32, ptr %99, align 8 +// CHECK-NEXT: %100 = getelementptr inbounds %main.StructWithAllTypeFields, ptr %45, i32 0, i32 24 +// CHECK-NEXT: %101 = call ptr @"{{.*}}/runtime/internal/runtime.NewChan"(i64 8, i64 0) +// CHECK-NEXT: %102 = getelementptr inbounds %main.StructWithAllTypeFields, ptr %45, i32 0, i32 25 +// CHECK-NEXT: %103 = call %"{{.*}}/runtime/internal/runtime.iface" @errors.New(%"{{.*}}/runtime/internal/runtime.String" { ptr @{{[0-9]+}}, i64 10 }) +// CHECK-NEXT: %104 = getelementptr inbounds %main.StructWithAllTypeFields, ptr %45, i32 0, i32 26 +// CHECK-NEXT: %105 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 8) +// CHECK-NEXT: %106 = getelementptr inbounds { ptr }, ptr %105, i32 0, i32 0 +// CHECK-NEXT: store ptr %44, ptr %106, align 8 +// CHECK-NEXT: %107 = insertvalue { ptr, ptr } { ptr @"main.main$1", ptr undef }, ptr %105, 1 +// CHECK-NEXT: %108 = getelementptr inbounds %main.StructWithAllTypeFields, ptr %45, i32 0, i32 27 +// CHECK-NEXT: %109 = getelementptr inbounds %main.StructWithAllTypeFields, ptr %45, i32 0, i32 28 +// CHECK-NEXT: store i8 1, ptr %46, align 1 +// CHECK-NEXT: store i16 2, ptr %47, align 2 +// CHECK-NEXT: store i32 3, ptr %48, align 4 +// CHECK-NEXT: store i64 4, ptr %49, align 8 +// CHECK-NEXT: store i64 5, ptr %50, align 8 +// CHECK-NEXT: store i8 6, ptr %51, align 1 +// CHECK-NEXT: store i16 7, ptr %52, align 2 +// CHECK-NEXT: store i32 8, ptr %53, align 4 +// CHECK-NEXT: store i64 9, ptr %54, align 8 +// CHECK-NEXT: store i64 10, ptr %55, align 8 +// CHECK-NEXT: store float 1.100000e+01, ptr %56, align 4 +// CHECK-NEXT: store double 1.200000e+01, ptr %57, align 8 +// CHECK-NEXT: store i1 true, ptr %58, align 1 +// CHECK-NEXT: store { float, float } { float 1.300000e+01, float 1.400000e+01 }, ptr %59, align 4 +// CHECK-NEXT: store { double, double } { double 1.500000e+01, double 1.600000e+01 }, ptr %60, align 8 +// CHECK-NEXT: store %"{{.*}}/runtime/internal/runtime.Slice" %68, ptr %61, align 8 +// CHECK-NEXT: store i64 24, ptr %71, align 8 +// CHECK-NEXT: store i64 25, ptr %73, align 8 +// CHECK-NEXT: store i64 26, ptr %75, align 8 +// CHECK-NEXT: store i64 27, ptr %79, align 8 +// CHECK-NEXT: store i64 28, ptr %82, align 8 +// CHECK-NEXT: store i64 29, ptr %85, align 8 +// CHECK-NEXT: store %"{{.*}}/runtime/internal/runtime.String" { ptr @{{[0-9]+}}, i64 5 }, ptr %86, align 8 +// CHECK-NEXT: store i64 30, ptr %88, align 8 +// CHECK-NEXT: store ptr %90, ptr %89, align 8 +// CHECK-NEXT: store ptr %44, ptr %92, align 8 +// CHECK-NEXT: %110 = call ptr @"{{.*}}/runtime/internal/runtime.NewItab"(ptr @"_llgo_iface$opv3stH14p-JT6UN0WEYD-Tr6bHK3MHpC4KSk10pjNU", ptr @"*_llgo_main.Struct") +// CHECK-NEXT: %111 = insertvalue %"{{.*}}/runtime/internal/runtime.iface" undef, ptr %110, 0 +// CHECK-NEXT: %112 = insertvalue %"{{.*}}/runtime/internal/runtime.iface" %111, ptr @"__llgo.moduleZeroSizedAlloc$", 1 +// CHECK-NEXT: store %"{{.*}}/runtime/internal/runtime.iface" %112, ptr %93, align 8 +// CHECK-NEXT: store ptr %95, ptr %94, align 8 +// CHECK-NEXT: store ptr %101, ptr %100, align 8 +// CHECK-NEXT: store %"{{.*}}/runtime/internal/runtime.iface" %103, ptr %102, align 8 +// CHECK-NEXT: store { ptr, ptr } %107, ptr %104, align 8 +// CHECK-NEXT: store i64 100, ptr %108, align 8 +// CHECK-NEXT: store i64 200, ptr %109, align 8 +// CHECK-NEXT: #dbg_declare(ptr %45, !{{[0-9]+}}, !DIExpression(), !{{[0-9]+}}) +// CHECK-NEXT: store ptr %45, ptr @main.globalStructPtr, align 8 +// CHECK-NEXT: %113 = load %main.StructWithAllTypeFields, ptr %45, align 8 +// CHECK-NEXT: %114 = alloca %main.StructWithAllTypeFields, align 8 +// CHECK-NEXT: store %main.StructWithAllTypeFields %113, ptr %114, align 8 +// CHECK-NEXT: %115 = load %main.StructWithAllTypeFields, ptr %114, align 8 +// CHECK-NEXT: #dbg_value(ptr %114, !{{[0-9]+}}, !DIExpression(DW_OP_deref), !{{[0-9]+}}) +// CHECK-NEXT: store %main.StructWithAllTypeFields %113, ptr @main.globalStruct, align 8 +// CHECK-NEXT: %116 = load i64, ptr @main.globalInt, align 8 +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.PrintString"(%"{{.*}}/runtime/internal/runtime.String" { ptr @{{[0-9]+}}, i64 10 }) +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.PrintByte"(i8 32) +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.PrintInt"(i64 %116) +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.PrintByte"(i8 10) +// CHECK-NEXT: #dbg_declare(ptr %45, !{{[0-9]+}}, !DIExpression(), !{{[0-9]+}}) +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.PrintString"(%"{{.*}}/runtime/internal/runtime.String" { ptr @{{[0-9]+}}, i64 2 }) +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.PrintByte"(i8 32) +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.PrintPointer"(ptr %45) +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.PrintByte"(i8 10) +// CHECK-NEXT: %117 = load %main.StructWithAllTypeFields, ptr %45, align 8 +// CHECK-NEXT: %118 = alloca %main.StructWithAllTypeFields, align 8 +// CHECK-NEXT: store %main.StructWithAllTypeFields %117, ptr %118, align 8 +// CHECK-NEXT: %119 = load %main.StructWithAllTypeFields, ptr %118, align 8 +// CHECK-NEXT: #dbg_value(ptr %118, !{{[0-9]+}}, !DIExpression(DW_OP_deref), !{{[0-9]+}}) +// CHECK-NEXT: call void @main.FuncWithAllTypeStructParam(%main.StructWithAllTypeFields %117) +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.PrintString"(%"{{.*}}/runtime/internal/runtime.String" { ptr @{{[0-9]+}}, i64 27 }) +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.PrintByte"(i8 10) +// CHECK-NEXT: #dbg_declare(ptr %45, !{{[0-9]+}}, !DIExpression(), !{{[0-9]+}}) +// CHECK-NEXT: %120 = getelementptr inbounds %main.StructWithAllTypeFields, ptr %45, i32 0, i32 0 +// CHECK-NEXT: %121 = load i8, ptr %120, align 1 +// CHECK-NEXT: #dbg_declare(ptr %45, !{{[0-9]+}}, !DIExpression(), !{{[0-9]+}}) +// CHECK-NEXT: %122 = getelementptr inbounds %main.StructWithAllTypeFields, ptr %45, i32 0, i32 1 +// CHECK-NEXT: %123 = load i16, ptr %122, align 2 +// CHECK-NEXT: #dbg_declare(ptr %45, !{{[0-9]+}}, !DIExpression(), !{{[0-9]+}}) +// CHECK-NEXT: %124 = getelementptr inbounds %main.StructWithAllTypeFields, ptr %45, i32 0, i32 2 +// CHECK-NEXT: %125 = load i32, ptr %124, align 4 +// CHECK-NEXT: #dbg_declare(ptr %45, !{{[0-9]+}}, !DIExpression(), !{{[0-9]+}}) +// CHECK-NEXT: %126 = getelementptr inbounds %main.StructWithAllTypeFields, ptr %45, i32 0, i32 3 +// CHECK-NEXT: %127 = load i64, ptr %126, align 8 +// CHECK-NEXT: #dbg_declare(ptr %45, !{{[0-9]+}}, !DIExpression(), !{{[0-9]+}}) +// CHECK-NEXT: %128 = getelementptr inbounds %main.StructWithAllTypeFields, ptr %45, i32 0, i32 4 +// CHECK-NEXT: %129 = load i64, ptr %128, align 8 +// CHECK-NEXT: #dbg_declare(ptr %45, !{{[0-9]+}}, !DIExpression(), !{{[0-9]+}}) +// CHECK-NEXT: %130 = getelementptr inbounds %main.StructWithAllTypeFields, ptr %45, i32 0, i32 5 +// CHECK-NEXT: %131 = load i8, ptr %130, align 1 +// CHECK-NEXT: #dbg_declare(ptr %45, !{{[0-9]+}}, !DIExpression(), !{{[0-9]+}}) +// CHECK-NEXT: %132 = getelementptr inbounds %main.StructWithAllTypeFields, ptr %45, i32 0, i32 6 +// CHECK-NEXT: %133 = load i16, ptr %132, align 2 +// CHECK-NEXT: #dbg_declare(ptr %45, !{{[0-9]+}}, !DIExpression(), !{{[0-9]+}}) +// CHECK-NEXT: %134 = getelementptr inbounds %main.StructWithAllTypeFields, ptr %45, i32 0, i32 7 +// CHECK-NEXT: %135 = load i32, ptr %134, align 4 +// CHECK-NEXT: #dbg_declare(ptr %45, !{{[0-9]+}}, !DIExpression(), !{{[0-9]+}}) +// CHECK-NEXT: %136 = getelementptr inbounds %main.StructWithAllTypeFields, ptr %45, i32 0, i32 8 +// CHECK-NEXT: %137 = load i64, ptr %136, align 8 +// CHECK-NEXT: #dbg_declare(ptr %45, !{{[0-9]+}}, !DIExpression(), !{{[0-9]+}}) +// CHECK-NEXT: %138 = getelementptr inbounds %main.StructWithAllTypeFields, ptr %45, i32 0, i32 9 +// CHECK-NEXT: %139 = load i64, ptr %138, align 8 +// CHECK-NEXT: #dbg_declare(ptr %45, !{{[0-9]+}}, !DIExpression(), !{{[0-9]+}}) +// CHECK-NEXT: %140 = getelementptr inbounds %main.StructWithAllTypeFields, ptr %45, i32 0, i32 10 +// CHECK-NEXT: %141 = load float, ptr %140, align 4 +// CHECK-NEXT: #dbg_declare(ptr %45, !{{[0-9]+}}, !DIExpression(), !{{[0-9]+}}) +// CHECK-NEXT: %142 = getelementptr inbounds %main.StructWithAllTypeFields, ptr %45, i32 0, i32 11 +// CHECK-NEXT: %143 = load double, ptr %142, align 8 +// CHECK-NEXT: #dbg_declare(ptr %45, !{{[0-9]+}}, !DIExpression(), !{{[0-9]+}}) +// CHECK-NEXT: %144 = getelementptr inbounds %main.StructWithAllTypeFields, ptr %45, i32 0, i32 12 +// CHECK-NEXT: %145 = load i1, ptr %144, align 1 +// CHECK-NEXT: #dbg_declare(ptr %45, !{{[0-9]+}}, !DIExpression(), !{{[0-9]+}}) +// CHECK-NEXT: %146 = getelementptr inbounds %main.StructWithAllTypeFields, ptr %45, i32 0, i32 13 +// CHECK-NEXT: %147 = load { float, float }, ptr %146, align 4 +// CHECK-NEXT: #dbg_declare(ptr %45, !{{[0-9]+}}, !DIExpression(), !{{[0-9]+}}) +// CHECK-NEXT: %148 = getelementptr inbounds %main.StructWithAllTypeFields, ptr %45, i32 0, i32 14 +// CHECK-NEXT: %149 = load { double, double }, ptr %148, align 8 +// CHECK-NEXT: #dbg_declare(ptr %45, !{{[0-9]+}}, !DIExpression(), !{{[0-9]+}}) +// CHECK-NEXT: %150 = getelementptr inbounds %main.StructWithAllTypeFields, ptr %45, i32 0, i32 15 +// CHECK-NEXT: %151 = load %"{{.*}}/runtime/internal/runtime.Slice", ptr %150, align 8 +// CHECK-NEXT: #dbg_declare(ptr %45, !{{[0-9]+}}, !DIExpression(), !{{[0-9]+}}) +// CHECK-NEXT: %152 = getelementptr inbounds %main.StructWithAllTypeFields, ptr %45, i32 0, i32 16 +// CHECK-NEXT: %153 = load [3 x i64], ptr %152, align 8 +// CHECK-NEXT: #dbg_declare(ptr %45, !{{[0-9]+}}, !DIExpression(), !{{[0-9]+}}) +// CHECK-NEXT: %154 = getelementptr inbounds %main.StructWithAllTypeFields, ptr %45, i32 0, i32 17 +// CHECK-NEXT: %155 = load [3 x %main.E], ptr %154, align 8 +// CHECK-NEXT: #dbg_declare(ptr %45, !{{[0-9]+}}, !DIExpression(), !{{[0-9]+}}) +// CHECK-NEXT: %156 = getelementptr inbounds %main.StructWithAllTypeFields, ptr %45, i32 0, i32 18 +// CHECK-NEXT: %157 = load %"{{.*}}/runtime/internal/runtime.String", ptr %156, align 8 +// CHECK-NEXT: #dbg_declare(ptr %45, !{{[0-9]+}}, !DIExpression(), !{{[0-9]+}}) +// CHECK-NEXT: %158 = getelementptr inbounds %main.StructWithAllTypeFields, ptr %45, i32 0, i32 19 +// CHECK-NEXT: %159 = load %main.E, ptr %158, align 8 +// CHECK-NEXT: %160 = load %main.StructWithAllTypeFields, ptr %45, align 8 +// CHECK-NEXT: %161 = alloca %main.StructWithAllTypeFields, align 8 +// CHECK-NEXT: store %main.StructWithAllTypeFields %160, ptr %161, align 8 +// CHECK-NEXT: %162 = load %main.StructWithAllTypeFields, ptr %161, align 8 +// CHECK-NEXT: #dbg_value(ptr %161, !{{[0-9]+}}, !DIExpression(DW_OP_deref), !{{[0-9]+}}) +// CHECK-NEXT: #dbg_declare(ptr %45, !{{[0-9]+}}, !DIExpression(), !{{[0-9]+}}) +// CHECK-NEXT: %163 = getelementptr inbounds %main.StructWithAllTypeFields, ptr %45, i32 0, i32 20 +// CHECK-NEXT: %164 = load ptr, ptr %163, align 8 +// CHECK-NEXT: #dbg_declare(ptr %45, !{{[0-9]+}}, !DIExpression(), !{{[0-9]+}}) +// CHECK-NEXT: %165 = getelementptr inbounds %main.StructWithAllTypeFields, ptr %45, i32 0, i32 21 +// CHECK-NEXT: %166 = load ptr, ptr %165, align 8 +// CHECK-NEXT: #dbg_declare(ptr %45, !{{[0-9]+}}, !DIExpression(), !{{[0-9]+}}) +// CHECK-NEXT: %167 = getelementptr inbounds %main.StructWithAllTypeFields, ptr %45, i32 0, i32 22 +// CHECK-NEXT: %168 = load %"{{.*}}/runtime/internal/runtime.iface", ptr %167, align 8 +// CHECK-NEXT: #dbg_declare(ptr %45, !{{[0-9]+}}, !DIExpression(), !{{[0-9]+}}) +// CHECK-NEXT: %169 = getelementptr inbounds %main.StructWithAllTypeFields, ptr %45, i32 0, i32 23 +// CHECK-NEXT: %170 = load ptr, ptr %169, align 8 +// CHECK-NEXT: #dbg_declare(ptr %45, !{{[0-9]+}}, !DIExpression(), !{{[0-9]+}}) +// CHECK-NEXT: %171 = getelementptr inbounds %main.StructWithAllTypeFields, ptr %45, i32 0, i32 24 +// CHECK-NEXT: %172 = load ptr, ptr %171, align 8 +// CHECK-NEXT: #dbg_declare(ptr %45, !{{[0-9]+}}, !DIExpression(), !{{[0-9]+}}) +// CHECK-NEXT: %173 = getelementptr inbounds %main.StructWithAllTypeFields, ptr %45, i32 0, i32 25 +// CHECK-NEXT: %174 = load %"{{.*}}/runtime/internal/runtime.iface", ptr %173, align 8 +// CHECK-NEXT: #dbg_declare(ptr %45, !{{[0-9]+}}, !DIExpression(), !{{[0-9]+}}) +// CHECK-NEXT: %175 = getelementptr inbounds %main.StructWithAllTypeFields, ptr %45, i32 0, i32 26 +// CHECK-NEXT: %176 = load { ptr, ptr }, ptr %175, align 8 +// CHECK-NEXT: %177 = call { i64, %"{{.*}}/runtime/internal/runtime.iface" } @main.FuncWithAllTypeParams(i8 %121, i16 %123, i32 %125, i64 %127, i64 %129, i8 %131, i16 %133, i32 %135, i64 %137, i64 %139, float %141, double %143, i1 %145, { float, float } %147, { double, double } %149, %"{{.*}}/runtime/internal/runtime.Slice" %151, [3 x i64] %153, [3 x %main.E] %155, %"{{.*}}/runtime/internal/runtime.String" %157, %main.E %159, %main.StructWithAllTypeFields %160, ptr %164, ptr %166, %"{{.*}}/runtime/internal/runtime.iface" %168, ptr %170, ptr %172, %"{{.*}}/runtime/internal/runtime.iface" %174, { ptr, ptr } %176) +// CHECK-NEXT: %178 = extractvalue { i64, %"{{.*}}/runtime/internal/runtime.iface" } %177, 0 +// CHECK-NEXT: store i64 %178, ptr %44, align 8 +// CHECK-NEXT: #dbg_value(i64 %178, !{{[0-9]+}}, !DIExpression(), !{{[0-9]+}}) +// CHECK-NEXT: %179 = extractvalue { i64, %"{{.*}}/runtime/internal/runtime.iface" } %177, 1 +// CHECK-NEXT: %180 = alloca %"{{.*}}/runtime/internal/runtime.iface", align 8 +// CHECK-NEXT: store %"{{.*}}/runtime/internal/runtime.iface" %179, ptr %180, align 8 +// CHECK-NEXT: %181 = load %"{{.*}}/runtime/internal/runtime.iface", ptr %180, align 8 +// CHECK-NEXT: #dbg_value(ptr %180, !{{[0-9]+}}, !DIExpression(DW_OP_deref), !{{[0-9]+}}) +// CHECK-NEXT: %182 = load i64, ptr %44, align 8 +// CHECK-NEXT: #dbg_value(i64 %182, !{{[0-9]+}}, !DIExpression(), !{{[0-9]+}}) +// CHECK-NEXT: %183 = alloca %"{{.*}}/runtime/internal/runtime.iface", align 8 +// CHECK-NEXT: store %"{{.*}}/runtime/internal/runtime.iface" %179, ptr %183, align 8 +// CHECK-NEXT: %184 = load %"{{.*}}/runtime/internal/runtime.iface", ptr %183, align 8 +// CHECK-NEXT: #dbg_value(ptr %183, !{{[0-9]+}}, !DIExpression(DW_OP_deref), !{{[0-9]+}}) +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.PrintInt"(i64 %182) +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.PrintByte"(i8 32) +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.PrintIface"(%"{{.*}}/runtime/internal/runtime.iface" %179) +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.PrintByte"(i8 10) +// CHECK-NEXT: call void @main.ScopeIf(i64 1) +// CHECK-NEXT: call void @main.ScopeIf(i64 0) +// CHECK-NEXT: call void @main.ScopeFor() +// CHECK-NEXT: call void @main.ScopeSwitch(i64 1) +// CHECK-NEXT: call void @main.ScopeSwitch(i64 2) +// CHECK-NEXT: call void @main.ScopeSwitch(i64 3) +// CHECK-NEXT: %185 = load ptr, ptr @main.globalStructPtr, align 8 +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.PrintPointer"(ptr %185) +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.PrintByte"(i8 10) +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.PrintPointer"(ptr @main.globalStruct) +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.PrintByte"(i8 10) +// CHECK-NEXT: #dbg_declare(ptr %45, !{{[0-9]+}}, !DIExpression(), !{{[0-9]+}}) +// CHECK-NEXT: %186 = getelementptr inbounds %main.StructWithAllTypeFields, ptr %45, i32 0, i32 0 +// CHECK-NEXT: store i8 18, ptr %186, align 1 +// CHECK-NEXT: #dbg_declare(ptr %45, !{{[0-9]+}}, !DIExpression(), !{{[0-9]+}}) +// CHECK-NEXT: %187 = getelementptr inbounds %main.StructWithAllTypeFields, ptr %45, i32 0, i32 0 +// CHECK-NEXT: %188 = load i8, ptr %187, align 1 +// CHECK-NEXT: %189 = sext i8 %188 to i64 +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.PrintInt"(i64 %189) +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.PrintByte"(i8 10) +// CHECK-NEXT: %190 = load ptr, ptr @main.globalStructPtr, align 8 +// CHECK-NEXT: %191 = getelementptr inbounds %main.StructWithAllTypeFields, ptr %190, i32 0, i32 0 +// CHECK-NEXT: %192 = load i8, ptr %191, align 1 +// CHECK-NEXT: %193 = sext i8 %192 to i64 +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.PrintInt"(i64 %193) +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.PrintByte"(i8 10) +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.PrintString"(%"{{.*}}/runtime/internal/runtime.String" { ptr @{{[0-9]+}}, i64 4 }) +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.PrintByte"(i8 10) +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.PrintString"(%"{{.*}}/runtime/internal/runtime.String" zeroinitializer) +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.PrintByte"(i8 10) +// CHECK-NEXT: #dbg_declare(ptr %45, !{{[0-9]+}}, !DIExpression(), !{{[0-9]+}}) +// CHECK-NEXT: %194 = load ptr, ptr @main.globalStructPtr, align 8 +// CHECK-NEXT: %195 = getelementptr inbounds %main.StructWithAllTypeFields, ptr %194, i32 0, i32 1 +// CHECK-NEXT: %196 = load i16, ptr %195, align 2 +// CHECK-NEXT: %197 = load ptr, ptr @main.globalStructPtr, align 8 +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.PrintPointer"(ptr %45) +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.PrintByte"(i8 32) +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.PrintPointer"(ptr @main.globalStruct) +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.PrintByte"(i8 32) +// CHECK-NEXT: %198 = sext i16 %196 to i64 +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.PrintInt"(i64 %198) +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.PrintByte"(i8 32) +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.PrintPointer"(ptr %197) +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.PrintByte"(i8 10) +// CHECK-NEXT: store ptr null, ptr @main.globalStructPtr, align 8 +// CHECK-NEXT: ret void +// CHECK-NEXT: } + +// CHECK-LABEL: define { i64, %"{{.*}}/runtime/internal/runtime.iface" } @"main.main$1"(ptr {{(nest|swiftself)}} %0, %"{{.*}}/runtime/internal/runtime.String" %1){{.*}} { +// CHECK-NEXT: _llgo_0: +// CHECK-NEXT: %2 = alloca %"{{.*}}/runtime/internal/runtime.String", align 8 +// CHECK-NEXT: store %"{{.*}}/runtime/internal/runtime.String" %1, ptr %2, align 8 +// CHECK-NEXT: %3 = load %"{{.*}}/runtime/internal/runtime.String", ptr %2, align 8 +// CHECK-NEXT: #dbg_value(ptr %2, !{{[0-9]+}}, !DIExpression(DW_OP_deref), !{{[0-9]+}}) +// CHECK-NEXT: %4 = alloca %"{{.*}}/runtime/internal/runtime.String", align 8 +// CHECK-NEXT: store %"{{.*}}/runtime/internal/runtime.String" %1, ptr %4, align 8 +// CHECK-NEXT: %5 = load %"{{.*}}/runtime/internal/runtime.String", ptr %4, align 8 +// CHECK-NEXT: #dbg_value(ptr %4, !{{[0-9]+}}, !DIExpression(DW_OP_deref), !{{[0-9]+}}) +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.PrintString"(%"{{.*}}/runtime/internal/runtime.String" { ptr @{{[0-9]+}}, i64 3 }) +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.PrintByte"(i8 32) +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.PrintString"(%"{{.*}}/runtime/internal/runtime.String" %1) +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.PrintByte"(i8 10) +// CHECK-NEXT: %6 = load { ptr }, ptr %0, align 8 +// CHECK-NEXT: %7 = extractvalue { ptr } %6, 0 +// CHECK-NEXT: store i64 201, ptr %7, align 8 +// CHECK-NEXT: #dbg_value(i64 201, !{{[0-9]+}}, !DIExpression(), !{{[0-9]+}}) +// CHECK-NEXT: %8 = call %"{{.*}}/runtime/internal/runtime.iface" @errors.New(%"{{.*}}/runtime/internal/runtime.String" { ptr @{{[0-9]+}}, i64 8 }) +// CHECK-NEXT: %9 = insertvalue { i64, %"{{.*}}/runtime/internal/runtime.iface" } { i64 1, %"{{.*}}/runtime/internal/runtime.iface" undef }, %"{{.*}}/runtime/internal/runtime.iface" %8, 1 +// CHECK-NEXT: ret { i64, %"{{.*}}/runtime/internal/runtime.iface" } %9 +// CHECK-NEXT: } + +// CHECK: !llvm.dbg.cu = !{!{{[0-9]+}}} +// CHECK: !{{[0-9]+}} = distinct !DICompileUnit({{.*}}producer: "LLGo"{{.*}}emissionKind: FullDebug{{.*}}) +// CHECK: !{{[0-9]+}} = !DILocalVariable(name: "s", arg: 1, {{.*}}) diff --git a/cl/_testgo/cgofull/cgofull.go b/cl/_testgo/cgofull/cgofull.go index 0ccecc5ceb..91818705da 100644 --- a/cl/_testgo/cgofull/cgofull.go +++ b/cl/_testgo/cgofull/cgofull.go @@ -1,10 +1,6 @@ // LITTEST package main -// CHECK-DAG: call {{.*}}_C2func_test_structs{{.*}} -// CHECK-DAG: call {{.*}}cliteErrno{{.*}} -// CHECK-DAG: define i32 @go_callback(i32 %{{.*}}){{.*}} { - /* #cgo windows,!amd64 CFLAGS: -D_WIN32 #cgo !windows CFLAGS: -D_POSIX @@ -115,6 +111,16 @@ import ( "github.com/goplus/llgo/cl/_testgo/cgofull/pymod2" ) +// CHECK: {{^}}@{{[0-9]+}} = private unnamed_addr constant [18 x i8] c"failed to run code", align 1{{$}} +// CHECK: {{^}}@{{[0-9]+}} = private unnamed_addr constant [19 x i8] c"test_structs failed", align 1{{$}} +// CHECK: {{^}}@{{[0-9]+}} = private unnamed_addr constant [5 x i8] c"1.0.0", align 1{{$}} +// CHECK: {{^}}@{{[0-9]+}} = private unnamed_addr constant [17 x i8] c"call run_callback", align 1{{$}} +// CHECK: {{^}}@{{[0-9]+}} = private unnamed_addr constant [21 x i8] c"call with go_callback", align 1{{$}} +// CHECK: {{^}}@{{[0-9]+}} = private unnamed_addr constant [20 x i8] c"call with c_callback", align 1{{$}} +// CHECK: {{^}}@{{[0-9]+}} = private unnamed_addr constant [23 x i8] c"print('Hello, Python!')", align 1{{$}} +// CHECK: {{^}}@{{[0-9]+}} = private unnamed_addr constant [26 x i8] c"C2func test_structs failed", align 1{{$}} +// CHECK: {{^}}@{{[0-9]+}} = private unnamed_addr constant [9 x i8] c"c2func ok", align 1{{$}} + //export go_callback_not_use_in_go func go_callback_not_use_in_go(i C.int) C.int { return i + 1 @@ -177,3 +183,539 @@ func runPy() { // test _Cgo_use C.PyObject_Print((*C.PyObject)(unsafe.Pointer(C.PyComplex_FromDoubles(C.double(1.23), C.double(4.56)))), C.stdout, 0) } + +// CHECK-LABEL: define void @main.Bar(ptr %0){{.*}} { +// CHECK-NEXT: _llgo_0: +// CHECK-NEXT: %1 = call [0 x i8] @main._Cfunc_print_foo(ptr %0) +// CHECK-NEXT: %2 = call [0 x i8] @main._Cfunc_foo(ptr %0) +// CHECK-NEXT: ret void +// CHECK-NEXT: } + +// CHECK-LABEL: define void @main.Finalize(){{.*}} { +// CHECK-NEXT: _llgo_0: +// CHECK-NEXT: %0 = call [0 x i8] @main._Cfunc_Py_Finalize() +// CHECK-NEXT: ret void +// CHECK-NEXT: } + +// CHECK-LABEL: define void @main.Foo(ptr %0){{.*}} { +// CHECK-NEXT: _llgo_0: +// CHECK-NEXT: %1 = call [0 x i8] @main._Cfunc_print_foo(ptr %0) +// CHECK-NEXT: %2 = call [0 x i8] @main._Cfunc_foo(ptr %0) +// CHECK-NEXT: ret void +// CHECK-NEXT: } + +// CHECK-LABEL: define void @main.Initialize(){{.*}} { +// CHECK-NEXT: _llgo_0: +// CHECK-NEXT: %0 = call [0 x i8] @main._Cfunc_Py_Initialize() +// CHECK-NEXT: ret void +// CHECK-NEXT: } + +// CHECK-LABEL: define %"{{.*}}/runtime/internal/runtime.iface" @main.Run(%"{{.*}}/runtime/internal/runtime.String" %0){{.*}} { +// CHECK-NEXT: _llgo_0: +// CHECK-NEXT: %1 = call ptr @"{{.*}}/runtime/internal/runtime.CString"(%"{{.*}}/runtime/internal/runtime.String" %0) +// CHECK-NEXT: %2 = call i32 @main._Cfunc_PyRun_SimpleString(ptr %1) +// CHECK-NEXT: %3 = icmp ne i32 %2, 0 +// CHECK-NEXT: br i1 %3, label %_llgo_1, label %_llgo_2 +// CHECK-EMPTY: +// CHECK-NEXT: _llgo_1: ; preds = %_llgo_0 +// CHECK-NEXT: %4 = call [0 x i8] @main._Cfunc_PyErr_Print() +// CHECK-NEXT: %5 = call %"{{.*}}/runtime/internal/runtime.iface" @fmt.Errorf(%"{{.*}}/runtime/internal/runtime.String" { ptr @{{[0-9]+}}, i64 18 }, %"{{.*}}/runtime/internal/runtime.Slice" zeroinitializer) +// CHECK-NEXT: ret %"{{.*}}/runtime/internal/runtime.iface" %5 +// CHECK-EMPTY: +// CHECK-NEXT: _llgo_2: ; preds = %_llgo_0 +// CHECK-NEXT: ret %"{{.*}}/runtime/internal/runtime.iface" zeroinitializer +// CHECK-NEXT: } + +// CHECK-LABEL: define { i32, %"{{.*}}/runtime/internal/runtime.iface" } @main._C2func_test_structs(ptr %0, ptr %1, ptr %2, ptr %3, ptr %4){{.*}} { +// CHECK-NEXT: _llgo_0: +// CHECK-NEXT: %5 = call ptr @"{{.*}}/runtime/internal/runtime.AllocZ"(i64 8) +// CHECK-NEXT: %6 = load ptr, ptr @main._cgo_{{[0-9a-f]+}}_C2func_test_structs, align 8 +// CHECK-NEXT: %7 = load ptr, ptr %6, align 8 +// CHECK-NEXT: %8 = call i32 %7(ptr %0, ptr %1, ptr %2, ptr %3, ptr %4) +// CHECK-NEXT: %9 = call i32 @cliteErrno() +// CHECK-NEXT: %10 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 16) +// CHECK-NEXT: store %"{{.*}}/runtime/internal/runtime.iface" zeroinitializer, ptr %10, align 8 +// CHECK-NEXT: %11 = load %"{{.*}}/runtime/internal/runtime.iface", ptr %10, align 8 +// CHECK-NEXT: %12 = icmp ne i32 %9, 0 +// CHECK-NEXT: %13 = sext i32 %9 to i64 +// CHECK-NEXT: %14 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 8) +// CHECK-NEXT: store i64 %13, ptr %14, align 8 +// CHECK-NEXT: %15 = call ptr @"{{.*}}/runtime/internal/runtime.NewItab"(ptr @"_llgo_iface$Fh8eUJ-Gw4e6TYuajcFIOSCuqSPKAt5nS4ow7xeGXEU", ptr @_llgo_syscall.Errno) +// CHECK-NEXT: %16 = insertvalue %"{{.*}}/runtime/internal/runtime.iface" undef, ptr %15, 0 +// CHECK-NEXT: %17 = insertvalue %"{{.*}}/runtime/internal/runtime.iface" %16, ptr %14, 1 +// CHECK-NEXT: br i1 %12, label %_llgo_1, label %_llgo_2 +// CHECK-EMPTY: +// CHECK-NEXT: _llgo_1: ; preds = %_llgo_0 +// CHECK-NEXT: %18 = insertvalue { i32, %"{{.*}}/runtime/internal/runtime.iface" } undef, i32 %8, 0 +// CHECK-NEXT: %19 = insertvalue { i32, %"{{.*}}/runtime/internal/runtime.iface" } %18, %"{{.*}}/runtime/internal/runtime.iface" %17, 1 +// CHECK-NEXT: ret { i32, %"{{.*}}/runtime/internal/runtime.iface" } %19 +// CHECK-EMPTY: +// CHECK-NEXT: _llgo_2: ; preds = %_llgo_0 +// CHECK-NEXT: %20 = insertvalue { i32, %"{{.*}}/runtime/internal/runtime.iface" } undef, i32 %8, 0 +// CHECK-NEXT: %21 = insertvalue { i32, %"{{.*}}/runtime/internal/runtime.iface" } %20, %"{{.*}}/runtime/internal/runtime.iface" %11, 1 +// CHECK-NEXT: ret { i32, %"{{.*}}/runtime/internal/runtime.iface" } %21 +// CHECK-NEXT: } + +// CHECK-LABEL: define ptr @main._Cfunc_PyComplex_FromDoubles(double %0, double %1){{.*}} { +// CHECK-NEXT: _llgo_0: +// CHECK-NEXT: %2 = call ptr @"{{.*}}/runtime/internal/runtime.AllocZ"(i64 8) +// CHECK-NEXT: %3 = load ptr, ptr @main._cgo_{{[0-9a-f]+}}_Cfunc_PyComplex_FromDoubles, align 8 +// CHECK-NEXT: %4 = load ptr, ptr %3, align 8 +// CHECK-NEXT: %5 = call ptr %4(double %0, double %1) +// CHECK-NEXT: ret ptr %5 +// CHECK-NEXT: } + +// CHECK-LABEL: define [0 x i8] @main._Cfunc_PyErr_Print(){{.*}} { +// CHECK-NEXT: _llgo_0: +// CHECK-NEXT: %0 = load ptr, ptr @main._cgo_{{[0-9a-f]+}}_Cfunc_PyErr_Print, align 8 +// CHECK-NEXT: %1 = load ptr, ptr %0, align 8 +// CHECK-NEXT: %2 = call [0 x i8] %1() +// CHECK-NEXT: ret [0 x i8] %2 +// CHECK-NEXT: } + +// CHECK-LABEL: define i32 @main._Cfunc_PyObject_Print(ptr %0, ptr %1, i32 %2){{.*}} { +// CHECK-NEXT: _llgo_0: +// CHECK-NEXT: %3 = call ptr @"{{.*}}/runtime/internal/runtime.AllocZ"(i64 8) +// CHECK-NEXT: %4 = load ptr, ptr @main._cgo_{{[0-9a-f]+}}_Cfunc_PyObject_Print, align 8 +// CHECK-NEXT: %5 = load ptr, ptr %4, align 8 +// CHECK-NEXT: %6 = call i32 %5(ptr %0, ptr %1, i32 %2) +// CHECK-NEXT: ret i32 %6 +// CHECK-NEXT: } + +// CHECK-LABEL: define i32 @main._Cfunc_PyRun_SimpleString(ptr %0){{.*}} { +// CHECK-NEXT: _llgo_0: +// CHECK-NEXT: %1 = call ptr @"{{.*}}/runtime/internal/runtime.AllocZ"(i64 8) +// CHECK-NEXT: %2 = load ptr, ptr @main._cgo_{{[0-9a-f]+}}_Cfunc_PyRun_SimpleString, align 8 +// CHECK-NEXT: %3 = load ptr, ptr %2, align 8 +// CHECK-NEXT: %4 = call i32 %3(ptr %0) +// CHECK-NEXT: ret i32 %4 +// CHECK-NEXT: } + +// CHECK-LABEL: define [0 x i8] @main._Cfunc_Py_Finalize(){{.*}} { +// CHECK-NEXT: _llgo_0: +// CHECK-NEXT: %0 = load ptr, ptr @main._cgo_{{[0-9a-f]+}}_Cfunc_Py_Finalize, align 8 +// CHECK-NEXT: %1 = load ptr, ptr %0, align 8 +// CHECK-NEXT: %2 = call [0 x i8] %1() +// CHECK-NEXT: ret [0 x i8] %2 +// CHECK-NEXT: } + +// CHECK-LABEL: define [0 x i8] @main._Cfunc_Py_Initialize(){{.*}} { +// CHECK-NEXT: _llgo_0: +// CHECK-NEXT: %0 = load ptr, ptr @main._cgo_{{[0-9a-f]+}}_Cfunc_Py_Initialize, align 8 +// CHECK-NEXT: %1 = load ptr, ptr %0, align 8 +// CHECK-NEXT: %2 = call [0 x i8] %1() +// CHECK-NEXT: ret [0 x i8] %2 +// CHECK-NEXT: } + +// CHECK-LABEL: define [0 x i8] @main._Cfunc_foo(ptr %0){{.*}} { +// CHECK-NEXT: _llgo_0: +// CHECK-NEXT: %1 = call ptr @"{{.*}}/runtime/internal/runtime.AllocZ"(i64 8) +// CHECK-NEXT: %2 = load ptr, ptr @main._cgo_{{[0-9a-f]+}}_Cfunc_foo, align 8 +// CHECK-NEXT: %3 = load ptr, ptr %2, align 8 +// CHECK-NEXT: %4 = call [0 x i8] %3(ptr %0) +// CHECK-NEXT: ret [0 x i8] %4 +// CHECK-NEXT: } + +// CHECK-LABEL: define [0 x i8] @main._Cfunc_print_foo(ptr %0){{.*}} { +// CHECK-NEXT: _llgo_0: +// CHECK-NEXT: %1 = call ptr @"{{.*}}/runtime/internal/runtime.AllocZ"(i64 8) +// CHECK-NEXT: %2 = load ptr, ptr @main._cgo_{{[0-9a-f]+}}_Cfunc_print_foo, align 8 +// CHECK-NEXT: %3 = load ptr, ptr %2, align 8 +// CHECK-NEXT: %4 = call [0 x i8] %3(ptr %0) +// CHECK-NEXT: ret [0 x i8] %4 +// CHECK-NEXT: } + +// CHECK-LABEL: define [0 x i8] @main._Cfunc_run_callback(){{.*}} { +// CHECK-NEXT: _llgo_0: +// CHECK-NEXT: %0 = load ptr, ptr @main._cgo_{{[0-9a-f]+}}_Cfunc_run_callback, align 8 +// CHECK-NEXT: %1 = load ptr, ptr %0, align 8 +// CHECK-NEXT: %2 = call [0 x i8] %1() +// CHECK-NEXT: ret [0 x i8] %2 +// CHECK-NEXT: } + +// CHECK-LABEL: define [0 x i8] @main._Cfunc_test_callback(ptr %0){{.*}} { +// CHECK-NEXT: _llgo_0: +// CHECK-NEXT: %1 = call ptr @"{{.*}}/runtime/internal/runtime.AllocZ"(i64 8) +// CHECK-NEXT: %2 = load ptr, ptr @main._cgo_{{[0-9a-f]+}}_Cfunc_test_callback, align 8 +// CHECK-NEXT: %3 = load ptr, ptr %2, align 8 +// CHECK-NEXT: %4 = call [0 x i8] %3(ptr %0) +// CHECK-NEXT: ret [0 x i8] %4 +// CHECK-NEXT: } + +// CHECK-LABEL: define [0 x i8] @main._Cfunc_test_macros(){{.*}} { +// CHECK-NEXT: _llgo_0: +// CHECK-NEXT: %0 = load ptr, ptr @main._cgo_{{[0-9a-f]+}}_Cfunc_test_macros, align 8 +// CHECK-NEXT: %1 = load ptr, ptr %0, align 8 +// CHECK-NEXT: %2 = call [0 x i8] %1() +// CHECK-NEXT: ret [0 x i8] %2 +// CHECK-NEXT: } + +// CHECK-LABEL: define i32 @main._Cfunc_test_structs(ptr %0, ptr %1, ptr %2, ptr %3, ptr %4){{.*}} { +// CHECK-NEXT: _llgo_0: +// CHECK-NEXT: %5 = call ptr @"{{.*}}/runtime/internal/runtime.AllocZ"(i64 8) +// CHECK-NEXT: %6 = load ptr, ptr @main._cgo_{{[0-9a-f]+}}_Cfunc_test_structs, align 8 +// CHECK-NEXT: %7 = load ptr, ptr %6, align 8 +// CHECK-NEXT: %8 = call i32 %7(ptr %0, ptr %1, ptr %2, ptr %3, ptr %4) +// CHECK-NEXT: ret i32 %8 +// CHECK-NEXT: } + +// CHECK-LABEL: define [0 x i8] @main._Cfunc_test_void(){{.*}} { +// CHECK-NEXT: _llgo_0: +// CHECK-NEXT: %0 = load ptr, ptr @main._cgo_{{[0-9a-f]+}}_Cfunc_test_void, align 8 +// CHECK-NEXT: %1 = load ptr, ptr %0, align 8 +// CHECK-NEXT: %2 = call [0 x i8] %1() +// CHECK-NEXT: ret [0 x i8] %2 +// CHECK-NEXT: } + +// CHECK-LABEL: define ptr @main._Cgo_ptr(ptr %0){{.*}} { +// CHECK-NEXT: _llgo_0: +// CHECK-NEXT: ret ptr %0 +// CHECK-NEXT: } + +// CHECK-LABEL: define ptr @main._Cmacro_stderr(){{.*}} { +// CHECK-NEXT: _llgo_0: +// CHECK-NEXT: %0 = call ptr @"{{.*}}/runtime/internal/runtime.AllocZ"(i64 8) +// CHECK-NEXT: %1 = load ptr, ptr @main._cgo_{{[0-9a-f]+}}_Cmacro_stderr, align 8 +// CHECK-NEXT: %2 = load ptr, ptr %1, align 8 +// CHECK-NEXT: ret ptr %2 +// CHECK-NEXT: } + +// CHECK-LABEL: define ptr @main._Cmacro_stdout(){{.*}} { +// CHECK-NEXT: _llgo_0: +// CHECK-NEXT: %0 = call ptr @"{{.*}}/runtime/internal/runtime.AllocZ"(i64 8) +// CHECK-NEXT: %1 = load ptr, ptr @main._cgo_{{[0-9a-f]+}}_Cmacro_stdout, align 8 +// CHECK-NEXT: %2 = load ptr, ptr %1, align 8 +// CHECK-NEXT: ret ptr %2 +// CHECK-NEXT: } + +// CHECK-LABEL: define i32 @go_callback(i32 %0){{.*}} { +// CHECK-NEXT: _llgo_0: +// CHECK-NEXT: %1 = alloca %"{{.*}}/runtime/internal/runtime.LocalContext", align 8 +// CHECK-NEXT: call void @llvm.memset.p0.i64(ptr %1, i8 0, i64 8, i1 false) +// CHECK-NEXT: %2 = call i64 @"{{.*}}/runtime/internal/runtime.EnterLocalContext"(ptr %1) +// CHECK-NEXT: %3 = add i32 %0, 1 +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.LeaveLocalContext"(ptr %1, i64 %2) +// CHECK-NEXT: ret i32 %3 +// CHECK-NEXT: } + +// CHECK-LABEL: define i32 @go_callback_not_use_in_go(i32 %0){{.*}} { +// CHECK-NEXT: _llgo_0: +// CHECK-NEXT: %1 = alloca %"{{.*}}/runtime/internal/runtime.LocalContext", align 8 +// CHECK-NEXT: call void @llvm.memset.p0.i64(ptr %1, i8 0, i64 8, i1 false) +// CHECK-NEXT: %2 = call i64 @"{{.*}}/runtime/internal/runtime.EnterLocalContext"(ptr %1) +// CHECK-NEXT: %3 = add i32 %0, 1 +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.LeaveLocalContext"(ptr %1, i64 %2) +// CHECK-NEXT: ret i32 %3 +// CHECK-NEXT: } + +// CHECK-LABEL: define void @main.init(){{.*}} { +// CHECK-NEXT: _llgo_0: +// CHECK-NEXT: %0 = load i1, ptr @"main.init$guard", align 1 +// CHECK-NEXT: br i1 %0, label %_llgo_2, label %_llgo_1 +// CHECK-EMPTY: +// CHECK-NEXT: _llgo_1: ; preds = %_llgo_0 +// CHECK-NEXT: store i1 true, ptr @"main.init$guard", align 1 +// CHECK-NEXT: call void @syscall.init() +// CHECK-NEXT: call void @fmt.init() +// CHECK-NEXT: call void @"{{.*}}/cl/_testgo/cgofull/pymod1.init"() +// CHECK-NEXT: call void @"{{.*}}/cl/_testgo/cgofull/pymod2.init"() +// CHECK-NEXT: store ptr @main.__cgo_c_callback, ptr @main._Cfpvar_fp_c_callback, align 8 +// CHECK-NEXT: store ptr @main.__cgo_go_callback, ptr @main._Cfpvar_fp_go_callback, align 8 +// CHECK-NEXT: store ptr @_cgo_{{[0-9a-f]+}}_C2func_test_structs, ptr @main._cgo_{{[0-9a-f]+}}_C2func_test_structs, align 8 +// CHECK-NEXT: store ptr @_cgo_{{[0-9a-f]+}}_Cfunc_PyComplex_FromDoubles, ptr @main._cgo_{{[0-9a-f]+}}_Cfunc_PyComplex_FromDoubles, align 8 +// CHECK-NEXT: store ptr @_cgo_{{[0-9a-f]+}}_Cfunc_PyErr_Print, ptr @main._cgo_{{[0-9a-f]+}}_Cfunc_PyErr_Print, align 8 +// CHECK-NEXT: store ptr @_cgo_{{[0-9a-f]+}}_Cfunc_PyObject_Print, ptr @main._cgo_{{[0-9a-f]+}}_Cfunc_PyObject_Print, align 8 +// CHECK-NEXT: store ptr @_cgo_{{[0-9a-f]+}}_Cfunc_PyRun_SimpleString, ptr @main._cgo_{{[0-9a-f]+}}_Cfunc_PyRun_SimpleString, align 8 +// CHECK-NEXT: store ptr @_cgo_{{[0-9a-f]+}}_Cfunc_Py_Finalize, ptr @main._cgo_{{[0-9a-f]+}}_Cfunc_Py_Finalize, align 8 +// CHECK-NEXT: store ptr @_cgo_{{[0-9a-f]+}}_Cfunc_Py_Initialize, ptr @main._cgo_{{[0-9a-f]+}}_Cfunc_Py_Initialize, align 8 +// CHECK-NEXT: store ptr @_cgo_{{[0-9a-f]+}}_Cfunc_foo, ptr @main._cgo_{{[0-9a-f]+}}_Cfunc_foo, align 8 +// CHECK-NEXT: store ptr @_cgo_{{[0-9a-f]+}}_Cfunc_print_foo, ptr @main._cgo_{{[0-9a-f]+}}_Cfunc_print_foo, align 8 +// CHECK-NEXT: store ptr @_cgo_{{[0-9a-f]+}}_Cfunc_run_callback, ptr @main._cgo_{{[0-9a-f]+}}_Cfunc_run_callback, align 8 +// CHECK-NEXT: store ptr @_cgo_{{[0-9a-f]+}}_Cmacro_stderr, ptr @main._cgo_{{[0-9a-f]+}}_Cmacro_stderr, align 8 +// CHECK-NEXT: store ptr @_cgo_{{[0-9a-f]+}}_Cmacro_stdout, ptr @main._cgo_{{[0-9a-f]+}}_Cmacro_stdout, align 8 +// CHECK-NEXT: store ptr @_cgo_{{[0-9a-f]+}}_Cfunc_test_callback, ptr @main._cgo_{{[0-9a-f]+}}_Cfunc_test_callback, align 8 +// CHECK-NEXT: store ptr @_cgo_{{[0-9a-f]+}}_Cfunc_test_macros, ptr @main._cgo_{{[0-9a-f]+}}_Cfunc_test_macros, align 8 +// CHECK-NEXT: store ptr @_cgo_{{[0-9a-f]+}}_Cfunc_test_structs, ptr @main._cgo_{{[0-9a-f]+}}_Cfunc_test_structs, align 8 +// CHECK-NEXT: store ptr @_cgo_{{[0-9a-f]+}}_Cfunc_test_void, ptr @main._cgo_{{[0-9a-f]+}}_Cfunc_test_void, align 8 +// CHECK-NEXT: store ptr @_cgo_{{[0-9a-f]+}}_Cfunc__Cmalloc, ptr @main._cgo_{{[0-9a-f]+}}_Cfunc__Cmalloc, align 8 +// CHECK-NEXT: br label %_llgo_2 +// CHECK-EMPTY: +// CHECK-NEXT: _llgo_2: ; preds = %_llgo_1, %_llgo_0 +// CHECK-NEXT: ret void +// CHECK-NEXT: } + +// CHECK-LABEL: define void @main.main(){{.*}} { +// CHECK-NEXT: _llgo_0: +// CHECK-NEXT: call void @main.runPy() +// CHECK-NEXT: call void @main.triggerC2func() +// CHECK-NEXT: %0 = call ptr @"{{.*}}/runtime/internal/runtime.AllocZ"(i64 4) +// CHECK-NEXT: %1 = getelementptr inbounds %main._Ctype_struct___0, ptr %0, i32 0, i32 0 +// CHECK-NEXT: store i32 1, ptr %1, align 4 +// CHECK-NEXT: call void @main.Foo(ptr %0) +// CHECK-NEXT: call void @main.Bar(ptr %0) +// CHECK-NEXT: %2 = call [0 x i8] @main._Cfunc_test_macros() +// CHECK-NEXT: %3 = call ptr @"{{.*}}/runtime/internal/runtime.AllocZ"(i64 4) +// CHECK-NEXT: %4 = getelementptr inbounds %main._Ctype_struct___12, ptr %3, i32 0, i32 0 +// CHECK-NEXT: store i32 1, ptr %4, align 4 +// CHECK-NEXT: %5 = call ptr @"{{.*}}/runtime/internal/runtime.AllocZ"(i64 8) +// CHECK-NEXT: %6 = getelementptr inbounds %main._Ctype_struct___13, ptr %5, i32 0, i32 0 +// CHECK-NEXT: %7 = getelementptr inbounds %main._Ctype_struct___13, ptr %5, i32 0, i32 1 +// CHECK-NEXT: store i32 1, ptr %6, align 4 +// CHECK-NEXT: store i32 2, ptr %7, align 4 +// CHECK-NEXT: %8 = call ptr @"{{.*}}/runtime/internal/runtime.AllocZ"(i64 12) +// CHECK-NEXT: %9 = getelementptr inbounds %main._Ctype_struct___9, ptr %8, i32 0, i32 0 +// CHECK-NEXT: %10 = getelementptr inbounds %main._Ctype_struct___9, ptr %8, i32 0, i32 1 +// CHECK-NEXT: %11 = getelementptr inbounds %main._Ctype_struct___9, ptr %8, i32 0, i32 2 +// CHECK-NEXT: store i32 1, ptr %9, align 4 +// CHECK-NEXT: store i32 2, ptr %10, align 4 +// CHECK-NEXT: store i32 3, ptr %11, align 4 +// CHECK-NEXT: %12 = call ptr @"{{.*}}/runtime/internal/runtime.AllocZ"(i64 16) +// CHECK-NEXT: %13 = getelementptr inbounds %main._Ctype_struct___10, ptr %12, i32 0, i32 0 +// CHECK-NEXT: %14 = getelementptr inbounds %main._Ctype_struct___10, ptr %12, i32 0, i32 1 +// CHECK-NEXT: %15 = getelementptr inbounds %main._Ctype_struct___10, ptr %12, i32 0, i32 2 +// CHECK-NEXT: %16 = getelementptr inbounds %main._Ctype_struct___10, ptr %12, i32 0, i32 3 +// CHECK-NEXT: store i32 1, ptr %13, align 4 +// CHECK-NEXT: store i32 2, ptr %14, align 4 +// CHECK-NEXT: store i32 3, ptr %15, align 4 +// CHECK-NEXT: store i32 4, ptr %16, align 4 +// CHECK-NEXT: %17 = call ptr @"{{.*}}/runtime/internal/runtime.AllocZ"(i64 20) +// CHECK-NEXT: %18 = getelementptr inbounds %main._Ctype_struct___11, ptr %17, i32 0, i32 0 +// CHECK-NEXT: %19 = getelementptr inbounds %main._Ctype_struct___11, ptr %17, i32 0, i32 1 +// CHECK-NEXT: %20 = getelementptr inbounds %main._Ctype_struct___11, ptr %17, i32 0, i32 2 +// CHECK-NEXT: %21 = getelementptr inbounds %main._Ctype_struct___11, ptr %17, i32 0, i32 3 +// CHECK-NEXT: %22 = getelementptr inbounds %main._Ctype_struct___11, ptr %17, i32 0, i32 4 +// CHECK-NEXT: store i32 1, ptr %18, align 4 +// CHECK-NEXT: store i32 2, ptr %19, align 4 +// CHECK-NEXT: store i32 3, ptr %20, align 4 +// CHECK-NEXT: store i32 4, ptr %21, align 4 +// CHECK-NEXT: store i32 5, ptr %22, align 4 +// CHECK-NEXT: %23 = call i32 @main._Cfunc_test_structs(ptr %3, ptr %5, ptr %8, ptr %12, ptr %17) +// CHECK-NEXT: %24 = call ptr @"{{.*}}/runtime/internal/runtime.AllocZ"(i64 16) +// CHECK-NEXT: %25 = getelementptr inbounds %"{{.*}}/runtime/internal/runtime.eface", ptr %24, i64 0 +// CHECK-NEXT: %26 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 4) +// CHECK-NEXT: store i32 %23, ptr %26, align 4 +// CHECK-NEXT: %27 = insertvalue %"{{.*}}/runtime/internal/runtime.eface" { ptr @_llgo_main._Ctype_int, ptr undef }, ptr %26, 1 +// CHECK-NEXT: store %"{{.*}}/runtime/internal/runtime.eface" %27, ptr %25, align 8 +// CHECK-NEXT: %28 = insertvalue %"{{.*}}/runtime/internal/runtime.Slice" undef, ptr %24, 0 +// CHECK-NEXT: %29 = insertvalue %"{{.*}}/runtime/internal/runtime.Slice" %28, i64 1, 1 +// CHECK-NEXT: %30 = insertvalue %"{{.*}}/runtime/internal/runtime.Slice" %29, i64 1, 2 +// CHECK-NEXT: %31 = call { i64, %"{{.*}}/runtime/internal/runtime.iface" } @fmt.Println(%"{{.*}}/runtime/internal/runtime.Slice" %30) +// CHECK-NEXT: %32 = icmp ne i32 %23, 35 +// CHECK-NEXT: br i1 %32, label %_llgo_1, label %_llgo_2 +// CHECK-EMPTY: +// CHECK-NEXT: _llgo_1: ; preds = %_llgo_0 +// CHECK-NEXT: %33 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 16) +// CHECK-NEXT: store %"{{.*}}/runtime/internal/runtime.String" { ptr @{{[0-9]+}}, i64 19 }, ptr %33, align 8 +// CHECK-NEXT: %34 = insertvalue %"{{.*}}/runtime/internal/runtime.eface" { ptr @_llgo_string, ptr undef }, ptr %33, 1 +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.Panic"(%"{{.*}}/runtime/internal/runtime.eface" %34) +// CHECK-NEXT: unreachable +// CHECK-EMPTY: +// CHECK-NEXT: _llgo_2: ; preds = %_llgo_0 +// CHECK-NEXT: %35 = call ptr @"{{.*}}/runtime/internal/runtime.AllocZ"(i64 16) +// CHECK-NEXT: %36 = getelementptr inbounds %"{{.*}}/runtime/internal/runtime.eface", ptr %35, i64 0 +// CHECK-NEXT: %37 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 16) +// CHECK-NEXT: store %"{{.*}}/runtime/internal/runtime.String" { ptr @{{[0-9]+}}, i64 5 }, ptr %37, align 8 +// CHECK-NEXT: %38 = insertvalue %"{{.*}}/runtime/internal/runtime.eface" { ptr @_llgo_string, ptr undef }, ptr %37, 1 +// CHECK-NEXT: store %"{{.*}}/runtime/internal/runtime.eface" %38, ptr %36, align 8 +// CHECK-NEXT: %39 = insertvalue %"{{.*}}/runtime/internal/runtime.Slice" undef, ptr %35, 0 +// CHECK-NEXT: %40 = insertvalue %"{{.*}}/runtime/internal/runtime.Slice" %39, i64 1, 1 +// CHECK-NEXT: %41 = insertvalue %"{{.*}}/runtime/internal/runtime.Slice" %40, i64 1, 2 +// CHECK-NEXT: %42 = call { i64, %"{{.*}}/runtime/internal/runtime.iface" } @fmt.Println(%"{{.*}}/runtime/internal/runtime.Slice" %41) +// CHECK-NEXT: %43 = call ptr @"{{.*}}/runtime/internal/runtime.AllocZ"(i64 16) +// CHECK-NEXT: %44 = getelementptr inbounds %"{{.*}}/runtime/internal/runtime.eface", ptr %43, i64 0 +// CHECK-NEXT: %45 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 8) +// CHECK-NEXT: store i64 305419896, ptr %45, align 8 +// CHECK-NEXT: %46 = insertvalue %"{{.*}}/runtime/internal/runtime.eface" { ptr @_llgo_int, ptr undef }, ptr %45, 1 +// CHECK-NEXT: store %"{{.*}}/runtime/internal/runtime.eface" %46, ptr %44, align 8 +// CHECK-NEXT: %47 = insertvalue %"{{.*}}/runtime/internal/runtime.Slice" undef, ptr %43, 0 +// CHECK-NEXT: %48 = insertvalue %"{{.*}}/runtime/internal/runtime.Slice" %47, i64 1, 1 +// CHECK-NEXT: %49 = insertvalue %"{{.*}}/runtime/internal/runtime.Slice" %48, i64 1, 2 +// CHECK-NEXT: %50 = call { i64, %"{{.*}}/runtime/internal/runtime.iface" } @fmt.Println(%"{{.*}}/runtime/internal/runtime.Slice" %49) +// CHECK-NEXT: %51 = call [0 x i8] @main._Cfunc_test_void() +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.PrintString"(%"{{.*}}/runtime/internal/runtime.String" { ptr @{{[0-9]+}}, i64 17 }) +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.PrintByte"(i8 10) +// CHECK-NEXT: %52 = call [0 x i8] @main._Cfunc_run_callback() +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.PrintString"(%"{{.*}}/runtime/internal/runtime.String" { ptr @{{[0-9]+}}, i64 21 }) +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.PrintByte"(i8 10) +// CHECK-NEXT: %53 = load ptr, ptr @main._Cfpvar_fp_go_callback, align 8 +// CHECK-NEXT: %54 = call ptr @main._Cgo_ptr(ptr %53) +// CHECK-NEXT: %55 = call [0 x i8] @main._Cfunc_test_callback(ptr %54) +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.PrintString"(%"{{.*}}/runtime/internal/runtime.String" { ptr @{{[0-9]+}}, i64 20 }) +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.PrintByte"(i8 10) +// CHECK-NEXT: %56 = load ptr, ptr @main._Cfpvar_fp_c_callback, align 8 +// CHECK-NEXT: %57 = call ptr @main._Cgo_ptr(ptr %56) +// CHECK-NEXT: %58 = call [0 x i8] @main._Cfunc_test_callback(ptr %57) +// CHECK-NEXT: ret void +// CHECK-NEXT: } + +// CHECK-LABEL: define void @main.runPy(){{.*}} { +// CHECK-NEXT: _llgo_0: +// CHECK-NEXT: call void @main.Initialize() +// CHECK-NEXT: %0 = call ptr @"{{.*}}/runtime/internal/runtime.GetThreadDefer"() +// CHECK-NEXT: %1 = alloca i8 +// CHECK-NEXT: %2 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 48) +// CHECK-NEXT: %3 = getelementptr inbounds %"{{.*}}/runtime/internal/runtime.Defer", ptr %2, i32 0, i32 0 +// CHECK-NEXT: store ptr %1, ptr %3, align 8 +// CHECK-NEXT: %4 = getelementptr inbounds %"{{.*}}/runtime/internal/runtime.Defer", ptr %2, i32 0, i32 1 +// CHECK-NEXT: store i64 0, ptr %4, align 8 +// CHECK-NEXT: %5 = getelementptr inbounds %"{{.*}}/runtime/internal/runtime.Defer", ptr %2, i32 0, i32 2 +// CHECK-NEXT: store ptr %0, ptr %5, align 8 +// CHECK-NEXT: %6 = getelementptr inbounds %"{{.*}}/runtime/internal/runtime.Defer", ptr %2, i32 0, i32 3 +// CHECK-NEXT: store ptr blockaddress(@main.runPy, %_llgo_2), ptr %6, align 8 +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.SetThreadDefer"(ptr %2) +// CHECK-NEXT: %7 = getelementptr inbounds %"{{.*}}/runtime/internal/runtime.Defer", ptr %2, i32 0, i32 1 +// CHECK-NEXT: %8 = getelementptr inbounds %"{{.*}}/runtime/internal/runtime.Defer", ptr %2, i32 0, i32 3 +// CHECK-NEXT: %9 = getelementptr inbounds %"{{.*}}/runtime/internal/runtime.Defer", ptr %2, i32 0, i32 4 +// CHECK-NEXT: %10 = getelementptr inbounds %"{{.*}}/runtime/internal/runtime.Defer", ptr %2, i32 0, i32 5 +// CHECK-NEXT: store ptr null, ptr %10, align 8 +// CHECK-NEXT: %11 = call i32 @{{(__)?}}sigsetjmp(ptr %1, i32 0) +// CHECK-NEXT: %12 = icmp eq i32 %11, 0 +// CHECK-NEXT: br i1 %12, label %_llgo_4, label %_llgo_5 +// CHECK-EMPTY: +// CHECK-NEXT: _llgo_1: ; preds = %_llgo_3 +// CHECK-NEXT: ret void +// CHECK-EMPTY: +// CHECK-NEXT: _llgo_2: ; preds = %_llgo_5, %_llgo_4 +// CHECK-NEXT: store ptr blockaddress(@main.runPy, %_llgo_3), ptr %8, align 8 +// CHECK-NEXT: %13 = load i64, ptr %7, align 8 +// CHECK-NEXT: call void @main.Finalize() +// CHECK-NEXT: %14 = load %"{{.*}}/runtime/internal/runtime.Defer", ptr %2, align 8 +// CHECK-NEXT: %15 = extractvalue %"{{.*}}/runtime/internal/runtime.Defer" %14, 2 +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.SetThreadDefer"(ptr %15) +// CHECK-NEXT: %16 = load ptr, ptr %9, align 8 +// CHECK-NEXT: indirectbr ptr %16, [label %_llgo_3, label %_llgo_6] +// CHECK-EMPTY: +// CHECK-NEXT: _llgo_3: ; preds = %_llgo_5, %_llgo_2 +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.Rethrow"(ptr %0) +// CHECK-NEXT: br label %_llgo_1 +// CHECK-EMPTY: +// CHECK-NEXT: _llgo_4: ; preds = %_llgo_0 +// CHECK-NEXT: %17 = call %"{{.*}}/runtime/internal/runtime.iface" @main.Run(%"{{.*}}/runtime/internal/runtime.String" { ptr @{{[0-9]+}}, i64 23 }) +// CHECK-NEXT: %18 = call i32 @"main.runPy$1"() +// CHECK-NEXT: %19 = call i32 @"main.runPy$2"() +// CHECK-NEXT: %20 = call i32 @"main.runPy$3"() +// CHECK-NEXT: store ptr blockaddress(@main.runPy, %_llgo_6), ptr %9, align 8 +// CHECK-NEXT: br label %_llgo_2 +// CHECK-EMPTY: +// CHECK-NEXT: _llgo_5: ; preds = %_llgo_0 +// CHECK-NEXT: store ptr blockaddress(@main.runPy, %_llgo_3), ptr %9, align 8 +// CHECK-NEXT: %21 = load ptr, ptr %8, align 8 +// CHECK-NEXT: indirectbr ptr %21, [label %_llgo_3, label %_llgo_2] +// CHECK-EMPTY: +// CHECK-NEXT: _llgo_6: ; preds = %_llgo_2 +// CHECK-NEXT: ret void +// CHECK-NEXT: } + +// CHECK-LABEL: define i32 @"main.runPy$1"(){{.*}} { +// CHECK-NEXT: _llgo_0: +// CHECK-NEXT: %0 = call ptr @"{{.*}}/cl/_testgo/cgofull/pymod1.Float"(double 1.230000e+00) +// CHECK-NEXT: %1 = call ptr @main._Cmacro_stderr() +// CHECK-NEXT: %2 = insertvalue %"{{.*}}/runtime/internal/runtime.eface" { ptr @"*_llgo_main._Ctype_struct__object", ptr undef }, ptr %0, 1 +// CHECK-NEXT: %3 = insertvalue %"{{.*}}/runtime/internal/runtime.eface" { ptr @"*_llgo_main._Ctype_struct_{{(__sFILE|_IO_FILE)}}", ptr undef }, ptr %1, 1 +// CHECK-NEXT: %4 = call i32 @main._Cfunc_PyObject_Print(ptr %0, ptr %1, i32 0) +// CHECK-NEXT: ret i32 %4 +// CHECK-NEXT: } + +// CHECK-LABEL: define i32 @"main.runPy$2"(){{.*}} { +// CHECK-NEXT: _llgo_0: +// CHECK-NEXT: %0 = call ptr @"{{.*}}/cl/_testgo/cgofull/pymod2.Long"(i64 123) +// CHECK-NEXT: %1 = call ptr @main._Cmacro_stdout() +// CHECK-NEXT: %2 = insertvalue %"{{.*}}/runtime/internal/runtime.eface" { ptr @"*_llgo_main._Ctype_struct__object", ptr undef }, ptr %0, 1 +// CHECK-NEXT: %3 = insertvalue %"{{.*}}/runtime/internal/runtime.eface" { ptr @"*_llgo_main._Ctype_struct_{{(__sFILE|_IO_FILE)}}", ptr undef }, ptr %1, 1 +// CHECK-NEXT: %4 = call i32 @main._Cfunc_PyObject_Print(ptr %0, ptr %1, i32 0) +// CHECK-NEXT: ret i32 %4 +// CHECK-NEXT: } + +// CHECK-LABEL: define i32 @"main.runPy$3"(){{.*}} { +// CHECK-NEXT: _llgo_0: +// CHECK-NEXT: %0 = call ptr @main._Cfunc_PyComplex_FromDoubles(double 1.230000e+00, double 4.560000e+00) +// CHECK-NEXT: %1 = call ptr @main._Cmacro_stdout() +// CHECK-NEXT: %2 = insertvalue %"{{.*}}/runtime/internal/runtime.eface" { ptr @"*_llgo_main._Ctype_struct__object", ptr undef }, ptr %0, 1 +// CHECK-NEXT: %3 = insertvalue %"{{.*}}/runtime/internal/runtime.eface" { ptr @"*_llgo_main._Ctype_struct_{{(__sFILE|_IO_FILE)}}", ptr undef }, ptr %1, 1 +// CHECK-NEXT: %4 = call i32 @main._Cfunc_PyObject_Print(ptr %0, ptr %1, i32 0) +// CHECK-NEXT: ret i32 %4 +// CHECK-NEXT: } + +// CHECK-LABEL: define void @main.triggerC2func(){{.*}} { +// CHECK-NEXT: _llgo_0: +// CHECK-NEXT: %0 = call ptr @"{{.*}}/runtime/internal/runtime.AllocZ"(i64 4) +// CHECK-NEXT: %1 = getelementptr inbounds %main._Ctype_struct___12, ptr %0, i32 0, i32 0 +// CHECK-NEXT: store i32 1, ptr %1, align 4 +// CHECK-NEXT: %2 = call ptr @"{{.*}}/runtime/internal/runtime.AllocZ"(i64 8) +// CHECK-NEXT: %3 = getelementptr inbounds %main._Ctype_struct___13, ptr %2, i32 0, i32 0 +// CHECK-NEXT: %4 = getelementptr inbounds %main._Ctype_struct___13, ptr %2, i32 0, i32 1 +// CHECK-NEXT: store i32 1, ptr %3, align 4 +// CHECK-NEXT: store i32 2, ptr %4, align 4 +// CHECK-NEXT: %5 = call ptr @"{{.*}}/runtime/internal/runtime.AllocZ"(i64 12) +// CHECK-NEXT: %6 = getelementptr inbounds %main._Ctype_struct___9, ptr %5, i32 0, i32 0 +// CHECK-NEXT: %7 = getelementptr inbounds %main._Ctype_struct___9, ptr %5, i32 0, i32 1 +// CHECK-NEXT: %8 = getelementptr inbounds %main._Ctype_struct___9, ptr %5, i32 0, i32 2 +// CHECK-NEXT: store i32 1, ptr %6, align 4 +// CHECK-NEXT: store i32 2, ptr %7, align 4 +// CHECK-NEXT: store i32 3, ptr %8, align 4 +// CHECK-NEXT: %9 = call ptr @"{{.*}}/runtime/internal/runtime.AllocZ"(i64 16) +// CHECK-NEXT: %10 = getelementptr inbounds %main._Ctype_struct___10, ptr %9, i32 0, i32 0 +// CHECK-NEXT: %11 = getelementptr inbounds %main._Ctype_struct___10, ptr %9, i32 0, i32 1 +// CHECK-NEXT: %12 = getelementptr inbounds %main._Ctype_struct___10, ptr %9, i32 0, i32 2 +// CHECK-NEXT: %13 = getelementptr inbounds %main._Ctype_struct___10, ptr %9, i32 0, i32 3 +// CHECK-NEXT: store i32 1, ptr %10, align 4 +// CHECK-NEXT: store i32 2, ptr %11, align 4 +// CHECK-NEXT: store i32 3, ptr %12, align 4 +// CHECK-NEXT: store i32 4, ptr %13, align 4 +// CHECK-NEXT: %14 = call ptr @"{{.*}}/runtime/internal/runtime.AllocZ"(i64 20) +// CHECK-NEXT: %15 = getelementptr inbounds %main._Ctype_struct___11, ptr %14, i32 0, i32 0 +// CHECK-NEXT: %16 = getelementptr inbounds %main._Ctype_struct___11, ptr %14, i32 0, i32 1 +// CHECK-NEXT: %17 = getelementptr inbounds %main._Ctype_struct___11, ptr %14, i32 0, i32 2 +// CHECK-NEXT: %18 = getelementptr inbounds %main._Ctype_struct___11, ptr %14, i32 0, i32 3 +// CHECK-NEXT: %19 = getelementptr inbounds %main._Ctype_struct___11, ptr %14, i32 0, i32 4 +// CHECK-NEXT: store i32 1, ptr %15, align 4 +// CHECK-NEXT: store i32 2, ptr %16, align 4 +// CHECK-NEXT: store i32 3, ptr %17, align 4 +// CHECK-NEXT: store i32 4, ptr %18, align 4 +// CHECK-NEXT: store i32 5, ptr %19, align 4 +// CHECK-NEXT: %20 = call { i32, %"{{.*}}/runtime/internal/runtime.iface" } @main._C2func_test_structs(ptr %0, ptr %2, ptr %5, ptr %9, ptr %14) +// CHECK-NEXT: %21 = extractvalue { i32, %"{{.*}}/runtime/internal/runtime.iface" } %20, 0 +// CHECK-NEXT: %22 = extractvalue { i32, %"{{.*}}/runtime/internal/runtime.iface" } %20, 1 +// CHECK-NEXT: %23 = call ptr @"{{.*}}/runtime/internal/runtime.IfaceType"(%"{{.*}}/runtime/internal/runtime.iface" %22) +// CHECK-NEXT: %24 = extractvalue %"{{.*}}/runtime/internal/runtime.iface" %22, 1 +// CHECK-NEXT: %25 = insertvalue %"{{.*}}/runtime/internal/runtime.eface" undef, ptr %23, 0 +// CHECK-NEXT: %26 = insertvalue %"{{.*}}/runtime/internal/runtime.eface" %25, ptr %24, 1 +// CHECK-NEXT: %27 = call ptr @"{{.*}}/runtime/internal/runtime.IfaceType"(%"{{.*}}/runtime/internal/runtime.iface" zeroinitializer) +// CHECK-NEXT: %28 = insertvalue %"{{.*}}/runtime/internal/runtime.eface" undef, ptr %27, 0 +// CHECK-NEXT: %29 = insertvalue %"{{.*}}/runtime/internal/runtime.eface" %28, ptr null, 1 +// CHECK-NEXT: %30 = call i1 @"{{.*}}/runtime/internal/runtime.EfaceEqual"(%"{{.*}}/runtime/internal/runtime.eface" %26, %"{{.*}}/runtime/internal/runtime.eface" %29) +// CHECK-NEXT: %31 = xor i1 %30, true +// CHECK-NEXT: br i1 %31, label %_llgo_1, label %_llgo_2 +// CHECK-EMPTY: +// CHECK-NEXT: _llgo_1: ; preds = %_llgo_0 +// CHECK-NEXT: %32 = call ptr @"{{.*}}/runtime/internal/runtime.IfaceType"(%"{{.*}}/runtime/internal/runtime.iface" %22) +// CHECK-NEXT: %33 = extractvalue %"{{.*}}/runtime/internal/runtime.iface" %22, 1 +// CHECK-NEXT: %34 = insertvalue %"{{.*}}/runtime/internal/runtime.eface" undef, ptr %32, 0 +// CHECK-NEXT: %35 = insertvalue %"{{.*}}/runtime/internal/runtime.eface" %34, ptr %33, 1 +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.Panic"(%"{{.*}}/runtime/internal/runtime.eface" %35) +// CHECK-NEXT: unreachable +// CHECK-EMPTY: +// CHECK-NEXT: _llgo_2: ; preds = %_llgo_0 +// CHECK-NEXT: %36 = icmp ne i32 %21, 35 +// CHECK-NEXT: br i1 %36, label %_llgo_3, label %_llgo_4 +// CHECK-EMPTY: +// CHECK-NEXT: _llgo_3: ; preds = %_llgo_2 +// CHECK-NEXT: %37 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 16) +// CHECK-NEXT: store %"{{.*}}/runtime/internal/runtime.String" { ptr @{{[0-9]+}}, i64 26 }, ptr %37, align 8 +// CHECK-NEXT: %38 = insertvalue %"{{.*}}/runtime/internal/runtime.eface" { ptr @_llgo_string, ptr undef }, ptr %37, 1 +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.Panic"(%"{{.*}}/runtime/internal/runtime.eface" %38) +// CHECK-NEXT: unreachable +// CHECK-EMPTY: +// CHECK-NEXT: _llgo_4: ; preds = %_llgo_2 +// CHECK-NEXT: %39 = call ptr @"{{.*}}/runtime/internal/runtime.AllocZ"(i64 16) +// CHECK-NEXT: %40 = getelementptr inbounds %"{{.*}}/runtime/internal/runtime.eface", ptr %39, i64 0 +// CHECK-NEXT: %41 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 16) +// CHECK-NEXT: store %"{{.*}}/runtime/internal/runtime.String" { ptr @{{[0-9]+}}, i64 9 }, ptr %41, align 8 +// CHECK-NEXT: %42 = insertvalue %"{{.*}}/runtime/internal/runtime.eface" { ptr @_llgo_string, ptr undef }, ptr %41, 1 +// CHECK-NEXT: store %"{{.*}}/runtime/internal/runtime.eface" %42, ptr %40, align 8 +// CHECK-NEXT: %43 = insertvalue %"{{.*}}/runtime/internal/runtime.Slice" undef, ptr %39, 0 +// CHECK-NEXT: %44 = insertvalue %"{{.*}}/runtime/internal/runtime.Slice" %43, i64 1, 1 +// CHECK-NEXT: %45 = insertvalue %"{{.*}}/runtime/internal/runtime.Slice" %44, i64 1, 2 +// CHECK-NEXT: %46 = call { i64, %"{{.*}}/runtime/internal/runtime.iface" } @fmt.Println(%"{{.*}}/runtime/internal/runtime.Slice" %45) +// CHECK-NEXT: ret void +// CHECK-NEXT: } diff --git a/cl/_testgo/chan/in.go b/cl/_testgo/chan/in.go index e76b688bfc..a930ace2ea 100644 --- a/cl/_testgo/chan/in.go +++ b/cl/_testgo/chan/in.go @@ -1,11 +1,6 @@ // LITTEST package main -// CHECK-DAG: call ptr @"{{.*}}/runtime/internal/runtime.NewChan"({{.*}}) -// CHECK-DAG: call void @"{{.*}}/runtime/internal/runtime.NewProc"({{.*}}) -// CHECK-DAG: call i1 @"{{.*}}/runtime/internal/runtime.ChanRecv"({{.*}}) -// CHECK-DAG: call void @"{{.*}}/runtime/internal/runtime.ChanClose"({{.*}}) - func main() { ch := make(chan int, 10) var v any = ch @@ -23,3 +18,129 @@ func main() { n2, ok := <-ch2 println(n2, ok) } + +// CHECK-LABEL: define void @main.init(){{.*}} { +// CHECK-NEXT: _llgo_0: +// CHECK-NEXT: %0 = load i1, ptr @"main.init$guard", align 1 +// CHECK-NEXT: br i1 %0, label %_llgo_2, label %_llgo_1 +// CHECK-EMPTY: +// CHECK-NEXT: _llgo_1: ; preds = %_llgo_0 +// CHECK-NEXT: store i1 true, ptr @"main.init$guard", align 1 +// CHECK-NEXT: br label %_llgo_2 +// CHECK-EMPTY: +// CHECK-NEXT: _llgo_2: ; preds = %_llgo_1, %_llgo_0 +// CHECK-NEXT: ret void +// CHECK-NEXT: } + +// CHECK-LABEL: define void @main.main(){{.*}} { +// CHECK-NEXT: _llgo_0: +// CHECK-NEXT: %0 = call ptr @"{{.*}}/runtime/internal/runtime.AllocZ"(i64 8) +// CHECK-NEXT: %1 = call ptr @"{{.*}}/runtime/internal/runtime.NewChan"(i64 8, i64 10) +// CHECK-NEXT: store ptr %1, ptr %0, align 8 +// CHECK-NEXT: %2 = load ptr, ptr %0, align 8 +// CHECK-NEXT: %3 = insertvalue %"{{.*}}/runtime/internal/runtime.eface" { ptr @"chan _llgo_int", ptr undef }, ptr %2, 1 +// CHECK-NEXT: %4 = load ptr, ptr %0, align 8 +// CHECK-NEXT: %5 = load ptr, ptr %0, align 8 +// CHECK-NEXT: %6 = call i64 @"{{.*}}/runtime/internal/runtime.ChanLen"(ptr %5) +// CHECK-NEXT: %7 = load ptr, ptr %0, align 8 +// CHECK-NEXT: %8 = call i64 @"{{.*}}/runtime/internal/runtime.ChanCap"(ptr %7) +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.PrintPointer"(ptr %4) +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.PrintByte"(i8 32) +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.PrintInt"(i64 %6) +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.PrintByte"(i8 32) +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.PrintInt"(i64 %8) +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.PrintByte"(i8 32) +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.PrintEface"(%"{{.*}}/runtime/internal/runtime.eface" %3) +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.PrintByte"(i8 10) +// CHECK-NEXT: %9 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 8) +// CHECK-NEXT: %10 = getelementptr inbounds { ptr }, ptr %9, i32 0, i32 0 +// CHECK-NEXT: store ptr %0, ptr %10, align 8 +// CHECK-NEXT: %11 = insertvalue { ptr, ptr } { ptr @"main.main$1", ptr undef }, ptr %9, 1 +// CHECK-NEXT: %12 = call ptr @"{{.*}}/runtime/internal/runtime.AllocRoot"(i64 16) +// CHECK-NEXT: %13 = getelementptr inbounds { { ptr, ptr } }, ptr %12, i32 0, i32 0 +// CHECK-NEXT: store { ptr, ptr } %11, ptr %13, align 8 +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.NewProc"(ptr @"main._llgo_routine$1", ptr %12, i64 0) +// CHECK-NEXT: %14 = load ptr, ptr %0, align 8 +// CHECK-NEXT: %15 = call ptr @llvm.stacksave.p0() +// CHECK-NEXT: %16 = alloca i64, align 8 +// CHECK-NEXT: call void @llvm.memset.p0.i64(ptr %16, i8 0, i64 8, i1 false) +// CHECK-NEXT: %17 = call i1 @"{{.*}}/runtime/internal/runtime.ChanRecv"(ptr %14, ptr %16, i64 8) +// CHECK-NEXT: %18 = load i64, ptr %16, align 8 +// CHECK-NEXT: call void @llvm.stackrestore.p0(ptr %15) +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.PrintInt"(i64 %18) +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.PrintByte"(i8 10) +// CHECK-NEXT: %19 = call ptr @"{{.*}}/runtime/internal/runtime.AllocZ"(i64 8) +// CHECK-NEXT: %20 = call ptr @"{{.*}}/runtime/internal/runtime.NewChan"(i64 8, i64 10) +// CHECK-NEXT: store ptr %20, ptr %19, align 8 +// CHECK-NEXT: %21 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 8) +// CHECK-NEXT: %22 = getelementptr inbounds { ptr }, ptr %21, i32 0, i32 0 +// CHECK-NEXT: store ptr %19, ptr %22, align 8 +// CHECK-NEXT: %23 = insertvalue { ptr, ptr } { ptr @"main.main$2", ptr undef }, ptr %21, 1 +// CHECK-NEXT: %24 = call ptr @"{{.*}}/runtime/internal/runtime.AllocRoot"(i64 16) +// CHECK-NEXT: %25 = getelementptr inbounds { { ptr, ptr } }, ptr %24, i32 0, i32 0 +// CHECK-NEXT: store { ptr, ptr } %23, ptr %25, align 8 +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.NewProc"(ptr @"main._llgo_routine$2", ptr %24, i64 0) +// CHECK-NEXT: %26 = load ptr, ptr %19, align 8 +// CHECK-NEXT: %27 = call ptr @llvm.stacksave.p0() +// CHECK-NEXT: %28 = alloca i64, align 8 +// CHECK-NEXT: call void @llvm.memset.p0.i64(ptr %28, i8 0, i64 8, i1 false) +// CHECK-NEXT: %29 = call i1 @"{{.*}}/runtime/internal/runtime.ChanRecv"(ptr %26, ptr %28, i64 8) +// CHECK-NEXT: %30 = load i64, ptr %28, align 8 +// CHECK-NEXT: call void @llvm.stackrestore.p0(ptr %27) +// CHECK-NEXT: %31 = insertvalue { i64, i1 } undef, i64 %30, 0 +// CHECK-NEXT: %32 = insertvalue { i64, i1 } %31, i1 %29, 1 +// CHECK-NEXT: %33 = extractvalue { i64, i1 } %32, 0 +// CHECK-NEXT: %34 = extractvalue { i64, i1 } %32, 1 +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.PrintInt"(i64 %33) +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.PrintByte"(i8 32) +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.PrintBool"(i1 %34) +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.PrintByte"(i8 10) +// CHECK-NEXT: ret void +// CHECK-NEXT: } + +// CHECK-LABEL: define void @"main.main$1"(ptr {{(nest|swiftself)}} %0){{.*}} { +// CHECK-NEXT: _llgo_0: +// CHECK-NEXT: %1 = load { ptr }, ptr %0, align 8 +// CHECK-NEXT: %2 = extractvalue { ptr } %1, 0 +// CHECK-NEXT: %3 = load ptr, ptr %2, align 8 +// CHECK-NEXT: %4 = call ptr @llvm.stacksave.p0() +// CHECK-NEXT: %5 = alloca i64, align 8 +// CHECK-NEXT: call void @llvm.memset.p0.i64(ptr %5, i8 0, i64 8, i1 false) +// CHECK-NEXT: store i64 100, ptr %5, align 8 +// CHECK-NEXT: %6 = call i1 @"{{.*}}/runtime/internal/runtime.ChanSend"(ptr %3, ptr %5, i64 8) +// CHECK-NEXT: call void @llvm.stackrestore.p0(ptr %4) +// CHECK-NEXT: ret void +// CHECK-NEXT: } + +// CHECK-LABEL: define void @"main.main$2"(ptr {{(nest|swiftself)}} %0){{.*}} { +// CHECK-NEXT: _llgo_0: +// CHECK-NEXT: %1 = load { ptr }, ptr %0, align 8 +// CHECK-NEXT: %2 = extractvalue { ptr } %1, 0 +// CHECK-NEXT: %3 = load ptr, ptr %2, align 8 +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.ChanClose"(ptr %3) +// CHECK-NEXT: ret void +// CHECK-NEXT: } + +// CHECK-LABEL: define ptr @"main._llgo_routine$1"(ptr %0){{.*}} { +// CHECK-NEXT: _llgo_0: +// CHECK-NEXT: %1 = load { { ptr, ptr } }, ptr %0, align 8 +// CHECK-NEXT: %2 = extractvalue { { ptr, ptr } } %1, 0 +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.FreeRoot"(ptr %0) +// CHECK-NEXT: %3 = extractvalue { ptr, ptr } %2, 1 +// CHECK-NEXT: %4 = extractvalue { ptr, ptr } %2, 0 +// CHECK-NEXT: %__llgo_funcval_code = call ptr asm "", "=r,0"(ptr %4) +// CHECK-NEXT: call void %__llgo_funcval_code(ptr {{(nest|swiftself)}} %3) +// CHECK-NEXT: ret ptr null +// CHECK-NEXT: } + +// CHECK-LABEL: define ptr @"main._llgo_routine$2"(ptr %0){{.*}} { +// CHECK-NEXT: _llgo_0: +// CHECK-NEXT: %1 = load { { ptr, ptr } }, ptr %0, align 8 +// CHECK-NEXT: %2 = extractvalue { { ptr, ptr } } %1, 0 +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.FreeRoot"(ptr %0) +// CHECK-NEXT: %3 = extractvalue { ptr, ptr } %2, 1 +// CHECK-NEXT: %4 = extractvalue { ptr, ptr } %2, 0 +// CHECK-NEXT: %__llgo_funcval_code = call ptr asm "", "=r,0"(ptr %4) +// CHECK-NEXT: call void %__llgo_funcval_code(ptr {{(nest|swiftself)}} %3) +// CHECK-NEXT: ret ptr null +// CHECK-NEXT: } diff --git a/cl/_testgo/defer1/in.go b/cl/_testgo/defer1/in.go index 86d2f621ab..3ebfbc1987 100644 --- a/cl/_testgo/defer1/in.go +++ b/cl/_testgo/defer1/in.go @@ -1,10 +1,10 @@ // LITTEST package main -// CHECK-DAG: call ptr @"{{.*}}/runtime/internal/runtime.GetThreadDefer"() -// CHECK-DAG: call void @"{{.*}}/runtime/internal/runtime.SetThreadDefer"(ptr %{{.*}}) -// CHECK-DAG: call i32 @{{.*}}setjmp(ptr %{{.*}}{{.*}}) -// CHECK-DAG: call void @"{{.*}}/runtime/internal/runtime.Rethrow"(ptr %{{.*}}) +// CHECK: {{^}}@{{[0-9]+}} = private unnamed_addr constant [5 x i8] c"hello", align 1{{$}} +// CHECK: {{^}}@{{[0-9]+}} = private unnamed_addr constant [3 x i8] c"bye", align 1{{$}} +// CHECK: {{^}}@{{[0-9]+}} = private unnamed_addr constant [5 x i8] c"world", align 1{{$}} +// CHECK: {{^}}@{{[0-9]+}} = private unnamed_addr constant [2 x i8] c"hi", align 1{{$}} func f(s string) bool { return len(s) > 2 @@ -22,3 +22,217 @@ func main() { } defer println("bye") } + +// CHECK-LABEL: define i1 @main.f(%"{{.*}}/runtime/internal/runtime.String" %0){{.*}} { +// CHECK-NEXT: _llgo_0: +// CHECK-NEXT: %1 = extractvalue %"{{.*}}/runtime/internal/runtime.String" %0, 1 +// CHECK-NEXT: %2 = icmp sgt i64 %1, 2 +// CHECK-NEXT: ret i1 %2 +// CHECK-NEXT: } + +// CHECK-LABEL: define void @main.init(){{.*}} { +// CHECK-NEXT: _llgo_0: +// CHECK-NEXT: %0 = load i1, ptr @"main.init$guard", align 1 +// CHECK-NEXT: br i1 %0, label %_llgo_2, label %_llgo_1 +// CHECK-EMPTY: +// CHECK-NEXT: _llgo_1: ; preds = %_llgo_0 +// CHECK-NEXT: store i1 true, ptr @"main.init$guard", align 1 +// CHECK-NEXT: br label %_llgo_2 +// CHECK-EMPTY: +// CHECK-NEXT: _llgo_2: ; preds = %_llgo_1, %_llgo_0 +// CHECK-NEXT: ret void +// CHECK-NEXT: } + +// CHECK-LABEL: define void @main.main(){{.*}} { +// CHECK-NEXT: _llgo_0: +// CHECK-NEXT: %0 = call ptr @"{{.*}}/runtime/internal/runtime.GetThreadDefer"() +// CHECK-NEXT: %1 = alloca i8 +// CHECK-NEXT: %2 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 48) +// CHECK-NEXT: %3 = getelementptr inbounds %"{{.*}}/runtime/internal/runtime.Defer", ptr %2, i32 0, i32 0 +// CHECK-NEXT: store ptr %1, ptr %3, align 8 +// CHECK-NEXT: %4 = getelementptr inbounds %"{{.*}}/runtime/internal/runtime.Defer", ptr %2, i32 0, i32 1 +// CHECK-NEXT: store i64 0, ptr %4, align 8 +// CHECK-NEXT: %5 = getelementptr inbounds %"{{.*}}/runtime/internal/runtime.Defer", ptr %2, i32 0, i32 2 +// CHECK-NEXT: store ptr %0, ptr %5, align 8 +// CHECK-NEXT: %6 = getelementptr inbounds %"{{.*}}/runtime/internal/runtime.Defer", ptr %2, i32 0, i32 3 +// CHECK-NEXT: store ptr blockaddress(@main.main, %_llgo_4), ptr %6, align 8 +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.SetThreadDefer"(ptr %2) +// CHECK-NEXT: %7 = getelementptr inbounds %"{{.*}}/runtime/internal/runtime.Defer", ptr %2, i32 0, i32 1 +// CHECK-NEXT: %8 = getelementptr inbounds %"{{.*}}/runtime/internal/runtime.Defer", ptr %2, i32 0, i32 3 +// CHECK-NEXT: %9 = getelementptr inbounds %"{{.*}}/runtime/internal/runtime.Defer", ptr %2, i32 0, i32 4 +// CHECK-NEXT: %10 = getelementptr inbounds %"{{.*}}/runtime/internal/runtime.Defer", ptr %2, i32 0, i32 5 +// CHECK-NEXT: store ptr null, ptr %10, align 8 +// CHECK-NEXT: %11 = call i32 @{{(__)?}}sigsetjmp(ptr %1, i32 0) +// CHECK-NEXT: %12 = icmp eq i32 %11, 0 +// CHECK-NEXT: br i1 %12, label %_llgo_6, label %_llgo_7 +// CHECK-EMPTY: +// CHECK-NEXT: _llgo_1: ; preds = %_llgo_5 +// CHECK-NEXT: ret void +// CHECK-EMPTY: +// CHECK-NEXT: _llgo_2: ; preds = %_llgo_6 +// CHECK-NEXT: %13 = load i64, ptr %7, align 8 +// CHECK-NEXT: %14 = or i64 %13, 1 +// CHECK-NEXT: store i64 %14, ptr %7, align 8 +// CHECK-NEXT: %15 = load ptr, ptr %10, align 8 +// CHECK-NEXT: %16 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 32) +// CHECK-NEXT: %17 = getelementptr inbounds { ptr, i64, %"{{.*}}/runtime/internal/runtime.String" }, ptr %16, i32 0, i32 0 +// CHECK-NEXT: store ptr %15, ptr %17, align 8 +// CHECK-NEXT: %18 = getelementptr inbounds { ptr, i64, %"{{.*}}/runtime/internal/runtime.String" }, ptr %16, i32 0, i32 1 +// CHECK-NEXT: store i64 1, ptr %18, align 8 +// CHECK-NEXT: %19 = getelementptr inbounds { ptr, i64, %"{{.*}}/runtime/internal/runtime.String" }, ptr %16, i32 0, i32 2 +// CHECK-NEXT: store %"{{.*}}/runtime/internal/runtime.String" { ptr @{{[0-9]+}}, i64 5 }, ptr %19, align 8 +// CHECK-NEXT: store ptr %16, ptr %10, align 8 +// CHECK-NEXT: %20 = load i64, ptr %7, align 8 +// CHECK-NEXT: %21 = or i64 %20, 2 +// CHECK-NEXT: store i64 %21, ptr %7, align 8 +// CHECK-NEXT: %22 = load ptr, ptr %10, align 8 +// CHECK-NEXT: %23 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 32) +// CHECK-NEXT: %24 = getelementptr inbounds { ptr, i64, %"{{.*}}/runtime/internal/runtime.String" }, ptr %23, i32 0, i32 0 +// CHECK-NEXT: store ptr %22, ptr %24, align 8 +// CHECK-NEXT: %25 = getelementptr inbounds { ptr, i64, %"{{.*}}/runtime/internal/runtime.String" }, ptr %23, i32 0, i32 1 +// CHECK-NEXT: store i64 2, ptr %25, align 8 +// CHECK-NEXT: %26 = getelementptr inbounds { ptr, i64, %"{{.*}}/runtime/internal/runtime.String" }, ptr %23, i32 0, i32 2 +// CHECK-NEXT: store %"{{.*}}/runtime/internal/runtime.String" { ptr @{{[0-9]+}}, i64 3 }, ptr %26, align 8 +// CHECK-NEXT: store ptr %23, ptr %10, align 8 +// CHECK-NEXT: store ptr blockaddress(@main.main, %_llgo_8), ptr %9, align 8 +// CHECK-NEXT: br label %_llgo_4 +// CHECK-EMPTY: +// CHECK-NEXT: _llgo_3: ; preds = %_llgo_6 +// CHECK-NEXT: %27 = load i64, ptr %7, align 8 +// CHECK-NEXT: %28 = or i64 %27, 4 +// CHECK-NEXT: store i64 %28, ptr %7, align 8 +// CHECK-NEXT: %29 = load ptr, ptr %10, align 8 +// CHECK-NEXT: %30 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 32) +// CHECK-NEXT: %31 = getelementptr inbounds { ptr, i64, %"{{.*}}/runtime/internal/runtime.String" }, ptr %30, i32 0, i32 0 +// CHECK-NEXT: store ptr %29, ptr %31, align 8 +// CHECK-NEXT: %32 = getelementptr inbounds { ptr, i64, %"{{.*}}/runtime/internal/runtime.String" }, ptr %30, i32 0, i32 1 +// CHECK-NEXT: store i64 3, ptr %32, align 8 +// CHECK-NEXT: %33 = getelementptr inbounds { ptr, i64, %"{{.*}}/runtime/internal/runtime.String" }, ptr %30, i32 0, i32 2 +// CHECK-NEXT: store %"{{.*}}/runtime/internal/runtime.String" { ptr @{{[0-9]+}}, i64 5 }, ptr %33, align 8 +// CHECK-NEXT: store ptr %30, ptr %10, align 8 +// CHECK-NEXT: store ptr blockaddress(@main.main, %_llgo_9), ptr %9, align 8 +// CHECK-NEXT: br label %_llgo_4 +// CHECK-EMPTY: +// CHECK-NEXT: _llgo_4: ; preds = %_llgo_7, %_llgo_3, %_llgo_2 +// CHECK-NEXT: store ptr blockaddress(@main.main, %_llgo_12), ptr %8, align 8 +// CHECK-NEXT: %34 = load i64, ptr %7, align 8 +// CHECK-NEXT: %35 = and i64 %34, 4 +// CHECK-NEXT: %36 = icmp ne i64 %35, 0 +// CHECK-NEXT: br i1 %36, label %_llgo_13, label %_llgo_14 +// CHECK-EMPTY: +// CHECK-NEXT: _llgo_5: ; preds = %_llgo_7, %_llgo_10 +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.Rethrow"(ptr %0) +// CHECK-NEXT: br label %_llgo_1 +// CHECK-EMPTY: +// CHECK-NEXT: _llgo_6: ; preds = %_llgo_0 +// CHECK-NEXT: %37 = call i1 @main.f(%"{{.*}}/runtime/internal/runtime.String" { ptr @{{[0-9]+}}, i64 5 }) +// CHECK-NEXT: br i1 %37, label %_llgo_2, label %_llgo_3 +// CHECK-EMPTY: +// CHECK-NEXT: _llgo_7: ; preds = %_llgo_0 +// CHECK-NEXT: store ptr blockaddress(@main.main, %_llgo_5), ptr %9, align 8 +// CHECK-NEXT: %38 = load ptr, ptr %8, align 8 +// CHECK-NEXT: indirectbr ptr %38, [label %_llgo_5, label %_llgo_10, label %_llgo_11, label %_llgo_12, label %_llgo_4] +// CHECK-EMPTY: +// CHECK-NEXT: _llgo_8: ; preds = %_llgo_10 +// CHECK-NEXT: ret void +// CHECK-EMPTY: +// CHECK-NEXT: _llgo_9: ; preds = %_llgo_10 +// CHECK-NEXT: ret void +// CHECK-EMPTY: +// CHECK-NEXT: _llgo_10: ; preds = %_llgo_7, %_llgo_22 +// CHECK-NEXT: store ptr blockaddress(@main.main, %_llgo_5), ptr %8, align 8 +// CHECK-NEXT: %39 = load i64, ptr %7, align 8 +// CHECK-NEXT: call void @"main.main$1"() +// CHECK-NEXT: %40 = load %"{{.*}}/runtime/internal/runtime.Defer", ptr %2, align 8 +// CHECK-NEXT: %41 = extractvalue %"{{.*}}/runtime/internal/runtime.Defer" %40, 2 +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.SetThreadDefer"(ptr %41) +// CHECK-NEXT: %42 = load ptr, ptr %9, align 8 +// CHECK-NEXT: indirectbr ptr %42, [label %_llgo_5, label %_llgo_8, label %_llgo_9] +// CHECK-EMPTY: +// CHECK-NEXT: _llgo_11: ; preds = %_llgo_7, %_llgo_18 +// CHECK-NEXT: store ptr blockaddress(@main.main, %_llgo_10), ptr %8, align 8 +// CHECK-NEXT: %43 = load i64, ptr %7, align 8 +// CHECK-NEXT: %44 = and i64 %43, 1 +// CHECK-NEXT: %45 = icmp ne i64 %44, 0 +// CHECK-NEXT: br i1 %45, label %_llgo_21, label %_llgo_22 +// CHECK-EMPTY: +// CHECK-NEXT: _llgo_12: ; preds = %_llgo_7, %_llgo_14 +// CHECK-NEXT: store ptr blockaddress(@main.main, %_llgo_11), ptr %8, align 8 +// CHECK-NEXT: %46 = load i64, ptr %7, align 8 +// CHECK-NEXT: %47 = and i64 %46, 2 +// CHECK-NEXT: %48 = icmp ne i64 %47, 0 +// CHECK-NEXT: br i1 %48, label %_llgo_17, label %_llgo_18 +// CHECK-EMPTY: +// CHECK-NEXT: _llgo_13: ; preds = %_llgo_4 +// CHECK-NEXT: %49 = load ptr, ptr %10, align 8 +// CHECK-NEXT: %50 = icmp ne ptr %49, null +// CHECK-NEXT: br i1 %50, label %_llgo_15, label %_llgo_16 +// CHECK-EMPTY: +// CHECK-NEXT: _llgo_14: ; preds = %_llgo_16, %_llgo_4 +// CHECK-NEXT: br label %_llgo_12 +// CHECK-EMPTY: +// CHECK-NEXT: _llgo_15: ; preds = %_llgo_13 +// CHECK-NEXT: %51 = load ptr, ptr %10, align 8 +// CHECK-NEXT: %52 = load { ptr, i64, %"{{.*}}/runtime/internal/runtime.String" }, ptr %51, align 8 +// CHECK-NEXT: %53 = extractvalue { ptr, i64, %"{{.*}}/runtime/internal/runtime.String" } %52, 0 +// CHECK-NEXT: store ptr %53, ptr %10, align 8 +// CHECK-NEXT: %54 = extractvalue { ptr, i64, %"{{.*}}/runtime/internal/runtime.String" } %52, 2 +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.FreeDeferNode"(ptr %51) +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.PrintString"(%"{{.*}}/runtime/internal/runtime.String" %54) +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.PrintByte"(i8 10) +// CHECK-NEXT: br label %_llgo_16 +// CHECK-EMPTY: +// CHECK-NEXT: _llgo_16: ; preds = %_llgo_15, %_llgo_13 +// CHECK-NEXT: br label %_llgo_14 +// CHECK-EMPTY: +// CHECK-NEXT: _llgo_17: ; preds = %_llgo_12 +// CHECK-NEXT: %55 = load ptr, ptr %10, align 8 +// CHECK-NEXT: %56 = icmp ne ptr %55, null +// CHECK-NEXT: br i1 %56, label %_llgo_19, label %_llgo_20 +// CHECK-EMPTY: +// CHECK-NEXT: _llgo_18: ; preds = %_llgo_20, %_llgo_12 +// CHECK-NEXT: br label %_llgo_11 +// CHECK-EMPTY: +// CHECK-NEXT: _llgo_19: ; preds = %_llgo_17 +// CHECK-NEXT: %57 = load ptr, ptr %10, align 8 +// CHECK-NEXT: %58 = load { ptr, i64, %"{{.*}}/runtime/internal/runtime.String" }, ptr %57, align 8 +// CHECK-NEXT: %59 = extractvalue { ptr, i64, %"{{.*}}/runtime/internal/runtime.String" } %58, 0 +// CHECK-NEXT: store ptr %59, ptr %10, align 8 +// CHECK-NEXT: %60 = extractvalue { ptr, i64, %"{{.*}}/runtime/internal/runtime.String" } %58, 2 +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.FreeDeferNode"(ptr %57) +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.PrintString"(%"{{.*}}/runtime/internal/runtime.String" %60) +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.PrintByte"(i8 10) +// CHECK-NEXT: br label %_llgo_20 +// CHECK-EMPTY: +// CHECK-NEXT: _llgo_20: ; preds = %_llgo_19, %_llgo_17 +// CHECK-NEXT: br label %_llgo_18 +// CHECK-EMPTY: +// CHECK-NEXT: _llgo_21: ; preds = %_llgo_11 +// CHECK-NEXT: %61 = load ptr, ptr %10, align 8 +// CHECK-NEXT: %62 = icmp ne ptr %61, null +// CHECK-NEXT: br i1 %62, label %_llgo_23, label %_llgo_24 +// CHECK-EMPTY: +// CHECK-NEXT: _llgo_22: ; preds = %_llgo_24, %_llgo_11 +// CHECK-NEXT: br label %_llgo_10 +// CHECK-EMPTY: +// CHECK-NEXT: _llgo_23: ; preds = %_llgo_21 +// CHECK-NEXT: %63 = load ptr, ptr %10, align 8 +// CHECK-NEXT: %64 = load { ptr, i64, %"{{.*}}/runtime/internal/runtime.String" }, ptr %63, align 8 +// CHECK-NEXT: %65 = extractvalue { ptr, i64, %"{{.*}}/runtime/internal/runtime.String" } %64, 0 +// CHECK-NEXT: store ptr %65, ptr %10, align 8 +// CHECK-NEXT: %66 = extractvalue { ptr, i64, %"{{.*}}/runtime/internal/runtime.String" } %64, 2 +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.FreeDeferNode"(ptr %63) +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.PrintString"(%"{{.*}}/runtime/internal/runtime.String" %66) +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.PrintByte"(i8 10) +// CHECK-NEXT: br label %_llgo_24 +// CHECK-EMPTY: +// CHECK-NEXT: _llgo_24: ; preds = %_llgo_23, %_llgo_21 +// CHECK-NEXT: br label %_llgo_22 +// CHECK-NEXT: } + +// CHECK-LABEL: define void @"main.main$1"(){{.*}} { +// CHECK-NEXT: _llgo_0: +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.PrintString"(%"{{.*}}/runtime/internal/runtime.String" { ptr @{{[0-9]+}}, i64 2 }) +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.PrintByte"(i8 10) +// CHECK-NEXT: ret void +// CHECK-NEXT: } diff --git a/cl/_testgo/defer2/in.go b/cl/_testgo/defer2/in.go index a37886d57c..08adb62f02 100644 --- a/cl/_testgo/defer2/in.go +++ b/cl/_testgo/defer2/in.go @@ -1,10 +1,9 @@ // LITTEST package main -// CHECK-DAG: call ptr @"{{.*}}/runtime/internal/runtime.GetThreadDefer"() -// CHECK-DAG: call void @"{{.*}}/runtime/internal/runtime.SetThreadDefer"(ptr %{{.*}}) -// CHECK-DAG: call i32 @{{.*}}setjmp(ptr %{{.*}}{{.*}}) -// CHECK-DAG: call void @"{{.*}}/runtime/internal/runtime.Rethrow"(ptr %{{.*}}) +// CHECK: {{^}}@{{[0-9]+}} = private unnamed_addr constant [5 x i8] c"hello", align 1{{$}} +// CHECK: {{^}}@{{[0-9]+}} = private unnamed_addr constant [3 x i8] c"bye", align 1{{$}} +// CHECK: {{^}}@{{[0-9]+}} = private unnamed_addr constant [5 x i8] c"world", align 1{{$}} func f(s string) bool { return len(s) > 2 @@ -19,3 +18,204 @@ func main() { } defer println("bye") } + +// CHECK-LABEL: define i1 @main.f(%"{{.*}}/runtime/internal/runtime.String" %0){{.*}} { +// CHECK-NEXT: _llgo_0: +// CHECK-NEXT: %1 = extractvalue %"{{.*}}/runtime/internal/runtime.String" %0, 1 +// CHECK-NEXT: %2 = icmp sgt i64 %1, 2 +// CHECK-NEXT: ret i1 %2 +// CHECK-NEXT: } + +// CHECK-LABEL: define void @main.init(){{.*}} { +// CHECK-NEXT: _llgo_0: +// CHECK-NEXT: %0 = load i1, ptr @"main.init$guard", align 1 +// CHECK-NEXT: br i1 %0, label %_llgo_2, label %_llgo_1 +// CHECK-EMPTY: +// CHECK-NEXT: _llgo_1: ; preds = %_llgo_0 +// CHECK-NEXT: store i1 true, ptr @"main.init$guard", align 1 +// CHECK-NEXT: br label %_llgo_2 +// CHECK-EMPTY: +// CHECK-NEXT: _llgo_2: ; preds = %_llgo_1, %_llgo_0 +// CHECK-NEXT: ret void +// CHECK-NEXT: } + +// CHECK-LABEL: define void @main.main(){{.*}} { +// CHECK-NEXT: _llgo_0: +// CHECK-NEXT: %0 = call i1 @main.f(%"{{.*}}/runtime/internal/runtime.String" { ptr @{{[0-9]+}}, i64 5 }) +// CHECK-NEXT: %1 = call ptr @"{{.*}}/runtime/internal/runtime.GetThreadDefer"() +// CHECK-NEXT: %2 = alloca i8 +// CHECK-NEXT: %3 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 48) +// CHECK-NEXT: %4 = getelementptr inbounds %"{{.*}}/runtime/internal/runtime.Defer", ptr %3, i32 0, i32 0 +// CHECK-NEXT: store ptr %2, ptr %4, align 8 +// CHECK-NEXT: %5 = getelementptr inbounds %"{{.*}}/runtime/internal/runtime.Defer", ptr %3, i32 0, i32 1 +// CHECK-NEXT: store i64 0, ptr %5, align 8 +// CHECK-NEXT: %6 = getelementptr inbounds %"{{.*}}/runtime/internal/runtime.Defer", ptr %3, i32 0, i32 2 +// CHECK-NEXT: store ptr %1, ptr %6, align 8 +// CHECK-NEXT: %7 = getelementptr inbounds %"{{.*}}/runtime/internal/runtime.Defer", ptr %3, i32 0, i32 3 +// CHECK-NEXT: store ptr blockaddress(@main.main, %_llgo_5), ptr %7, align 8 +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.SetThreadDefer"(ptr %3) +// CHECK-NEXT: %8 = getelementptr inbounds %"{{.*}}/runtime/internal/runtime.Defer", ptr %3, i32 0, i32 1 +// CHECK-NEXT: %9 = getelementptr inbounds %"{{.*}}/runtime/internal/runtime.Defer", ptr %3, i32 0, i32 3 +// CHECK-NEXT: %10 = getelementptr inbounds %"{{.*}}/runtime/internal/runtime.Defer", ptr %3, i32 0, i32 4 +// CHECK-NEXT: %11 = getelementptr inbounds %"{{.*}}/runtime/internal/runtime.Defer", ptr %3, i32 0, i32 5 +// CHECK-NEXT: store ptr null, ptr %11, align 8 +// CHECK-NEXT: %12 = call i32 @{{(__)?}}sigsetjmp(ptr %2, i32 0) +// CHECK-NEXT: %13 = icmp eq i32 %12, 0 +// CHECK-NEXT: br i1 %13, label %_llgo_4, label %_llgo_7 +// CHECK-EMPTY: +// CHECK-NEXT: _llgo_1: ; preds = %_llgo_4 +// CHECK-NEXT: %14 = load i64, ptr %8, align 8 +// CHECK-NEXT: %15 = or i64 %14, 1 +// CHECK-NEXT: store i64 %15, ptr %8, align 8 +// CHECK-NEXT: %16 = load ptr, ptr %11, align 8 +// CHECK-NEXT: %17 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 32) +// CHECK-NEXT: %18 = getelementptr inbounds { ptr, i64, %"{{.*}}/runtime/internal/runtime.String" }, ptr %17, i32 0, i32 0 +// CHECK-NEXT: store ptr %16, ptr %18, align 8 +// CHECK-NEXT: %19 = getelementptr inbounds { ptr, i64, %"{{.*}}/runtime/internal/runtime.String" }, ptr %17, i32 0, i32 1 +// CHECK-NEXT: store i64 0, ptr %19, align 8 +// CHECK-NEXT: %20 = getelementptr inbounds { ptr, i64, %"{{.*}}/runtime/internal/runtime.String" }, ptr %17, i32 0, i32 2 +// CHECK-NEXT: store %"{{.*}}/runtime/internal/runtime.String" { ptr @{{[0-9]+}}, i64 5 }, ptr %20, align 8 +// CHECK-NEXT: store ptr %17, ptr %11, align 8 +// CHECK-NEXT: %21 = load i64, ptr %8, align 8 +// CHECK-NEXT: %22 = or i64 %21, 2 +// CHECK-NEXT: store i64 %22, ptr %8, align 8 +// CHECK-NEXT: %23 = load ptr, ptr %11, align 8 +// CHECK-NEXT: %24 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 32) +// CHECK-NEXT: %25 = getelementptr inbounds { ptr, i64, %"{{.*}}/runtime/internal/runtime.String" }, ptr %24, i32 0, i32 0 +// CHECK-NEXT: store ptr %23, ptr %25, align 8 +// CHECK-NEXT: %26 = getelementptr inbounds { ptr, i64, %"{{.*}}/runtime/internal/runtime.String" }, ptr %24, i32 0, i32 1 +// CHECK-NEXT: store i64 1, ptr %26, align 8 +// CHECK-NEXT: %27 = getelementptr inbounds { ptr, i64, %"{{.*}}/runtime/internal/runtime.String" }, ptr %24, i32 0, i32 2 +// CHECK-NEXT: store %"{{.*}}/runtime/internal/runtime.String" { ptr @{{[0-9]+}}, i64 3 }, ptr %27, align 8 +// CHECK-NEXT: store ptr %24, ptr %11, align 8 +// CHECK-NEXT: store ptr blockaddress(@main.main, %_llgo_8), ptr %10, align 8 +// CHECK-NEXT: br label %_llgo_5 +// CHECK-EMPTY: +// CHECK-NEXT: _llgo_2: ; preds = %_llgo_4 +// CHECK-NEXT: %28 = load i64, ptr %8, align 8 +// CHECK-NEXT: %29 = or i64 %28, 4 +// CHECK-NEXT: store i64 %29, ptr %8, align 8 +// CHECK-NEXT: %30 = load ptr, ptr %11, align 8 +// CHECK-NEXT: %31 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 32) +// CHECK-NEXT: %32 = getelementptr inbounds { ptr, i64, %"{{.*}}/runtime/internal/runtime.String" }, ptr %31, i32 0, i32 0 +// CHECK-NEXT: store ptr %30, ptr %32, align 8 +// CHECK-NEXT: %33 = getelementptr inbounds { ptr, i64, %"{{.*}}/runtime/internal/runtime.String" }, ptr %31, i32 0, i32 1 +// CHECK-NEXT: store i64 2, ptr %33, align 8 +// CHECK-NEXT: %34 = getelementptr inbounds { ptr, i64, %"{{.*}}/runtime/internal/runtime.String" }, ptr %31, i32 0, i32 2 +// CHECK-NEXT: store %"{{.*}}/runtime/internal/runtime.String" { ptr @{{[0-9]+}}, i64 5 }, ptr %34, align 8 +// CHECK-NEXT: store ptr %31, ptr %11, align 8 +// CHECK-NEXT: store ptr blockaddress(@main.main, %_llgo_9), ptr %10, align 8 +// CHECK-NEXT: br label %_llgo_5 +// CHECK-EMPTY: +// CHECK-NEXT: _llgo_3: ; preds = %_llgo_6 +// CHECK-NEXT: ret void +// CHECK-EMPTY: +// CHECK-NEXT: _llgo_4: ; preds = %_llgo_0 +// CHECK-NEXT: br i1 %0, label %_llgo_1, label %_llgo_2 +// CHECK-EMPTY: +// CHECK-NEXT: _llgo_5: ; preds = %_llgo_7, %_llgo_2, %_llgo_1 +// CHECK-NEXT: store ptr blockaddress(@main.main, %_llgo_11), ptr %9, align 8 +// CHECK-NEXT: %35 = load i64, ptr %8, align 8 +// CHECK-NEXT: %36 = and i64 %35, 4 +// CHECK-NEXT: %37 = icmp ne i64 %36, 0 +// CHECK-NEXT: br i1 %37, label %_llgo_12, label %_llgo_13 +// CHECK-EMPTY: +// CHECK-NEXT: _llgo_6: ; preds = %_llgo_7, %_llgo_21 +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.Rethrow"(ptr %1) +// CHECK-NEXT: br label %_llgo_3 +// CHECK-EMPTY: +// CHECK-NEXT: _llgo_7: ; preds = %_llgo_0 +// CHECK-NEXT: store ptr blockaddress(@main.main, %_llgo_6), ptr %10, align 8 +// CHECK-NEXT: %38 = load ptr, ptr %9, align 8 +// CHECK-NEXT: indirectbr ptr %38, [label %_llgo_6, label %_llgo_10, label %_llgo_11, label %_llgo_5] +// CHECK-EMPTY: +// CHECK-NEXT: _llgo_8: ; preds = %_llgo_21 +// CHECK-NEXT: ret void +// CHECK-EMPTY: +// CHECK-NEXT: _llgo_9: ; preds = %_llgo_21 +// CHECK-NEXT: ret void +// CHECK-EMPTY: +// CHECK-NEXT: _llgo_10: ; preds = %_llgo_7, %_llgo_17 +// CHECK-NEXT: store ptr blockaddress(@main.main, %_llgo_6), ptr %9, align 8 +// CHECK-NEXT: %39 = load i64, ptr %8, align 8 +// CHECK-NEXT: %40 = and i64 %39, 1 +// CHECK-NEXT: %41 = icmp ne i64 %40, 0 +// CHECK-NEXT: br i1 %41, label %_llgo_20, label %_llgo_21 +// CHECK-EMPTY: +// CHECK-NEXT: _llgo_11: ; preds = %_llgo_7, %_llgo_13 +// CHECK-NEXT: store ptr blockaddress(@main.main, %_llgo_10), ptr %9, align 8 +// CHECK-NEXT: %42 = load i64, ptr %8, align 8 +// CHECK-NEXT: %43 = and i64 %42, 2 +// CHECK-NEXT: %44 = icmp ne i64 %43, 0 +// CHECK-NEXT: br i1 %44, label %_llgo_16, label %_llgo_17 +// CHECK-EMPTY: +// CHECK-NEXT: _llgo_12: ; preds = %_llgo_5 +// CHECK-NEXT: %45 = load ptr, ptr %11, align 8 +// CHECK-NEXT: %46 = icmp ne ptr %45, null +// CHECK-NEXT: br i1 %46, label %_llgo_14, label %_llgo_15 +// CHECK-EMPTY: +// CHECK-NEXT: _llgo_13: ; preds = %_llgo_15, %_llgo_5 +// CHECK-NEXT: br label %_llgo_11 +// CHECK-EMPTY: +// CHECK-NEXT: _llgo_14: ; preds = %_llgo_12 +// CHECK-NEXT: %47 = load ptr, ptr %11, align 8 +// CHECK-NEXT: %48 = load { ptr, i64, %"{{.*}}/runtime/internal/runtime.String" }, ptr %47, align 8 +// CHECK-NEXT: %49 = extractvalue { ptr, i64, %"{{.*}}/runtime/internal/runtime.String" } %48, 0 +// CHECK-NEXT: store ptr %49, ptr %11, align 8 +// CHECK-NEXT: %50 = extractvalue { ptr, i64, %"{{.*}}/runtime/internal/runtime.String" } %48, 2 +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.FreeDeferNode"(ptr %47) +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.PrintString"(%"{{.*}}/runtime/internal/runtime.String" %50) +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.PrintByte"(i8 10) +// CHECK-NEXT: br label %_llgo_15 +// CHECK-EMPTY: +// CHECK-NEXT: _llgo_15: ; preds = %_llgo_14, %_llgo_12 +// CHECK-NEXT: br label %_llgo_13 +// CHECK-EMPTY: +// CHECK-NEXT: _llgo_16: ; preds = %_llgo_11 +// CHECK-NEXT: %51 = load ptr, ptr %11, align 8 +// CHECK-NEXT: %52 = icmp ne ptr %51, null +// CHECK-NEXT: br i1 %52, label %_llgo_18, label %_llgo_19 +// CHECK-EMPTY: +// CHECK-NEXT: _llgo_17: ; preds = %_llgo_19, %_llgo_11 +// CHECK-NEXT: br label %_llgo_10 +// CHECK-EMPTY: +// CHECK-NEXT: _llgo_18: ; preds = %_llgo_16 +// CHECK-NEXT: %53 = load ptr, ptr %11, align 8 +// CHECK-NEXT: %54 = load { ptr, i64, %"{{.*}}/runtime/internal/runtime.String" }, ptr %53, align 8 +// CHECK-NEXT: %55 = extractvalue { ptr, i64, %"{{.*}}/runtime/internal/runtime.String" } %54, 0 +// CHECK-NEXT: store ptr %55, ptr %11, align 8 +// CHECK-NEXT: %56 = extractvalue { ptr, i64, %"{{.*}}/runtime/internal/runtime.String" } %54, 2 +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.FreeDeferNode"(ptr %53) +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.PrintString"(%"{{.*}}/runtime/internal/runtime.String" %56) +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.PrintByte"(i8 10) +// CHECK-NEXT: br label %_llgo_19 +// CHECK-EMPTY: +// CHECK-NEXT: _llgo_19: ; preds = %_llgo_18, %_llgo_16 +// CHECK-NEXT: br label %_llgo_17 +// CHECK-EMPTY: +// CHECK-NEXT: _llgo_20: ; preds = %_llgo_10 +// CHECK-NEXT: %57 = load ptr, ptr %11, align 8 +// CHECK-NEXT: %58 = icmp ne ptr %57, null +// CHECK-NEXT: br i1 %58, label %_llgo_22, label %_llgo_23 +// CHECK-EMPTY: +// CHECK-NEXT: _llgo_21: ; preds = %_llgo_23, %_llgo_10 +// CHECK-NEXT: %59 = load %"{{.*}}/runtime/internal/runtime.Defer", ptr %3, align 8 +// CHECK-NEXT: %60 = extractvalue %"{{.*}}/runtime/internal/runtime.Defer" %59, 2 +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.SetThreadDefer"(ptr %60) +// CHECK-NEXT: %61 = load ptr, ptr %10, align 8 +// CHECK-NEXT: indirectbr ptr %61, [label %_llgo_6, label %_llgo_8, label %_llgo_9] +// CHECK-EMPTY: +// CHECK-NEXT: _llgo_22: ; preds = %_llgo_20 +// CHECK-NEXT: %62 = load ptr, ptr %11, align 8 +// CHECK-NEXT: %63 = load { ptr, i64, %"{{.*}}/runtime/internal/runtime.String" }, ptr %62, align 8 +// CHECK-NEXT: %64 = extractvalue { ptr, i64, %"{{.*}}/runtime/internal/runtime.String" } %63, 0 +// CHECK-NEXT: store ptr %64, ptr %11, align 8 +// CHECK-NEXT: %65 = extractvalue { ptr, i64, %"{{.*}}/runtime/internal/runtime.String" } %63, 2 +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.FreeDeferNode"(ptr %62) +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.PrintString"(%"{{.*}}/runtime/internal/runtime.String" %65) +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.PrintByte"(i8 10) +// CHECK-NEXT: br label %_llgo_23 +// CHECK-EMPTY: +// CHECK-NEXT: _llgo_23: ; preds = %_llgo_22, %_llgo_20 +// CHECK-NEXT: br label %_llgo_21 +// CHECK-NEXT: } diff --git a/cl/_testgo/defer3/in.go b/cl/_testgo/defer3/in.go index f4172acdc4..f1f9dc77f6 100644 --- a/cl/_testgo/defer3/in.go +++ b/cl/_testgo/defer3/in.go @@ -1,10 +1,12 @@ // LITTEST package main -// CHECK-DAG: call ptr @"{{.*}}/runtime/internal/runtime.GetThreadDefer"() -// CHECK-DAG: call i32 @{{.*}}setjmp(ptr %{{.*}}{{.*}}) -// CHECK-DAG: call void @"{{.*}}/runtime/internal/runtime.Panic"({{.*}}) -// CHECK-DAG: call void @"{{.*}}/runtime/internal/runtime.Rethrow"(ptr %{{.*}}) +// CHECK: {{^}}@{{[0-9]+}} = private unnamed_addr constant [3 x i8] c"bye", align 1{{$}} +// CHECK: {{^}}@{{[0-9]+}} = private unnamed_addr constant [13 x i8] c"panic message", align 1{{$}} +// CHECK: {{^}}@{{[0-9]+}} = private unnamed_addr constant [5 x i8] c"hello", align 1{{$}} +// CHECK: {{^}}@{{[0-9]+}} = private unnamed_addr constant [11 x i8] c"unreachable", align 1{{$}} +// CHECK: {{^}}@{{[0-9]+}} = private unnamed_addr constant [5 x i8] c"world", align 1{{$}} +// CHECK: {{^}}@{{[0-9]+}} = private unnamed_addr constant [2 x i8] c"hi", align 1{{$}} func f(s string) bool { return len(s) > 2 @@ -28,3 +30,256 @@ func main() { fail() println("unreachable") } + +// CHECK-LABEL: define i1 @main.f(%"{{.*}}/runtime/internal/runtime.String" %0){{.*}} { +// CHECK-NEXT: _llgo_0: +// CHECK-NEXT: %1 = extractvalue %"{{.*}}/runtime/internal/runtime.String" %0, 1 +// CHECK-NEXT: %2 = icmp sgt i64 %1, 2 +// CHECK-NEXT: ret i1 %2 +// CHECK-NEXT: } + +// CHECK-LABEL: define void @main.fail(){{.*}} { +// CHECK-NEXT: _llgo_0: +// CHECK-NEXT: %0 = call ptr @"{{.*}}/runtime/internal/runtime.GetThreadDefer"() +// CHECK-NEXT: %1 = alloca i8 +// CHECK-NEXT: %2 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 48) +// CHECK-NEXT: %3 = getelementptr inbounds %"{{.*}}/runtime/internal/runtime.Defer", ptr %2, i32 0, i32 0 +// CHECK-NEXT: store ptr %1, ptr %3, align 8 +// CHECK-NEXT: %4 = getelementptr inbounds %"{{.*}}/runtime/internal/runtime.Defer", ptr %2, i32 0, i32 1 +// CHECK-NEXT: store i64 0, ptr %4, align 8 +// CHECK-NEXT: %5 = getelementptr inbounds %"{{.*}}/runtime/internal/runtime.Defer", ptr %2, i32 0, i32 2 +// CHECK-NEXT: store ptr %0, ptr %5, align 8 +// CHECK-NEXT: %6 = getelementptr inbounds %"{{.*}}/runtime/internal/runtime.Defer", ptr %2, i32 0, i32 3 +// CHECK-NEXT: store ptr blockaddress(@main.fail, %_llgo_2), ptr %6, align 8 +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.SetThreadDefer"(ptr %2) +// CHECK-NEXT: %7 = getelementptr inbounds %"{{.*}}/runtime/internal/runtime.Defer", ptr %2, i32 0, i32 1 +// CHECK-NEXT: %8 = getelementptr inbounds %"{{.*}}/runtime/internal/runtime.Defer", ptr %2, i32 0, i32 3 +// CHECK-NEXT: %9 = getelementptr inbounds %"{{.*}}/runtime/internal/runtime.Defer", ptr %2, i32 0, i32 4 +// CHECK-NEXT: %10 = getelementptr inbounds %"{{.*}}/runtime/internal/runtime.Defer", ptr %2, i32 0, i32 5 +// CHECK-NEXT: store ptr null, ptr %10, align 8 +// CHECK-NEXT: %11 = call i32 @{{(__)?}}sigsetjmp(ptr %1, i32 0) +// CHECK-NEXT: %12 = icmp eq i32 %11, 0 +// CHECK-NEXT: br i1 %12, label %_llgo_4, label %_llgo_5 +// CHECK-EMPTY: +// CHECK-NEXT: _llgo_1: ; preds = %_llgo_3 +// CHECK-NEXT: ret void +// CHECK-EMPTY: +// CHECK-NEXT: _llgo_2: ; preds = %_llgo_5 +// CHECK-NEXT: store ptr blockaddress(@main.fail, %_llgo_3), ptr %8, align 8 +// CHECK-NEXT: %13 = load i64, ptr %7, align 8 +// CHECK-NEXT: %14 = load ptr, ptr %10, align 8 +// CHECK-NEXT: %15 = icmp ne ptr %14, null +// CHECK-NEXT: br i1 %15, label %_llgo_6, label %_llgo_7 +// CHECK-EMPTY: +// CHECK-NEXT: _llgo_3: ; preds = %_llgo_5, %_llgo_7 +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.Rethrow"(ptr %0) +// CHECK-NEXT: br label %_llgo_1 +// CHECK-EMPTY: +// CHECK-NEXT: _llgo_4: ; preds = %_llgo_0 +// CHECK-NEXT: %16 = load ptr, ptr %10, align 8 +// CHECK-NEXT: %17 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 32) +// CHECK-NEXT: %18 = getelementptr inbounds { ptr, i64, %"{{.*}}/runtime/internal/runtime.String" }, ptr %17, i32 0, i32 0 +// CHECK-NEXT: store ptr %16, ptr %18, align 8 +// CHECK-NEXT: %19 = getelementptr inbounds { ptr, i64, %"{{.*}}/runtime/internal/runtime.String" }, ptr %17, i32 0, i32 1 +// CHECK-NEXT: store i64 0, ptr %19, align 8 +// CHECK-NEXT: %20 = getelementptr inbounds { ptr, i64, %"{{.*}}/runtime/internal/runtime.String" }, ptr %17, i32 0, i32 2 +// CHECK-NEXT: store %"{{.*}}/runtime/internal/runtime.String" { ptr @{{[0-9]+}}, i64 3 }, ptr %20, align 8 +// CHECK-NEXT: store ptr %17, ptr %10, align 8 +// CHECK-NEXT: %21 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 16) +// CHECK-NEXT: store %"{{.*}}/runtime/internal/runtime.String" { ptr @{{[0-9]+}}, i64 13 }, ptr %21, align 8 +// CHECK-NEXT: %22 = insertvalue %"{{.*}}/runtime/internal/runtime.eface" { ptr @_llgo_string, ptr undef }, ptr %21, 1 +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.Panic"(%"{{.*}}/runtime/internal/runtime.eface" %22) +// CHECK-NEXT: unreachable +// CHECK-EMPTY: +// CHECK-NEXT: _llgo_5: ; preds = %_llgo_0 +// CHECK-NEXT: store ptr blockaddress(@main.fail, %_llgo_3), ptr %9, align 8 +// CHECK-NEXT: %23 = load ptr, ptr %8, align 8 +// CHECK-NEXT: indirectbr ptr %23, [label %_llgo_3, label %_llgo_2] +// CHECK-EMPTY: +// CHECK-NEXT: _llgo_6: ; preds = %_llgo_2 +// CHECK-NEXT: %24 = load ptr, ptr %10, align 8 +// CHECK-NEXT: %25 = load { ptr, i64, %"{{.*}}/runtime/internal/runtime.String" }, ptr %24, align 8 +// CHECK-NEXT: %26 = extractvalue { ptr, i64, %"{{.*}}/runtime/internal/runtime.String" } %25, 0 +// CHECK-NEXT: store ptr %26, ptr %10, align 8 +// CHECK-NEXT: %27 = extractvalue { ptr, i64, %"{{.*}}/runtime/internal/runtime.String" } %25, 2 +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.FreeDeferNode"(ptr %24) +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.PrintString"(%"{{.*}}/runtime/internal/runtime.String" %27) +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.PrintByte"(i8 10) +// CHECK-NEXT: br label %_llgo_7 +// CHECK-EMPTY: +// CHECK-NEXT: _llgo_7: ; preds = %_llgo_6, %_llgo_2 +// CHECK-NEXT: %28 = load %"{{.*}}/runtime/internal/runtime.Defer", ptr %2, align 8 +// CHECK-NEXT: %29 = extractvalue %"{{.*}}/runtime/internal/runtime.Defer" %28, 2 +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.SetThreadDefer"(ptr %29) +// CHECK-NEXT: %30 = load ptr, ptr %9, align 8 +// CHECK-NEXT: indirectbr ptr %30, [label %_llgo_3] +// CHECK-NEXT: } + +// CHECK-LABEL: define void @main.init(){{.*}} { +// CHECK-NEXT: _llgo_0: +// CHECK-NEXT: %0 = load i1, ptr @"main.init$guard", align 1 +// CHECK-NEXT: br i1 %0, label %_llgo_2, label %_llgo_1 +// CHECK-EMPTY: +// CHECK-NEXT: _llgo_1: ; preds = %_llgo_0 +// CHECK-NEXT: store i1 true, ptr @"main.init$guard", align 1 +// CHECK-NEXT: br label %_llgo_2 +// CHECK-EMPTY: +// CHECK-NEXT: _llgo_2: ; preds = %_llgo_1, %_llgo_0 +// CHECK-NEXT: ret void +// CHECK-NEXT: } + +// CHECK-LABEL: define void @main.main(){{.*}} { +// CHECK-NEXT: _llgo_0: +// CHECK-NEXT: %0 = call ptr @"{{.*}}/runtime/internal/runtime.GetThreadDefer"() +// CHECK-NEXT: %1 = alloca i8 +// CHECK-NEXT: %2 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 48) +// CHECK-NEXT: %3 = getelementptr inbounds %"{{.*}}/runtime/internal/runtime.Defer", ptr %2, i32 0, i32 0 +// CHECK-NEXT: store ptr %1, ptr %3, align 8 +// CHECK-NEXT: %4 = getelementptr inbounds %"{{.*}}/runtime/internal/runtime.Defer", ptr %2, i32 0, i32 1 +// CHECK-NEXT: store i64 0, ptr %4, align 8 +// CHECK-NEXT: %5 = getelementptr inbounds %"{{.*}}/runtime/internal/runtime.Defer", ptr %2, i32 0, i32 2 +// CHECK-NEXT: store ptr %0, ptr %5, align 8 +// CHECK-NEXT: %6 = getelementptr inbounds %"{{.*}}/runtime/internal/runtime.Defer", ptr %2, i32 0, i32 3 +// CHECK-NEXT: store ptr blockaddress(@main.main, %_llgo_4), ptr %6, align 8 +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.SetThreadDefer"(ptr %2) +// CHECK-NEXT: %7 = getelementptr inbounds %"{{.*}}/runtime/internal/runtime.Defer", ptr %2, i32 0, i32 1 +// CHECK-NEXT: %8 = getelementptr inbounds %"{{.*}}/runtime/internal/runtime.Defer", ptr %2, i32 0, i32 3 +// CHECK-NEXT: %9 = getelementptr inbounds %"{{.*}}/runtime/internal/runtime.Defer", ptr %2, i32 0, i32 4 +// CHECK-NEXT: %10 = getelementptr inbounds %"{{.*}}/runtime/internal/runtime.Defer", ptr %2, i32 0, i32 5 +// CHECK-NEXT: store ptr null, ptr %10, align 8 +// CHECK-NEXT: %11 = call i32 @{{(__)?}}sigsetjmp(ptr %1, i32 0) +// CHECK-NEXT: %12 = icmp eq i32 %11, 0 +// CHECK-NEXT: br i1 %12, label %_llgo_6, label %_llgo_7 +// CHECK-EMPTY: +// CHECK-NEXT: _llgo_1: ; preds = %_llgo_5 +// CHECK-NEXT: ret void +// CHECK-EMPTY: +// CHECK-NEXT: _llgo_2: ; preds = %_llgo_6 +// CHECK-NEXT: %13 = load i64, ptr %7, align 8 +// CHECK-NEXT: %14 = or i64 %13, 1 +// CHECK-NEXT: store i64 %14, ptr %7, align 8 +// CHECK-NEXT: %15 = load ptr, ptr %10, align 8 +// CHECK-NEXT: %16 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 32) +// CHECK-NEXT: %17 = getelementptr inbounds { ptr, i64, %"{{.*}}/runtime/internal/runtime.String" }, ptr %16, i32 0, i32 0 +// CHECK-NEXT: store ptr %15, ptr %17, align 8 +// CHECK-NEXT: %18 = getelementptr inbounds { ptr, i64, %"{{.*}}/runtime/internal/runtime.String" }, ptr %16, i32 0, i32 1 +// CHECK-NEXT: store i64 1, ptr %18, align 8 +// CHECK-NEXT: %19 = getelementptr inbounds { ptr, i64, %"{{.*}}/runtime/internal/runtime.String" }, ptr %16, i32 0, i32 2 +// CHECK-NEXT: store %"{{.*}}/runtime/internal/runtime.String" { ptr @{{[0-9]+}}, i64 5 }, ptr %19, align 8 +// CHECK-NEXT: store ptr %16, ptr %10, align 8 +// CHECK-NEXT: call void @main.fail() +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.PrintString"(%"{{.*}}/runtime/internal/runtime.String" { ptr @{{[0-9]+}}, i64 11 }) +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.PrintByte"(i8 10) +// CHECK-NEXT: store ptr blockaddress(@main.main, %_llgo_8), ptr %9, align 8 +// CHECK-NEXT: br label %_llgo_4 +// CHECK-EMPTY: +// CHECK-NEXT: _llgo_3: ; preds = %_llgo_6 +// CHECK-NEXT: %20 = load i64, ptr %7, align 8 +// CHECK-NEXT: %21 = or i64 %20, 2 +// CHECK-NEXT: store i64 %21, ptr %7, align 8 +// CHECK-NEXT: %22 = load ptr, ptr %10, align 8 +// CHECK-NEXT: %23 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 32) +// CHECK-NEXT: %24 = getelementptr inbounds { ptr, i64, %"{{.*}}/runtime/internal/runtime.String" }, ptr %23, i32 0, i32 0 +// CHECK-NEXT: store ptr %22, ptr %24, align 8 +// CHECK-NEXT: %25 = getelementptr inbounds { ptr, i64, %"{{.*}}/runtime/internal/runtime.String" }, ptr %23, i32 0, i32 1 +// CHECK-NEXT: store i64 2, ptr %25, align 8 +// CHECK-NEXT: %26 = getelementptr inbounds { ptr, i64, %"{{.*}}/runtime/internal/runtime.String" }, ptr %23, i32 0, i32 2 +// CHECK-NEXT: store %"{{.*}}/runtime/internal/runtime.String" { ptr @{{[0-9]+}}, i64 5 }, ptr %26, align 8 +// CHECK-NEXT: store ptr %23, ptr %10, align 8 +// CHECK-NEXT: store ptr blockaddress(@main.main, %_llgo_9), ptr %9, align 8 +// CHECK-NEXT: br label %_llgo_4 +// CHECK-EMPTY: +// CHECK-NEXT: _llgo_4: ; preds = %_llgo_7, %_llgo_3, %_llgo_2 +// CHECK-NEXT: store ptr blockaddress(@main.main, %_llgo_11), ptr %8, align 8 +// CHECK-NEXT: %27 = load i64, ptr %7, align 8 +// CHECK-NEXT: %28 = and i64 %27, 2 +// CHECK-NEXT: %29 = icmp ne i64 %28, 0 +// CHECK-NEXT: br i1 %29, label %_llgo_12, label %_llgo_13 +// CHECK-EMPTY: +// CHECK-NEXT: _llgo_5: ; preds = %_llgo_7, %_llgo_10 +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.Rethrow"(ptr %0) +// CHECK-NEXT: br label %_llgo_1 +// CHECK-EMPTY: +// CHECK-NEXT: _llgo_6: ; preds = %_llgo_0 +// CHECK-NEXT: %30 = call i1 @main.f(%"{{.*}}/runtime/internal/runtime.String" { ptr @{{[0-9]+}}, i64 5 }) +// CHECK-NEXT: br i1 %30, label %_llgo_2, label %_llgo_3 +// CHECK-EMPTY: +// CHECK-NEXT: _llgo_7: ; preds = %_llgo_0 +// CHECK-NEXT: store ptr blockaddress(@main.main, %_llgo_5), ptr %9, align 8 +// CHECK-NEXT: %31 = load ptr, ptr %8, align 8 +// CHECK-NEXT: indirectbr ptr %31, [label %_llgo_5, label %_llgo_10, label %_llgo_11, label %_llgo_4] +// CHECK-EMPTY: +// CHECK-NEXT: _llgo_8: ; preds = %_llgo_10 +// CHECK-NEXT: ret void +// CHECK-EMPTY: +// CHECK-NEXT: _llgo_9: ; preds = %_llgo_10 +// CHECK-NEXT: ret void +// CHECK-EMPTY: +// CHECK-NEXT: _llgo_10: ; preds = %_llgo_7, %_llgo_17 +// CHECK-NEXT: store ptr blockaddress(@main.main, %_llgo_5), ptr %8, align 8 +// CHECK-NEXT: %32 = load i64, ptr %7, align 8 +// CHECK-NEXT: call void @"main.main$1"() +// CHECK-NEXT: %33 = load %"{{.*}}/runtime/internal/runtime.Defer", ptr %2, align 8 +// CHECK-NEXT: %34 = extractvalue %"{{.*}}/runtime/internal/runtime.Defer" %33, 2 +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.SetThreadDefer"(ptr %34) +// CHECK-NEXT: %35 = load ptr, ptr %9, align 8 +// CHECK-NEXT: indirectbr ptr %35, [label %_llgo_5, label %_llgo_8, label %_llgo_9] +// CHECK-EMPTY: +// CHECK-NEXT: _llgo_11: ; preds = %_llgo_7, %_llgo_13 +// CHECK-NEXT: store ptr blockaddress(@main.main, %_llgo_10), ptr %8, align 8 +// CHECK-NEXT: %36 = load i64, ptr %7, align 8 +// CHECK-NEXT: %37 = and i64 %36, 1 +// CHECK-NEXT: %38 = icmp ne i64 %37, 0 +// CHECK-NEXT: br i1 %38, label %_llgo_16, label %_llgo_17 +// CHECK-EMPTY: +// CHECK-NEXT: _llgo_12: ; preds = %_llgo_4 +// CHECK-NEXT: %39 = load ptr, ptr %10, align 8 +// CHECK-NEXT: %40 = icmp ne ptr %39, null +// CHECK-NEXT: br i1 %40, label %_llgo_14, label %_llgo_15 +// CHECK-EMPTY: +// CHECK-NEXT: _llgo_13: ; preds = %_llgo_15, %_llgo_4 +// CHECK-NEXT: br label %_llgo_11 +// CHECK-EMPTY: +// CHECK-NEXT: _llgo_14: ; preds = %_llgo_12 +// CHECK-NEXT: %41 = load ptr, ptr %10, align 8 +// CHECK-NEXT: %42 = load { ptr, i64, %"{{.*}}/runtime/internal/runtime.String" }, ptr %41, align 8 +// CHECK-NEXT: %43 = extractvalue { ptr, i64, %"{{.*}}/runtime/internal/runtime.String" } %42, 0 +// CHECK-NEXT: store ptr %43, ptr %10, align 8 +// CHECK-NEXT: %44 = extractvalue { ptr, i64, %"{{.*}}/runtime/internal/runtime.String" } %42, 2 +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.FreeDeferNode"(ptr %41) +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.PrintString"(%"{{.*}}/runtime/internal/runtime.String" %44) +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.PrintByte"(i8 10) +// CHECK-NEXT: br label %_llgo_15 +// CHECK-EMPTY: +// CHECK-NEXT: _llgo_15: ; preds = %_llgo_14, %_llgo_12 +// CHECK-NEXT: br label %_llgo_13 +// CHECK-EMPTY: +// CHECK-NEXT: _llgo_16: ; preds = %_llgo_11 +// CHECK-NEXT: %45 = load ptr, ptr %10, align 8 +// CHECK-NEXT: %46 = icmp ne ptr %45, null +// CHECK-NEXT: br i1 %46, label %_llgo_18, label %_llgo_19 +// CHECK-EMPTY: +// CHECK-NEXT: _llgo_17: ; preds = %_llgo_19, %_llgo_11 +// CHECK-NEXT: br label %_llgo_10 +// CHECK-EMPTY: +// CHECK-NEXT: _llgo_18: ; preds = %_llgo_16 +// CHECK-NEXT: %47 = load ptr, ptr %10, align 8 +// CHECK-NEXT: %48 = load { ptr, i64, %"{{.*}}/runtime/internal/runtime.String" }, ptr %47, align 8 +// CHECK-NEXT: %49 = extractvalue { ptr, i64, %"{{.*}}/runtime/internal/runtime.String" } %48, 0 +// CHECK-NEXT: store ptr %49, ptr %10, align 8 +// CHECK-NEXT: %50 = extractvalue { ptr, i64, %"{{.*}}/runtime/internal/runtime.String" } %48, 2 +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.FreeDeferNode"(ptr %47) +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.PrintString"(%"{{.*}}/runtime/internal/runtime.String" %50) +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.PrintByte"(i8 10) +// CHECK-NEXT: br label %_llgo_19 +// CHECK-EMPTY: +// CHECK-NEXT: _llgo_19: ; preds = %_llgo_18, %_llgo_16 +// CHECK-NEXT: br label %_llgo_17 +// CHECK-NEXT: } + +// CHECK-LABEL: define void @"main.main$1"(){{.*}} { +// CHECK-NEXT: _llgo_0: +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.PrintString"(%"{{.*}}/runtime/internal/runtime.String" { ptr @{{[0-9]+}}, i64 2 }) +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.PrintByte"(i8 10) +// CHECK-NEXT: ret void +// CHECK-NEXT: } diff --git a/cl/_testgo/defer4/in.go b/cl/_testgo/defer4/in.go index 2fa0df8a2c..583580903e 100644 --- a/cl/_testgo/defer4/in.go +++ b/cl/_testgo/defer4/in.go @@ -1,10 +1,14 @@ // LITTEST package main -// CHECK-DAG: call ptr @"{{.*}}/runtime/internal/runtime.GetThreadDefer"() -// CHECK-DAG: call i32 @{{.*}}setjmp(ptr %{{.*}}{{.*}}) -// CHECK-DAG: call %"{{.*}}/runtime/internal/runtime.eface" @"{{.*}}/runtime/internal/runtime.Recover"() -// CHECK-DAG: call void @"{{.*}}/runtime/internal/runtime.Panic"({{.*}}) +// CHECK: {{^}}@{{[0-9]+}} = private unnamed_addr constant [3 x i8] c"bye", align 1{{$}} +// CHECK: {{^}}@{{[0-9]+}} = private unnamed_addr constant [13 x i8] c"panic message", align 1{{$}} +// CHECK: {{^}}@{{[0-9]+}} = private unnamed_addr constant [6 x i8] c"string", align 1{{$}} +// CHECK: {{^}}@{{[0-9]+}} = private unnamed_addr constant [8 x i8] c"recover:", align 1{{$}} +// CHECK: {{^}}@{{[0-9]+}} = private unnamed_addr constant [5 x i8] c"hello", align 1{{$}} +// CHECK: {{^}}@{{[0-9]+}} = private unnamed_addr constant [9 x i8] c"reachable", align 1{{$}} +// CHECK: {{^}}@{{[0-9]+}} = private unnamed_addr constant [5 x i8] c"world", align 1{{$}} +// CHECK: {{^}}@{{[0-9]+}} = private unnamed_addr constant [2 x i8] c"hi", align 1{{$}} func f(s string) bool { return len(s) > 2 @@ -33,3 +37,291 @@ func main() { fail() println("reachable") } + +// CHECK-LABEL: define i1 @main.f(%"{{.*}}/runtime/internal/runtime.String" %0){{.*}} { +// CHECK-NEXT: _llgo_0: +// CHECK-NEXT: %1 = extractvalue %"{{.*}}/runtime/internal/runtime.String" %0, 1 +// CHECK-NEXT: %2 = icmp sgt i64 %1, 2 +// CHECK-NEXT: ret i1 %2 +// CHECK-NEXT: } + +// CHECK-LABEL: define void @main.fail(){{.*}} { +// CHECK-NEXT: _llgo_0: +// CHECK-NEXT: %0 = call ptr @"{{.*}}/runtime/internal/runtime.GetThreadDefer"() +// CHECK-NEXT: %1 = alloca i8 +// CHECK-NEXT: %2 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 48) +// CHECK-NEXT: %3 = getelementptr inbounds %"{{.*}}/runtime/internal/runtime.Defer", ptr %2, i32 0, i32 0 +// CHECK-NEXT: store ptr %1, ptr %3, align 8 +// CHECK-NEXT: %4 = getelementptr inbounds %"{{.*}}/runtime/internal/runtime.Defer", ptr %2, i32 0, i32 1 +// CHECK-NEXT: store i64 0, ptr %4, align 8 +// CHECK-NEXT: %5 = getelementptr inbounds %"{{.*}}/runtime/internal/runtime.Defer", ptr %2, i32 0, i32 2 +// CHECK-NEXT: store ptr %0, ptr %5, align 8 +// CHECK-NEXT: %6 = getelementptr inbounds %"{{.*}}/runtime/internal/runtime.Defer", ptr %2, i32 0, i32 3 +// CHECK-NEXT: store ptr blockaddress(@main.fail, %_llgo_2), ptr %6, align 8 +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.SetThreadDefer"(ptr %2) +// CHECK-NEXT: %7 = getelementptr inbounds %"{{.*}}/runtime/internal/runtime.Defer", ptr %2, i32 0, i32 1 +// CHECK-NEXT: %8 = getelementptr inbounds %"{{.*}}/runtime/internal/runtime.Defer", ptr %2, i32 0, i32 3 +// CHECK-NEXT: %9 = getelementptr inbounds %"{{.*}}/runtime/internal/runtime.Defer", ptr %2, i32 0, i32 4 +// CHECK-NEXT: %10 = getelementptr inbounds %"{{.*}}/runtime/internal/runtime.Defer", ptr %2, i32 0, i32 5 +// CHECK-NEXT: store ptr null, ptr %10, align 8 +// CHECK-NEXT: %11 = call i32 @{{(__)?}}sigsetjmp(ptr %1, i32 0) +// CHECK-NEXT: %12 = icmp eq i32 %11, 0 +// CHECK-NEXT: br i1 %12, label %_llgo_4, label %_llgo_5 +// CHECK-EMPTY: +// CHECK-NEXT: _llgo_1: ; preds = %_llgo_3 +// CHECK-NEXT: ret void +// CHECK-EMPTY: +// CHECK-NEXT: _llgo_2: ; preds = %_llgo_5 +// CHECK-NEXT: store ptr blockaddress(@main.fail, %_llgo_6), ptr %8, align 8 +// CHECK-NEXT: %13 = load i64, ptr %7, align 8 +// CHECK-NEXT: call void @"main.fail$1"() +// CHECK-NEXT: br label %_llgo_6 +// CHECK-EMPTY: +// CHECK-NEXT: _llgo_3: ; preds = %_llgo_5, %_llgo_8 +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.Rethrow"(ptr %0) +// CHECK-NEXT: br label %_llgo_1 +// CHECK-EMPTY: +// CHECK-NEXT: _llgo_4: ; preds = %_llgo_0 +// CHECK-NEXT: %14 = load ptr, ptr %10, align 8 +// CHECK-NEXT: %15 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 32) +// CHECK-NEXT: %16 = getelementptr inbounds { ptr, i64, %"{{.*}}/runtime/internal/runtime.String" }, ptr %15, i32 0, i32 0 +// CHECK-NEXT: store ptr %14, ptr %16, align 8 +// CHECK-NEXT: %17 = getelementptr inbounds { ptr, i64, %"{{.*}}/runtime/internal/runtime.String" }, ptr %15, i32 0, i32 1 +// CHECK-NEXT: store i64 0, ptr %17, align 8 +// CHECK-NEXT: %18 = getelementptr inbounds { ptr, i64, %"{{.*}}/runtime/internal/runtime.String" }, ptr %15, i32 0, i32 2 +// CHECK-NEXT: store %"{{.*}}/runtime/internal/runtime.String" { ptr @{{[0-9]+}}, i64 3 }, ptr %18, align 8 +// CHECK-NEXT: store ptr %15, ptr %10, align 8 +// CHECK-NEXT: %19 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 16) +// CHECK-NEXT: store %"{{.*}}/runtime/internal/runtime.String" { ptr @{{[0-9]+}}, i64 13 }, ptr %19, align 8 +// CHECK-NEXT: %20 = insertvalue %"{{.*}}/runtime/internal/runtime.eface" { ptr @_llgo_string, ptr undef }, ptr %19, 1 +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.Panic"(%"{{.*}}/runtime/internal/runtime.eface" %20) +// CHECK-NEXT: unreachable +// CHECK-EMPTY: +// CHECK-NEXT: _llgo_5: ; preds = %_llgo_0 +// CHECK-NEXT: store ptr blockaddress(@main.fail, %_llgo_3), ptr %9, align 8 +// CHECK-NEXT: %21 = load ptr, ptr %8, align 8 +// CHECK-NEXT: indirectbr ptr %21, [label %_llgo_3, label %_llgo_6, label %_llgo_2] +// CHECK-EMPTY: +// CHECK-NEXT: _llgo_6: ; preds = %_llgo_5, %_llgo_2 +// CHECK-NEXT: store ptr blockaddress(@main.fail, %_llgo_3), ptr %8, align 8 +// CHECK-NEXT: %22 = load i64, ptr %7, align 8 +// CHECK-NEXT: %23 = load ptr, ptr %10, align 8 +// CHECK-NEXT: %24 = icmp ne ptr %23, null +// CHECK-NEXT: br i1 %24, label %_llgo_7, label %_llgo_8 +// CHECK-EMPTY: +// CHECK-NEXT: _llgo_7: ; preds = %_llgo_6 +// CHECK-NEXT: %25 = load ptr, ptr %10, align 8 +// CHECK-NEXT: %26 = load { ptr, i64, %"{{.*}}/runtime/internal/runtime.String" }, ptr %25, align 8 +// CHECK-NEXT: %27 = extractvalue { ptr, i64, %"{{.*}}/runtime/internal/runtime.String" } %26, 0 +// CHECK-NEXT: store ptr %27, ptr %10, align 8 +// CHECK-NEXT: %28 = extractvalue { ptr, i64, %"{{.*}}/runtime/internal/runtime.String" } %26, 2 +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.FreeDeferNode"(ptr %25) +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.PrintString"(%"{{.*}}/runtime/internal/runtime.String" %28) +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.PrintByte"(i8 10) +// CHECK-NEXT: br label %_llgo_8 +// CHECK-EMPTY: +// CHECK-NEXT: _llgo_8: ; preds = %_llgo_7, %_llgo_6 +// CHECK-NEXT: %29 = load %"{{.*}}/runtime/internal/runtime.Defer", ptr %2, align 8 +// CHECK-NEXT: %30 = extractvalue %"{{.*}}/runtime/internal/runtime.Defer" %29, 2 +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.SetThreadDefer"(ptr %30) +// CHECK-NEXT: %31 = load ptr, ptr %9, align 8 +// CHECK-NEXT: indirectbr ptr %31, [label %_llgo_3] +// CHECK-NEXT: } + +// CHECK-LABEL: define void @"main.fail$1"(){{.*}} { +// CHECK-NEXT: _llgo_0: +// CHECK-NEXT: %0 = call %"{{.*}}/runtime/internal/runtime.eface" @"{{.*}}/runtime/internal/runtime.Recover"() +// CHECK-NEXT: %1 = call i1 @"{{.*}}/runtime/internal/runtime.EfaceEqual"(%"{{.*}}/runtime/internal/runtime.eface" %0, %"{{.*}}/runtime/internal/runtime.eface" zeroinitializer) +// CHECK-NEXT: %2 = xor i1 %1, true +// CHECK-NEXT: br i1 %2, label %_llgo_1, label %_llgo_2 +// CHECK-EMPTY: +// CHECK-NEXT: _llgo_1: ; preds = %_llgo_0 +// CHECK-NEXT: %3 = extractvalue %"{{.*}}/runtime/internal/runtime.eface" %0, 0 +// CHECK-NEXT: %4 = icmp eq ptr %3, @_llgo_string +// CHECK-NEXT: br i1 %4, label %_llgo_3, label %_llgo_4 +// CHECK-EMPTY: +// CHECK-NEXT: _llgo_2: ; preds = %_llgo_3, %_llgo_0 +// CHECK-NEXT: ret void +// CHECK-EMPTY: +// CHECK-NEXT: _llgo_3: ; preds = %_llgo_1 +// CHECK-NEXT: %5 = extractvalue %"{{.*}}/runtime/internal/runtime.eface" %0, 1 +// CHECK-NEXT: %6 = load %"{{.*}}/runtime/internal/runtime.String", ptr %5, align 8 +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.PrintString"(%"{{.*}}/runtime/internal/runtime.String" { ptr @{{[0-9]+}}, i64 8 }) +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.PrintByte"(i8 32) +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.PrintString"(%"{{.*}}/runtime/internal/runtime.String" %6) +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.PrintByte"(i8 10) +// CHECK-NEXT: br label %_llgo_2 +// CHECK-EMPTY: +// CHECK-NEXT: _llgo_4: ; preds = %_llgo_1 +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.PanicTypeAssert"(ptr %3, %"{{.*}}/runtime/internal/runtime.String" { ptr @{{[0-9]+}}, i64 6 }, %"{{.*}}/runtime/internal/runtime.String" zeroinitializer) +// CHECK-NEXT: unreachable +// CHECK-NEXT: } + +// CHECK-LABEL: define void @main.init(){{.*}} { +// CHECK-NEXT: _llgo_0: +// CHECK-NEXT: %0 = load i1, ptr @"main.init$guard", align 1 +// CHECK-NEXT: br i1 %0, label %_llgo_2, label %_llgo_1 +// CHECK-EMPTY: +// CHECK-NEXT: _llgo_1: ; preds = %_llgo_0 +// CHECK-NEXT: store i1 true, ptr @"main.init$guard", align 1 +// CHECK-NEXT: br label %_llgo_2 +// CHECK-EMPTY: +// CHECK-NEXT: _llgo_2: ; preds = %_llgo_1, %_llgo_0 +// CHECK-NEXT: ret void +// CHECK-NEXT: } + +// CHECK-LABEL: define void @main.main(){{.*}} { +// CHECK-NEXT: _llgo_0: +// CHECK-NEXT: %0 = call ptr @"{{.*}}/runtime/internal/runtime.GetThreadDefer"() +// CHECK-NEXT: %1 = alloca i8 +// CHECK-NEXT: %2 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 48) +// CHECK-NEXT: %3 = getelementptr inbounds %"{{.*}}/runtime/internal/runtime.Defer", ptr %2, i32 0, i32 0 +// CHECK-NEXT: store ptr %1, ptr %3, align 8 +// CHECK-NEXT: %4 = getelementptr inbounds %"{{.*}}/runtime/internal/runtime.Defer", ptr %2, i32 0, i32 1 +// CHECK-NEXT: store i64 0, ptr %4, align 8 +// CHECK-NEXT: %5 = getelementptr inbounds %"{{.*}}/runtime/internal/runtime.Defer", ptr %2, i32 0, i32 2 +// CHECK-NEXT: store ptr %0, ptr %5, align 8 +// CHECK-NEXT: %6 = getelementptr inbounds %"{{.*}}/runtime/internal/runtime.Defer", ptr %2, i32 0, i32 3 +// CHECK-NEXT: store ptr blockaddress(@main.main, %_llgo_4), ptr %6, align 8 +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.SetThreadDefer"(ptr %2) +// CHECK-NEXT: %7 = getelementptr inbounds %"{{.*}}/runtime/internal/runtime.Defer", ptr %2, i32 0, i32 1 +// CHECK-NEXT: %8 = getelementptr inbounds %"{{.*}}/runtime/internal/runtime.Defer", ptr %2, i32 0, i32 3 +// CHECK-NEXT: %9 = getelementptr inbounds %"{{.*}}/runtime/internal/runtime.Defer", ptr %2, i32 0, i32 4 +// CHECK-NEXT: %10 = getelementptr inbounds %"{{.*}}/runtime/internal/runtime.Defer", ptr %2, i32 0, i32 5 +// CHECK-NEXT: store ptr null, ptr %10, align 8 +// CHECK-NEXT: %11 = call i32 @{{(__)?}}sigsetjmp(ptr %1, i32 0) +// CHECK-NEXT: %12 = icmp eq i32 %11, 0 +// CHECK-NEXT: br i1 %12, label %_llgo_6, label %_llgo_7 +// CHECK-EMPTY: +// CHECK-NEXT: _llgo_1: ; preds = %_llgo_5 +// CHECK-NEXT: ret void +// CHECK-EMPTY: +// CHECK-NEXT: _llgo_2: ; preds = %_llgo_6 +// CHECK-NEXT: %13 = load i64, ptr %7, align 8 +// CHECK-NEXT: %14 = or i64 %13, 1 +// CHECK-NEXT: store i64 %14, ptr %7, align 8 +// CHECK-NEXT: %15 = load ptr, ptr %10, align 8 +// CHECK-NEXT: %16 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 32) +// CHECK-NEXT: %17 = getelementptr inbounds { ptr, i64, %"{{.*}}/runtime/internal/runtime.String" }, ptr %16, i32 0, i32 0 +// CHECK-NEXT: store ptr %15, ptr %17, align 8 +// CHECK-NEXT: %18 = getelementptr inbounds { ptr, i64, %"{{.*}}/runtime/internal/runtime.String" }, ptr %16, i32 0, i32 1 +// CHECK-NEXT: store i64 1, ptr %18, align 8 +// CHECK-NEXT: %19 = getelementptr inbounds { ptr, i64, %"{{.*}}/runtime/internal/runtime.String" }, ptr %16, i32 0, i32 2 +// CHECK-NEXT: store %"{{.*}}/runtime/internal/runtime.String" { ptr @{{[0-9]+}}, i64 5 }, ptr %19, align 8 +// CHECK-NEXT: store ptr %16, ptr %10, align 8 +// CHECK-NEXT: call void @main.fail() +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.PrintString"(%"{{.*}}/runtime/internal/runtime.String" { ptr @{{[0-9]+}}, i64 9 }) +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.PrintByte"(i8 10) +// CHECK-NEXT: store ptr blockaddress(@main.main, %_llgo_8), ptr %9, align 8 +// CHECK-NEXT: br label %_llgo_4 +// CHECK-EMPTY: +// CHECK-NEXT: _llgo_3: ; preds = %_llgo_6 +// CHECK-NEXT: %20 = load i64, ptr %7, align 8 +// CHECK-NEXT: %21 = or i64 %20, 2 +// CHECK-NEXT: store i64 %21, ptr %7, align 8 +// CHECK-NEXT: %22 = load ptr, ptr %10, align 8 +// CHECK-NEXT: %23 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 32) +// CHECK-NEXT: %24 = getelementptr inbounds { ptr, i64, %"{{.*}}/runtime/internal/runtime.String" }, ptr %23, i32 0, i32 0 +// CHECK-NEXT: store ptr %22, ptr %24, align 8 +// CHECK-NEXT: %25 = getelementptr inbounds { ptr, i64, %"{{.*}}/runtime/internal/runtime.String" }, ptr %23, i32 0, i32 1 +// CHECK-NEXT: store i64 2, ptr %25, align 8 +// CHECK-NEXT: %26 = getelementptr inbounds { ptr, i64, %"{{.*}}/runtime/internal/runtime.String" }, ptr %23, i32 0, i32 2 +// CHECK-NEXT: store %"{{.*}}/runtime/internal/runtime.String" { ptr @{{[0-9]+}}, i64 5 }, ptr %26, align 8 +// CHECK-NEXT: store ptr %23, ptr %10, align 8 +// CHECK-NEXT: store ptr blockaddress(@main.main, %_llgo_9), ptr %9, align 8 +// CHECK-NEXT: br label %_llgo_4 +// CHECK-EMPTY: +// CHECK-NEXT: _llgo_4: ; preds = %_llgo_7, %_llgo_3, %_llgo_2 +// CHECK-NEXT: store ptr blockaddress(@main.main, %_llgo_11), ptr %8, align 8 +// CHECK-NEXT: %27 = load i64, ptr %7, align 8 +// CHECK-NEXT: %28 = and i64 %27, 2 +// CHECK-NEXT: %29 = icmp ne i64 %28, 0 +// CHECK-NEXT: br i1 %29, label %_llgo_12, label %_llgo_13 +// CHECK-EMPTY: +// CHECK-NEXT: _llgo_5: ; preds = %_llgo_7, %_llgo_10 +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.Rethrow"(ptr %0) +// CHECK-NEXT: br label %_llgo_1 +// CHECK-EMPTY: +// CHECK-NEXT: _llgo_6: ; preds = %_llgo_0 +// CHECK-NEXT: %30 = call i1 @main.f(%"{{.*}}/runtime/internal/runtime.String" { ptr @{{[0-9]+}}, i64 5 }) +// CHECK-NEXT: br i1 %30, label %_llgo_2, label %_llgo_3 +// CHECK-EMPTY: +// CHECK-NEXT: _llgo_7: ; preds = %_llgo_0 +// CHECK-NEXT: store ptr blockaddress(@main.main, %_llgo_5), ptr %9, align 8 +// CHECK-NEXT: %31 = load ptr, ptr %8, align 8 +// CHECK-NEXT: indirectbr ptr %31, [label %_llgo_5, label %_llgo_10, label %_llgo_11, label %_llgo_4] +// CHECK-EMPTY: +// CHECK-NEXT: _llgo_8: ; preds = %_llgo_10 +// CHECK-NEXT: ret void +// CHECK-EMPTY: +// CHECK-NEXT: _llgo_9: ; preds = %_llgo_10 +// CHECK-NEXT: ret void +// CHECK-EMPTY: +// CHECK-NEXT: _llgo_10: ; preds = %_llgo_7, %_llgo_17 +// CHECK-NEXT: store ptr blockaddress(@main.main, %_llgo_5), ptr %8, align 8 +// CHECK-NEXT: %32 = load i64, ptr %7, align 8 +// CHECK-NEXT: call void @"main.main$1"() +// CHECK-NEXT: %33 = load %"{{.*}}/runtime/internal/runtime.Defer", ptr %2, align 8 +// CHECK-NEXT: %34 = extractvalue %"{{.*}}/runtime/internal/runtime.Defer" %33, 2 +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.SetThreadDefer"(ptr %34) +// CHECK-NEXT: %35 = load ptr, ptr %9, align 8 +// CHECK-NEXT: indirectbr ptr %35, [label %_llgo_5, label %_llgo_8, label %_llgo_9] +// CHECK-EMPTY: +// CHECK-NEXT: _llgo_11: ; preds = %_llgo_7, %_llgo_13 +// CHECK-NEXT: store ptr blockaddress(@main.main, %_llgo_10), ptr %8, align 8 +// CHECK-NEXT: %36 = load i64, ptr %7, align 8 +// CHECK-NEXT: %37 = and i64 %36, 1 +// CHECK-NEXT: %38 = icmp ne i64 %37, 0 +// CHECK-NEXT: br i1 %38, label %_llgo_16, label %_llgo_17 +// CHECK-EMPTY: +// CHECK-NEXT: _llgo_12: ; preds = %_llgo_4 +// CHECK-NEXT: %39 = load ptr, ptr %10, align 8 +// CHECK-NEXT: %40 = icmp ne ptr %39, null +// CHECK-NEXT: br i1 %40, label %_llgo_14, label %_llgo_15 +// CHECK-EMPTY: +// CHECK-NEXT: _llgo_13: ; preds = %_llgo_15, %_llgo_4 +// CHECK-NEXT: br label %_llgo_11 +// CHECK-EMPTY: +// CHECK-NEXT: _llgo_14: ; preds = %_llgo_12 +// CHECK-NEXT: %41 = load ptr, ptr %10, align 8 +// CHECK-NEXT: %42 = load { ptr, i64, %"{{.*}}/runtime/internal/runtime.String" }, ptr %41, align 8 +// CHECK-NEXT: %43 = extractvalue { ptr, i64, %"{{.*}}/runtime/internal/runtime.String" } %42, 0 +// CHECK-NEXT: store ptr %43, ptr %10, align 8 +// CHECK-NEXT: %44 = extractvalue { ptr, i64, %"{{.*}}/runtime/internal/runtime.String" } %42, 2 +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.FreeDeferNode"(ptr %41) +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.PrintString"(%"{{.*}}/runtime/internal/runtime.String" %44) +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.PrintByte"(i8 10) +// CHECK-NEXT: br label %_llgo_15 +// CHECK-EMPTY: +// CHECK-NEXT: _llgo_15: ; preds = %_llgo_14, %_llgo_12 +// CHECK-NEXT: br label %_llgo_13 +// CHECK-EMPTY: +// CHECK-NEXT: _llgo_16: ; preds = %_llgo_11 +// CHECK-NEXT: %45 = load ptr, ptr %10, align 8 +// CHECK-NEXT: %46 = icmp ne ptr %45, null +// CHECK-NEXT: br i1 %46, label %_llgo_18, label %_llgo_19 +// CHECK-EMPTY: +// CHECK-NEXT: _llgo_17: ; preds = %_llgo_19, %_llgo_11 +// CHECK-NEXT: br label %_llgo_10 +// CHECK-EMPTY: +// CHECK-NEXT: _llgo_18: ; preds = %_llgo_16 +// CHECK-NEXT: %47 = load ptr, ptr %10, align 8 +// CHECK-NEXT: %48 = load { ptr, i64, %"{{.*}}/runtime/internal/runtime.String" }, ptr %47, align 8 +// CHECK-NEXT: %49 = extractvalue { ptr, i64, %"{{.*}}/runtime/internal/runtime.String" } %48, 0 +// CHECK-NEXT: store ptr %49, ptr %10, align 8 +// CHECK-NEXT: %50 = extractvalue { ptr, i64, %"{{.*}}/runtime/internal/runtime.String" } %48, 2 +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.FreeDeferNode"(ptr %47) +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.PrintString"(%"{{.*}}/runtime/internal/runtime.String" %50) +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.PrintByte"(i8 10) +// CHECK-NEXT: br label %_llgo_19 +// CHECK-EMPTY: +// CHECK-NEXT: _llgo_19: ; preds = %_llgo_18, %_llgo_16 +// CHECK-NEXT: br label %_llgo_17 +// CHECK-NEXT: } + +// CHECK-LABEL: define void @"main.main$1"(){{.*}} { +// CHECK-NEXT: _llgo_0: +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.PrintString"(%"{{.*}}/runtime/internal/runtime.String" { ptr @{{[0-9]+}}, i64 2 }) +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.PrintByte"(i8 10) +// CHECK-NEXT: ret void +// CHECK-NEXT: } diff --git a/cl/_testgo/deferclosure/in.go b/cl/_testgo/deferclosure/in.go index 60a3b0cebc..ecd61152a3 100644 --- a/cl/_testgo/deferclosure/in.go +++ b/cl/_testgo/deferclosure/in.go @@ -1,14 +1,19 @@ // LITTEST package main -// CHECK-DAG: call ptr @"{{.*}}/runtime/internal/runtime.GetThreadDefer"() -// CHECK-DAG: define void @"main.testDeferClosureValue$1"(ptr {{((nest|swiftself) )?}}%{{.*}}){{.*}} { -// CHECK-DAG: define void @"main.testDeferStructClosure$1"(ptr {{((nest|swiftself) )?}}%{{.*}}, %"{{.*}}/runtime/internal/runtime.String" %{{.*}}){{.*}} { -// CHECK-DAG: call void %{{.*}}(ptr {{((nest|swiftself) )?}}%{{.*}}) - // Test deferred closure and method-value lowering. // Type for holding a function + +// CHECK: {{^}}@{{[0-9]+}} = private unnamed_addr constant [16 x i8] c"deferred closure", align 1{{$}} +// CHECK: {{^}}@{{[0-9]+}} = private unnamed_addr constant [13 x i8] c"closure value", align 1{{$}} +// CHECK: {{^}}@{{[0-9]+}} = private unnamed_addr constant [17 x i8] c"field access test", align 1{{$}} +// CHECK: {{^}}@{{[0-9]+}} = private unnamed_addr constant [19 x i8] c"callback from field", align 1{{$}} +// CHECK: {{^}}@{{[0-9]+}} = private unnamed_addr constant [13 x i8] c"before return", align 1{{$}} +// CHECK: {{^}}@{{[0-9]+}} = private unnamed_addr constant [8 x i8] c"deferred", align 1{{$}} +// CHECK: {{^}}@{{[0-9]+}} = private unnamed_addr constant [8 x i8] c"captured", align 1{{$}} +// CHECK: {{^}}@{{[0-9]+}} = private unnamed_addr constant [19 x i8] c"struct closure test", align 1{{$}} + type Handler struct { fn func(int) } @@ -82,3 +87,431 @@ func main() { testDeferStructClosure() testDeferFieldAccess() } + +// CHECK-LABEL: define void @"main.(*Handler).SetHandler"(ptr %0, { ptr, ptr } %1){{.*}} { +// CHECK-NEXT: _llgo_0: +// CHECK-NEXT: %2 = getelementptr inbounds %main.Handler, ptr %0, i32 0, i32 0 +// CHECK-NEXT: store { ptr, ptr } %1, ptr %2, align 8 +// CHECK-NEXT: ret void +// CHECK-NEXT: } + +// CHECK-LABEL: define void @"main.(*Processor).SetCallback"(ptr %0, { ptr, ptr } %1){{.*}} { +// CHECK-NEXT: _llgo_0: +// CHECK-NEXT: %2 = getelementptr inbounds %main.Processor, ptr %0, i32 0, i32 0 +// CHECK-NEXT: store { ptr, ptr } %1, ptr %2, align 8 +// CHECK-NEXT: ret void +// CHECK-NEXT: } + +// CHECK-LABEL: define void @main.init(){{.*}} { +// CHECK-NEXT: _llgo_0: +// CHECK-NEXT: %0 = load i1, ptr @"main.init$guard", align 1 +// CHECK-NEXT: br i1 %0, label %_llgo_2, label %_llgo_1 +// CHECK-EMPTY: +// CHECK-NEXT: _llgo_1: ; preds = %_llgo_0 +// CHECK-NEXT: store i1 true, ptr @"main.init$guard", align 1 +// CHECK-NEXT: br label %_llgo_2 +// CHECK-EMPTY: +// CHECK-NEXT: _llgo_2: ; preds = %_llgo_1, %_llgo_0 +// CHECK-NEXT: ret void +// CHECK-NEXT: } + +// CHECK-LABEL: define void @main.main(){{.*}} { +// CHECK-NEXT: _llgo_0: +// CHECK-NEXT: call void @main.testDeferMethodLiteral() +// CHECK-NEXT: call void @main.testDeferClosureValue() +// CHECK-NEXT: call void @main.testDeferStructClosure() +// CHECK-NEXT: call void @main.testDeferFieldAccess() +// CHECK-NEXT: ret void +// CHECK-NEXT: } + +// CHECK-LABEL: define void @main.testDeferClosureValue(){{.*}} { +// CHECK-NEXT: _llgo_0: +// CHECK-NEXT: %0 = call ptr @"{{.*}}/runtime/internal/runtime.AllocZ"(i64 8) +// CHECK-NEXT: store i64 42, ptr %0, align 8 +// CHECK-NEXT: %1 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 8) +// CHECK-NEXT: %2 = getelementptr inbounds { ptr }, ptr %1, i32 0, i32 0 +// CHECK-NEXT: store ptr %0, ptr %2, align 8 +// CHECK-NEXT: %3 = insertvalue { ptr, ptr } { ptr @"main.testDeferClosureValue$1", ptr undef }, ptr %1, 1 +// CHECK-NEXT: %4 = call ptr @"{{.*}}/runtime/internal/runtime.GetThreadDefer"() +// CHECK-NEXT: %5 = alloca i8 +// CHECK-NEXT: %6 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 48) +// CHECK-NEXT: %7 = getelementptr inbounds %"{{.*}}/runtime/internal/runtime.Defer", ptr %6, i32 0, i32 0 +// CHECK-NEXT: store ptr %5, ptr %7, align 8 +// CHECK-NEXT: %8 = getelementptr inbounds %"{{.*}}/runtime/internal/runtime.Defer", ptr %6, i32 0, i32 1 +// CHECK-NEXT: store i64 0, ptr %8, align 8 +// CHECK-NEXT: %9 = getelementptr inbounds %"{{.*}}/runtime/internal/runtime.Defer", ptr %6, i32 0, i32 2 +// CHECK-NEXT: store ptr %4, ptr %9, align 8 +// CHECK-NEXT: %10 = getelementptr inbounds %"{{.*}}/runtime/internal/runtime.Defer", ptr %6, i32 0, i32 3 +// CHECK-NEXT: store ptr blockaddress(@main.testDeferClosureValue, %_llgo_2), ptr %10, align 8 +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.SetThreadDefer"(ptr %6) +// CHECK-NEXT: %11 = getelementptr inbounds %"{{.*}}/runtime/internal/runtime.Defer", ptr %6, i32 0, i32 1 +// CHECK-NEXT: %12 = getelementptr inbounds %"{{.*}}/runtime/internal/runtime.Defer", ptr %6, i32 0, i32 3 +// CHECK-NEXT: %13 = getelementptr inbounds %"{{.*}}/runtime/internal/runtime.Defer", ptr %6, i32 0, i32 4 +// CHECK-NEXT: %14 = getelementptr inbounds %"{{.*}}/runtime/internal/runtime.Defer", ptr %6, i32 0, i32 5 +// CHECK-NEXT: store ptr null, ptr %14, align 8 +// CHECK-NEXT: %15 = call i32 @{{(__)?}}sigsetjmp(ptr %5, i32 0) +// CHECK-NEXT: %16 = icmp eq i32 %15, 0 +// CHECK-NEXT: br i1 %16, label %_llgo_4, label %_llgo_5 +// CHECK-EMPTY: +// CHECK-NEXT: _llgo_1: ; preds = %_llgo_3 +// CHECK-NEXT: ret void +// CHECK-EMPTY: +// CHECK-NEXT: _llgo_2: ; preds = %_llgo_5, %_llgo_4 +// CHECK-NEXT: store ptr blockaddress(@main.testDeferClosureValue, %_llgo_3), ptr %12, align 8 +// CHECK-NEXT: %17 = load i64, ptr %11, align 8 +// CHECK-NEXT: %18 = load ptr, ptr %14, align 8 +// CHECK-NEXT: %19 = icmp ne ptr %18, null +// CHECK-NEXT: br i1 %19, label %_llgo_7, label %_llgo_8 +// CHECK-EMPTY: +// CHECK-NEXT: _llgo_3: ; preds = %_llgo_5, %_llgo_8 +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.Rethrow"(ptr %4) +// CHECK-NEXT: br label %_llgo_1 +// CHECK-EMPTY: +// CHECK-NEXT: _llgo_4: ; preds = %_llgo_0 +// CHECK-NEXT: %20 = load ptr, ptr %14, align 8 +// CHECK-NEXT: %21 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 32) +// CHECK-NEXT: %22 = getelementptr inbounds { ptr, i64, { ptr, ptr } }, ptr %21, i32 0, i32 0 +// CHECK-NEXT: store ptr %20, ptr %22, align 8 +// CHECK-NEXT: %23 = getelementptr inbounds { ptr, i64, { ptr, ptr } }, ptr %21, i32 0, i32 1 +// CHECK-NEXT: store i64 0, ptr %23, align 8 +// CHECK-NEXT: %24 = getelementptr inbounds { ptr, i64, { ptr, ptr } }, ptr %21, i32 0, i32 2 +// CHECK-NEXT: store { ptr, ptr } %3, ptr %24, align 8 +// CHECK-NEXT: store ptr %21, ptr %14, align 8 +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.PrintString"(%"{{.*}}/runtime/internal/runtime.String" { ptr @{{[0-9]+}}, i64 16 }) +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.PrintByte"(i8 10) +// CHECK-NEXT: store ptr blockaddress(@main.testDeferClosureValue, %_llgo_6), ptr %13, align 8 +// CHECK-NEXT: br label %_llgo_2 +// CHECK-EMPTY: +// CHECK-NEXT: _llgo_5: ; preds = %_llgo_0 +// CHECK-NEXT: store ptr blockaddress(@main.testDeferClosureValue, %_llgo_3), ptr %13, align 8 +// CHECK-NEXT: %25 = load ptr, ptr %12, align 8 +// CHECK-NEXT: indirectbr ptr %25, [label %_llgo_3, label %_llgo_2] +// CHECK-EMPTY: +// CHECK-NEXT: _llgo_6: ; preds = %_llgo_8 +// CHECK-NEXT: ret void +// CHECK-EMPTY: +// CHECK-NEXT: _llgo_7: ; preds = %_llgo_2 +// CHECK-NEXT: %26 = load ptr, ptr %14, align 8 +// CHECK-NEXT: %27 = load { ptr, i64, { ptr, ptr } }, ptr %26, align 8 +// CHECK-NEXT: %28 = extractvalue { ptr, i64, { ptr, ptr } } %27, 0 +// CHECK-NEXT: store ptr %28, ptr %14, align 8 +// CHECK-NEXT: %29 = extractvalue { ptr, i64, { ptr, ptr } } %27, 2 +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.FreeDeferNode"(ptr %26) +// CHECK-NEXT: %30 = extractvalue { ptr, ptr } %29, 1 +// CHECK-NEXT: %31 = extractvalue { ptr, ptr } %29, 0 +// CHECK-NEXT: %__llgo_funcval_code = call ptr asm "", "=r,0"(ptr %31) +// CHECK-NEXT: call void %__llgo_funcval_code(ptr {{(nest|swiftself)}} %30) +// CHECK-NEXT: br label %_llgo_8 +// CHECK-EMPTY: +// CHECK-NEXT: _llgo_8: ; preds = %_llgo_7, %_llgo_2 +// CHECK-NEXT: %32 = load %"{{.*}}/runtime/internal/runtime.Defer", ptr %6, align 8 +// CHECK-NEXT: %33 = extractvalue %"{{.*}}/runtime/internal/runtime.Defer" %32, 2 +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.SetThreadDefer"(ptr %33) +// CHECK-NEXT: %34 = load ptr, ptr %13, align 8 +// CHECK-NEXT: indirectbr ptr %34, [label %_llgo_3, label %_llgo_6] +// CHECK-NEXT: } + +// CHECK-LABEL: define void @"main.testDeferClosureValue$1"(ptr {{(nest|swiftself)}} %0){{.*}} { +// CHECK-NEXT: _llgo_0: +// CHECK-NEXT: %1 = load { ptr }, ptr %0, align 8 +// CHECK-NEXT: %2 = extractvalue { ptr } %1, 0 +// CHECK-NEXT: %3 = load i64, ptr %2, align 8 +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.PrintString"(%"{{.*}}/runtime/internal/runtime.String" { ptr @{{[0-9]+}}, i64 13 }) +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.PrintByte"(i8 32) +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.PrintInt"(i64 %3) +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.PrintByte"(i8 10) +// CHECK-NEXT: ret void +// CHECK-NEXT: } + +// CHECK-LABEL: define void @main.testDeferFieldAccess(){{.*}} { +// CHECK-NEXT: _llgo_0: +// CHECK-NEXT: %0 = alloca %main.FuncHolder, align 8 +// CHECK-NEXT: call void @llvm.memset.p0.i64(ptr %0, i8 0, i64 16, i1 false) +// CHECK-NEXT: %1 = getelementptr inbounds %main.FuncHolder, ptr %0, i32 0, i32 0 +// CHECK-NEXT: store { ptr, ptr } { ptr @"main.testDeferFieldAccess$1", ptr null }, ptr %1, align 8 +// CHECK-NEXT: %2 = getelementptr inbounds %main.FuncHolder, ptr %0, i32 0, i32 0 +// CHECK-NEXT: %3 = load { ptr, ptr }, ptr %2, align 8 +// CHECK-NEXT: %4 = call ptr @"{{.*}}/runtime/internal/runtime.GetThreadDefer"() +// CHECK-NEXT: %5 = alloca i8 +// CHECK-NEXT: %6 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 48) +// CHECK-NEXT: %7 = getelementptr inbounds %"{{.*}}/runtime/internal/runtime.Defer", ptr %6, i32 0, i32 0 +// CHECK-NEXT: store ptr %5, ptr %7, align 8 +// CHECK-NEXT: %8 = getelementptr inbounds %"{{.*}}/runtime/internal/runtime.Defer", ptr %6, i32 0, i32 1 +// CHECK-NEXT: store i64 0, ptr %8, align 8 +// CHECK-NEXT: %9 = getelementptr inbounds %"{{.*}}/runtime/internal/runtime.Defer", ptr %6, i32 0, i32 2 +// CHECK-NEXT: store ptr %4, ptr %9, align 8 +// CHECK-NEXT: %10 = getelementptr inbounds %"{{.*}}/runtime/internal/runtime.Defer", ptr %6, i32 0, i32 3 +// CHECK-NEXT: store ptr blockaddress(@main.testDeferFieldAccess, %_llgo_2), ptr %10, align 8 +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.SetThreadDefer"(ptr %6) +// CHECK-NEXT: %11 = getelementptr inbounds %"{{.*}}/runtime/internal/runtime.Defer", ptr %6, i32 0, i32 1 +// CHECK-NEXT: %12 = getelementptr inbounds %"{{.*}}/runtime/internal/runtime.Defer", ptr %6, i32 0, i32 3 +// CHECK-NEXT: %13 = getelementptr inbounds %"{{.*}}/runtime/internal/runtime.Defer", ptr %6, i32 0, i32 4 +// CHECK-NEXT: %14 = getelementptr inbounds %"{{.*}}/runtime/internal/runtime.Defer", ptr %6, i32 0, i32 5 +// CHECK-NEXT: store ptr null, ptr %14, align 8 +// CHECK-NEXT: %15 = call i32 @{{(__)?}}sigsetjmp(ptr %5, i32 0) +// CHECK-NEXT: %16 = icmp eq i32 %15, 0 +// CHECK-NEXT: br i1 %16, label %_llgo_4, label %_llgo_5 +// CHECK-EMPTY: +// CHECK-NEXT: _llgo_1: ; preds = %_llgo_3 +// CHECK-NEXT: ret void +// CHECK-EMPTY: +// CHECK-NEXT: _llgo_2: ; preds = %_llgo_5, %_llgo_4 +// CHECK-NEXT: store ptr blockaddress(@main.testDeferFieldAccess, %_llgo_3), ptr %12, align 8 +// CHECK-NEXT: %17 = load i64, ptr %11, align 8 +// CHECK-NEXT: %18 = load ptr, ptr %14, align 8 +// CHECK-NEXT: %19 = icmp ne ptr %18, null +// CHECK-NEXT: br i1 %19, label %_llgo_7, label %_llgo_8 +// CHECK-EMPTY: +// CHECK-NEXT: _llgo_3: ; preds = %_llgo_5, %_llgo_8 +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.Rethrow"(ptr %4) +// CHECK-NEXT: br label %_llgo_1 +// CHECK-EMPTY: +// CHECK-NEXT: _llgo_4: ; preds = %_llgo_0 +// CHECK-NEXT: %20 = load ptr, ptr %14, align 8 +// CHECK-NEXT: %21 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 32) +// CHECK-NEXT: %22 = getelementptr inbounds { ptr, i64, { ptr, ptr } }, ptr %21, i32 0, i32 0 +// CHECK-NEXT: store ptr %20, ptr %22, align 8 +// CHECK-NEXT: %23 = getelementptr inbounds { ptr, i64, { ptr, ptr } }, ptr %21, i32 0, i32 1 +// CHECK-NEXT: store i64 0, ptr %23, align 8 +// CHECK-NEXT: %24 = getelementptr inbounds { ptr, i64, { ptr, ptr } }, ptr %21, i32 0, i32 2 +// CHECK-NEXT: store { ptr, ptr } %3, ptr %24, align 8 +// CHECK-NEXT: store ptr %21, ptr %14, align 8 +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.PrintString"(%"{{.*}}/runtime/internal/runtime.String" { ptr @{{[0-9]+}}, i64 17 }) +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.PrintByte"(i8 10) +// CHECK-NEXT: store ptr blockaddress(@main.testDeferFieldAccess, %_llgo_6), ptr %13, align 8 +// CHECK-NEXT: br label %_llgo_2 +// CHECK-EMPTY: +// CHECK-NEXT: _llgo_5: ; preds = %_llgo_0 +// CHECK-NEXT: store ptr blockaddress(@main.testDeferFieldAccess, %_llgo_3), ptr %13, align 8 +// CHECK-NEXT: %25 = load ptr, ptr %12, align 8 +// CHECK-NEXT: indirectbr ptr %25, [label %_llgo_3, label %_llgo_2] +// CHECK-EMPTY: +// CHECK-NEXT: _llgo_6: ; preds = %_llgo_8 +// CHECK-NEXT: ret void +// CHECK-EMPTY: +// CHECK-NEXT: _llgo_7: ; preds = %_llgo_2 +// CHECK-NEXT: %26 = load ptr, ptr %14, align 8 +// CHECK-NEXT: %27 = load { ptr, i64, { ptr, ptr } }, ptr %26, align 8 +// CHECK-NEXT: %28 = extractvalue { ptr, i64, { ptr, ptr } } %27, 0 +// CHECK-NEXT: store ptr %28, ptr %14, align 8 +// CHECK-NEXT: %29 = extractvalue { ptr, i64, { ptr, ptr } } %27, 2 +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.FreeDeferNode"(ptr %26) +// CHECK-NEXT: %30 = extractvalue { ptr, ptr } %29, 1 +// CHECK-NEXT: %31 = extractvalue { ptr, ptr } %29, 0 +// CHECK-NEXT: %__llgo_funcval_code = call ptr asm "", "=r,0"(ptr %31) +// CHECK-NEXT: call void %__llgo_funcval_code(ptr {{(nest|swiftself)}} %30) +// CHECK-NEXT: br label %_llgo_8 +// CHECK-EMPTY: +// CHECK-NEXT: _llgo_8: ; preds = %_llgo_7, %_llgo_2 +// CHECK-NEXT: %32 = load %"{{.*}}/runtime/internal/runtime.Defer", ptr %6, align 8 +// CHECK-NEXT: %33 = extractvalue %"{{.*}}/runtime/internal/runtime.Defer" %32, 2 +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.SetThreadDefer"(ptr %33) +// CHECK-NEXT: %34 = load ptr, ptr %13, align 8 +// CHECK-NEXT: indirectbr ptr %34, [label %_llgo_3, label %_llgo_6] +// CHECK-NEXT: } + +// CHECK-LABEL: define void @"main.testDeferFieldAccess$1"(){{.*}} { +// CHECK-NEXT: _llgo_0: +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.PrintString"(%"{{.*}}/runtime/internal/runtime.String" { ptr @{{[0-9]+}}, i64 19 }) +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.PrintByte"(i8 10) +// CHECK-NEXT: ret void +// CHECK-NEXT: } + +// CHECK-LABEL: define void @main.testDeferMethodLiteral(){{.*}} { +// CHECK-NEXT: _llgo_0: +// CHECK-NEXT: %0 = call ptr @"{{.*}}/runtime/internal/runtime.AllocZ"(i64 16) +// CHECK-NEXT: call void @"main.(*Handler).SetHandler"(ptr %0, { ptr, ptr } { ptr @"main.testDeferMethodLiteral$1", ptr null }) +// CHECK-NEXT: %1 = call ptr @"{{.*}}/runtime/internal/runtime.GetThreadDefer"() +// CHECK-NEXT: %2 = alloca i8 +// CHECK-NEXT: %3 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 48) +// CHECK-NEXT: %4 = getelementptr inbounds %"{{.*}}/runtime/internal/runtime.Defer", ptr %3, i32 0, i32 0 +// CHECK-NEXT: store ptr %2, ptr %4, align 8 +// CHECK-NEXT: %5 = getelementptr inbounds %"{{.*}}/runtime/internal/runtime.Defer", ptr %3, i32 0, i32 1 +// CHECK-NEXT: store i64 0, ptr %5, align 8 +// CHECK-NEXT: %6 = getelementptr inbounds %"{{.*}}/runtime/internal/runtime.Defer", ptr %3, i32 0, i32 2 +// CHECK-NEXT: store ptr %1, ptr %6, align 8 +// CHECK-NEXT: %7 = getelementptr inbounds %"{{.*}}/runtime/internal/runtime.Defer", ptr %3, i32 0, i32 3 +// CHECK-NEXT: store ptr blockaddress(@main.testDeferMethodLiteral, %_llgo_2), ptr %7, align 8 +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.SetThreadDefer"(ptr %3) +// CHECK-NEXT: %8 = getelementptr inbounds %"{{.*}}/runtime/internal/runtime.Defer", ptr %3, i32 0, i32 1 +// CHECK-NEXT: %9 = getelementptr inbounds %"{{.*}}/runtime/internal/runtime.Defer", ptr %3, i32 0, i32 3 +// CHECK-NEXT: %10 = getelementptr inbounds %"{{.*}}/runtime/internal/runtime.Defer", ptr %3, i32 0, i32 4 +// CHECK-NEXT: %11 = getelementptr inbounds %"{{.*}}/runtime/internal/runtime.Defer", ptr %3, i32 0, i32 5 +// CHECK-NEXT: store ptr null, ptr %11, align 8 +// CHECK-NEXT: %12 = call i32 @{{(__)?}}sigsetjmp(ptr %2, i32 0) +// CHECK-NEXT: %13 = icmp eq i32 %12, 0 +// CHECK-NEXT: br i1 %13, label %_llgo_4, label %_llgo_5 +// CHECK-EMPTY: +// CHECK-NEXT: _llgo_1: ; preds = %_llgo_3 +// CHECK-NEXT: ret void +// CHECK-EMPTY: +// CHECK-NEXT: _llgo_2: ; preds = %_llgo_5, %_llgo_4 +// CHECK-NEXT: store ptr blockaddress(@main.testDeferMethodLiteral, %_llgo_3), ptr %9, align 8 +// CHECK-NEXT: %14 = load i64, ptr %8, align 8 +// CHECK-NEXT: %15 = load ptr, ptr %11, align 8 +// CHECK-NEXT: %16 = icmp ne ptr %15, null +// CHECK-NEXT: br i1 %16, label %_llgo_7, label %_llgo_8 +// CHECK-EMPTY: +// CHECK-NEXT: _llgo_3: ; preds = %_llgo_5, %_llgo_8 +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.Rethrow"(ptr %1) +// CHECK-NEXT: br label %_llgo_1 +// CHECK-EMPTY: +// CHECK-NEXT: _llgo_4: ; preds = %_llgo_0 +// CHECK-NEXT: %17 = load ptr, ptr %11, align 8 +// CHECK-NEXT: %18 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 32) +// CHECK-NEXT: %19 = getelementptr inbounds { ptr, i64, ptr, ptr }, ptr %18, i32 0, i32 0 +// CHECK-NEXT: store ptr %17, ptr %19, align 8 +// CHECK-NEXT: %20 = getelementptr inbounds { ptr, i64, ptr, ptr }, ptr %18, i32 0, i32 1 +// CHECK-NEXT: store i64 0, ptr %20, align 8 +// CHECK-NEXT: %21 = getelementptr inbounds { ptr, i64, ptr, ptr }, ptr %18, i32 0, i32 2 +// CHECK-NEXT: store ptr %0, ptr %21, align 8 +// CHECK-NEXT: %22 = getelementptr inbounds { ptr, i64, ptr, ptr }, ptr %18, i32 0, i32 3 +// CHECK-NEXT: store ptr @"main.testDeferMethodLiteral$2", ptr %22, align 8 +// CHECK-NEXT: store ptr %18, ptr %11, align 8 +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.PrintString"(%"{{.*}}/runtime/internal/runtime.String" { ptr @{{[0-9]+}}, i64 13 }) +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.PrintByte"(i8 10) +// CHECK-NEXT: store ptr blockaddress(@main.testDeferMethodLiteral, %_llgo_6), ptr %10, align 8 +// CHECK-NEXT: br label %_llgo_2 +// CHECK-EMPTY: +// CHECK-NEXT: _llgo_5: ; preds = %_llgo_0 +// CHECK-NEXT: store ptr blockaddress(@main.testDeferMethodLiteral, %_llgo_3), ptr %10, align 8 +// CHECK-NEXT: %23 = load ptr, ptr %9, align 8 +// CHECK-NEXT: indirectbr ptr %23, [label %_llgo_3, label %_llgo_2] +// CHECK-EMPTY: +// CHECK-NEXT: _llgo_6: ; preds = %_llgo_8 +// CHECK-NEXT: ret void +// CHECK-EMPTY: +// CHECK-NEXT: _llgo_7: ; preds = %_llgo_2 +// CHECK-NEXT: %24 = load ptr, ptr %11, align 8 +// CHECK-NEXT: %25 = load { ptr, i64, ptr, ptr }, ptr %24, align 8 +// CHECK-NEXT: %26 = extractvalue { ptr, i64, ptr, ptr } %25, 0 +// CHECK-NEXT: store ptr %26, ptr %11, align 8 +// CHECK-NEXT: %27 = extractvalue { ptr, i64, ptr, ptr } %25, 2 +// CHECK-NEXT: %28 = extractvalue { ptr, i64, ptr, ptr } %25, 3 +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.FreeDeferNode"(ptr %24) +// CHECK-NEXT: %29 = insertvalue { ptr, ptr } undef, ptr %28, 0 +// CHECK-NEXT: %30 = insertvalue { ptr, ptr } %29, ptr null, 1 +// CHECK-NEXT: call void @"main.(*Handler).SetHandler"(ptr %27, { ptr, ptr } %30) +// CHECK-NEXT: br label %_llgo_8 +// CHECK-EMPTY: +// CHECK-NEXT: _llgo_8: ; preds = %_llgo_7, %_llgo_2 +// CHECK-NEXT: %31 = load %"{{.*}}/runtime/internal/runtime.Defer", ptr %3, align 8 +// CHECK-NEXT: %32 = extractvalue %"{{.*}}/runtime/internal/runtime.Defer" %31, 2 +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.SetThreadDefer"(ptr %32) +// CHECK-NEXT: %33 = load ptr, ptr %10, align 8 +// CHECK-NEXT: indirectbr ptr %33, [label %_llgo_3, label %_llgo_6] +// CHECK-NEXT: } + +// CHECK-LABEL: define void @"main.testDeferMethodLiteral$1"(i64 %0){{.*}} { +// CHECK-NEXT: _llgo_0: +// CHECK-NEXT: ret void +// CHECK-NEXT: } + +// CHECK-LABEL: define void @"main.testDeferMethodLiteral$2"(i64 %0){{.*}} { +// CHECK-NEXT: _llgo_0: +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.PrintString"(%"{{.*}}/runtime/internal/runtime.String" { ptr @{{[0-9]+}}, i64 8 }) +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.PrintByte"(i8 32) +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.PrintInt"(i64 %0) +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.PrintByte"(i8 10) +// CHECK-NEXT: ret void +// CHECK-NEXT: } + +// CHECK-LABEL: define void @main.testDeferStructClosure(){{.*}} { +// CHECK-NEXT: _llgo_0: +// CHECK-NEXT: %0 = call ptr @"{{.*}}/runtime/internal/runtime.AllocZ"(i64 16) +// CHECK-NEXT: %1 = call ptr @"{{.*}}/runtime/internal/runtime.AllocZ"(i64 16) +// CHECK-NEXT: store %"{{.*}}/runtime/internal/runtime.String" { ptr @{{[0-9]+}}, i64 8 }, ptr %1, align 8 +// CHECK-NEXT: %2 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 8) +// CHECK-NEXT: %3 = getelementptr inbounds { ptr }, ptr %2, i32 0, i32 0 +// CHECK-NEXT: store ptr %1, ptr %3, align 8 +// CHECK-NEXT: %4 = insertvalue { ptr, ptr } { ptr @"main.testDeferStructClosure$1", ptr undef }, ptr %2, 1 +// CHECK-NEXT: %5 = call ptr @"{{.*}}/runtime/internal/runtime.GetThreadDefer"() +// CHECK-NEXT: %6 = alloca i8 +// CHECK-NEXT: %7 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 48) +// CHECK-NEXT: %8 = getelementptr inbounds %"{{.*}}/runtime/internal/runtime.Defer", ptr %7, i32 0, i32 0 +// CHECK-NEXT: store ptr %6, ptr %8, align 8 +// CHECK-NEXT: %9 = getelementptr inbounds %"{{.*}}/runtime/internal/runtime.Defer", ptr %7, i32 0, i32 1 +// CHECK-NEXT: store i64 0, ptr %9, align 8 +// CHECK-NEXT: %10 = getelementptr inbounds %"{{.*}}/runtime/internal/runtime.Defer", ptr %7, i32 0, i32 2 +// CHECK-NEXT: store ptr %5, ptr %10, align 8 +// CHECK-NEXT: %11 = getelementptr inbounds %"{{.*}}/runtime/internal/runtime.Defer", ptr %7, i32 0, i32 3 +// CHECK-NEXT: store ptr blockaddress(@main.testDeferStructClosure, %_llgo_2), ptr %11, align 8 +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.SetThreadDefer"(ptr %7) +// CHECK-NEXT: %12 = getelementptr inbounds %"{{.*}}/runtime/internal/runtime.Defer", ptr %7, i32 0, i32 1 +// CHECK-NEXT: %13 = getelementptr inbounds %"{{.*}}/runtime/internal/runtime.Defer", ptr %7, i32 0, i32 3 +// CHECK-NEXT: %14 = getelementptr inbounds %"{{.*}}/runtime/internal/runtime.Defer", ptr %7, i32 0, i32 4 +// CHECK-NEXT: %15 = getelementptr inbounds %"{{.*}}/runtime/internal/runtime.Defer", ptr %7, i32 0, i32 5 +// CHECK-NEXT: store ptr null, ptr %15, align 8 +// CHECK-NEXT: %16 = call i32 @{{(__)?}}sigsetjmp(ptr %6, i32 0) +// CHECK-NEXT: %17 = icmp eq i32 %16, 0 +// CHECK-NEXT: br i1 %17, label %_llgo_4, label %_llgo_5 +// CHECK-EMPTY: +// CHECK-NEXT: _llgo_1: ; preds = %_llgo_3 +// CHECK-NEXT: ret void +// CHECK-EMPTY: +// CHECK-NEXT: _llgo_2: ; preds = %_llgo_5, %_llgo_4 +// CHECK-NEXT: store ptr blockaddress(@main.testDeferStructClosure, %_llgo_3), ptr %13, align 8 +// CHECK-NEXT: %18 = load i64, ptr %12, align 8 +// CHECK-NEXT: %19 = load ptr, ptr %15, align 8 +// CHECK-NEXT: %20 = icmp ne ptr %19, null +// CHECK-NEXT: br i1 %20, label %_llgo_7, label %_llgo_8 +// CHECK-EMPTY: +// CHECK-NEXT: _llgo_3: ; preds = %_llgo_5, %_llgo_8 +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.Rethrow"(ptr %5) +// CHECK-NEXT: br label %_llgo_1 +// CHECK-EMPTY: +// CHECK-NEXT: _llgo_4: ; preds = %_llgo_0 +// CHECK-NEXT: %21 = load ptr, ptr %15, align 8 +// CHECK-NEXT: %22 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 40) +// CHECK-NEXT: %23 = getelementptr inbounds { ptr, i64, ptr, { ptr, ptr } }, ptr %22, i32 0, i32 0 +// CHECK-NEXT: store ptr %21, ptr %23, align 8 +// CHECK-NEXT: %24 = getelementptr inbounds { ptr, i64, ptr, { ptr, ptr } }, ptr %22, i32 0, i32 1 +// CHECK-NEXT: store i64 0, ptr %24, align 8 +// CHECK-NEXT: %25 = getelementptr inbounds { ptr, i64, ptr, { ptr, ptr } }, ptr %22, i32 0, i32 2 +// CHECK-NEXT: store ptr %0, ptr %25, align 8 +// CHECK-NEXT: %26 = getelementptr inbounds { ptr, i64, ptr, { ptr, ptr } }, ptr %22, i32 0, i32 3 +// CHECK-NEXT: store { ptr, ptr } %4, ptr %26, align 8 +// CHECK-NEXT: store ptr %22, ptr %15, align 8 +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.PrintString"(%"{{.*}}/runtime/internal/runtime.String" { ptr @{{[0-9]+}}, i64 19 }) +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.PrintByte"(i8 10) +// CHECK-NEXT: store ptr blockaddress(@main.testDeferStructClosure, %_llgo_6), ptr %14, align 8 +// CHECK-NEXT: br label %_llgo_2 +// CHECK-EMPTY: +// CHECK-NEXT: _llgo_5: ; preds = %_llgo_0 +// CHECK-NEXT: store ptr blockaddress(@main.testDeferStructClosure, %_llgo_3), ptr %14, align 8 +// CHECK-NEXT: %27 = load ptr, ptr %13, align 8 +// CHECK-NEXT: indirectbr ptr %27, [label %_llgo_3, label %_llgo_2] +// CHECK-EMPTY: +// CHECK-NEXT: _llgo_6: ; preds = %_llgo_8 +// CHECK-NEXT: ret void +// CHECK-EMPTY: +// CHECK-NEXT: _llgo_7: ; preds = %_llgo_2 +// CHECK-NEXT: %28 = load ptr, ptr %15, align 8 +// CHECK-NEXT: %29 = load { ptr, i64, ptr, { ptr, ptr } }, ptr %28, align 8 +// CHECK-NEXT: %30 = extractvalue { ptr, i64, ptr, { ptr, ptr } } %29, 0 +// CHECK-NEXT: store ptr %30, ptr %15, align 8 +// CHECK-NEXT: %31 = extractvalue { ptr, i64, ptr, { ptr, ptr } } %29, 2 +// CHECK-NEXT: %32 = extractvalue { ptr, i64, ptr, { ptr, ptr } } %29, 3 +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.FreeDeferNode"(ptr %28) +// CHECK-NEXT: call void @"main.(*Processor).SetCallback"(ptr %31, { ptr, ptr } %32) +// CHECK-NEXT: br label %_llgo_8 +// CHECK-EMPTY: +// CHECK-NEXT: _llgo_8: ; preds = %_llgo_7, %_llgo_2 +// CHECK-NEXT: %33 = load %"{{.*}}/runtime/internal/runtime.Defer", ptr %7, align 8 +// CHECK-NEXT: %34 = extractvalue %"{{.*}}/runtime/internal/runtime.Defer" %33, 2 +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.SetThreadDefer"(ptr %34) +// CHECK-NEXT: %35 = load ptr, ptr %14, align 8 +// CHECK-NEXT: indirectbr ptr %35, [label %_llgo_3, label %_llgo_6] +// CHECK-NEXT: } + +// CHECK-LABEL: define void @"main.testDeferStructClosure$1"(ptr {{(nest|swiftself)}} %0, %"{{.*}}/runtime/internal/runtime.String" %1){{.*}} { +// CHECK-NEXT: _llgo_0: +// CHECK-NEXT: %2 = load { ptr }, ptr %0, align 8 +// CHECK-NEXT: %3 = extractvalue { ptr } %2, 0 +// CHECK-NEXT: %4 = load %"{{.*}}/runtime/internal/runtime.String", ptr %3, align 8 +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.PrintString"(%"{{.*}}/runtime/internal/runtime.String" %1) +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.PrintByte"(i8 32) +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.PrintString"(%"{{.*}}/runtime/internal/runtime.String" %4) +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.PrintByte"(i8 10) +// CHECK-NEXT: ret void +// CHECK-NEXT: } diff --git a/cl/_testgo/defercomplex/in.go b/cl/_testgo/defercomplex/in.go index c03d1ce792..19a74dbdaf 100644 --- a/cl/_testgo/defercomplex/in.go +++ b/cl/_testgo/defercomplex/in.go @@ -1,10 +1,15 @@ // LITTEST package main -// CHECK-DAG: call ptr @"{{.*}}/runtime/internal/runtime.GetThreadDefer"() -// CHECK-DAG: call void @"{{.*}}/runtime/internal/runtime.SetThreadDefer"(ptr %{{.*}}) -// CHECK-DAG: define void @"main.complexOrder$1"(ptr {{((nest|swiftself) )?}}%{{.*}}, %"{{.*}}/runtime/internal/runtime.String" %{{.*}}){{.*}} { -// CHECK-DAG: call %"{{.*}}/runtime/internal/runtime.Slice" @"{{.*}}/runtime/internal/runtime.SliceAppend"({{.*}}) +// CHECK: {{^}}@{{[0-9]+}} = private unnamed_addr constant [13 x i8] c"cleanup-final", align 1{{$}} +// CHECK: {{^}}@{{[0-9]+}} = private unnamed_addr constant [19 x i8] c"cleanup-before-loop", align 1{{$}} +// CHECK: {{^}}@{{[0-9]+}} = private unnamed_addr constant [10 x i8] c"exit-outer", align 1{{$}} +// CHECK: {{^}}@{{[0-9]+}} = private unnamed_addr constant [9 x i8] c"post-loop", align 1{{$}} +// CHECK: {{^}}@{{[0-9]+}} = private unnamed_addr constant [11 x i8] c"branch-even", align 1{{$}} +// CHECK: {{^}}@{{[0-9]+}} = private unnamed_addr constant [10 x i8] c"branch-odd", align 1{{$}} +// CHECK: {{^}}@{{[0-9]+}} = private unnamed_addr constant [6 x i8] c"nested", align 1{{$}} +// CHECK: {{^}}@{{[0-9]+}} = private unnamed_addr constant [11 x i8] c"nested-tail", align 1{{$}} +// CHECK: {{^}}@{{[0-9]+}} = private unnamed_addr constant [1 x i8] c"-", align 1{{$}} func main() { for _, label := range complexOrder() { @@ -55,3 +60,702 @@ func label3(prefix string, a, b, c int) string { func digit(n int) string { return string(rune('0' + n)) } + +// CHECK-LABEL: define %"{{.*}}/runtime/internal/runtime.Slice" @main.complexOrder(){{.*}} { +// CHECK-NEXT: _llgo_0: +// CHECK-NEXT: %0 = call ptr @"{{.*}}/runtime/internal/runtime.AllocZ"(i64 24) +// CHECK-NEXT: %1 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 8) +// CHECK-NEXT: %2 = getelementptr inbounds { ptr }, ptr %1, i32 0, i32 0 +// CHECK-NEXT: store ptr %0, ptr %2, align 8 +// CHECK-NEXT: %3 = insertvalue { ptr, ptr } { ptr @"main.complexOrder$1", ptr undef }, ptr %1, 1 +// CHECK-NEXT: %4 = call %"{{.*}}/runtime/internal/runtime.String" @main.label1(%"{{.*}}/runtime/internal/runtime.String" { ptr @{{[0-9]+}}, i64 13 }, i64 0) +// CHECK-NEXT: %5 = call ptr @"{{.*}}/runtime/internal/runtime.GetThreadDefer"() +// CHECK-NEXT: %6 = alloca i8 +// CHECK-NEXT: %7 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 48) +// CHECK-NEXT: %8 = getelementptr inbounds %"{{.*}}/runtime/internal/runtime.Defer", ptr %7, i32 0, i32 0 +// CHECK-NEXT: store ptr %6, ptr %8, align 8 +// CHECK-NEXT: %9 = getelementptr inbounds %"{{.*}}/runtime/internal/runtime.Defer", ptr %7, i32 0, i32 1 +// CHECK-NEXT: store i64 0, ptr %9, align 8 +// CHECK-NEXT: %10 = getelementptr inbounds %"{{.*}}/runtime/internal/runtime.Defer", ptr %7, i32 0, i32 2 +// CHECK-NEXT: store ptr %5, ptr %10, align 8 +// CHECK-NEXT: %11 = getelementptr inbounds %"{{.*}}/runtime/internal/runtime.Defer", ptr %7, i32 0, i32 3 +// CHECK-NEXT: store ptr blockaddress(@main.complexOrder, %_llgo_16), ptr %11, align 8 +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.SetThreadDefer"(ptr %7) +// CHECK-NEXT: %12 = getelementptr inbounds %"{{.*}}/runtime/internal/runtime.Defer", ptr %7, i32 0, i32 1 +// CHECK-NEXT: %13 = getelementptr inbounds %"{{.*}}/runtime/internal/runtime.Defer", ptr %7, i32 0, i32 3 +// CHECK-NEXT: %14 = getelementptr inbounds %"{{.*}}/runtime/internal/runtime.Defer", ptr %7, i32 0, i32 4 +// CHECK-NEXT: %15 = getelementptr inbounds %"{{.*}}/runtime/internal/runtime.Defer", ptr %7, i32 0, i32 5 +// CHECK-NEXT: store ptr null, ptr %15, align 8 +// CHECK-NEXT: %16 = call i32 @{{(__)?}}sigsetjmp(ptr %6, i32 0) +// CHECK-NEXT: %17 = icmp eq i32 %16, 0 +// CHECK-NEXT: br i1 %17, label %_llgo_18, label %_llgo_19 +// CHECK-EMPTY: +// CHECK-NEXT: _llgo_1: ; preds = %_llgo_17 +// CHECK-NEXT: %18 = load %"{{.*}}/runtime/internal/runtime.Slice", ptr %0, align 8 +// CHECK-NEXT: ret %"{{.*}}/runtime/internal/runtime.Slice" %18 +// CHECK-EMPTY: +// CHECK-NEXT: _llgo_2: ; preds = %_llgo_7, %_llgo_18 +// CHECK-NEXT: %19 = phi i64 [ 0, %_llgo_18 ], [ %38, %_llgo_7 ] +// CHECK-NEXT: %20 = icmp slt i64 %19, 2 +// CHECK-NEXT: br i1 %20, label %_llgo_3, label %_llgo_4 +// CHECK-EMPTY: +// CHECK-NEXT: _llgo_3: ; preds = %_llgo_2 +// CHECK-NEXT: %21 = call %"{{.*}}/runtime/internal/runtime.String" @main.label1(%"{{.*}}/runtime/internal/runtime.String" { ptr @{{[0-9]+}}, i64 10 }, i64 %19) +// CHECK-NEXT: %22 = load ptr, ptr %15, align 8 +// CHECK-NEXT: %23 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 48) +// CHECK-NEXT: %24 = getelementptr inbounds { ptr, i64, { ptr, ptr }, %"{{.*}}/runtime/internal/runtime.String" }, ptr %23, i32 0, i32 0 +// CHECK-NEXT: store ptr %22, ptr %24, align 8 +// CHECK-NEXT: %25 = getelementptr inbounds { ptr, i64, { ptr, ptr }, %"{{.*}}/runtime/internal/runtime.String" }, ptr %23, i32 0, i32 1 +// CHECK-NEXT: store i64 2, ptr %25, align 8 +// CHECK-NEXT: %26 = getelementptr inbounds { ptr, i64, { ptr, ptr }, %"{{.*}}/runtime/internal/runtime.String" }, ptr %23, i32 0, i32 2 +// CHECK-NEXT: store { ptr, ptr } %3, ptr %26, align 8 +// CHECK-NEXT: %27 = getelementptr inbounds { ptr, i64, { ptr, ptr }, %"{{.*}}/runtime/internal/runtime.String" }, ptr %23, i32 0, i32 3 +// CHECK-NEXT: store %"{{.*}}/runtime/internal/runtime.String" %21, ptr %27, align 8 +// CHECK-NEXT: store ptr %23, ptr %15, align 8 +// CHECK-NEXT: br label %_llgo_5 +// CHECK-EMPTY: +// CHECK-NEXT: _llgo_4: ; preds = %_llgo_2 +// CHECK-NEXT: %28 = call %"{{.*}}/runtime/internal/runtime.String" @main.label1(%"{{.*}}/runtime/internal/runtime.String" { ptr @{{[0-9]+}}, i64 9 }, i64 0) +// CHECK-NEXT: %29 = load ptr, ptr %15, align 8 +// CHECK-NEXT: %30 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 48) +// CHECK-NEXT: %31 = getelementptr inbounds { ptr, i64, { ptr, ptr }, %"{{.*}}/runtime/internal/runtime.String" }, ptr %30, i32 0, i32 0 +// CHECK-NEXT: store ptr %29, ptr %31, align 8 +// CHECK-NEXT: %32 = getelementptr inbounds { ptr, i64, { ptr, ptr }, %"{{.*}}/runtime/internal/runtime.String" }, ptr %30, i32 0, i32 1 +// CHECK-NEXT: store i64 3, ptr %32, align 8 +// CHECK-NEXT: %33 = getelementptr inbounds { ptr, i64, { ptr, ptr }, %"{{.*}}/runtime/internal/runtime.String" }, ptr %30, i32 0, i32 2 +// CHECK-NEXT: store { ptr, ptr } %3, ptr %33, align 8 +// CHECK-NEXT: %34 = getelementptr inbounds { ptr, i64, { ptr, ptr }, %"{{.*}}/runtime/internal/runtime.String" }, ptr %30, i32 0, i32 3 +// CHECK-NEXT: store %"{{.*}}/runtime/internal/runtime.String" %28, ptr %34, align 8 +// CHECK-NEXT: store ptr %30, ptr %15, align 8 +// CHECK-NEXT: store ptr blockaddress(@main.complexOrder, %_llgo_20), ptr %14, align 8 +// CHECK-NEXT: br label %_llgo_16 +// CHECK-EMPTY: +// CHECK-NEXT: _llgo_5: ; preds = %_llgo_13, %_llgo_3 +// CHECK-NEXT: %35 = phi i64 [ 0, %_llgo_3 ], [ %63, %_llgo_13 ] +// CHECK-NEXT: %36 = icmp slt i64 %35, 2 +// CHECK-NEXT: br i1 %36, label %_llgo_6, label %_llgo_7 +// CHECK-EMPTY: +// CHECK-NEXT: _llgo_6: ; preds = %_llgo_5 +// CHECK-NEXT: %37 = icmp eq i64 %35, 0 +// CHECK-NEXT: br i1 %37, label %_llgo_8, label %_llgo_10 +// CHECK-EMPTY: +// CHECK-NEXT: _llgo_7: ; preds = %_llgo_5 +// CHECK-NEXT: %38 = add i64 %19, 1 +// CHECK-NEXT: br label %_llgo_2 +// CHECK-EMPTY: +// CHECK-NEXT: _llgo_8: ; preds = %_llgo_6 +// CHECK-NEXT: %39 = call %"{{.*}}/runtime/internal/runtime.String" @main.label2(%"{{.*}}/runtime/internal/runtime.String" { ptr @{{[0-9]+}}, i64 11 }, i64 %19, i64 %35) +// CHECK-NEXT: %40 = load ptr, ptr %15, align 8 +// CHECK-NEXT: %41 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 48) +// CHECK-NEXT: %42 = getelementptr inbounds { ptr, i64, { ptr, ptr }, %"{{.*}}/runtime/internal/runtime.String" }, ptr %41, i32 0, i32 0 +// CHECK-NEXT: store ptr %40, ptr %42, align 8 +// CHECK-NEXT: %43 = getelementptr inbounds { ptr, i64, { ptr, ptr }, %"{{.*}}/runtime/internal/runtime.String" }, ptr %41, i32 0, i32 1 +// CHECK-NEXT: store i64 4, ptr %43, align 8 +// CHECK-NEXT: %44 = getelementptr inbounds { ptr, i64, { ptr, ptr }, %"{{.*}}/runtime/internal/runtime.String" }, ptr %41, i32 0, i32 2 +// CHECK-NEXT: store { ptr, ptr } %3, ptr %44, align 8 +// CHECK-NEXT: %45 = getelementptr inbounds { ptr, i64, { ptr, ptr }, %"{{.*}}/runtime/internal/runtime.String" }, ptr %41, i32 0, i32 3 +// CHECK-NEXT: store %"{{.*}}/runtime/internal/runtime.String" %39, ptr %45, align 8 +// CHECK-NEXT: store ptr %41, ptr %15, align 8 +// CHECK-NEXT: br label %_llgo_9 +// CHECK-EMPTY: +// CHECK-NEXT: _llgo_9: ; preds = %_llgo_10, %_llgo_8 +// CHECK-NEXT: br label %_llgo_11 +// CHECK-EMPTY: +// CHECK-NEXT: _llgo_10: ; preds = %_llgo_6 +// CHECK-NEXT: %46 = call %"{{.*}}/runtime/internal/runtime.String" @main.label2(%"{{.*}}/runtime/internal/runtime.String" { ptr @{{[0-9]+}}, i64 10 }, i64 %19, i64 %35) +// CHECK-NEXT: %47 = load ptr, ptr %15, align 8 +// CHECK-NEXT: %48 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 48) +// CHECK-NEXT: %49 = getelementptr inbounds { ptr, i64, { ptr, ptr }, %"{{.*}}/runtime/internal/runtime.String" }, ptr %48, i32 0, i32 0 +// CHECK-NEXT: store ptr %47, ptr %49, align 8 +// CHECK-NEXT: %50 = getelementptr inbounds { ptr, i64, { ptr, ptr }, %"{{.*}}/runtime/internal/runtime.String" }, ptr %48, i32 0, i32 1 +// CHECK-NEXT: store i64 5, ptr %50, align 8 +// CHECK-NEXT: %51 = getelementptr inbounds { ptr, i64, { ptr, ptr }, %"{{.*}}/runtime/internal/runtime.String" }, ptr %48, i32 0, i32 2 +// CHECK-NEXT: store { ptr, ptr } %3, ptr %51, align 8 +// CHECK-NEXT: %52 = getelementptr inbounds { ptr, i64, { ptr, ptr }, %"{{.*}}/runtime/internal/runtime.String" }, ptr %48, i32 0, i32 3 +// CHECK-NEXT: store %"{{.*}}/runtime/internal/runtime.String" %46, ptr %52, align 8 +// CHECK-NEXT: store ptr %48, ptr %15, align 8 +// CHECK-NEXT: br label %_llgo_9 +// CHECK-EMPTY: +// CHECK-NEXT: _llgo_11: ; preds = %_llgo_15, %_llgo_9 +// CHECK-NEXT: %53 = phi i64 [ 0, %_llgo_9 ], [ %71, %_llgo_15 ] +// CHECK-NEXT: %54 = icmp slt i64 %53, 2 +// CHECK-NEXT: br i1 %54, label %_llgo_12, label %_llgo_13 +// CHECK-EMPTY: +// CHECK-NEXT: _llgo_12: ; preds = %_llgo_11 +// CHECK-NEXT: %55 = call %"{{.*}}/runtime/internal/runtime.String" @main.label3(%"{{.*}}/runtime/internal/runtime.String" { ptr @{{[0-9]+}}, i64 6 }, i64 %19, i64 %35, i64 %53) +// CHECK-NEXT: %56 = load ptr, ptr %15, align 8 +// CHECK-NEXT: %57 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 48) +// CHECK-NEXT: %58 = getelementptr inbounds { ptr, i64, { ptr, ptr }, %"{{.*}}/runtime/internal/runtime.String" }, ptr %57, i32 0, i32 0 +// CHECK-NEXT: store ptr %56, ptr %58, align 8 +// CHECK-NEXT: %59 = getelementptr inbounds { ptr, i64, { ptr, ptr }, %"{{.*}}/runtime/internal/runtime.String" }, ptr %57, i32 0, i32 1 +// CHECK-NEXT: store i64 6, ptr %59, align 8 +// CHECK-NEXT: %60 = getelementptr inbounds { ptr, i64, { ptr, ptr }, %"{{.*}}/runtime/internal/runtime.String" }, ptr %57, i32 0, i32 2 +// CHECK-NEXT: store { ptr, ptr } %3, ptr %60, align 8 +// CHECK-NEXT: %61 = getelementptr inbounds { ptr, i64, { ptr, ptr }, %"{{.*}}/runtime/internal/runtime.String" }, ptr %57, i32 0, i32 3 +// CHECK-NEXT: store %"{{.*}}/runtime/internal/runtime.String" %55, ptr %61, align 8 +// CHECK-NEXT: store ptr %57, ptr %15, align 8 +// CHECK-NEXT: %62 = icmp eq i64 %53, 1 +// CHECK-NEXT: br i1 %62, label %_llgo_14, label %_llgo_15 +// CHECK-EMPTY: +// CHECK-NEXT: _llgo_13: ; preds = %_llgo_11 +// CHECK-NEXT: %63 = add i64 %35, 1 +// CHECK-NEXT: br label %_llgo_5 +// CHECK-EMPTY: +// CHECK-NEXT: _llgo_14: ; preds = %_llgo_12 +// CHECK-NEXT: %64 = call %"{{.*}}/runtime/internal/runtime.String" @main.label3(%"{{.*}}/runtime/internal/runtime.String" { ptr @{{[0-9]+}}, i64 11 }, i64 %19, i64 %35, i64 %53) +// CHECK-NEXT: %65 = load ptr, ptr %15, align 8 +// CHECK-NEXT: %66 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 48) +// CHECK-NEXT: %67 = getelementptr inbounds { ptr, i64, { ptr, ptr }, %"{{.*}}/runtime/internal/runtime.String" }, ptr %66, i32 0, i32 0 +// CHECK-NEXT: store ptr %65, ptr %67, align 8 +// CHECK-NEXT: %68 = getelementptr inbounds { ptr, i64, { ptr, ptr }, %"{{.*}}/runtime/internal/runtime.String" }, ptr %66, i32 0, i32 1 +// CHECK-NEXT: store i64 7, ptr %68, align 8 +// CHECK-NEXT: %69 = getelementptr inbounds { ptr, i64, { ptr, ptr }, %"{{.*}}/runtime/internal/runtime.String" }, ptr %66, i32 0, i32 2 +// CHECK-NEXT: store { ptr, ptr } %3, ptr %69, align 8 +// CHECK-NEXT: %70 = getelementptr inbounds { ptr, i64, { ptr, ptr }, %"{{.*}}/runtime/internal/runtime.String" }, ptr %66, i32 0, i32 3 +// CHECK-NEXT: store %"{{.*}}/runtime/internal/runtime.String" %64, ptr %70, align 8 +// CHECK-NEXT: store ptr %66, ptr %15, align 8 +// CHECK-NEXT: br label %_llgo_15 +// CHECK-EMPTY: +// CHECK-NEXT: _llgo_15: ; preds = %_llgo_14, %_llgo_12 +// CHECK-NEXT: %71 = add i64 %53, 1 +// CHECK-NEXT: br label %_llgo_11 +// CHECK-EMPTY: +// CHECK-NEXT: _llgo_16: ; preds = %_llgo_19, %_llgo_4 +// CHECK-NEXT: store ptr blockaddress(@main.complexOrder, %_llgo_27), ptr %13, align 8 +// CHECK-NEXT: %72 = load i64, ptr %12, align 8 +// CHECK-NEXT: br label %_llgo_28 +// CHECK-EMPTY: +// CHECK-NEXT: _llgo_17: ; preds = %_llgo_19, %_llgo_79 +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.Rethrow"(ptr %5) +// CHECK-NEXT: br label %_llgo_1 +// CHECK-EMPTY: +// CHECK-NEXT: _llgo_18: ; preds = %_llgo_0 +// CHECK-NEXT: %73 = load ptr, ptr %15, align 8 +// CHECK-NEXT: %74 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 48) +// CHECK-NEXT: %75 = getelementptr inbounds { ptr, i64, { ptr, ptr }, %"{{.*}}/runtime/internal/runtime.String" }, ptr %74, i32 0, i32 0 +// CHECK-NEXT: store ptr %73, ptr %75, align 8 +// CHECK-NEXT: %76 = getelementptr inbounds { ptr, i64, { ptr, ptr }, %"{{.*}}/runtime/internal/runtime.String" }, ptr %74, i32 0, i32 1 +// CHECK-NEXT: store i64 0, ptr %76, align 8 +// CHECK-NEXT: %77 = getelementptr inbounds { ptr, i64, { ptr, ptr }, %"{{.*}}/runtime/internal/runtime.String" }, ptr %74, i32 0, i32 2 +// CHECK-NEXT: store { ptr, ptr } %3, ptr %77, align 8 +// CHECK-NEXT: %78 = getelementptr inbounds { ptr, i64, { ptr, ptr }, %"{{.*}}/runtime/internal/runtime.String" }, ptr %74, i32 0, i32 3 +// CHECK-NEXT: store %"{{.*}}/runtime/internal/runtime.String" %4, ptr %78, align 8 +// CHECK-NEXT: store ptr %74, ptr %15, align 8 +// CHECK-NEXT: %79 = call %"{{.*}}/runtime/internal/runtime.String" @main.label1(%"{{.*}}/runtime/internal/runtime.String" { ptr @{{[0-9]+}}, i64 19 }, i64 0) +// CHECK-NEXT: %80 = load ptr, ptr %15, align 8 +// CHECK-NEXT: %81 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 48) +// CHECK-NEXT: %82 = getelementptr inbounds { ptr, i64, { ptr, ptr }, %"{{.*}}/runtime/internal/runtime.String" }, ptr %81, i32 0, i32 0 +// CHECK-NEXT: store ptr %80, ptr %82, align 8 +// CHECK-NEXT: %83 = getelementptr inbounds { ptr, i64, { ptr, ptr }, %"{{.*}}/runtime/internal/runtime.String" }, ptr %81, i32 0, i32 1 +// CHECK-NEXT: store i64 1, ptr %83, align 8 +// CHECK-NEXT: %84 = getelementptr inbounds { ptr, i64, { ptr, ptr }, %"{{.*}}/runtime/internal/runtime.String" }, ptr %81, i32 0, i32 2 +// CHECK-NEXT: store { ptr, ptr } %3, ptr %84, align 8 +// CHECK-NEXT: %85 = getelementptr inbounds { ptr, i64, { ptr, ptr }, %"{{.*}}/runtime/internal/runtime.String" }, ptr %81, i32 0, i32 3 +// CHECK-NEXT: store %"{{.*}}/runtime/internal/runtime.String" %79, ptr %85, align 8 +// CHECK-NEXT: store ptr %81, ptr %15, align 8 +// CHECK-NEXT: br label %_llgo_2 +// CHECK-EMPTY: +// CHECK-NEXT: _llgo_19: ; preds = %_llgo_0 +// CHECK-NEXT: store ptr blockaddress(@main.complexOrder, %_llgo_17), ptr %14, align 8 +// CHECK-NEXT: %86 = load ptr, ptr %13, align 8 +// CHECK-NEXT: indirectbr ptr %86, [label %_llgo_17, label %_llgo_21, label %_llgo_22, label %_llgo_23, label %_llgo_24, label %_llgo_25, label %_llgo_26, label %_llgo_27, label %_llgo_16] +// CHECK-EMPTY: +// CHECK-NEXT: _llgo_20: ; preds = %_llgo_79 +// CHECK-NEXT: %87 = load %"{{.*}}/runtime/internal/runtime.Slice", ptr %0, align 8 +// CHECK-NEXT: ret %"{{.*}}/runtime/internal/runtime.Slice" %87 +// CHECK-EMPTY: +// CHECK-NEXT: _llgo_21: ; preds = %_llgo_19, %_llgo_77 +// CHECK-NEXT: store ptr blockaddress(@main.complexOrder, %_llgo_17), ptr %13, align 8 +// CHECK-NEXT: %88 = load i64, ptr %12, align 8 +// CHECK-NEXT: %89 = load ptr, ptr %15, align 8 +// CHECK-NEXT: %90 = icmp ne ptr %89, null +// CHECK-NEXT: br i1 %90, label %_llgo_78, label %_llgo_79 +// CHECK-EMPTY: +// CHECK-NEXT: _llgo_22: ; preds = %_llgo_19, %_llgo_54 +// CHECK-NEXT: store ptr blockaddress(@main.complexOrder, %_llgo_21), ptr %13, align 8 +// CHECK-NEXT: %91 = load i64, ptr %12, align 8 +// CHECK-NEXT: %92 = load ptr, ptr %15, align 8 +// CHECK-NEXT: %93 = icmp ne ptr %92, null +// CHECK-NEXT: br i1 %93, label %_llgo_76, label %_llgo_77 +// CHECK-EMPTY: +// CHECK-NEXT: _llgo_23: ; preds = %_llgo_19, %_llgo_52 +// CHECK-NEXT: store ptr blockaddress(@main.complexOrder, %_llgo_22), ptr %13, align 8 +// CHECK-NEXT: %94 = load i64, ptr %12, align 8 +// CHECK-NEXT: br label %_llgo_53 +// CHECK-EMPTY: +// CHECK-NEXT: _llgo_24: ; preds = %_llgo_19, %_llgo_25 +// CHECK-NEXT: store ptr blockaddress(@main.complexOrder, %_llgo_23), ptr %13, align 8 +// CHECK-NEXT: %95 = load i64, ptr %12, align 8 +// CHECK-NEXT: %96 = load ptr, ptr %15, align 8 +// CHECK-NEXT: %97 = icmp ne ptr %96, null +// CHECK-NEXT: br i1 %97, label %_llgo_51, label %_llgo_52 +// CHECK-EMPTY: +// CHECK-NEXT: _llgo_25: ; preds = %_llgo_19, %_llgo_26 +// CHECK-NEXT: store ptr blockaddress(@main.complexOrder, %_llgo_24), ptr %13, align 8 +// CHECK-NEXT: %98 = load i64, ptr %12, align 8 +// CHECK-NEXT: br label %_llgo_24 +// CHECK-EMPTY: +// CHECK-NEXT: _llgo_26: ; preds = %_llgo_19, %_llgo_27 +// CHECK-NEXT: store ptr blockaddress(@main.complexOrder, %_llgo_25), ptr %13, align 8 +// CHECK-NEXT: %99 = load i64, ptr %12, align 8 +// CHECK-NEXT: br label %_llgo_25 +// CHECK-EMPTY: +// CHECK-NEXT: _llgo_27: ; preds = %_llgo_19, %_llgo_29 +// CHECK-NEXT: store ptr blockaddress(@main.complexOrder, %_llgo_26), ptr %13, align 8 +// CHECK-NEXT: %100 = load i64, ptr %12, align 8 +// CHECK-NEXT: br label %_llgo_26 +// CHECK-EMPTY: +// CHECK-NEXT: _llgo_28: ; preds = %_llgo_50, %_llgo_48, %_llgo_46, %_llgo_44, %_llgo_42, %_llgo_16 +// CHECK-NEXT: %101 = load ptr, ptr %15, align 8 +// CHECK-NEXT: %102 = icmp ne ptr %101, null +// CHECK-NEXT: br i1 %102, label %_llgo_30, label %_llgo_29 +// CHECK-EMPTY: +// CHECK-NEXT: _llgo_29: ; preds = %_llgo_39, %_llgo_28 +// CHECK-NEXT: br label %_llgo_27 +// CHECK-EMPTY: +// CHECK-NEXT: _llgo_30: ; preds = %_llgo_28 +// CHECK-NEXT: %103 = load { ptr, i64 }, ptr %101, align 8 +// CHECK-NEXT: %104 = extractvalue { ptr, i64 } %103, 1 +// CHECK-NEXT: br label %_llgo_31 +// CHECK-EMPTY: +// CHECK-NEXT: _llgo_31: ; preds = %_llgo_30 +// CHECK-NEXT: %105 = icmp eq i64 %104, 2 +// CHECK-NEXT: br i1 %105, label %_llgo_32, label %_llgo_33 +// CHECK-EMPTY: +// CHECK-NEXT: _llgo_32: ; preds = %_llgo_31 +// CHECK-NEXT: store ptr blockaddress(@main.complexOrder, %_llgo_16), ptr %13, align 8 +// CHECK-NEXT: %106 = load ptr, ptr %15, align 8 +// CHECK-NEXT: %107 = icmp ne ptr %106, null +// CHECK-NEXT: br i1 %107, label %_llgo_41, label %_llgo_42 +// CHECK-EMPTY: +// CHECK-NEXT: _llgo_33: ; preds = %_llgo_31 +// CHECK-NEXT: %108 = icmp eq i64 %104, 4 +// CHECK-NEXT: br i1 %108, label %_llgo_34, label %_llgo_35 +// CHECK-EMPTY: +// CHECK-NEXT: _llgo_34: ; preds = %_llgo_33 +// CHECK-NEXT: store ptr blockaddress(@main.complexOrder, %_llgo_16), ptr %13, align 8 +// CHECK-NEXT: %109 = load ptr, ptr %15, align 8 +// CHECK-NEXT: %110 = icmp ne ptr %109, null +// CHECK-NEXT: br i1 %110, label %_llgo_43, label %_llgo_44 +// CHECK-EMPTY: +// CHECK-NEXT: _llgo_35: ; preds = %_llgo_33 +// CHECK-NEXT: %111 = icmp eq i64 %104, 5 +// CHECK-NEXT: br i1 %111, label %_llgo_36, label %_llgo_37 +// CHECK-EMPTY: +// CHECK-NEXT: _llgo_36: ; preds = %_llgo_35 +// CHECK-NEXT: store ptr blockaddress(@main.complexOrder, %_llgo_16), ptr %13, align 8 +// CHECK-NEXT: %112 = load ptr, ptr %15, align 8 +// CHECK-NEXT: %113 = icmp ne ptr %112, null +// CHECK-NEXT: br i1 %113, label %_llgo_45, label %_llgo_46 +// CHECK-EMPTY: +// CHECK-NEXT: _llgo_37: ; preds = %_llgo_35 +// CHECK-NEXT: %114 = icmp eq i64 %104, 6 +// CHECK-NEXT: br i1 %114, label %_llgo_38, label %_llgo_39 +// CHECK-EMPTY: +// CHECK-NEXT: _llgo_38: ; preds = %_llgo_37 +// CHECK-NEXT: store ptr blockaddress(@main.complexOrder, %_llgo_16), ptr %13, align 8 +// CHECK-NEXT: %115 = load ptr, ptr %15, align 8 +// CHECK-NEXT: %116 = icmp ne ptr %115, null +// CHECK-NEXT: br i1 %116, label %_llgo_47, label %_llgo_48 +// CHECK-EMPTY: +// CHECK-NEXT: _llgo_39: ; preds = %_llgo_37 +// CHECK-NEXT: %117 = icmp eq i64 %104, 7 +// CHECK-NEXT: br i1 %117, label %_llgo_40, label %_llgo_29 +// CHECK-EMPTY: +// CHECK-NEXT: _llgo_40: ; preds = %_llgo_39 +// CHECK-NEXT: store ptr blockaddress(@main.complexOrder, %_llgo_16), ptr %13, align 8 +// CHECK-NEXT: %118 = load ptr, ptr %15, align 8 +// CHECK-NEXT: %119 = icmp ne ptr %118, null +// CHECK-NEXT: br i1 %119, label %_llgo_49, label %_llgo_50 +// CHECK-EMPTY: +// CHECK-NEXT: _llgo_41: ; preds = %_llgo_32 +// CHECK-NEXT: %120 = load ptr, ptr %15, align 8 +// CHECK-NEXT: %121 = load { ptr, i64, { ptr, ptr }, %"{{.*}}/runtime/internal/runtime.String" }, ptr %120, align 8 +// CHECK-NEXT: %122 = extractvalue { ptr, i64, { ptr, ptr }, %"{{.*}}/runtime/internal/runtime.String" } %121, 0 +// CHECK-NEXT: store ptr %122, ptr %15, align 8 +// CHECK-NEXT: %123 = extractvalue { ptr, i64, { ptr, ptr }, %"{{.*}}/runtime/internal/runtime.String" } %121, 2 +// CHECK-NEXT: %124 = extractvalue { ptr, i64, { ptr, ptr }, %"{{.*}}/runtime/internal/runtime.String" } %121, 3 +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.FreeDeferNode"(ptr %120) +// CHECK-NEXT: %125 = extractvalue { ptr, ptr } %123, 1 +// CHECK-NEXT: %126 = extractvalue { ptr, ptr } %123, 0 +// CHECK-NEXT: %__llgo_funcval_code = call ptr asm "", "=r,0"(ptr %126) +// CHECK-NEXT: call void %__llgo_funcval_code(ptr {{(nest|swiftself)}} %125, %"{{.*}}/runtime/internal/runtime.String" %124) +// CHECK-NEXT: br label %_llgo_42 +// CHECK-EMPTY: +// CHECK-NEXT: _llgo_42: ; preds = %_llgo_41, %_llgo_32 +// CHECK-NEXT: br label %_llgo_28 +// CHECK-EMPTY: +// CHECK-NEXT: _llgo_43: ; preds = %_llgo_34 +// CHECK-NEXT: %127 = load ptr, ptr %15, align 8 +// CHECK-NEXT: %128 = load { ptr, i64, { ptr, ptr }, %"{{.*}}/runtime/internal/runtime.String" }, ptr %127, align 8 +// CHECK-NEXT: %129 = extractvalue { ptr, i64, { ptr, ptr }, %"{{.*}}/runtime/internal/runtime.String" } %128, 0 +// CHECK-NEXT: store ptr %129, ptr %15, align 8 +// CHECK-NEXT: %130 = extractvalue { ptr, i64, { ptr, ptr }, %"{{.*}}/runtime/internal/runtime.String" } %128, 2 +// CHECK-NEXT: %131 = extractvalue { ptr, i64, { ptr, ptr }, %"{{.*}}/runtime/internal/runtime.String" } %128, 3 +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.FreeDeferNode"(ptr %127) +// CHECK-NEXT: %132 = extractvalue { ptr, ptr } %130, 1 +// CHECK-NEXT: %133 = extractvalue { ptr, ptr } %130, 0 +// CHECK-NEXT: %__llgo_funcval_code1 = call ptr asm "", "=r,0"(ptr %133) +// CHECK-NEXT: call void %__llgo_funcval_code1(ptr {{(nest|swiftself)}} %132, %"{{.*}}/runtime/internal/runtime.String" %131) +// CHECK-NEXT: br label %_llgo_44 +// CHECK-EMPTY: +// CHECK-NEXT: _llgo_44: ; preds = %_llgo_43, %_llgo_34 +// CHECK-NEXT: br label %_llgo_28 +// CHECK-EMPTY: +// CHECK-NEXT: _llgo_45: ; preds = %_llgo_36 +// CHECK-NEXT: %134 = load ptr, ptr %15, align 8 +// CHECK-NEXT: %135 = load { ptr, i64, { ptr, ptr }, %"{{.*}}/runtime/internal/runtime.String" }, ptr %134, align 8 +// CHECK-NEXT: %136 = extractvalue { ptr, i64, { ptr, ptr }, %"{{.*}}/runtime/internal/runtime.String" } %135, 0 +// CHECK-NEXT: store ptr %136, ptr %15, align 8 +// CHECK-NEXT: %137 = extractvalue { ptr, i64, { ptr, ptr }, %"{{.*}}/runtime/internal/runtime.String" } %135, 2 +// CHECK-NEXT: %138 = extractvalue { ptr, i64, { ptr, ptr }, %"{{.*}}/runtime/internal/runtime.String" } %135, 3 +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.FreeDeferNode"(ptr %134) +// CHECK-NEXT: %139 = extractvalue { ptr, ptr } %137, 1 +// CHECK-NEXT: %140 = extractvalue { ptr, ptr } %137, 0 +// CHECK-NEXT: %__llgo_funcval_code2 = call ptr asm "", "=r,0"(ptr %140) +// CHECK-NEXT: call void %__llgo_funcval_code2(ptr {{(nest|swiftself)}} %139, %"{{.*}}/runtime/internal/runtime.String" %138) +// CHECK-NEXT: br label %_llgo_46 +// CHECK-EMPTY: +// CHECK-NEXT: _llgo_46: ; preds = %_llgo_45, %_llgo_36 +// CHECK-NEXT: br label %_llgo_28 +// CHECK-EMPTY: +// CHECK-NEXT: _llgo_47: ; preds = %_llgo_38 +// CHECK-NEXT: %141 = load ptr, ptr %15, align 8 +// CHECK-NEXT: %142 = load { ptr, i64, { ptr, ptr }, %"{{.*}}/runtime/internal/runtime.String" }, ptr %141, align 8 +// CHECK-NEXT: %143 = extractvalue { ptr, i64, { ptr, ptr }, %"{{.*}}/runtime/internal/runtime.String" } %142, 0 +// CHECK-NEXT: store ptr %143, ptr %15, align 8 +// CHECK-NEXT: %144 = extractvalue { ptr, i64, { ptr, ptr }, %"{{.*}}/runtime/internal/runtime.String" } %142, 2 +// CHECK-NEXT: %145 = extractvalue { ptr, i64, { ptr, ptr }, %"{{.*}}/runtime/internal/runtime.String" } %142, 3 +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.FreeDeferNode"(ptr %141) +// CHECK-NEXT: %146 = extractvalue { ptr, ptr } %144, 1 +// CHECK-NEXT: %147 = extractvalue { ptr, ptr } %144, 0 +// CHECK-NEXT: %__llgo_funcval_code3 = call ptr asm "", "=r,0"(ptr %147) +// CHECK-NEXT: call void %__llgo_funcval_code3(ptr {{(nest|swiftself)}} %146, %"{{.*}}/runtime/internal/runtime.String" %145) +// CHECK-NEXT: br label %_llgo_48 +// CHECK-EMPTY: +// CHECK-NEXT: _llgo_48: ; preds = %_llgo_47, %_llgo_38 +// CHECK-NEXT: br label %_llgo_28 +// CHECK-EMPTY: +// CHECK-NEXT: _llgo_49: ; preds = %_llgo_40 +// CHECK-NEXT: %148 = load ptr, ptr %15, align 8 +// CHECK-NEXT: %149 = load { ptr, i64, { ptr, ptr }, %"{{.*}}/runtime/internal/runtime.String" }, ptr %148, align 8 +// CHECK-NEXT: %150 = extractvalue { ptr, i64, { ptr, ptr }, %"{{.*}}/runtime/internal/runtime.String" } %149, 0 +// CHECK-NEXT: store ptr %150, ptr %15, align 8 +// CHECK-NEXT: %151 = extractvalue { ptr, i64, { ptr, ptr }, %"{{.*}}/runtime/internal/runtime.String" } %149, 2 +// CHECK-NEXT: %152 = extractvalue { ptr, i64, { ptr, ptr }, %"{{.*}}/runtime/internal/runtime.String" } %149, 3 +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.FreeDeferNode"(ptr %148) +// CHECK-NEXT: %153 = extractvalue { ptr, ptr } %151, 1 +// CHECK-NEXT: %154 = extractvalue { ptr, ptr } %151, 0 +// CHECK-NEXT: %__llgo_funcval_code4 = call ptr asm "", "=r,0"(ptr %154) +// CHECK-NEXT: call void %__llgo_funcval_code4(ptr {{(nest|swiftself)}} %153, %"{{.*}}/runtime/internal/runtime.String" %152) +// CHECK-NEXT: br label %_llgo_50 +// CHECK-EMPTY: +// CHECK-NEXT: _llgo_50: ; preds = %_llgo_49, %_llgo_40 +// CHECK-NEXT: br label %_llgo_28 +// CHECK-EMPTY: +// CHECK-NEXT: _llgo_51: ; preds = %_llgo_24 +// CHECK-NEXT: %155 = load ptr, ptr %15, align 8 +// CHECK-NEXT: %156 = load { ptr, i64, { ptr, ptr }, %"{{.*}}/runtime/internal/runtime.String" }, ptr %155, align 8 +// CHECK-NEXT: %157 = extractvalue { ptr, i64, { ptr, ptr }, %"{{.*}}/runtime/internal/runtime.String" } %156, 0 +// CHECK-NEXT: store ptr %157, ptr %15, align 8 +// CHECK-NEXT: %158 = extractvalue { ptr, i64, { ptr, ptr }, %"{{.*}}/runtime/internal/runtime.String" } %156, 2 +// CHECK-NEXT: %159 = extractvalue { ptr, i64, { ptr, ptr }, %"{{.*}}/runtime/internal/runtime.String" } %156, 3 +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.FreeDeferNode"(ptr %155) +// CHECK-NEXT: %160 = extractvalue { ptr, ptr } %158, 1 +// CHECK-NEXT: %161 = extractvalue { ptr, ptr } %158, 0 +// CHECK-NEXT: %__llgo_funcval_code5 = call ptr asm "", "=r,0"(ptr %161) +// CHECK-NEXT: call void %__llgo_funcval_code5(ptr {{(nest|swiftself)}} %160, %"{{.*}}/runtime/internal/runtime.String" %159) +// CHECK-NEXT: br label %_llgo_52 +// CHECK-EMPTY: +// CHECK-NEXT: _llgo_52: ; preds = %_llgo_51, %_llgo_24 +// CHECK-NEXT: br label %_llgo_23 +// CHECK-EMPTY: +// CHECK-NEXT: _llgo_53: ; preds = %_llgo_75, %_llgo_73, %_llgo_71, %_llgo_69, %_llgo_67, %_llgo_23 +// CHECK-NEXT: %162 = load ptr, ptr %15, align 8 +// CHECK-NEXT: %163 = icmp ne ptr %162, null +// CHECK-NEXT: br i1 %163, label %_llgo_55, label %_llgo_54 +// CHECK-EMPTY: +// CHECK-NEXT: _llgo_54: ; preds = %_llgo_64, %_llgo_53 +// CHECK-NEXT: br label %_llgo_22 +// CHECK-EMPTY: +// CHECK-NEXT: _llgo_55: ; preds = %_llgo_53 +// CHECK-NEXT: %164 = load { ptr, i64 }, ptr %162, align 8 +// CHECK-NEXT: %165 = extractvalue { ptr, i64 } %164, 1 +// CHECK-NEXT: br label %_llgo_56 +// CHECK-EMPTY: +// CHECK-NEXT: _llgo_56: ; preds = %_llgo_55 +// CHECK-NEXT: %166 = icmp eq i64 %165, 2 +// CHECK-NEXT: br i1 %166, label %_llgo_57, label %_llgo_58 +// CHECK-EMPTY: +// CHECK-NEXT: _llgo_57: ; preds = %_llgo_56 +// CHECK-NEXT: store ptr blockaddress(@main.complexOrder, %_llgo_23), ptr %13, align 8 +// CHECK-NEXT: %167 = load ptr, ptr %15, align 8 +// CHECK-NEXT: %168 = icmp ne ptr %167, null +// CHECK-NEXT: br i1 %168, label %_llgo_66, label %_llgo_67 +// CHECK-EMPTY: +// CHECK-NEXT: _llgo_58: ; preds = %_llgo_56 +// CHECK-NEXT: %169 = icmp eq i64 %165, 4 +// CHECK-NEXT: br i1 %169, label %_llgo_59, label %_llgo_60 +// CHECK-EMPTY: +// CHECK-NEXT: _llgo_59: ; preds = %_llgo_58 +// CHECK-NEXT: store ptr blockaddress(@main.complexOrder, %_llgo_23), ptr %13, align 8 +// CHECK-NEXT: %170 = load ptr, ptr %15, align 8 +// CHECK-NEXT: %171 = icmp ne ptr %170, null +// CHECK-NEXT: br i1 %171, label %_llgo_68, label %_llgo_69 +// CHECK-EMPTY: +// CHECK-NEXT: _llgo_60: ; preds = %_llgo_58 +// CHECK-NEXT: %172 = icmp eq i64 %165, 5 +// CHECK-NEXT: br i1 %172, label %_llgo_61, label %_llgo_62 +// CHECK-EMPTY: +// CHECK-NEXT: _llgo_61: ; preds = %_llgo_60 +// CHECK-NEXT: store ptr blockaddress(@main.complexOrder, %_llgo_23), ptr %13, align 8 +// CHECK-NEXT: %173 = load ptr, ptr %15, align 8 +// CHECK-NEXT: %174 = icmp ne ptr %173, null +// CHECK-NEXT: br i1 %174, label %_llgo_70, label %_llgo_71 +// CHECK-EMPTY: +// CHECK-NEXT: _llgo_62: ; preds = %_llgo_60 +// CHECK-NEXT: %175 = icmp eq i64 %165, 6 +// CHECK-NEXT: br i1 %175, label %_llgo_63, label %_llgo_64 +// CHECK-EMPTY: +// CHECK-NEXT: _llgo_63: ; preds = %_llgo_62 +// CHECK-NEXT: store ptr blockaddress(@main.complexOrder, %_llgo_23), ptr %13, align 8 +// CHECK-NEXT: %176 = load ptr, ptr %15, align 8 +// CHECK-NEXT: %177 = icmp ne ptr %176, null +// CHECK-NEXT: br i1 %177, label %_llgo_72, label %_llgo_73 +// CHECK-EMPTY: +// CHECK-NEXT: _llgo_64: ; preds = %_llgo_62 +// CHECK-NEXT: %178 = icmp eq i64 %165, 7 +// CHECK-NEXT: br i1 %178, label %_llgo_65, label %_llgo_54 +// CHECK-EMPTY: +// CHECK-NEXT: _llgo_65: ; preds = %_llgo_64 +// CHECK-NEXT: store ptr blockaddress(@main.complexOrder, %_llgo_23), ptr %13, align 8 +// CHECK-NEXT: %179 = load ptr, ptr %15, align 8 +// CHECK-NEXT: %180 = icmp ne ptr %179, null +// CHECK-NEXT: br i1 %180, label %_llgo_74, label %_llgo_75 +// CHECK-EMPTY: +// CHECK-NEXT: _llgo_66: ; preds = %_llgo_57 +// CHECK-NEXT: %181 = load ptr, ptr %15, align 8 +// CHECK-NEXT: %182 = load { ptr, i64, { ptr, ptr }, %"{{.*}}/runtime/internal/runtime.String" }, ptr %181, align 8 +// CHECK-NEXT: %183 = extractvalue { ptr, i64, { ptr, ptr }, %"{{.*}}/runtime/internal/runtime.String" } %182, 0 +// CHECK-NEXT: store ptr %183, ptr %15, align 8 +// CHECK-NEXT: %184 = extractvalue { ptr, i64, { ptr, ptr }, %"{{.*}}/runtime/internal/runtime.String" } %182, 2 +// CHECK-NEXT: %185 = extractvalue { ptr, i64, { ptr, ptr }, %"{{.*}}/runtime/internal/runtime.String" } %182, 3 +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.FreeDeferNode"(ptr %181) +// CHECK-NEXT: %186 = extractvalue { ptr, ptr } %184, 1 +// CHECK-NEXT: %187 = extractvalue { ptr, ptr } %184, 0 +// CHECK-NEXT: %__llgo_funcval_code6 = call ptr asm "", "=r,0"(ptr %187) +// CHECK-NEXT: call void %__llgo_funcval_code6(ptr {{(nest|swiftself)}} %186, %"{{.*}}/runtime/internal/runtime.String" %185) +// CHECK-NEXT: br label %_llgo_67 +// CHECK-EMPTY: +// CHECK-NEXT: _llgo_67: ; preds = %_llgo_66, %_llgo_57 +// CHECK-NEXT: br label %_llgo_53 +// CHECK-EMPTY: +// CHECK-NEXT: _llgo_68: ; preds = %_llgo_59 +// CHECK-NEXT: %188 = load ptr, ptr %15, align 8 +// CHECK-NEXT: %189 = load { ptr, i64, { ptr, ptr }, %"{{.*}}/runtime/internal/runtime.String" }, ptr %188, align 8 +// CHECK-NEXT: %190 = extractvalue { ptr, i64, { ptr, ptr }, %"{{.*}}/runtime/internal/runtime.String" } %189, 0 +// CHECK-NEXT: store ptr %190, ptr %15, align 8 +// CHECK-NEXT: %191 = extractvalue { ptr, i64, { ptr, ptr }, %"{{.*}}/runtime/internal/runtime.String" } %189, 2 +// CHECK-NEXT: %192 = extractvalue { ptr, i64, { ptr, ptr }, %"{{.*}}/runtime/internal/runtime.String" } %189, 3 +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.FreeDeferNode"(ptr %188) +// CHECK-NEXT: %193 = extractvalue { ptr, ptr } %191, 1 +// CHECK-NEXT: %194 = extractvalue { ptr, ptr } %191, 0 +// CHECK-NEXT: %__llgo_funcval_code7 = call ptr asm "", "=r,0"(ptr %194) +// CHECK-NEXT: call void %__llgo_funcval_code7(ptr {{(nest|swiftself)}} %193, %"{{.*}}/runtime/internal/runtime.String" %192) +// CHECK-NEXT: br label %_llgo_69 +// CHECK-EMPTY: +// CHECK-NEXT: _llgo_69: ; preds = %_llgo_68, %_llgo_59 +// CHECK-NEXT: br label %_llgo_53 +// CHECK-EMPTY: +// CHECK-NEXT: _llgo_70: ; preds = %_llgo_61 +// CHECK-NEXT: %195 = load ptr, ptr %15, align 8 +// CHECK-NEXT: %196 = load { ptr, i64, { ptr, ptr }, %"{{.*}}/runtime/internal/runtime.String" }, ptr %195, align 8 +// CHECK-NEXT: %197 = extractvalue { ptr, i64, { ptr, ptr }, %"{{.*}}/runtime/internal/runtime.String" } %196, 0 +// CHECK-NEXT: store ptr %197, ptr %15, align 8 +// CHECK-NEXT: %198 = extractvalue { ptr, i64, { ptr, ptr }, %"{{.*}}/runtime/internal/runtime.String" } %196, 2 +// CHECK-NEXT: %199 = extractvalue { ptr, i64, { ptr, ptr }, %"{{.*}}/runtime/internal/runtime.String" } %196, 3 +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.FreeDeferNode"(ptr %195) +// CHECK-NEXT: %200 = extractvalue { ptr, ptr } %198, 1 +// CHECK-NEXT: %201 = extractvalue { ptr, ptr } %198, 0 +// CHECK-NEXT: %__llgo_funcval_code8 = call ptr asm "", "=r,0"(ptr %201) +// CHECK-NEXT: call void %__llgo_funcval_code8(ptr {{(nest|swiftself)}} %200, %"{{.*}}/runtime/internal/runtime.String" %199) +// CHECK-NEXT: br label %_llgo_71 +// CHECK-EMPTY: +// CHECK-NEXT: _llgo_71: ; preds = %_llgo_70, %_llgo_61 +// CHECK-NEXT: br label %_llgo_53 +// CHECK-EMPTY: +// CHECK-NEXT: _llgo_72: ; preds = %_llgo_63 +// CHECK-NEXT: %202 = load ptr, ptr %15, align 8 +// CHECK-NEXT: %203 = load { ptr, i64, { ptr, ptr }, %"{{.*}}/runtime/internal/runtime.String" }, ptr %202, align 8 +// CHECK-NEXT: %204 = extractvalue { ptr, i64, { ptr, ptr }, %"{{.*}}/runtime/internal/runtime.String" } %203, 0 +// CHECK-NEXT: store ptr %204, ptr %15, align 8 +// CHECK-NEXT: %205 = extractvalue { ptr, i64, { ptr, ptr }, %"{{.*}}/runtime/internal/runtime.String" } %203, 2 +// CHECK-NEXT: %206 = extractvalue { ptr, i64, { ptr, ptr }, %"{{.*}}/runtime/internal/runtime.String" } %203, 3 +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.FreeDeferNode"(ptr %202) +// CHECK-NEXT: %207 = extractvalue { ptr, ptr } %205, 1 +// CHECK-NEXT: %208 = extractvalue { ptr, ptr } %205, 0 +// CHECK-NEXT: %__llgo_funcval_code9 = call ptr asm "", "=r,0"(ptr %208) +// CHECK-NEXT: call void %__llgo_funcval_code9(ptr {{(nest|swiftself)}} %207, %"{{.*}}/runtime/internal/runtime.String" %206) +// CHECK-NEXT: br label %_llgo_73 +// CHECK-EMPTY: +// CHECK-NEXT: _llgo_73: ; preds = %_llgo_72, %_llgo_63 +// CHECK-NEXT: br label %_llgo_53 +// CHECK-EMPTY: +// CHECK-NEXT: _llgo_74: ; preds = %_llgo_65 +// CHECK-NEXT: %209 = load ptr, ptr %15, align 8 +// CHECK-NEXT: %210 = load { ptr, i64, { ptr, ptr }, %"{{.*}}/runtime/internal/runtime.String" }, ptr %209, align 8 +// CHECK-NEXT: %211 = extractvalue { ptr, i64, { ptr, ptr }, %"{{.*}}/runtime/internal/runtime.String" } %210, 0 +// CHECK-NEXT: store ptr %211, ptr %15, align 8 +// CHECK-NEXT: %212 = extractvalue { ptr, i64, { ptr, ptr }, %"{{.*}}/runtime/internal/runtime.String" } %210, 2 +// CHECK-NEXT: %213 = extractvalue { ptr, i64, { ptr, ptr }, %"{{.*}}/runtime/internal/runtime.String" } %210, 3 +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.FreeDeferNode"(ptr %209) +// CHECK-NEXT: %214 = extractvalue { ptr, ptr } %212, 1 +// CHECK-NEXT: %215 = extractvalue { ptr, ptr } %212, 0 +// CHECK-NEXT: %__llgo_funcval_code10 = call ptr asm "", "=r,0"(ptr %215) +// CHECK-NEXT: call void %__llgo_funcval_code10(ptr {{(nest|swiftself)}} %214, %"{{.*}}/runtime/internal/runtime.String" %213) +// CHECK-NEXT: br label %_llgo_75 +// CHECK-EMPTY: +// CHECK-NEXT: _llgo_75: ; preds = %_llgo_74, %_llgo_65 +// CHECK-NEXT: br label %_llgo_53 +// CHECK-EMPTY: +// CHECK-NEXT: _llgo_76: ; preds = %_llgo_22 +// CHECK-NEXT: %216 = load ptr, ptr %15, align 8 +// CHECK-NEXT: %217 = load { ptr, i64, { ptr, ptr }, %"{{.*}}/runtime/internal/runtime.String" }, ptr %216, align 8 +// CHECK-NEXT: %218 = extractvalue { ptr, i64, { ptr, ptr }, %"{{.*}}/runtime/internal/runtime.String" } %217, 0 +// CHECK-NEXT: store ptr %218, ptr %15, align 8 +// CHECK-NEXT: %219 = extractvalue { ptr, i64, { ptr, ptr }, %"{{.*}}/runtime/internal/runtime.String" } %217, 2 +// CHECK-NEXT: %220 = extractvalue { ptr, i64, { ptr, ptr }, %"{{.*}}/runtime/internal/runtime.String" } %217, 3 +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.FreeDeferNode"(ptr %216) +// CHECK-NEXT: %221 = extractvalue { ptr, ptr } %219, 1 +// CHECK-NEXT: %222 = extractvalue { ptr, ptr } %219, 0 +// CHECK-NEXT: %__llgo_funcval_code11 = call ptr asm "", "=r,0"(ptr %222) +// CHECK-NEXT: call void %__llgo_funcval_code11(ptr {{(nest|swiftself)}} %221, %"{{.*}}/runtime/internal/runtime.String" %220) +// CHECK-NEXT: br label %_llgo_77 +// CHECK-EMPTY: +// CHECK-NEXT: _llgo_77: ; preds = %_llgo_76, %_llgo_22 +// CHECK-NEXT: br label %_llgo_21 +// CHECK-EMPTY: +// CHECK-NEXT: _llgo_78: ; preds = %_llgo_21 +// CHECK-NEXT: %223 = load ptr, ptr %15, align 8 +// CHECK-NEXT: %224 = load { ptr, i64, { ptr, ptr }, %"{{.*}}/runtime/internal/runtime.String" }, ptr %223, align 8 +// CHECK-NEXT: %225 = extractvalue { ptr, i64, { ptr, ptr }, %"{{.*}}/runtime/internal/runtime.String" } %224, 0 +// CHECK-NEXT: store ptr %225, ptr %15, align 8 +// CHECK-NEXT: %226 = extractvalue { ptr, i64, { ptr, ptr }, %"{{.*}}/runtime/internal/runtime.String" } %224, 2 +// CHECK-NEXT: %227 = extractvalue { ptr, i64, { ptr, ptr }, %"{{.*}}/runtime/internal/runtime.String" } %224, 3 +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.FreeDeferNode"(ptr %223) +// CHECK-NEXT: %228 = extractvalue { ptr, ptr } %226, 1 +// CHECK-NEXT: %229 = extractvalue { ptr, ptr } %226, 0 +// CHECK-NEXT: %__llgo_funcval_code12 = call ptr asm "", "=r,0"(ptr %229) +// CHECK-NEXT: call void %__llgo_funcval_code12(ptr {{(nest|swiftself)}} %228, %"{{.*}}/runtime/internal/runtime.String" %227) +// CHECK-NEXT: br label %_llgo_79 +// CHECK-EMPTY: +// CHECK-NEXT: _llgo_79: ; preds = %_llgo_78, %_llgo_21 +// CHECK-NEXT: %230 = load %"{{.*}}/runtime/internal/runtime.Defer", ptr %7, align 8 +// CHECK-NEXT: %231 = extractvalue %"{{.*}}/runtime/internal/runtime.Defer" %230, 2 +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.SetThreadDefer"(ptr %231) +// CHECK-NEXT: %232 = load ptr, ptr %14, align 8 +// CHECK-NEXT: indirectbr ptr %232, [label %_llgo_17, label %_llgo_20] +// CHECK-NEXT: } + +// CHECK-LABEL: define void @"main.complexOrder$1"(ptr {{(nest|swiftself)}} %0, %"{{.*}}/runtime/internal/runtime.String" %1){{.*}} { +// CHECK-NEXT: _llgo_0: +// CHECK-NEXT: %2 = load { ptr }, ptr %0, align 8 +// CHECK-NEXT: %3 = extractvalue { ptr } %2, 0 +// CHECK-NEXT: %4 = load %"{{.*}}/runtime/internal/runtime.Slice", ptr %3, align 8 +// CHECK-NEXT: %5 = call ptr @"{{.*}}/runtime/internal/runtime.AllocZ"(i64 16) +// CHECK-NEXT: %6 = getelementptr inbounds %"{{.*}}/runtime/internal/runtime.String", ptr %5, i64 0 +// CHECK-NEXT: store %"{{.*}}/runtime/internal/runtime.String" %1, ptr %6, align 8 +// CHECK-NEXT: %7 = insertvalue %"{{.*}}/runtime/internal/runtime.Slice" undef, ptr %5, 0 +// CHECK-NEXT: %8 = insertvalue %"{{.*}}/runtime/internal/runtime.Slice" %7, i64 1, 1 +// CHECK-NEXT: %9 = insertvalue %"{{.*}}/runtime/internal/runtime.Slice" %8, i64 1, 2 +// CHECK-NEXT: %10 = extractvalue %"{{.*}}/runtime/internal/runtime.Slice" %9, 0 +// CHECK-NEXT: %11 = extractvalue %"{{.*}}/runtime/internal/runtime.Slice" %9, 1 +// CHECK-NEXT: %12 = call %"{{.*}}/runtime/internal/runtime.Slice" @"{{.*}}/runtime/internal/runtime.SliceAppend"(%"{{.*}}/runtime/internal/runtime.Slice" %4, ptr %10, i64 %11, i64 16) +// CHECK-NEXT: %13 = extractvalue { ptr } %2, 0 +// CHECK-NEXT: store %"{{.*}}/runtime/internal/runtime.Slice" %12, ptr %13, align 8 +// CHECK-NEXT: ret void +// CHECK-NEXT: } + +// CHECK-LABEL: define %"{{.*}}/runtime/internal/runtime.String" @main.digit(i64 %0){{.*}} { +// CHECK-NEXT: _llgo_0: +// CHECK-NEXT: %1 = add i64 48, %0 +// CHECK-NEXT: %2 = trunc i64 %1 to i32 +// CHECK-NEXT: %3 = sext i32 %2 to i64 +// CHECK-NEXT: %4 = call %"{{.*}}/runtime/internal/runtime.String" @"{{.*}}/runtime/internal/runtime.StringFromInt64"(i64 %3) +// CHECK-NEXT: ret %"{{.*}}/runtime/internal/runtime.String" %4 +// CHECK-NEXT: } + +// CHECK-LABEL: define void @main.init(){{.*}} { +// CHECK-NEXT: _llgo_0: +// CHECK-NEXT: %0 = load i1, ptr @"main.init$guard", align 1 +// CHECK-NEXT: br i1 %0, label %_llgo_2, label %_llgo_1 +// CHECK-EMPTY: +// CHECK-NEXT: _llgo_1: ; preds = %_llgo_0 +// CHECK-NEXT: store i1 true, ptr @"main.init$guard", align 1 +// CHECK-NEXT: br label %_llgo_2 +// CHECK-EMPTY: +// CHECK-NEXT: _llgo_2: ; preds = %_llgo_1, %_llgo_0 +// CHECK-NEXT: ret void +// CHECK-NEXT: } + +// CHECK-LABEL: define %"{{.*}}/runtime/internal/runtime.String" @main.label1(%"{{.*}}/runtime/internal/runtime.String" %0, i64 %1){{.*}} { +// CHECK-NEXT: _llgo_0: +// CHECK-NEXT: %2 = call %"{{.*}}/runtime/internal/runtime.String" @"{{.*}}/runtime/internal/runtime.StringCat"(%"{{.*}}/runtime/internal/runtime.String" %0, %"{{.*}}/runtime/internal/runtime.String" { ptr @{{[0-9]+}}, i64 1 }) +// CHECK-NEXT: %3 = call %"{{.*}}/runtime/internal/runtime.String" @main.digit(i64 %1) +// CHECK-NEXT: %4 = call %"{{.*}}/runtime/internal/runtime.String" @"{{.*}}/runtime/internal/runtime.StringCat"(%"{{.*}}/runtime/internal/runtime.String" %2, %"{{.*}}/runtime/internal/runtime.String" %3) +// CHECK-NEXT: ret %"{{.*}}/runtime/internal/runtime.String" %4 +// CHECK-NEXT: } + +// CHECK-LABEL: define %"{{.*}}/runtime/internal/runtime.String" @main.label2(%"{{.*}}/runtime/internal/runtime.String" %0, i64 %1, i64 %2){{.*}} { +// CHECK-NEXT: _llgo_0: +// CHECK-NEXT: %3 = call %"{{.*}}/runtime/internal/runtime.String" @"{{.*}}/runtime/internal/runtime.StringCat"(%"{{.*}}/runtime/internal/runtime.String" %0, %"{{.*}}/runtime/internal/runtime.String" { ptr @{{[0-9]+}}, i64 1 }) +// CHECK-NEXT: %4 = call %"{{.*}}/runtime/internal/runtime.String" @main.digit(i64 %1) +// CHECK-NEXT: %5 = call %"{{.*}}/runtime/internal/runtime.String" @"{{.*}}/runtime/internal/runtime.StringCat"(%"{{.*}}/runtime/internal/runtime.String" %3, %"{{.*}}/runtime/internal/runtime.String" %4) +// CHECK-NEXT: %6 = call %"{{.*}}/runtime/internal/runtime.String" @"{{.*}}/runtime/internal/runtime.StringCat"(%"{{.*}}/runtime/internal/runtime.String" %5, %"{{.*}}/runtime/internal/runtime.String" { ptr @{{[0-9]+}}, i64 1 }) +// CHECK-NEXT: %7 = call %"{{.*}}/runtime/internal/runtime.String" @main.digit(i64 %2) +// CHECK-NEXT: %8 = call %"{{.*}}/runtime/internal/runtime.String" @"{{.*}}/runtime/internal/runtime.StringCat"(%"{{.*}}/runtime/internal/runtime.String" %6, %"{{.*}}/runtime/internal/runtime.String" %7) +// CHECK-NEXT: ret %"{{.*}}/runtime/internal/runtime.String" %8 +// CHECK-NEXT: } + +// CHECK-LABEL: define %"{{.*}}/runtime/internal/runtime.String" @main.label3(%"{{.*}}/runtime/internal/runtime.String" %0, i64 %1, i64 %2, i64 %3){{.*}} { +// CHECK-NEXT: _llgo_0: +// CHECK-NEXT: %4 = call %"{{.*}}/runtime/internal/runtime.String" @"{{.*}}/runtime/internal/runtime.StringCat"(%"{{.*}}/runtime/internal/runtime.String" %0, %"{{.*}}/runtime/internal/runtime.String" { ptr @{{[0-9]+}}, i64 1 }) +// CHECK-NEXT: %5 = call %"{{.*}}/runtime/internal/runtime.String" @main.digit(i64 %1) +// CHECK-NEXT: %6 = call %"{{.*}}/runtime/internal/runtime.String" @"{{.*}}/runtime/internal/runtime.StringCat"(%"{{.*}}/runtime/internal/runtime.String" %4, %"{{.*}}/runtime/internal/runtime.String" %5) +// CHECK-NEXT: %7 = call %"{{.*}}/runtime/internal/runtime.String" @"{{.*}}/runtime/internal/runtime.StringCat"(%"{{.*}}/runtime/internal/runtime.String" %6, %"{{.*}}/runtime/internal/runtime.String" { ptr @{{[0-9]+}}, i64 1 }) +// CHECK-NEXT: %8 = call %"{{.*}}/runtime/internal/runtime.String" @main.digit(i64 %2) +// CHECK-NEXT: %9 = call %"{{.*}}/runtime/internal/runtime.String" @"{{.*}}/runtime/internal/runtime.StringCat"(%"{{.*}}/runtime/internal/runtime.String" %7, %"{{.*}}/runtime/internal/runtime.String" %8) +// CHECK-NEXT: %10 = call %"{{.*}}/runtime/internal/runtime.String" @"{{.*}}/runtime/internal/runtime.StringCat"(%"{{.*}}/runtime/internal/runtime.String" %9, %"{{.*}}/runtime/internal/runtime.String" { ptr @{{[0-9]+}}, i64 1 }) +// CHECK-NEXT: %11 = call %"{{.*}}/runtime/internal/runtime.String" @main.digit(i64 %3) +// CHECK-NEXT: %12 = call %"{{.*}}/runtime/internal/runtime.String" @"{{.*}}/runtime/internal/runtime.StringCat"(%"{{.*}}/runtime/internal/runtime.String" %10, %"{{.*}}/runtime/internal/runtime.String" %11) +// CHECK-NEXT: ret %"{{.*}}/runtime/internal/runtime.String" %12 +// CHECK-NEXT: } + +// CHECK-LABEL: define void @main.main(){{.*}} { +// CHECK-NEXT: _llgo_0: +// CHECK-NEXT: %0 = call %"{{.*}}/runtime/internal/runtime.Slice" @main.complexOrder() +// CHECK-NEXT: %1 = extractvalue %"{{.*}}/runtime/internal/runtime.Slice" %0, 1 +// CHECK-NEXT: br label %_llgo_1 +// CHECK-EMPTY: +// CHECK-NEXT: _llgo_1: ; preds = %_llgo_2, %_llgo_0 +// CHECK-NEXT: %2 = phi i64 [ -1, %_llgo_0 ], [ %3, %_llgo_2 ] +// CHECK-NEXT: %3 = add i64 %2, 1 +// CHECK-NEXT: %4 = icmp slt i64 %3, %1 +// CHECK-NEXT: br i1 %4, label %_llgo_2, label %_llgo_3 +// CHECK-EMPTY: +// CHECK-NEXT: _llgo_2: ; preds = %_llgo_1 +// CHECK-NEXT: %5 = extractvalue %"{{.*}}/runtime/internal/runtime.Slice" %0, 0 +// CHECK-NEXT: %6 = extractvalue %"{{.*}}/runtime/internal/runtime.Slice" %0, 1 +// CHECK-NEXT: %7 = icmp slt i64 %3, 0 +// CHECK-NEXT: %8 = icmp uge i64 %3, %6 +// CHECK-NEXT: %9 = or i1 %8, %7 +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.CheckIndexRange"(i1 %9, i64 %3, i1 true, i64 %6) +// CHECK-NEXT: %10 = getelementptr inbounds %"{{.*}}/runtime/internal/runtime.String", ptr %5, i64 %3 +// CHECK-NEXT: %11 = load %"{{.*}}/runtime/internal/runtime.String", ptr %10, align 8 +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.PrintString"(%"{{.*}}/runtime/internal/runtime.String" %11) +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.PrintByte"(i8 10) +// CHECK-NEXT: br label %_llgo_1 +// CHECK-EMPTY: +// CHECK-NEXT: _llgo_3: ; preds = %_llgo_1 +// CHECK-NEXT: ret void +// CHECK-NEXT: } diff --git a/cl/_testgo/goexit/in.go b/cl/_testgo/goexit/in.go index 480ab3e716..a2a9ba68fb 100644 --- a/cl/_testgo/goexit/in.go +++ b/cl/_testgo/goexit/in.go @@ -1,15 +1,14 @@ // LITTEST package main -// CHECK-DAG: call ptr @"{{.*}}/runtime/internal/runtime.NewChan"({{.*}}) -// CHECK-DAG: call void @"{{.*}}/runtime/internal/runtime.NewProc"({{.*}}) -// CHECK-DAG: call void @runtime.Goexit() -// CHECK-DAG: call %"{{.*}}/runtime/internal/runtime.eface" @"{{.*}}/runtime/internal/runtime.Recover"() - import ( "runtime" ) +// CHECK: {{^}}@{{[0-9]+}} = private unnamed_addr constant [8 x i8] c"must nil", align 1{{$}} +// CHECK: {{^}}@{{[0-9]+}} = private unnamed_addr constant [5 x i8] c"error", align 1{{$}} +// CHECK: {{^}}@{{[0-9]+}} = private unnamed_addr constant [10 x i8] c"must error", align 1{{$}} + func main() { demo1() demo2() @@ -61,3 +60,498 @@ func demo3() { }() <-ch } + +// CHECK-LABEL: define void @main.demo1(){{.*}} { +// CHECK-NEXT: _llgo_0: +// CHECK-NEXT: %0 = call ptr @"{{.*}}/runtime/internal/runtime.AllocZ"(i64 8) +// CHECK-NEXT: %1 = call ptr @"{{.*}}/runtime/internal/runtime.NewChan"(i64 1, i64 0) +// CHECK-NEXT: store ptr %1, ptr %0, align 8 +// CHECK-NEXT: %2 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 8) +// CHECK-NEXT: %3 = getelementptr inbounds { ptr }, ptr %2, i32 0, i32 0 +// CHECK-NEXT: store ptr %0, ptr %3, align 8 +// CHECK-NEXT: %4 = insertvalue { ptr, ptr } { ptr @"main.demo1$1", ptr undef }, ptr %2, 1 +// CHECK-NEXT: %5 = call ptr @"{{.*}}/runtime/internal/runtime.AllocRoot"(i64 16) +// CHECK-NEXT: %6 = getelementptr inbounds { { ptr, ptr } }, ptr %5, i32 0, i32 0 +// CHECK-NEXT: store { ptr, ptr } %4, ptr %6, align 8 +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.NewProc"(ptr @"main._llgo_routine$1", ptr %5, i64 0) +// CHECK-NEXT: %7 = load ptr, ptr %0, align 8 +// CHECK-NEXT: %8 = call ptr @llvm.stacksave.p0() +// CHECK-NEXT: %9 = alloca i1, align 1 +// CHECK-NEXT: call void @llvm.memset.p0.i64(ptr %9, i8 0, i64 1, i1 false) +// CHECK-NEXT: %10 = call i1 @"{{.*}}/runtime/internal/runtime.ChanRecv"(ptr %7, ptr %9, i64 1) +// CHECK-NEXT: %11 = load i1, ptr %9, align 1 +// CHECK-NEXT: call void @llvm.stackrestore.p0(ptr %8) +// CHECK-NEXT: ret void +// CHECK-NEXT: } + +// CHECK-LABEL: define void @"main.demo1$1"(ptr {{(nest|swiftself)}} %0){{.*}} { +// CHECK-NEXT: _llgo_0: +// CHECK-NEXT: %1 = load { ptr }, ptr %0, align 8 +// CHECK-NEXT: %2 = extractvalue { ptr } %1, 0 +// CHECK-NEXT: %3 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 8) +// CHECK-NEXT: %4 = getelementptr inbounds { ptr }, ptr %3, i32 0, i32 0 +// CHECK-NEXT: store ptr %2, ptr %4, align 8 +// CHECK-NEXT: %5 = insertvalue { ptr, ptr } { ptr @"main.demo1$1$1", ptr undef }, ptr %3, 1 +// CHECK-NEXT: %6 = call ptr @"{{.*}}/runtime/internal/runtime.GetThreadDefer"() +// CHECK-NEXT: %7 = alloca i8 +// CHECK-NEXT: %8 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 48) +// CHECK-NEXT: %9 = getelementptr inbounds %"{{.*}}/runtime/internal/runtime.Defer", ptr %8, i32 0, i32 0 +// CHECK-NEXT: store ptr %7, ptr %9, align 8 +// CHECK-NEXT: %10 = getelementptr inbounds %"{{.*}}/runtime/internal/runtime.Defer", ptr %8, i32 0, i32 1 +// CHECK-NEXT: store i64 0, ptr %10, align 8 +// CHECK-NEXT: %11 = getelementptr inbounds %"{{.*}}/runtime/internal/runtime.Defer", ptr %8, i32 0, i32 2 +// CHECK-NEXT: store ptr %6, ptr %11, align 8 +// CHECK-NEXT: %12 = getelementptr inbounds %"{{.*}}/runtime/internal/runtime.Defer", ptr %8, i32 0, i32 3 +// CHECK-NEXT: store ptr blockaddress(@"main.demo1$1", %_llgo_2), ptr %12, align 8 +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.SetThreadDefer"(ptr %8) +// CHECK-NEXT: %13 = getelementptr inbounds %"{{.*}}/runtime/internal/runtime.Defer", ptr %8, i32 0, i32 1 +// CHECK-NEXT: %14 = getelementptr inbounds %"{{.*}}/runtime/internal/runtime.Defer", ptr %8, i32 0, i32 3 +// CHECK-NEXT: %15 = getelementptr inbounds %"{{.*}}/runtime/internal/runtime.Defer", ptr %8, i32 0, i32 4 +// CHECK-NEXT: %16 = getelementptr inbounds %"{{.*}}/runtime/internal/runtime.Defer", ptr %8, i32 0, i32 5 +// CHECK-NEXT: store ptr null, ptr %16, align 8 +// CHECK-NEXT: %17 = call i32 @{{(__)?}}sigsetjmp(ptr %7, i32 0) +// CHECK-NEXT: %18 = icmp eq i32 %17, 0 +// CHECK-NEXT: br i1 %18, label %_llgo_4, label %_llgo_5 +// CHECK-EMPTY: +// CHECK-NEXT: _llgo_1: ; preds = %_llgo_3 +// CHECK-NEXT: ret void +// CHECK-EMPTY: +// CHECK-NEXT: _llgo_2: ; preds = %_llgo_5, %_llgo_4 +// CHECK-NEXT: store ptr blockaddress(@"main.demo1$1", %_llgo_3), ptr %14, align 8 +// CHECK-NEXT: %19 = load i64, ptr %13, align 8 +// CHECK-NEXT: %20 = load ptr, ptr %16, align 8 +// CHECK-NEXT: %21 = icmp ne ptr %20, null +// CHECK-NEXT: br i1 %21, label %_llgo_7, label %_llgo_8 +// CHECK-EMPTY: +// CHECK-NEXT: _llgo_3: ; preds = %_llgo_5, %_llgo_8 +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.Rethrow"(ptr %6) +// CHECK-NEXT: br label %_llgo_1 +// CHECK-EMPTY: +// CHECK-NEXT: _llgo_4: ; preds = %_llgo_0 +// CHECK-NEXT: %22 = load ptr, ptr %16, align 8 +// CHECK-NEXT: %23 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 32) +// CHECK-NEXT: %24 = getelementptr inbounds { ptr, i64, { ptr, ptr } }, ptr %23, i32 0, i32 0 +// CHECK-NEXT: store ptr %22, ptr %24, align 8 +// CHECK-NEXT: %25 = getelementptr inbounds { ptr, i64, { ptr, ptr } }, ptr %23, i32 0, i32 1 +// CHECK-NEXT: store i64 0, ptr %25, align 8 +// CHECK-NEXT: %26 = getelementptr inbounds { ptr, i64, { ptr, ptr } }, ptr %23, i32 0, i32 2 +// CHECK-NEXT: store { ptr, ptr } %5, ptr %26, align 8 +// CHECK-NEXT: store ptr %23, ptr %16, align 8 +// CHECK-NEXT: call void @runtime.Goexit() +// CHECK-NEXT: store ptr blockaddress(@"main.demo1$1", %_llgo_6), ptr %15, align 8 +// CHECK-NEXT: br label %_llgo_2 +// CHECK-EMPTY: +// CHECK-NEXT: _llgo_5: ; preds = %_llgo_0 +// CHECK-NEXT: store ptr blockaddress(@"main.demo1$1", %_llgo_3), ptr %15, align 8 +// CHECK-NEXT: %27 = load ptr, ptr %14, align 8 +// CHECK-NEXT: indirectbr ptr %27, [label %_llgo_3, label %_llgo_2] +// CHECK-EMPTY: +// CHECK-NEXT: _llgo_6: ; preds = %_llgo_8 +// CHECK-NEXT: ret void +// CHECK-EMPTY: +// CHECK-NEXT: _llgo_7: ; preds = %_llgo_2 +// CHECK-NEXT: %28 = load ptr, ptr %16, align 8 +// CHECK-NEXT: %29 = load { ptr, i64, { ptr, ptr } }, ptr %28, align 8 +// CHECK-NEXT: %30 = extractvalue { ptr, i64, { ptr, ptr } } %29, 0 +// CHECK-NEXT: store ptr %30, ptr %16, align 8 +// CHECK-NEXT: %31 = extractvalue { ptr, i64, { ptr, ptr } } %29, 2 +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.FreeDeferNode"(ptr %28) +// CHECK-NEXT: %32 = extractvalue { ptr, ptr } %31, 1 +// CHECK-NEXT: %33 = extractvalue { ptr, ptr } %31, 0 +// CHECK-NEXT: %__llgo_funcval_code = call ptr asm "", "=r,0"(ptr %33) +// CHECK-NEXT: call void %__llgo_funcval_code(ptr {{(nest|swiftself)}} %32) +// CHECK-NEXT: br label %_llgo_8 +// CHECK-EMPTY: +// CHECK-NEXT: _llgo_8: ; preds = %_llgo_7, %_llgo_2 +// CHECK-NEXT: %34 = load %"{{.*}}/runtime/internal/runtime.Defer", ptr %8, align 8 +// CHECK-NEXT: %35 = extractvalue %"{{.*}}/runtime/internal/runtime.Defer" %34, 2 +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.SetThreadDefer"(ptr %35) +// CHECK-NEXT: %36 = load ptr, ptr %15, align 8 +// CHECK-NEXT: indirectbr ptr %36, [label %_llgo_3, label %_llgo_6] +// CHECK-NEXT: } + +// CHECK-LABEL: define void @"main.demo1$1$1"(ptr {{(nest|swiftself)}} %0){{.*}} { +// CHECK-NEXT: _llgo_0: +// CHECK-NEXT: %1 = load { ptr }, ptr %0, align 8 +// CHECK-NEXT: %2 = extractvalue { ptr } %1, 0 +// CHECK-NEXT: %3 = load ptr, ptr %2, align 8 +// CHECK-NEXT: %4 = call ptr @llvm.stacksave.p0() +// CHECK-NEXT: %5 = alloca i1, align 1 +// CHECK-NEXT: call void @llvm.memset.p0.i64(ptr %5, i8 0, i64 1, i1 false) +// CHECK-NEXT: store i1 true, ptr %5, align 1 +// CHECK-NEXT: %6 = call i1 @"{{.*}}/runtime/internal/runtime.ChanSend"(ptr %3, ptr %5, i64 1) +// CHECK-NEXT: call void @llvm.stackrestore.p0(ptr %4) +// CHECK-NEXT: ret void +// CHECK-NEXT: } + +// CHECK-LABEL: define void @main.demo2(){{.*}} { +// CHECK-NEXT: _llgo_0: +// CHECK-NEXT: %0 = call ptr @"{{.*}}/runtime/internal/runtime.AllocZ"(i64 8) +// CHECK-NEXT: %1 = call ptr @"{{.*}}/runtime/internal/runtime.NewChan"(i64 1, i64 0) +// CHECK-NEXT: store ptr %1, ptr %0, align 8 +// CHECK-NEXT: %2 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 8) +// CHECK-NEXT: %3 = getelementptr inbounds { ptr }, ptr %2, i32 0, i32 0 +// CHECK-NEXT: store ptr %0, ptr %3, align 8 +// CHECK-NEXT: %4 = insertvalue { ptr, ptr } { ptr @"main.demo2$1", ptr undef }, ptr %2, 1 +// CHECK-NEXT: %5 = call ptr @"{{.*}}/runtime/internal/runtime.AllocRoot"(i64 16) +// CHECK-NEXT: %6 = getelementptr inbounds { { ptr, ptr } }, ptr %5, i32 0, i32 0 +// CHECK-NEXT: store { ptr, ptr } %4, ptr %6, align 8 +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.NewProc"(ptr @"main._llgo_routine$2", ptr %5, i64 0) +// CHECK-NEXT: %7 = load ptr, ptr %0, align 8 +// CHECK-NEXT: %8 = call ptr @llvm.stacksave.p0() +// CHECK-NEXT: %9 = alloca i1, align 1 +// CHECK-NEXT: call void @llvm.memset.p0.i64(ptr %9, i8 0, i64 1, i1 false) +// CHECK-NEXT: %10 = call i1 @"{{.*}}/runtime/internal/runtime.ChanRecv"(ptr %7, ptr %9, i64 1) +// CHECK-NEXT: %11 = load i1, ptr %9, align 1 +// CHECK-NEXT: call void @llvm.stackrestore.p0(ptr %8) +// CHECK-NEXT: ret void +// CHECK-NEXT: } + +// CHECK-LABEL: define void @"main.demo2$1"(ptr {{(nest|swiftself)}} %0){{.*}} { +// CHECK-NEXT: _llgo_0: +// CHECK-NEXT: %1 = load { ptr }, ptr %0, align 8 +// CHECK-NEXT: %2 = extractvalue { ptr } %1, 0 +// CHECK-NEXT: %3 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 8) +// CHECK-NEXT: %4 = getelementptr inbounds { ptr }, ptr %3, i32 0, i32 0 +// CHECK-NEXT: store ptr %2, ptr %4, align 8 +// CHECK-NEXT: %5 = insertvalue { ptr, ptr } { ptr @"main.demo2$1$1", ptr undef }, ptr %3, 1 +// CHECK-NEXT: %6 = call ptr @"{{.*}}/runtime/internal/runtime.GetThreadDefer"() +// CHECK-NEXT: %7 = alloca i8 +// CHECK-NEXT: %8 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 48) +// CHECK-NEXT: %9 = getelementptr inbounds %"{{.*}}/runtime/internal/runtime.Defer", ptr %8, i32 0, i32 0 +// CHECK-NEXT: store ptr %7, ptr %9, align 8 +// CHECK-NEXT: %10 = getelementptr inbounds %"{{.*}}/runtime/internal/runtime.Defer", ptr %8, i32 0, i32 1 +// CHECK-NEXT: store i64 0, ptr %10, align 8 +// CHECK-NEXT: %11 = getelementptr inbounds %"{{.*}}/runtime/internal/runtime.Defer", ptr %8, i32 0, i32 2 +// CHECK-NEXT: store ptr %6, ptr %11, align 8 +// CHECK-NEXT: %12 = getelementptr inbounds %"{{.*}}/runtime/internal/runtime.Defer", ptr %8, i32 0, i32 3 +// CHECK-NEXT: store ptr blockaddress(@"main.demo2$1", %_llgo_2), ptr %12, align 8 +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.SetThreadDefer"(ptr %8) +// CHECK-NEXT: %13 = getelementptr inbounds %"{{.*}}/runtime/internal/runtime.Defer", ptr %8, i32 0, i32 1 +// CHECK-NEXT: %14 = getelementptr inbounds %"{{.*}}/runtime/internal/runtime.Defer", ptr %8, i32 0, i32 3 +// CHECK-NEXT: %15 = getelementptr inbounds %"{{.*}}/runtime/internal/runtime.Defer", ptr %8, i32 0, i32 4 +// CHECK-NEXT: %16 = getelementptr inbounds %"{{.*}}/runtime/internal/runtime.Defer", ptr %8, i32 0, i32 5 +// CHECK-NEXT: store ptr null, ptr %16, align 8 +// CHECK-NEXT: %17 = call i32 @{{(__)?}}sigsetjmp(ptr %7, i32 0) +// CHECK-NEXT: %18 = icmp eq i32 %17, 0 +// CHECK-NEXT: br i1 %18, label %_llgo_4, label %_llgo_5 +// CHECK-EMPTY: +// CHECK-NEXT: _llgo_1: ; preds = %_llgo_3 +// CHECK-NEXT: ret void +// CHECK-EMPTY: +// CHECK-NEXT: _llgo_2: ; preds = %_llgo_5, %_llgo_4 +// CHECK-NEXT: store ptr blockaddress(@"main.demo2$1", %_llgo_3), ptr %14, align 8 +// CHECK-NEXT: %19 = load i64, ptr %13, align 8 +// CHECK-NEXT: %20 = load ptr, ptr %16, align 8 +// CHECK-NEXT: %21 = icmp ne ptr %20, null +// CHECK-NEXT: br i1 %21, label %_llgo_7, label %_llgo_8 +// CHECK-EMPTY: +// CHECK-NEXT: _llgo_3: ; preds = %_llgo_5, %_llgo_8 +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.Rethrow"(ptr %6) +// CHECK-NEXT: br label %_llgo_1 +// CHECK-EMPTY: +// CHECK-NEXT: _llgo_4: ; preds = %_llgo_0 +// CHECK-NEXT: %22 = load ptr, ptr %16, align 8 +// CHECK-NEXT: %23 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 32) +// CHECK-NEXT: %24 = getelementptr inbounds { ptr, i64, { ptr, ptr } }, ptr %23, i32 0, i32 0 +// CHECK-NEXT: store ptr %22, ptr %24, align 8 +// CHECK-NEXT: %25 = getelementptr inbounds { ptr, i64, { ptr, ptr } }, ptr %23, i32 0, i32 1 +// CHECK-NEXT: store i64 0, ptr %25, align 8 +// CHECK-NEXT: %26 = getelementptr inbounds { ptr, i64, { ptr, ptr } }, ptr %23, i32 0, i32 2 +// CHECK-NEXT: store { ptr, ptr } %5, ptr %26, align 8 +// CHECK-NEXT: store ptr %23, ptr %16, align 8 +// CHECK-NEXT: call void @runtime.Goexit() +// CHECK-NEXT: store ptr blockaddress(@"main.demo2$1", %_llgo_6), ptr %15, align 8 +// CHECK-NEXT: br label %_llgo_2 +// CHECK-EMPTY: +// CHECK-NEXT: _llgo_5: ; preds = %_llgo_0 +// CHECK-NEXT: store ptr blockaddress(@"main.demo2$1", %_llgo_3), ptr %15, align 8 +// CHECK-NEXT: %27 = load ptr, ptr %14, align 8 +// CHECK-NEXT: indirectbr ptr %27, [label %_llgo_3, label %_llgo_2] +// CHECK-EMPTY: +// CHECK-NEXT: _llgo_6: ; preds = %_llgo_8 +// CHECK-NEXT: ret void +// CHECK-EMPTY: +// CHECK-NEXT: _llgo_7: ; preds = %_llgo_2 +// CHECK-NEXT: %28 = load ptr, ptr %16, align 8 +// CHECK-NEXT: %29 = load { ptr, i64, { ptr, ptr } }, ptr %28, align 8 +// CHECK-NEXT: %30 = extractvalue { ptr, i64, { ptr, ptr } } %29, 0 +// CHECK-NEXT: store ptr %30, ptr %16, align 8 +// CHECK-NEXT: %31 = extractvalue { ptr, i64, { ptr, ptr } } %29, 2 +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.FreeDeferNode"(ptr %28) +// CHECK-NEXT: %32 = extractvalue { ptr, ptr } %31, 1 +// CHECK-NEXT: %33 = extractvalue { ptr, ptr } %31, 0 +// CHECK-NEXT: %__llgo_funcval_code = call ptr asm "", "=r,0"(ptr %33) +// CHECK-NEXT: call void %__llgo_funcval_code(ptr {{(nest|swiftself)}} %32) +// CHECK-NEXT: br label %_llgo_8 +// CHECK-EMPTY: +// CHECK-NEXT: _llgo_8: ; preds = %_llgo_7, %_llgo_2 +// CHECK-NEXT: %34 = load %"{{.*}}/runtime/internal/runtime.Defer", ptr %8, align 8 +// CHECK-NEXT: %35 = extractvalue %"{{.*}}/runtime/internal/runtime.Defer" %34, 2 +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.SetThreadDefer"(ptr %35) +// CHECK-NEXT: %36 = load ptr, ptr %15, align 8 +// CHECK-NEXT: indirectbr ptr %36, [label %_llgo_3, label %_llgo_6] +// CHECK-NEXT: } + +// CHECK-LABEL: define void @"main.demo2$1$1"(ptr {{(nest|swiftself)}} %0){{.*}} { +// CHECK-NEXT: _llgo_0: +// CHECK-NEXT: %1 = load { ptr }, ptr %0, align 8 +// CHECK-NEXT: %2 = call %"{{.*}}/runtime/internal/runtime.eface" @"{{.*}}/runtime/internal/runtime.Recover"() +// CHECK-NEXT: %3 = call i1 @"{{.*}}/runtime/internal/runtime.EfaceEqual"(%"{{.*}}/runtime/internal/runtime.eface" %2, %"{{.*}}/runtime/internal/runtime.eface" zeroinitializer) +// CHECK-NEXT: %4 = xor i1 %3, true +// CHECK-NEXT: br i1 %4, label %_llgo_1, label %_llgo_2 +// CHECK-EMPTY: +// CHECK-NEXT: _llgo_1: ; preds = %_llgo_0 +// CHECK-NEXT: %5 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 16) +// CHECK-NEXT: store %"{{.*}}/runtime/internal/runtime.String" { ptr @{{[0-9]+}}, i64 8 }, ptr %5, align 8 +// CHECK-NEXT: %6 = insertvalue %"{{.*}}/runtime/internal/runtime.eface" { ptr @_llgo_string, ptr undef }, ptr %5, 1 +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.Panic"(%"{{.*}}/runtime/internal/runtime.eface" %6) +// CHECK-NEXT: unreachable +// CHECK-EMPTY: +// CHECK-NEXT: _llgo_2: ; preds = %_llgo_0 +// CHECK-NEXT: %7 = extractvalue { ptr } %1, 0 +// CHECK-NEXT: %8 = load ptr, ptr %7, align 8 +// CHECK-NEXT: %9 = call ptr @llvm.stacksave.p0() +// CHECK-NEXT: %10 = alloca i1, align 1 +// CHECK-NEXT: call void @llvm.memset.p0.i64(ptr %10, i8 0, i64 1, i1 false) +// CHECK-NEXT: store i1 true, ptr %10, align 1 +// CHECK-NEXT: %11 = call i1 @"{{.*}}/runtime/internal/runtime.ChanSend"(ptr %8, ptr %10, i64 1) +// CHECK-NEXT: call void @llvm.stackrestore.p0(ptr %9) +// CHECK-NEXT: ret void +// CHECK-NEXT: } + +// CHECK-LABEL: define void @main.demo3(){{.*}} { +// CHECK-NEXT: _llgo_0: +// CHECK-NEXT: %0 = call ptr @"{{.*}}/runtime/internal/runtime.AllocZ"(i64 8) +// CHECK-NEXT: %1 = call ptr @"{{.*}}/runtime/internal/runtime.NewChan"(i64 1, i64 0) +// CHECK-NEXT: store ptr %1, ptr %0, align 8 +// CHECK-NEXT: %2 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 8) +// CHECK-NEXT: %3 = getelementptr inbounds { ptr }, ptr %2, i32 0, i32 0 +// CHECK-NEXT: store ptr %0, ptr %3, align 8 +// CHECK-NEXT: %4 = insertvalue { ptr, ptr } { ptr @"main.demo3$1", ptr undef }, ptr %2, 1 +// CHECK-NEXT: %5 = call ptr @"{{.*}}/runtime/internal/runtime.AllocRoot"(i64 16) +// CHECK-NEXT: %6 = getelementptr inbounds { { ptr, ptr } }, ptr %5, i32 0, i32 0 +// CHECK-NEXT: store { ptr, ptr } %4, ptr %6, align 8 +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.NewProc"(ptr @"main._llgo_routine$3", ptr %5, i64 0) +// CHECK-NEXT: %7 = load ptr, ptr %0, align 8 +// CHECK-NEXT: %8 = call ptr @llvm.stacksave.p0() +// CHECK-NEXT: %9 = alloca i1, align 1 +// CHECK-NEXT: call void @llvm.memset.p0.i64(ptr %9, i8 0, i64 1, i1 false) +// CHECK-NEXT: %10 = call i1 @"{{.*}}/runtime/internal/runtime.ChanRecv"(ptr %7, ptr %9, i64 1) +// CHECK-NEXT: %11 = load i1, ptr %9, align 1 +// CHECK-NEXT: call void @llvm.stackrestore.p0(ptr %8) +// CHECK-NEXT: ret void +// CHECK-NEXT: } + +// CHECK-LABEL: define void @"main.demo3$1"(ptr {{(nest|swiftself)}} %0){{.*}} { +// CHECK-NEXT: _llgo_0: +// CHECK-NEXT: %1 = load { ptr }, ptr %0, align 8 +// CHECK-NEXT: %2 = extractvalue { ptr } %1, 0 +// CHECK-NEXT: %3 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 8) +// CHECK-NEXT: %4 = getelementptr inbounds { ptr }, ptr %3, i32 0, i32 0 +// CHECK-NEXT: store ptr %2, ptr %4, align 8 +// CHECK-NEXT: %5 = insertvalue { ptr, ptr } { ptr @"main.demo3$1$1", ptr undef }, ptr %3, 1 +// CHECK-NEXT: %6 = call ptr @"{{.*}}/runtime/internal/runtime.GetThreadDefer"() +// CHECK-NEXT: %7 = alloca i8 +// CHECK-NEXT: %8 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 48) +// CHECK-NEXT: %9 = getelementptr inbounds %"{{.*}}/runtime/internal/runtime.Defer", ptr %8, i32 0, i32 0 +// CHECK-NEXT: store ptr %7, ptr %9, align 8 +// CHECK-NEXT: %10 = getelementptr inbounds %"{{.*}}/runtime/internal/runtime.Defer", ptr %8, i32 0, i32 1 +// CHECK-NEXT: store i64 0, ptr %10, align 8 +// CHECK-NEXT: %11 = getelementptr inbounds %"{{.*}}/runtime/internal/runtime.Defer", ptr %8, i32 0, i32 2 +// CHECK-NEXT: store ptr %6, ptr %11, align 8 +// CHECK-NEXT: %12 = getelementptr inbounds %"{{.*}}/runtime/internal/runtime.Defer", ptr %8, i32 0, i32 3 +// CHECK-NEXT: store ptr blockaddress(@"main.demo3$1", %_llgo_2), ptr %12, align 8 +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.SetThreadDefer"(ptr %8) +// CHECK-NEXT: %13 = getelementptr inbounds %"{{.*}}/runtime/internal/runtime.Defer", ptr %8, i32 0, i32 1 +// CHECK-NEXT: %14 = getelementptr inbounds %"{{.*}}/runtime/internal/runtime.Defer", ptr %8, i32 0, i32 3 +// CHECK-NEXT: %15 = getelementptr inbounds %"{{.*}}/runtime/internal/runtime.Defer", ptr %8, i32 0, i32 4 +// CHECK-NEXT: %16 = getelementptr inbounds %"{{.*}}/runtime/internal/runtime.Defer", ptr %8, i32 0, i32 5 +// CHECK-NEXT: store ptr null, ptr %16, align 8 +// CHECK-NEXT: %17 = call i32 @{{(__)?}}sigsetjmp(ptr %7, i32 0) +// CHECK-NEXT: %18 = icmp eq i32 %17, 0 +// CHECK-NEXT: br i1 %18, label %_llgo_4, label %_llgo_5 +// CHECK-EMPTY: +// CHECK-NEXT: _llgo_1: ; preds = %_llgo_3 +// CHECK-NEXT: ret void +// CHECK-EMPTY: +// CHECK-NEXT: _llgo_2: ; preds = %_llgo_5, %_llgo_4 +// CHECK-NEXT: store ptr blockaddress(@"main.demo3$1", %_llgo_7), ptr %14, align 8 +// CHECK-NEXT: %19 = load i64, ptr %13, align 8 +// CHECK-NEXT: call void @"main.demo3$1$2"() +// CHECK-NEXT: br label %_llgo_7 +// CHECK-EMPTY: +// CHECK-NEXT: _llgo_3: ; preds = %_llgo_5, %_llgo_9 +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.Rethrow"(ptr %6) +// CHECK-NEXT: br label %_llgo_1 +// CHECK-EMPTY: +// CHECK-NEXT: _llgo_4: ; preds = %_llgo_0 +// CHECK-NEXT: %20 = load ptr, ptr %16, align 8 +// CHECK-NEXT: %21 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 32) +// CHECK-NEXT: %22 = getelementptr inbounds { ptr, i64, { ptr, ptr } }, ptr %21, i32 0, i32 0 +// CHECK-NEXT: store ptr %20, ptr %22, align 8 +// CHECK-NEXT: %23 = getelementptr inbounds { ptr, i64, { ptr, ptr } }, ptr %21, i32 0, i32 1 +// CHECK-NEXT: store i64 0, ptr %23, align 8 +// CHECK-NEXT: %24 = getelementptr inbounds { ptr, i64, { ptr, ptr } }, ptr %21, i32 0, i32 2 +// CHECK-NEXT: store { ptr, ptr } %5, ptr %24, align 8 +// CHECK-NEXT: store ptr %21, ptr %16, align 8 +// CHECK-NEXT: call void @runtime.Goexit() +// CHECK-NEXT: store ptr blockaddress(@"main.demo3$1", %_llgo_6), ptr %15, align 8 +// CHECK-NEXT: br label %_llgo_2 +// CHECK-EMPTY: +// CHECK-NEXT: _llgo_5: ; preds = %_llgo_0 +// CHECK-NEXT: store ptr blockaddress(@"main.demo3$1", %_llgo_3), ptr %15, align 8 +// CHECK-NEXT: %25 = load ptr, ptr %14, align 8 +// CHECK-NEXT: indirectbr ptr %25, [label %_llgo_3, label %_llgo_7, label %_llgo_2] +// CHECK-EMPTY: +// CHECK-NEXT: _llgo_6: ; preds = %_llgo_9 +// CHECK-NEXT: ret void +// CHECK-EMPTY: +// CHECK-NEXT: _llgo_7: ; preds = %_llgo_5, %_llgo_2 +// CHECK-NEXT: store ptr blockaddress(@"main.demo3$1", %_llgo_3), ptr %14, align 8 +// CHECK-NEXT: %26 = load i64, ptr %13, align 8 +// CHECK-NEXT: %27 = load ptr, ptr %16, align 8 +// CHECK-NEXT: %28 = icmp ne ptr %27, null +// CHECK-NEXT: br i1 %28, label %_llgo_8, label %_llgo_9 +// CHECK-EMPTY: +// CHECK-NEXT: _llgo_8: ; preds = %_llgo_7 +// CHECK-NEXT: %29 = load ptr, ptr %16, align 8 +// CHECK-NEXT: %30 = load { ptr, i64, { ptr, ptr } }, ptr %29, align 8 +// CHECK-NEXT: %31 = extractvalue { ptr, i64, { ptr, ptr } } %30, 0 +// CHECK-NEXT: store ptr %31, ptr %16, align 8 +// CHECK-NEXT: %32 = extractvalue { ptr, i64, { ptr, ptr } } %30, 2 +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.FreeDeferNode"(ptr %29) +// CHECK-NEXT: %33 = extractvalue { ptr, ptr } %32, 1 +// CHECK-NEXT: %34 = extractvalue { ptr, ptr } %32, 0 +// CHECK-NEXT: %__llgo_funcval_code = call ptr asm "", "=r,0"(ptr %34) +// CHECK-NEXT: call void %__llgo_funcval_code(ptr {{(nest|swiftself)}} %33) +// CHECK-NEXT: br label %_llgo_9 +// CHECK-EMPTY: +// CHECK-NEXT: _llgo_9: ; preds = %_llgo_8, %_llgo_7 +// CHECK-NEXT: %35 = load %"{{.*}}/runtime/internal/runtime.Defer", ptr %8, align 8 +// CHECK-NEXT: %36 = extractvalue %"{{.*}}/runtime/internal/runtime.Defer" %35, 2 +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.SetThreadDefer"(ptr %36) +// CHECK-NEXT: %37 = load ptr, ptr %15, align 8 +// CHECK-NEXT: indirectbr ptr %37, [label %_llgo_3, label %_llgo_6] +// CHECK-NEXT: } + +// CHECK-LABEL: define void @"main.demo3$1$1"(ptr {{(nest|swiftself)}} %0){{.*}} { +// CHECK-NEXT: _llgo_0: +// CHECK-NEXT: %1 = load { ptr }, ptr %0, align 8 +// CHECK-NEXT: %2 = call %"{{.*}}/runtime/internal/runtime.eface" @"{{.*}}/runtime/internal/runtime.Recover"() +// CHECK-NEXT: %3 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 16) +// CHECK-NEXT: store %"{{.*}}/runtime/internal/runtime.String" { ptr @{{[0-9]+}}, i64 5 }, ptr %3, align 8 +// CHECK-NEXT: %4 = insertvalue %"{{.*}}/runtime/internal/runtime.eface" { ptr @_llgo_string, ptr undef }, ptr %3, 1 +// CHECK-NEXT: %5 = call i1 @"{{.*}}/runtime/internal/runtime.EfaceEqual"(%"{{.*}}/runtime/internal/runtime.eface" %2, %"{{.*}}/runtime/internal/runtime.eface" %4) +// CHECK-NEXT: %6 = xor i1 %5, true +// CHECK-NEXT: br i1 %6, label %_llgo_1, label %_llgo_2 +// CHECK-EMPTY: +// CHECK-NEXT: _llgo_1: ; preds = %_llgo_0 +// CHECK-NEXT: %7 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 16) +// CHECK-NEXT: store %"{{.*}}/runtime/internal/runtime.String" { ptr @{{[0-9]+}}, i64 10 }, ptr %7, align 8 +// CHECK-NEXT: %8 = insertvalue %"{{.*}}/runtime/internal/runtime.eface" { ptr @_llgo_string, ptr undef }, ptr %7, 1 +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.Panic"(%"{{.*}}/runtime/internal/runtime.eface" %8) +// CHECK-NEXT: unreachable +// CHECK-EMPTY: +// CHECK-NEXT: _llgo_2: ; preds = %_llgo_0 +// CHECK-NEXT: %9 = extractvalue { ptr } %1, 0 +// CHECK-NEXT: %10 = load ptr, ptr %9, align 8 +// CHECK-NEXT: %11 = call ptr @llvm.stacksave.p0() +// CHECK-NEXT: %12 = alloca i1, align 1 +// CHECK-NEXT: call void @llvm.memset.p0.i64(ptr %12, i8 0, i64 1, i1 false) +// CHECK-NEXT: store i1 true, ptr %12, align 1 +// CHECK-NEXT: %13 = call i1 @"{{.*}}/runtime/internal/runtime.ChanSend"(ptr %10, ptr %12, i64 1) +// CHECK-NEXT: call void @llvm.stackrestore.p0(ptr %11) +// CHECK-NEXT: ret void +// CHECK-NEXT: } + +// CHECK-LABEL: define void @"main.demo3$1$2"(){{.*}} { +// CHECK-NEXT: _llgo_0: +// CHECK-NEXT: %0 = call %"{{.*}}/runtime/internal/runtime.eface" @"{{.*}}/runtime/internal/runtime.Recover"() +// CHECK-NEXT: %1 = call i1 @"{{.*}}/runtime/internal/runtime.EfaceEqual"(%"{{.*}}/runtime/internal/runtime.eface" %0, %"{{.*}}/runtime/internal/runtime.eface" zeroinitializer) +// CHECK-NEXT: %2 = xor i1 %1, true +// CHECK-NEXT: br i1 %2, label %_llgo_1, label %_llgo_2 +// CHECK-EMPTY: +// CHECK-NEXT: _llgo_1: ; preds = %_llgo_0 +// CHECK-NEXT: %3 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 16) +// CHECK-NEXT: store %"{{.*}}/runtime/internal/runtime.String" { ptr @{{[0-9]+}}, i64 8 }, ptr %3, align 8 +// CHECK-NEXT: %4 = insertvalue %"{{.*}}/runtime/internal/runtime.eface" { ptr @_llgo_string, ptr undef }, ptr %3, 1 +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.Panic"(%"{{.*}}/runtime/internal/runtime.eface" %4) +// CHECK-NEXT: unreachable +// CHECK-EMPTY: +// CHECK-NEXT: _llgo_2: ; preds = %_llgo_0 +// CHECK-NEXT: %5 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 16) +// CHECK-NEXT: store %"{{.*}}/runtime/internal/runtime.String" { ptr @{{[0-9]+}}, i64 5 }, ptr %5, align 8 +// CHECK-NEXT: %6 = insertvalue %"{{.*}}/runtime/internal/runtime.eface" { ptr @_llgo_string, ptr undef }, ptr %5, 1 +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.Panic"(%"{{.*}}/runtime/internal/runtime.eface" %6) +// CHECK-NEXT: unreachable +// CHECK-NEXT: } + +// CHECK-LABEL: define void @main.init(){{.*}} { +// CHECK-NEXT: _llgo_0: +// CHECK-NEXT: %0 = load i1, ptr @"main.init$guard", align 1 +// CHECK-NEXT: br i1 %0, label %_llgo_2, label %_llgo_1 +// CHECK-EMPTY: +// CHECK-NEXT: _llgo_1: ; preds = %_llgo_0 +// CHECK-NEXT: store i1 true, ptr @"main.init$guard", align 1 +// CHECK-NEXT: br label %_llgo_2 +// CHECK-EMPTY: +// CHECK-NEXT: _llgo_2: ; preds = %_llgo_1, %_llgo_0 +// CHECK-NEXT: ret void +// CHECK-NEXT: } + +// CHECK-LABEL: define void @main.main(){{.*}} { +// CHECK-NEXT: _llgo_0: +// CHECK-NEXT: call void @main.demo1() +// CHECK-NEXT: call void @main.demo2() +// CHECK-NEXT: call void @main.demo3() +// CHECK-NEXT: ret void +// CHECK-NEXT: } + +// CHECK-LABEL: define ptr @"main._llgo_routine$1"(ptr %0){{.*}} { +// CHECK-NEXT: _llgo_0: +// CHECK-NEXT: %1 = alloca %"{{.*}}/runtime/internal/runtime.LocalContext", align 8 +// CHECK-NEXT: call void @llvm.memset.p0.i64(ptr %1, i8 0, i64 8, i1 false) +// CHECK-NEXT: %2 = call i64 @"{{.*}}/runtime/internal/runtime.EnterLocalContext"(ptr %1) +// CHECK-NEXT: %3 = load { { ptr, ptr } }, ptr %0, align 8 +// CHECK-NEXT: %4 = extractvalue { { ptr, ptr } } %3, 0 +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.FreeRoot"(ptr %0) +// CHECK-NEXT: %5 = extractvalue { ptr, ptr } %4, 1 +// CHECK-NEXT: %6 = extractvalue { ptr, ptr } %4, 0 +// CHECK-NEXT: %__llgo_funcval_code = call ptr asm "", "=r,0"(ptr %6) +// CHECK-NEXT: call void %__llgo_funcval_code(ptr {{(nest|swiftself)}} %5) +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.LeaveLocalContext"(ptr %1, i64 %2) +// CHECK-NEXT: ret ptr null +// CHECK-NEXT: } + +// CHECK-LABEL: define ptr @"main._llgo_routine$2"(ptr %0){{.*}} { +// CHECK-NEXT: _llgo_0: +// CHECK-NEXT: %1 = alloca %"{{.*}}/runtime/internal/runtime.LocalContext", align 8 +// CHECK-NEXT: call void @llvm.memset.p0.i64(ptr %1, i8 0, i64 8, i1 false) +// CHECK-NEXT: %2 = call i64 @"{{.*}}/runtime/internal/runtime.EnterLocalContext"(ptr %1) +// CHECK-NEXT: %3 = load { { ptr, ptr } }, ptr %0, align 8 +// CHECK-NEXT: %4 = extractvalue { { ptr, ptr } } %3, 0 +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.FreeRoot"(ptr %0) +// CHECK-NEXT: %5 = extractvalue { ptr, ptr } %4, 1 +// CHECK-NEXT: %6 = extractvalue { ptr, ptr } %4, 0 +// CHECK-NEXT: %__llgo_funcval_code = call ptr asm "", "=r,0"(ptr %6) +// CHECK-NEXT: call void %__llgo_funcval_code(ptr {{(nest|swiftself)}} %5) +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.LeaveLocalContext"(ptr %1, i64 %2) +// CHECK-NEXT: ret ptr null +// CHECK-NEXT: } + +// CHECK-LABEL: define ptr @"main._llgo_routine$3"(ptr %0){{.*}} { +// CHECK-NEXT: _llgo_0: +// CHECK-NEXT: %1 = alloca %"{{.*}}/runtime/internal/runtime.LocalContext", align 8 +// CHECK-NEXT: call void @llvm.memset.p0.i64(ptr %1, i8 0, i64 8, i1 false) +// CHECK-NEXT: %2 = call i64 @"{{.*}}/runtime/internal/runtime.EnterLocalContext"(ptr %1) +// CHECK-NEXT: %3 = load { { ptr, ptr } }, ptr %0, align 8 +// CHECK-NEXT: %4 = extractvalue { { ptr, ptr } } %3, 0 +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.FreeRoot"(ptr %0) +// CHECK-NEXT: %5 = extractvalue { ptr, ptr } %4, 1 +// CHECK-NEXT: %6 = extractvalue { ptr, ptr } %4, 0 +// CHECK-NEXT: %__llgo_funcval_code = call ptr asm "", "=r,0"(ptr %6) +// CHECK-NEXT: call void %__llgo_funcval_code(ptr {{(nest|swiftself)}} %5) +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.LeaveLocalContext"(ptr %1, i64 %2) +// CHECK-NEXT: ret ptr null +// CHECK-NEXT: } diff --git a/cl/_testgo/indexerr/in.go b/cl/_testgo/indexerr/in.go index bdaf71928d..62fdecd500 100644 --- a/cl/_testgo/indexerr/in.go +++ b/cl/_testgo/indexerr/in.go @@ -1,8 +1,14 @@ // LITTEST package main -// CHECK-DAG: call void @"{{.*}}/runtime/internal/runtime.CheckIndexRange"({{.*}}i1 true{{.*}}) -// CHECK-DAG: call void @"{{.*}}/runtime/internal/runtime.CheckIndexRange"({{.*}}i1 false{{.*}}) +// CHECK: {{^}}@{{[0-9]+}} = private unnamed_addr constant [19 x i8] c"array -1 must error", align 1{{$}} +// CHECK: {{^}}@{{[0-9]+}} = private unnamed_addr constant [12 x i8] c"2 must error", align 1{{$}} +// CHECK: {{^}}@{{[0-9]+}} = private unnamed_addr constant [13 x i8] c"-1 must error", align 1{{$}} +// CHECK: {{^}}@{{[0-9]+}} = private unnamed_addr constant [18 x i8] c"array 2 must error", align 1{{$}} +// CHECK: {{^}}@{{[0-9]+}} = private unnamed_addr constant [17 x i8] c"array2 must error", align 1{{$}} +// CHECK: {{^}}@{{[0-9]+}} = private unnamed_addr constant [19 x i8] c"slice -1 must error", align 1{{$}} +// CHECK: {{^}}@{{[0-9]+}} = private unnamed_addr constant [18 x i8] c"slice 2 must error", align 1{{$}} +// CHECK: {{^}}@{{[0-9]+}} = private unnamed_addr constant [19 x i8] c"slice2 2 must error", align 1{{$}} func main() { } @@ -142,3 +148,1045 @@ func slice(n int) { func slice2(n int) { println([]int{1, 2}[n]) } + +// CHECK-LABEL: define void @main.array(i64 %0){{.*}} { +// CHECK-NEXT: _llgo_0: +// CHECK-NEXT: %1 = alloca [2 x i64], align 8 +// CHECK-NEXT: call void @llvm.memset.p0.i64(ptr %1, i8 0, i64 16, i1 false) +// CHECK-NEXT: %2 = getelementptr inbounds i64, ptr %1, i64 0 +// CHECK-NEXT: %3 = getelementptr inbounds i64, ptr %1, i64 1 +// CHECK-NEXT: store i64 1, ptr %2, align 8 +// CHECK-NEXT: store i64 2, ptr %3, align 8 +// CHECK-NEXT: %4 = load [2 x i64], ptr %1, align 8 +// CHECK-NEXT: %5 = icmp slt i64 %0, 0 +// CHECK-NEXT: %6 = icmp uge i64 %0, 2 +// CHECK-NEXT: %7 = or i1 %6, %5 +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.CheckIndexRange"(i1 %7, i64 %0, i1 true, i64 2) +// CHECK-NEXT: %8 = getelementptr inbounds i64, ptr %1, i64 %0 +// CHECK-NEXT: %9 = load i64, ptr %8, align 8 +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.PrintInt"(i64 %9) +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.PrintByte"(i8 10) +// CHECK-NEXT: ret void +// CHECK-NEXT: } + +// CHECK-LABEL: define void @main.array2(i64 %0){{.*}} { +// CHECK-NEXT: _llgo_0: +// CHECK-NEXT: %1 = alloca [2 x i64], align 8 +// CHECK-NEXT: call void @llvm.memset.p0.i64(ptr %1, i8 0, i64 16, i1 false) +// CHECK-NEXT: %2 = getelementptr inbounds i64, ptr %1, i64 0 +// CHECK-NEXT: %3 = getelementptr inbounds i64, ptr %1, i64 1 +// CHECK-NEXT: store i64 1, ptr %2, align 8 +// CHECK-NEXT: store i64 2, ptr %3, align 8 +// CHECK-NEXT: %4 = load [2 x i64], ptr %1, align 8 +// CHECK-NEXT: %5 = icmp uge i64 %0, 2 +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.CheckIndexRange"(i1 %5, i64 %0, i1 false, i64 2) +// CHECK-NEXT: %6 = getelementptr inbounds i64, ptr %1, i64 %0 +// CHECK-NEXT: %7 = load i64, ptr %6, align 8 +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.PrintInt"(i64 %7) +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.PrintByte"(i8 10) +// CHECK-NEXT: ret void +// CHECK-NEXT: } + +// CHECK-LABEL: define void @main.init(){{.*}} { +// CHECK-NEXT: _llgo_0: +// CHECK-NEXT: %0 = load i1, ptr @"main.init$guard", align 1 +// CHECK-NEXT: br i1 %0, label %_llgo_2, label %_llgo_1 +// CHECK-EMPTY: +// CHECK-NEXT: _llgo_1: ; preds = %_llgo_0 +// CHECK-NEXT: store i1 true, ptr @"main.init$guard", align 1 +// CHECK-NEXT: call void @"main.init#1"() +// CHECK-NEXT: call void @"main.init#2"() +// CHECK-NEXT: call void @"main.init#3"() +// CHECK-NEXT: call void @"main.init#4"() +// CHECK-NEXT: call void @"main.init#5"() +// CHECK-NEXT: call void @"main.init#6"() +// CHECK-NEXT: call void @"main.init#7"() +// CHECK-NEXT: call void @"main.init#8"() +// CHECK-NEXT: call void @"main.init#9"() +// CHECK-NEXT: call void @"main.init#10"() +// CHECK-NEXT: call void @"main.init#11"() +// CHECK-NEXT: call void @"main.init#12"() +// CHECK-NEXT: br label %_llgo_2 +// CHECK-EMPTY: +// CHECK-NEXT: _llgo_2: ; preds = %_llgo_1, %_llgo_0 +// CHECK-NEXT: ret void +// CHECK-NEXT: } + +// CHECK-LABEL: define void @"main.init#1"(){{.*}} { +// CHECK-NEXT: _llgo_0: +// CHECK-NEXT: %0 = call ptr @"{{.*}}/runtime/internal/runtime.GetThreadDefer"() +// CHECK-NEXT: %1 = alloca i8 +// CHECK-NEXT: %2 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 48) +// CHECK-NEXT: %3 = getelementptr inbounds %"{{.*}}/runtime/internal/runtime.Defer", ptr %2, i32 0, i32 0 +// CHECK-NEXT: store ptr %1, ptr %3, align 8 +// CHECK-NEXT: %4 = getelementptr inbounds %"{{.*}}/runtime/internal/runtime.Defer", ptr %2, i32 0, i32 1 +// CHECK-NEXT: store i64 0, ptr %4, align 8 +// CHECK-NEXT: %5 = getelementptr inbounds %"{{.*}}/runtime/internal/runtime.Defer", ptr %2, i32 0, i32 2 +// CHECK-NEXT: store ptr %0, ptr %5, align 8 +// CHECK-NEXT: %6 = getelementptr inbounds %"{{.*}}/runtime/internal/runtime.Defer", ptr %2, i32 0, i32 3 +// CHECK-NEXT: store ptr blockaddress(@"main.init#1", %_llgo_2), ptr %6, align 8 +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.SetThreadDefer"(ptr %2) +// CHECK-NEXT: %7 = getelementptr inbounds %"{{.*}}/runtime/internal/runtime.Defer", ptr %2, i32 0, i32 1 +// CHECK-NEXT: %8 = getelementptr inbounds %"{{.*}}/runtime/internal/runtime.Defer", ptr %2, i32 0, i32 3 +// CHECK-NEXT: %9 = getelementptr inbounds %"{{.*}}/runtime/internal/runtime.Defer", ptr %2, i32 0, i32 4 +// CHECK-NEXT: %10 = getelementptr inbounds %"{{.*}}/runtime/internal/runtime.Defer", ptr %2, i32 0, i32 5 +// CHECK-NEXT: store ptr null, ptr %10, align 8 +// CHECK-NEXT: %11 = call i32 @{{(__)?}}sigsetjmp(ptr %1, i32 0) +// CHECK-NEXT: %12 = icmp eq i32 %11, 0 +// CHECK-NEXT: br i1 %12, label %_llgo_4, label %_llgo_5 +// CHECK-EMPTY: +// CHECK-NEXT: _llgo_1: ; preds = %_llgo_3 +// CHECK-NEXT: ret void +// CHECK-EMPTY: +// CHECK-NEXT: _llgo_2: ; preds = %_llgo_5, %_llgo_4 +// CHECK-NEXT: store ptr blockaddress(@"main.init#1", %_llgo_3), ptr %8, align 8 +// CHECK-NEXT: %13 = load i64, ptr %7, align 8 +// CHECK-NEXT: call void @"main.init#1$1"() +// CHECK-NEXT: %14 = load %"{{.*}}/runtime/internal/runtime.Defer", ptr %2, align 8 +// CHECK-NEXT: %15 = extractvalue %"{{.*}}/runtime/internal/runtime.Defer" %14, 2 +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.SetThreadDefer"(ptr %15) +// CHECK-NEXT: %16 = load ptr, ptr %9, align 8 +// CHECK-NEXT: indirectbr ptr %16, [label %_llgo_3, label %_llgo_6] +// CHECK-EMPTY: +// CHECK-NEXT: _llgo_3: ; preds = %_llgo_5, %_llgo_2 +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.Rethrow"(ptr %0) +// CHECK-NEXT: br label %_llgo_1 +// CHECK-EMPTY: +// CHECK-NEXT: _llgo_4: ; preds = %_llgo_0 +// CHECK-NEXT: call void @main.array(i64 -1) +// CHECK-NEXT: store ptr blockaddress(@"main.init#1", %_llgo_6), ptr %9, align 8 +// CHECK-NEXT: br label %_llgo_2 +// CHECK-EMPTY: +// CHECK-NEXT: _llgo_5: ; preds = %_llgo_0 +// CHECK-NEXT: store ptr blockaddress(@"main.init#1", %_llgo_3), ptr %9, align 8 +// CHECK-NEXT: %17 = load ptr, ptr %8, align 8 +// CHECK-NEXT: indirectbr ptr %17, [label %_llgo_3, label %_llgo_2] +// CHECK-EMPTY: +// CHECK-NEXT: _llgo_6: ; preds = %_llgo_2 +// CHECK-NEXT: ret void +// CHECK-NEXT: } + +// CHECK-LABEL: define void @"main.init#1$1"(){{.*}} { +// CHECK-NEXT: _llgo_0: +// CHECK-NEXT: %0 = call %"{{.*}}/runtime/internal/runtime.eface" @"{{.*}}/runtime/internal/runtime.Recover"() +// CHECK-NEXT: %1 = call i1 @"{{.*}}/runtime/internal/runtime.EfaceEqual"(%"{{.*}}/runtime/internal/runtime.eface" %0, %"{{.*}}/runtime/internal/runtime.eface" zeroinitializer) +// CHECK-NEXT: br i1 %1, label %_llgo_1, label %_llgo_2 +// CHECK-EMPTY: +// CHECK-NEXT: _llgo_1: ; preds = %_llgo_0 +// CHECK-NEXT: %2 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 16) +// CHECK-NEXT: store %"{{.*}}/runtime/internal/runtime.String" { ptr @{{[0-9]+}}, i64 19 }, ptr %2, align 8 +// CHECK-NEXT: %3 = insertvalue %"{{.*}}/runtime/internal/runtime.eface" { ptr @_llgo_string, ptr undef }, ptr %2, 1 +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.Panic"(%"{{.*}}/runtime/internal/runtime.eface" %3) +// CHECK-NEXT: unreachable +// CHECK-EMPTY: +// CHECK-NEXT: _llgo_2: ; preds = %_llgo_0 +// CHECK-NEXT: ret void +// CHECK-NEXT: } + +// CHECK-LABEL: define void @"main.init#10"(){{.*}} { +// CHECK-NEXT: _llgo_0: +// CHECK-NEXT: %0 = call ptr @"{{.*}}/runtime/internal/runtime.GetThreadDefer"() +// CHECK-NEXT: %1 = alloca i8 +// CHECK-NEXT: %2 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 48) +// CHECK-NEXT: %3 = getelementptr inbounds %"{{.*}}/runtime/internal/runtime.Defer", ptr %2, i32 0, i32 0 +// CHECK-NEXT: store ptr %1, ptr %3, align 8 +// CHECK-NEXT: %4 = getelementptr inbounds %"{{.*}}/runtime/internal/runtime.Defer", ptr %2, i32 0, i32 1 +// CHECK-NEXT: store i64 0, ptr %4, align 8 +// CHECK-NEXT: %5 = getelementptr inbounds %"{{.*}}/runtime/internal/runtime.Defer", ptr %2, i32 0, i32 2 +// CHECK-NEXT: store ptr %0, ptr %5, align 8 +// CHECK-NEXT: %6 = getelementptr inbounds %"{{.*}}/runtime/internal/runtime.Defer", ptr %2, i32 0, i32 3 +// CHECK-NEXT: store ptr blockaddress(@"main.init#10", %_llgo_2), ptr %6, align 8 +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.SetThreadDefer"(ptr %2) +// CHECK-NEXT: %7 = getelementptr inbounds %"{{.*}}/runtime/internal/runtime.Defer", ptr %2, i32 0, i32 1 +// CHECK-NEXT: %8 = getelementptr inbounds %"{{.*}}/runtime/internal/runtime.Defer", ptr %2, i32 0, i32 3 +// CHECK-NEXT: %9 = getelementptr inbounds %"{{.*}}/runtime/internal/runtime.Defer", ptr %2, i32 0, i32 4 +// CHECK-NEXT: %10 = getelementptr inbounds %"{{.*}}/runtime/internal/runtime.Defer", ptr %2, i32 0, i32 5 +// CHECK-NEXT: store ptr null, ptr %10, align 8 +// CHECK-NEXT: %11 = call i32 @{{(__)?}}sigsetjmp(ptr %1, i32 0) +// CHECK-NEXT: %12 = icmp eq i32 %11, 0 +// CHECK-NEXT: br i1 %12, label %_llgo_4, label %_llgo_5 +// CHECK-EMPTY: +// CHECK-NEXT: _llgo_1: ; preds = %_llgo_3 +// CHECK-NEXT: ret void +// CHECK-EMPTY: +// CHECK-NEXT: _llgo_2: ; preds = %_llgo_5, %_llgo_4 +// CHECK-NEXT: store ptr blockaddress(@"main.init#10", %_llgo_3), ptr %8, align 8 +// CHECK-NEXT: %13 = load i64, ptr %7, align 8 +// CHECK-NEXT: call void @"main.init#10$1"() +// CHECK-NEXT: %14 = load %"{{.*}}/runtime/internal/runtime.Defer", ptr %2, align 8 +// CHECK-NEXT: %15 = extractvalue %"{{.*}}/runtime/internal/runtime.Defer" %14, 2 +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.SetThreadDefer"(ptr %15) +// CHECK-NEXT: %16 = load ptr, ptr %9, align 8 +// CHECK-NEXT: indirectbr ptr %16, [label %_llgo_3, label %_llgo_6] +// CHECK-EMPTY: +// CHECK-NEXT: _llgo_3: ; preds = %_llgo_5, %_llgo_2 +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.Rethrow"(ptr %0) +// CHECK-NEXT: br label %_llgo_1 +// CHECK-EMPTY: +// CHECK-NEXT: _llgo_4: ; preds = %_llgo_0 +// CHECK-NEXT: %17 = call ptr @"{{.*}}/runtime/internal/runtime.AllocZ"(i64 16) +// CHECK-NEXT: %18 = getelementptr inbounds i64, ptr %17, i64 0 +// CHECK-NEXT: store i64 1, ptr %18, align 8 +// CHECK-NEXT: %19 = getelementptr inbounds i64, ptr %17, i64 1 +// CHECK-NEXT: store i64 2, ptr %19, align 8 +// CHECK-NEXT: %20 = insertvalue %"{{.*}}/runtime/internal/runtime.Slice" undef, ptr %17, 0 +// CHECK-NEXT: %21 = insertvalue %"{{.*}}/runtime/internal/runtime.Slice" %20, i64 2, 1 +// CHECK-NEXT: %22 = insertvalue %"{{.*}}/runtime/internal/runtime.Slice" %21, i64 2, 2 +// CHECK-NEXT: %23 = extractvalue %"{{.*}}/runtime/internal/runtime.Slice" %22, 0 +// CHECK-NEXT: %24 = extractvalue %"{{.*}}/runtime/internal/runtime.Slice" %22, 1 +// CHECK-NEXT: %25 = icmp uge i64 -1, %24 +// CHECK-NEXT: %26 = or i1 %25, true +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.CheckIndexRange"(i1 %26, i64 -1, i1 true, i64 %24) +// CHECK-NEXT: %27 = getelementptr inbounds i64, ptr %23, i64 -1 +// CHECK-NEXT: %28 = load i64, ptr %27, align 8 +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.PrintInt"(i64 %28) +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.PrintByte"(i8 10) +// CHECK-NEXT: store ptr blockaddress(@"main.init#10", %_llgo_6), ptr %9, align 8 +// CHECK-NEXT: br label %_llgo_2 +// CHECK-EMPTY: +// CHECK-NEXT: _llgo_5: ; preds = %_llgo_0 +// CHECK-NEXT: store ptr blockaddress(@"main.init#10", %_llgo_3), ptr %9, align 8 +// CHECK-NEXT: %29 = load ptr, ptr %8, align 8 +// CHECK-NEXT: indirectbr ptr %29, [label %_llgo_3, label %_llgo_2] +// CHECK-EMPTY: +// CHECK-NEXT: _llgo_6: ; preds = %_llgo_2 +// CHECK-NEXT: ret void +// CHECK-NEXT: } + +// CHECK-LABEL: define void @"main.init#10$1"(){{.*}} { +// CHECK-NEXT: _llgo_0: +// CHECK-NEXT: %0 = call %"{{.*}}/runtime/internal/runtime.eface" @"{{.*}}/runtime/internal/runtime.Recover"() +// CHECK-NEXT: %1 = call i1 @"{{.*}}/runtime/internal/runtime.EfaceEqual"(%"{{.*}}/runtime/internal/runtime.eface" %0, %"{{.*}}/runtime/internal/runtime.eface" zeroinitializer) +// CHECK-NEXT: br i1 %1, label %_llgo_1, label %_llgo_2 +// CHECK-EMPTY: +// CHECK-NEXT: _llgo_1: ; preds = %_llgo_0 +// CHECK-NEXT: %2 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 16) +// CHECK-NEXT: store %"{{.*}}/runtime/internal/runtime.String" { ptr @{{[0-9]+}}, i64 12 }, ptr %2, align 8 +// CHECK-NEXT: %3 = insertvalue %"{{.*}}/runtime/internal/runtime.eface" { ptr @_llgo_string, ptr undef }, ptr %2, 1 +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.Panic"(%"{{.*}}/runtime/internal/runtime.eface" %3) +// CHECK-NEXT: unreachable +// CHECK-EMPTY: +// CHECK-NEXT: _llgo_2: ; preds = %_llgo_0 +// CHECK-NEXT: ret void +// CHECK-NEXT: } + +// CHECK-LABEL: define void @"main.init#11"(){{.*}} { +// CHECK-NEXT: _llgo_0: +// CHECK-NEXT: %0 = call ptr @"{{.*}}/runtime/internal/runtime.GetThreadDefer"() +// CHECK-NEXT: %1 = alloca i8 +// CHECK-NEXT: %2 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 48) +// CHECK-NEXT: %3 = getelementptr inbounds %"{{.*}}/runtime/internal/runtime.Defer", ptr %2, i32 0, i32 0 +// CHECK-NEXT: store ptr %1, ptr %3, align 8 +// CHECK-NEXT: %4 = getelementptr inbounds %"{{.*}}/runtime/internal/runtime.Defer", ptr %2, i32 0, i32 1 +// CHECK-NEXT: store i64 0, ptr %4, align 8 +// CHECK-NEXT: %5 = getelementptr inbounds %"{{.*}}/runtime/internal/runtime.Defer", ptr %2, i32 0, i32 2 +// CHECK-NEXT: store ptr %0, ptr %5, align 8 +// CHECK-NEXT: %6 = getelementptr inbounds %"{{.*}}/runtime/internal/runtime.Defer", ptr %2, i32 0, i32 3 +// CHECK-NEXT: store ptr blockaddress(@"main.init#11", %_llgo_2), ptr %6, align 8 +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.SetThreadDefer"(ptr %2) +// CHECK-NEXT: %7 = getelementptr inbounds %"{{.*}}/runtime/internal/runtime.Defer", ptr %2, i32 0, i32 1 +// CHECK-NEXT: %8 = getelementptr inbounds %"{{.*}}/runtime/internal/runtime.Defer", ptr %2, i32 0, i32 3 +// CHECK-NEXT: %9 = getelementptr inbounds %"{{.*}}/runtime/internal/runtime.Defer", ptr %2, i32 0, i32 4 +// CHECK-NEXT: %10 = getelementptr inbounds %"{{.*}}/runtime/internal/runtime.Defer", ptr %2, i32 0, i32 5 +// CHECK-NEXT: store ptr null, ptr %10, align 8 +// CHECK-NEXT: %11 = call i32 @{{(__)?}}sigsetjmp(ptr %1, i32 0) +// CHECK-NEXT: %12 = icmp eq i32 %11, 0 +// CHECK-NEXT: br i1 %12, label %_llgo_4, label %_llgo_5 +// CHECK-EMPTY: +// CHECK-NEXT: _llgo_1: ; preds = %_llgo_3 +// CHECK-NEXT: ret void +// CHECK-EMPTY: +// CHECK-NEXT: _llgo_2: ; preds = %_llgo_5, %_llgo_4 +// CHECK-NEXT: store ptr blockaddress(@"main.init#11", %_llgo_3), ptr %8, align 8 +// CHECK-NEXT: %13 = load i64, ptr %7, align 8 +// CHECK-NEXT: call void @"main.init#11$1"() +// CHECK-NEXT: %14 = load %"{{.*}}/runtime/internal/runtime.Defer", ptr %2, align 8 +// CHECK-NEXT: %15 = extractvalue %"{{.*}}/runtime/internal/runtime.Defer" %14, 2 +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.SetThreadDefer"(ptr %15) +// CHECK-NEXT: %16 = load ptr, ptr %9, align 8 +// CHECK-NEXT: indirectbr ptr %16, [label %_llgo_3, label %_llgo_6] +// CHECK-EMPTY: +// CHECK-NEXT: _llgo_3: ; preds = %_llgo_5, %_llgo_2 +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.Rethrow"(ptr %0) +// CHECK-NEXT: br label %_llgo_1 +// CHECK-EMPTY: +// CHECK-NEXT: _llgo_4: ; preds = %_llgo_0 +// CHECK-NEXT: %17 = call ptr @"{{.*}}/runtime/internal/runtime.AllocZ"(i64 16) +// CHECK-NEXT: %18 = getelementptr inbounds i64, ptr %17, i64 0 +// CHECK-NEXT: store i64 1, ptr %18, align 8 +// CHECK-NEXT: %19 = getelementptr inbounds i64, ptr %17, i64 1 +// CHECK-NEXT: store i64 2, ptr %19, align 8 +// CHECK-NEXT: %20 = insertvalue %"{{.*}}/runtime/internal/runtime.Slice" undef, ptr %17, 0 +// CHECK-NEXT: %21 = insertvalue %"{{.*}}/runtime/internal/runtime.Slice" %20, i64 2, 1 +// CHECK-NEXT: %22 = insertvalue %"{{.*}}/runtime/internal/runtime.Slice" %21, i64 2, 2 +// CHECK-NEXT: %23 = extractvalue %"{{.*}}/runtime/internal/runtime.Slice" %22, 0 +// CHECK-NEXT: %24 = extractvalue %"{{.*}}/runtime/internal/runtime.Slice" %22, 1 +// CHECK-NEXT: %25 = icmp uge i64 2, %24 +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.CheckIndexRange"(i1 %25, i64 2, i1 true, i64 %24) +// CHECK-NEXT: %26 = getelementptr inbounds i64, ptr %23, i64 2 +// CHECK-NEXT: %27 = load i64, ptr %26, align 8 +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.PrintInt"(i64 %27) +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.PrintByte"(i8 10) +// CHECK-NEXT: store ptr blockaddress(@"main.init#11", %_llgo_6), ptr %9, align 8 +// CHECK-NEXT: br label %_llgo_2 +// CHECK-EMPTY: +// CHECK-NEXT: _llgo_5: ; preds = %_llgo_0 +// CHECK-NEXT: store ptr blockaddress(@"main.init#11", %_llgo_3), ptr %9, align 8 +// CHECK-NEXT: %28 = load ptr, ptr %8, align 8 +// CHECK-NEXT: indirectbr ptr %28, [label %_llgo_3, label %_llgo_2] +// CHECK-EMPTY: +// CHECK-NEXT: _llgo_6: ; preds = %_llgo_2 +// CHECK-NEXT: ret void +// CHECK-NEXT: } + +// CHECK-LABEL: define void @"main.init#11$1"(){{.*}} { +// CHECK-NEXT: _llgo_0: +// CHECK-NEXT: %0 = call %"{{.*}}/runtime/internal/runtime.eface" @"{{.*}}/runtime/internal/runtime.Recover"() +// CHECK-NEXT: %1 = call i1 @"{{.*}}/runtime/internal/runtime.EfaceEqual"(%"{{.*}}/runtime/internal/runtime.eface" %0, %"{{.*}}/runtime/internal/runtime.eface" zeroinitializer) +// CHECK-NEXT: br i1 %1, label %_llgo_1, label %_llgo_2 +// CHECK-EMPTY: +// CHECK-NEXT: _llgo_1: ; preds = %_llgo_0 +// CHECK-NEXT: %2 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 16) +// CHECK-NEXT: store %"{{.*}}/runtime/internal/runtime.String" { ptr @{{[0-9]+}}, i64 13 }, ptr %2, align 8 +// CHECK-NEXT: %3 = insertvalue %"{{.*}}/runtime/internal/runtime.eface" { ptr @_llgo_string, ptr undef }, ptr %2, 1 +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.Panic"(%"{{.*}}/runtime/internal/runtime.eface" %3) +// CHECK-NEXT: unreachable +// CHECK-EMPTY: +// CHECK-NEXT: _llgo_2: ; preds = %_llgo_0 +// CHECK-NEXT: ret void +// CHECK-NEXT: } + +// CHECK-LABEL: define void @"main.init#12"(){{.*}} { +// CHECK-NEXT: _llgo_0: +// CHECK-NEXT: %0 = call ptr @"{{.*}}/runtime/internal/runtime.GetThreadDefer"() +// CHECK-NEXT: %1 = alloca i8 +// CHECK-NEXT: %2 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 48) +// CHECK-NEXT: %3 = getelementptr inbounds %"{{.*}}/runtime/internal/runtime.Defer", ptr %2, i32 0, i32 0 +// CHECK-NEXT: store ptr %1, ptr %3, align 8 +// CHECK-NEXT: %4 = getelementptr inbounds %"{{.*}}/runtime/internal/runtime.Defer", ptr %2, i32 0, i32 1 +// CHECK-NEXT: store i64 0, ptr %4, align 8 +// CHECK-NEXT: %5 = getelementptr inbounds %"{{.*}}/runtime/internal/runtime.Defer", ptr %2, i32 0, i32 2 +// CHECK-NEXT: store ptr %0, ptr %5, align 8 +// CHECK-NEXT: %6 = getelementptr inbounds %"{{.*}}/runtime/internal/runtime.Defer", ptr %2, i32 0, i32 3 +// CHECK-NEXT: store ptr blockaddress(@"main.init#12", %_llgo_2), ptr %6, align 8 +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.SetThreadDefer"(ptr %2) +// CHECK-NEXT: %7 = getelementptr inbounds %"{{.*}}/runtime/internal/runtime.Defer", ptr %2, i32 0, i32 1 +// CHECK-NEXT: %8 = getelementptr inbounds %"{{.*}}/runtime/internal/runtime.Defer", ptr %2, i32 0, i32 3 +// CHECK-NEXT: %9 = getelementptr inbounds %"{{.*}}/runtime/internal/runtime.Defer", ptr %2, i32 0, i32 4 +// CHECK-NEXT: %10 = getelementptr inbounds %"{{.*}}/runtime/internal/runtime.Defer", ptr %2, i32 0, i32 5 +// CHECK-NEXT: store ptr null, ptr %10, align 8 +// CHECK-NEXT: %11 = call i32 @{{(__)?}}sigsetjmp(ptr %1, i32 0) +// CHECK-NEXT: %12 = icmp eq i32 %11, 0 +// CHECK-NEXT: br i1 %12, label %_llgo_4, label %_llgo_5 +// CHECK-EMPTY: +// CHECK-NEXT: _llgo_1: ; preds = %_llgo_3 +// CHECK-NEXT: ret void +// CHECK-EMPTY: +// CHECK-NEXT: _llgo_2: ; preds = %_llgo_5, %_llgo_4 +// CHECK-NEXT: store ptr blockaddress(@"main.init#12", %_llgo_3), ptr %8, align 8 +// CHECK-NEXT: %13 = load i64, ptr %7, align 8 +// CHECK-NEXT: call void @"main.init#12$1"() +// CHECK-NEXT: %14 = load %"{{.*}}/runtime/internal/runtime.Defer", ptr %2, align 8 +// CHECK-NEXT: %15 = extractvalue %"{{.*}}/runtime/internal/runtime.Defer" %14, 2 +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.SetThreadDefer"(ptr %15) +// CHECK-NEXT: %16 = load ptr, ptr %9, align 8 +// CHECK-NEXT: indirectbr ptr %16, [label %_llgo_3, label %_llgo_6] +// CHECK-EMPTY: +// CHECK-NEXT: _llgo_3: ; preds = %_llgo_5, %_llgo_2 +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.Rethrow"(ptr %0) +// CHECK-NEXT: br label %_llgo_1 +// CHECK-EMPTY: +// CHECK-NEXT: _llgo_4: ; preds = %_llgo_0 +// CHECK-NEXT: %17 = call ptr @"{{.*}}/runtime/internal/runtime.AllocZ"(i64 16) +// CHECK-NEXT: %18 = getelementptr inbounds i64, ptr %17, i64 0 +// CHECK-NEXT: store i64 1, ptr %18, align 8 +// CHECK-NEXT: %19 = getelementptr inbounds i64, ptr %17, i64 1 +// CHECK-NEXT: store i64 2, ptr %19, align 8 +// CHECK-NEXT: %20 = insertvalue %"{{.*}}/runtime/internal/runtime.Slice" undef, ptr %17, 0 +// CHECK-NEXT: %21 = insertvalue %"{{.*}}/runtime/internal/runtime.Slice" %20, i64 2, 1 +// CHECK-NEXT: %22 = insertvalue %"{{.*}}/runtime/internal/runtime.Slice" %21, i64 2, 2 +// CHECK-NEXT: %23 = extractvalue %"{{.*}}/runtime/internal/runtime.Slice" %22, 0 +// CHECK-NEXT: %24 = extractvalue %"{{.*}}/runtime/internal/runtime.Slice" %22, 1 +// CHECK-NEXT: %25 = icmp uge i64 2, %24 +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.CheckIndexRange"(i1 %25, i64 2, i1 false, i64 %24) +// CHECK-NEXT: %26 = getelementptr inbounds i64, ptr %23, i64 2 +// CHECK-NEXT: %27 = load i64, ptr %26, align 8 +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.PrintInt"(i64 %27) +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.PrintByte"(i8 10) +// CHECK-NEXT: store ptr blockaddress(@"main.init#12", %_llgo_6), ptr %9, align 8 +// CHECK-NEXT: br label %_llgo_2 +// CHECK-EMPTY: +// CHECK-NEXT: _llgo_5: ; preds = %_llgo_0 +// CHECK-NEXT: store ptr blockaddress(@"main.init#12", %_llgo_3), ptr %9, align 8 +// CHECK-NEXT: %28 = load ptr, ptr %8, align 8 +// CHECK-NEXT: indirectbr ptr %28, [label %_llgo_3, label %_llgo_2] +// CHECK-EMPTY: +// CHECK-NEXT: _llgo_6: ; preds = %_llgo_2 +// CHECK-NEXT: ret void +// CHECK-NEXT: } + +// CHECK-LABEL: define void @"main.init#12$1"(){{.*}} { +// CHECK-NEXT: _llgo_0: +// CHECK-NEXT: %0 = call %"{{.*}}/runtime/internal/runtime.eface" @"{{.*}}/runtime/internal/runtime.Recover"() +// CHECK-NEXT: %1 = call i1 @"{{.*}}/runtime/internal/runtime.EfaceEqual"(%"{{.*}}/runtime/internal/runtime.eface" %0, %"{{.*}}/runtime/internal/runtime.eface" zeroinitializer) +// CHECK-NEXT: br i1 %1, label %_llgo_1, label %_llgo_2 +// CHECK-EMPTY: +// CHECK-NEXT: _llgo_1: ; preds = %_llgo_0 +// CHECK-NEXT: %2 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 16) +// CHECK-NEXT: store %"{{.*}}/runtime/internal/runtime.String" { ptr @{{[0-9]+}}, i64 12 }, ptr %2, align 8 +// CHECK-NEXT: %3 = insertvalue %"{{.*}}/runtime/internal/runtime.eface" { ptr @_llgo_string, ptr undef }, ptr %2, 1 +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.Panic"(%"{{.*}}/runtime/internal/runtime.eface" %3) +// CHECK-NEXT: unreachable +// CHECK-EMPTY: +// CHECK-NEXT: _llgo_2: ; preds = %_llgo_0 +// CHECK-NEXT: ret void +// CHECK-NEXT: } + +// CHECK-LABEL: define void @"main.init#2"(){{.*}} { +// CHECK-NEXT: _llgo_0: +// CHECK-NEXT: %0 = call ptr @"{{.*}}/runtime/internal/runtime.GetThreadDefer"() +// CHECK-NEXT: %1 = alloca i8 +// CHECK-NEXT: %2 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 48) +// CHECK-NEXT: %3 = getelementptr inbounds %"{{.*}}/runtime/internal/runtime.Defer", ptr %2, i32 0, i32 0 +// CHECK-NEXT: store ptr %1, ptr %3, align 8 +// CHECK-NEXT: %4 = getelementptr inbounds %"{{.*}}/runtime/internal/runtime.Defer", ptr %2, i32 0, i32 1 +// CHECK-NEXT: store i64 0, ptr %4, align 8 +// CHECK-NEXT: %5 = getelementptr inbounds %"{{.*}}/runtime/internal/runtime.Defer", ptr %2, i32 0, i32 2 +// CHECK-NEXT: store ptr %0, ptr %5, align 8 +// CHECK-NEXT: %6 = getelementptr inbounds %"{{.*}}/runtime/internal/runtime.Defer", ptr %2, i32 0, i32 3 +// CHECK-NEXT: store ptr blockaddress(@"main.init#2", %_llgo_2), ptr %6, align 8 +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.SetThreadDefer"(ptr %2) +// CHECK-NEXT: %7 = getelementptr inbounds %"{{.*}}/runtime/internal/runtime.Defer", ptr %2, i32 0, i32 1 +// CHECK-NEXT: %8 = getelementptr inbounds %"{{.*}}/runtime/internal/runtime.Defer", ptr %2, i32 0, i32 3 +// CHECK-NEXT: %9 = getelementptr inbounds %"{{.*}}/runtime/internal/runtime.Defer", ptr %2, i32 0, i32 4 +// CHECK-NEXT: %10 = getelementptr inbounds %"{{.*}}/runtime/internal/runtime.Defer", ptr %2, i32 0, i32 5 +// CHECK-NEXT: store ptr null, ptr %10, align 8 +// CHECK-NEXT: %11 = call i32 @{{(__)?}}sigsetjmp(ptr %1, i32 0) +// CHECK-NEXT: %12 = icmp eq i32 %11, 0 +// CHECK-NEXT: br i1 %12, label %_llgo_4, label %_llgo_5 +// CHECK-EMPTY: +// CHECK-NEXT: _llgo_1: ; preds = %_llgo_3 +// CHECK-NEXT: ret void +// CHECK-EMPTY: +// CHECK-NEXT: _llgo_2: ; preds = %_llgo_5, %_llgo_4 +// CHECK-NEXT: store ptr blockaddress(@"main.init#2", %_llgo_3), ptr %8, align 8 +// CHECK-NEXT: %13 = load i64, ptr %7, align 8 +// CHECK-NEXT: call void @"main.init#2$1"() +// CHECK-NEXT: %14 = load %"{{.*}}/runtime/internal/runtime.Defer", ptr %2, align 8 +// CHECK-NEXT: %15 = extractvalue %"{{.*}}/runtime/internal/runtime.Defer" %14, 2 +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.SetThreadDefer"(ptr %15) +// CHECK-NEXT: %16 = load ptr, ptr %9, align 8 +// CHECK-NEXT: indirectbr ptr %16, [label %_llgo_3, label %_llgo_6] +// CHECK-EMPTY: +// CHECK-NEXT: _llgo_3: ; preds = %_llgo_5, %_llgo_2 +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.Rethrow"(ptr %0) +// CHECK-NEXT: br label %_llgo_1 +// CHECK-EMPTY: +// CHECK-NEXT: _llgo_4: ; preds = %_llgo_0 +// CHECK-NEXT: call void @main.array(i64 2) +// CHECK-NEXT: store ptr blockaddress(@"main.init#2", %_llgo_6), ptr %9, align 8 +// CHECK-NEXT: br label %_llgo_2 +// CHECK-EMPTY: +// CHECK-NEXT: _llgo_5: ; preds = %_llgo_0 +// CHECK-NEXT: store ptr blockaddress(@"main.init#2", %_llgo_3), ptr %9, align 8 +// CHECK-NEXT: %17 = load ptr, ptr %8, align 8 +// CHECK-NEXT: indirectbr ptr %17, [label %_llgo_3, label %_llgo_2] +// CHECK-EMPTY: +// CHECK-NEXT: _llgo_6: ; preds = %_llgo_2 +// CHECK-NEXT: ret void +// CHECK-NEXT: } + +// CHECK-LABEL: define void @"main.init#2$1"(){{.*}} { +// CHECK-NEXT: _llgo_0: +// CHECK-NEXT: %0 = call %"{{.*}}/runtime/internal/runtime.eface" @"{{.*}}/runtime/internal/runtime.Recover"() +// CHECK-NEXT: %1 = call i1 @"{{.*}}/runtime/internal/runtime.EfaceEqual"(%"{{.*}}/runtime/internal/runtime.eface" %0, %"{{.*}}/runtime/internal/runtime.eface" zeroinitializer) +// CHECK-NEXT: br i1 %1, label %_llgo_1, label %_llgo_2 +// CHECK-EMPTY: +// CHECK-NEXT: _llgo_1: ; preds = %_llgo_0 +// CHECK-NEXT: %2 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 16) +// CHECK-NEXT: store %"{{.*}}/runtime/internal/runtime.String" { ptr @{{[0-9]+}}, i64 18 }, ptr %2, align 8 +// CHECK-NEXT: %3 = insertvalue %"{{.*}}/runtime/internal/runtime.eface" { ptr @_llgo_string, ptr undef }, ptr %2, 1 +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.Panic"(%"{{.*}}/runtime/internal/runtime.eface" %3) +// CHECK-NEXT: unreachable +// CHECK-EMPTY: +// CHECK-NEXT: _llgo_2: ; preds = %_llgo_0 +// CHECK-NEXT: ret void +// CHECK-NEXT: } + +// CHECK-LABEL: define void @"main.init#3"(){{.*}} { +// CHECK-NEXT: _llgo_0: +// CHECK-NEXT: %0 = call ptr @"{{.*}}/runtime/internal/runtime.GetThreadDefer"() +// CHECK-NEXT: %1 = alloca i8 +// CHECK-NEXT: %2 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 48) +// CHECK-NEXT: %3 = getelementptr inbounds %"{{.*}}/runtime/internal/runtime.Defer", ptr %2, i32 0, i32 0 +// CHECK-NEXT: store ptr %1, ptr %3, align 8 +// CHECK-NEXT: %4 = getelementptr inbounds %"{{.*}}/runtime/internal/runtime.Defer", ptr %2, i32 0, i32 1 +// CHECK-NEXT: store i64 0, ptr %4, align 8 +// CHECK-NEXT: %5 = getelementptr inbounds %"{{.*}}/runtime/internal/runtime.Defer", ptr %2, i32 0, i32 2 +// CHECK-NEXT: store ptr %0, ptr %5, align 8 +// CHECK-NEXT: %6 = getelementptr inbounds %"{{.*}}/runtime/internal/runtime.Defer", ptr %2, i32 0, i32 3 +// CHECK-NEXT: store ptr blockaddress(@"main.init#3", %_llgo_2), ptr %6, align 8 +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.SetThreadDefer"(ptr %2) +// CHECK-NEXT: %7 = getelementptr inbounds %"{{.*}}/runtime/internal/runtime.Defer", ptr %2, i32 0, i32 1 +// CHECK-NEXT: %8 = getelementptr inbounds %"{{.*}}/runtime/internal/runtime.Defer", ptr %2, i32 0, i32 3 +// CHECK-NEXT: %9 = getelementptr inbounds %"{{.*}}/runtime/internal/runtime.Defer", ptr %2, i32 0, i32 4 +// CHECK-NEXT: %10 = getelementptr inbounds %"{{.*}}/runtime/internal/runtime.Defer", ptr %2, i32 0, i32 5 +// CHECK-NEXT: store ptr null, ptr %10, align 8 +// CHECK-NEXT: %11 = call i32 @{{(__)?}}sigsetjmp(ptr %1, i32 0) +// CHECK-NEXT: %12 = icmp eq i32 %11, 0 +// CHECK-NEXT: br i1 %12, label %_llgo_4, label %_llgo_5 +// CHECK-EMPTY: +// CHECK-NEXT: _llgo_1: ; preds = %_llgo_3 +// CHECK-NEXT: ret void +// CHECK-EMPTY: +// CHECK-NEXT: _llgo_2: ; preds = %_llgo_5, %_llgo_4 +// CHECK-NEXT: store ptr blockaddress(@"main.init#3", %_llgo_3), ptr %8, align 8 +// CHECK-NEXT: %13 = load i64, ptr %7, align 8 +// CHECK-NEXT: call void @"main.init#3$1"() +// CHECK-NEXT: %14 = load %"{{.*}}/runtime/internal/runtime.Defer", ptr %2, align 8 +// CHECK-NEXT: %15 = extractvalue %"{{.*}}/runtime/internal/runtime.Defer" %14, 2 +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.SetThreadDefer"(ptr %15) +// CHECK-NEXT: %16 = load ptr, ptr %9, align 8 +// CHECK-NEXT: indirectbr ptr %16, [label %_llgo_3, label %_llgo_6] +// CHECK-EMPTY: +// CHECK-NEXT: _llgo_3: ; preds = %_llgo_5, %_llgo_2 +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.Rethrow"(ptr %0) +// CHECK-NEXT: br label %_llgo_1 +// CHECK-EMPTY: +// CHECK-NEXT: _llgo_4: ; preds = %_llgo_0 +// CHECK-NEXT: call void @main.array2(i64 2) +// CHECK-NEXT: store ptr blockaddress(@"main.init#3", %_llgo_6), ptr %9, align 8 +// CHECK-NEXT: br label %_llgo_2 +// CHECK-EMPTY: +// CHECK-NEXT: _llgo_5: ; preds = %_llgo_0 +// CHECK-NEXT: store ptr blockaddress(@"main.init#3", %_llgo_3), ptr %9, align 8 +// CHECK-NEXT: %17 = load ptr, ptr %8, align 8 +// CHECK-NEXT: indirectbr ptr %17, [label %_llgo_3, label %_llgo_2] +// CHECK-EMPTY: +// CHECK-NEXT: _llgo_6: ; preds = %_llgo_2 +// CHECK-NEXT: ret void +// CHECK-NEXT: } + +// CHECK-LABEL: define void @"main.init#3$1"(){{.*}} { +// CHECK-NEXT: _llgo_0: +// CHECK-NEXT: %0 = call %"{{.*}}/runtime/internal/runtime.eface" @"{{.*}}/runtime/internal/runtime.Recover"() +// CHECK-NEXT: %1 = call i1 @"{{.*}}/runtime/internal/runtime.EfaceEqual"(%"{{.*}}/runtime/internal/runtime.eface" %0, %"{{.*}}/runtime/internal/runtime.eface" zeroinitializer) +// CHECK-NEXT: br i1 %1, label %_llgo_1, label %_llgo_2 +// CHECK-EMPTY: +// CHECK-NEXT: _llgo_1: ; preds = %_llgo_0 +// CHECK-NEXT: %2 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 16) +// CHECK-NEXT: store %"{{.*}}/runtime/internal/runtime.String" { ptr @{{[0-9]+}}, i64 17 }, ptr %2, align 8 +// CHECK-NEXT: %3 = insertvalue %"{{.*}}/runtime/internal/runtime.eface" { ptr @_llgo_string, ptr undef }, ptr %2, 1 +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.Panic"(%"{{.*}}/runtime/internal/runtime.eface" %3) +// CHECK-NEXT: unreachable +// CHECK-EMPTY: +// CHECK-NEXT: _llgo_2: ; preds = %_llgo_0 +// CHECK-NEXT: ret void +// CHECK-NEXT: } + +// CHECK-LABEL: define void @"main.init#4"(){{.*}} { +// CHECK-NEXT: _llgo_0: +// CHECK-NEXT: %0 = call ptr @"{{.*}}/runtime/internal/runtime.GetThreadDefer"() +// CHECK-NEXT: %1 = alloca i8 +// CHECK-NEXT: %2 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 48) +// CHECK-NEXT: %3 = getelementptr inbounds %"{{.*}}/runtime/internal/runtime.Defer", ptr %2, i32 0, i32 0 +// CHECK-NEXT: store ptr %1, ptr %3, align 8 +// CHECK-NEXT: %4 = getelementptr inbounds %"{{.*}}/runtime/internal/runtime.Defer", ptr %2, i32 0, i32 1 +// CHECK-NEXT: store i64 0, ptr %4, align 8 +// CHECK-NEXT: %5 = getelementptr inbounds %"{{.*}}/runtime/internal/runtime.Defer", ptr %2, i32 0, i32 2 +// CHECK-NEXT: store ptr %0, ptr %5, align 8 +// CHECK-NEXT: %6 = getelementptr inbounds %"{{.*}}/runtime/internal/runtime.Defer", ptr %2, i32 0, i32 3 +// CHECK-NEXT: store ptr blockaddress(@"main.init#4", %_llgo_2), ptr %6, align 8 +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.SetThreadDefer"(ptr %2) +// CHECK-NEXT: %7 = getelementptr inbounds %"{{.*}}/runtime/internal/runtime.Defer", ptr %2, i32 0, i32 1 +// CHECK-NEXT: %8 = getelementptr inbounds %"{{.*}}/runtime/internal/runtime.Defer", ptr %2, i32 0, i32 3 +// CHECK-NEXT: %9 = getelementptr inbounds %"{{.*}}/runtime/internal/runtime.Defer", ptr %2, i32 0, i32 4 +// CHECK-NEXT: %10 = getelementptr inbounds %"{{.*}}/runtime/internal/runtime.Defer", ptr %2, i32 0, i32 5 +// CHECK-NEXT: store ptr null, ptr %10, align 8 +// CHECK-NEXT: %11 = call i32 @{{(__)?}}sigsetjmp(ptr %1, i32 0) +// CHECK-NEXT: %12 = icmp eq i32 %11, 0 +// CHECK-NEXT: br i1 %12, label %_llgo_4, label %_llgo_5 +// CHECK-EMPTY: +// CHECK-NEXT: _llgo_1: ; preds = %_llgo_3 +// CHECK-NEXT: ret void +// CHECK-EMPTY: +// CHECK-NEXT: _llgo_2: ; preds = %_llgo_5, %_llgo_4 +// CHECK-NEXT: store ptr blockaddress(@"main.init#4", %_llgo_3), ptr %8, align 8 +// CHECK-NEXT: %13 = load i64, ptr %7, align 8 +// CHECK-NEXT: call void @"main.init#4$1"() +// CHECK-NEXT: %14 = load %"{{.*}}/runtime/internal/runtime.Defer", ptr %2, align 8 +// CHECK-NEXT: %15 = extractvalue %"{{.*}}/runtime/internal/runtime.Defer" %14, 2 +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.SetThreadDefer"(ptr %15) +// CHECK-NEXT: %16 = load ptr, ptr %9, align 8 +// CHECK-NEXT: indirectbr ptr %16, [label %_llgo_3, label %_llgo_6] +// CHECK-EMPTY: +// CHECK-NEXT: _llgo_3: ; preds = %_llgo_5, %_llgo_2 +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.Rethrow"(ptr %0) +// CHECK-NEXT: br label %_llgo_1 +// CHECK-EMPTY: +// CHECK-NEXT: _llgo_4: ; preds = %_llgo_0 +// CHECK-NEXT: call void @main.slice(i64 -1) +// CHECK-NEXT: store ptr blockaddress(@"main.init#4", %_llgo_6), ptr %9, align 8 +// CHECK-NEXT: br label %_llgo_2 +// CHECK-EMPTY: +// CHECK-NEXT: _llgo_5: ; preds = %_llgo_0 +// CHECK-NEXT: store ptr blockaddress(@"main.init#4", %_llgo_3), ptr %9, align 8 +// CHECK-NEXT: %17 = load ptr, ptr %8, align 8 +// CHECK-NEXT: indirectbr ptr %17, [label %_llgo_3, label %_llgo_2] +// CHECK-EMPTY: +// CHECK-NEXT: _llgo_6: ; preds = %_llgo_2 +// CHECK-NEXT: ret void +// CHECK-NEXT: } + +// CHECK-LABEL: define void @"main.init#4$1"(){{.*}} { +// CHECK-NEXT: _llgo_0: +// CHECK-NEXT: %0 = call %"{{.*}}/runtime/internal/runtime.eface" @"{{.*}}/runtime/internal/runtime.Recover"() +// CHECK-NEXT: %1 = call i1 @"{{.*}}/runtime/internal/runtime.EfaceEqual"(%"{{.*}}/runtime/internal/runtime.eface" %0, %"{{.*}}/runtime/internal/runtime.eface" zeroinitializer) +// CHECK-NEXT: br i1 %1, label %_llgo_1, label %_llgo_2 +// CHECK-EMPTY: +// CHECK-NEXT: _llgo_1: ; preds = %_llgo_0 +// CHECK-NEXT: %2 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 16) +// CHECK-NEXT: store %"{{.*}}/runtime/internal/runtime.String" { ptr @{{[0-9]+}}, i64 19 }, ptr %2, align 8 +// CHECK-NEXT: %3 = insertvalue %"{{.*}}/runtime/internal/runtime.eface" { ptr @_llgo_string, ptr undef }, ptr %2, 1 +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.Panic"(%"{{.*}}/runtime/internal/runtime.eface" %3) +// CHECK-NEXT: unreachable +// CHECK-EMPTY: +// CHECK-NEXT: _llgo_2: ; preds = %_llgo_0 +// CHECK-NEXT: ret void +// CHECK-NEXT: } + +// CHECK-LABEL: define void @"main.init#5"(){{.*}} { +// CHECK-NEXT: _llgo_0: +// CHECK-NEXT: %0 = call ptr @"{{.*}}/runtime/internal/runtime.GetThreadDefer"() +// CHECK-NEXT: %1 = alloca i8 +// CHECK-NEXT: %2 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 48) +// CHECK-NEXT: %3 = getelementptr inbounds %"{{.*}}/runtime/internal/runtime.Defer", ptr %2, i32 0, i32 0 +// CHECK-NEXT: store ptr %1, ptr %3, align 8 +// CHECK-NEXT: %4 = getelementptr inbounds %"{{.*}}/runtime/internal/runtime.Defer", ptr %2, i32 0, i32 1 +// CHECK-NEXT: store i64 0, ptr %4, align 8 +// CHECK-NEXT: %5 = getelementptr inbounds %"{{.*}}/runtime/internal/runtime.Defer", ptr %2, i32 0, i32 2 +// CHECK-NEXT: store ptr %0, ptr %5, align 8 +// CHECK-NEXT: %6 = getelementptr inbounds %"{{.*}}/runtime/internal/runtime.Defer", ptr %2, i32 0, i32 3 +// CHECK-NEXT: store ptr blockaddress(@"main.init#5", %_llgo_2), ptr %6, align 8 +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.SetThreadDefer"(ptr %2) +// CHECK-NEXT: %7 = getelementptr inbounds %"{{.*}}/runtime/internal/runtime.Defer", ptr %2, i32 0, i32 1 +// CHECK-NEXT: %8 = getelementptr inbounds %"{{.*}}/runtime/internal/runtime.Defer", ptr %2, i32 0, i32 3 +// CHECK-NEXT: %9 = getelementptr inbounds %"{{.*}}/runtime/internal/runtime.Defer", ptr %2, i32 0, i32 4 +// CHECK-NEXT: %10 = getelementptr inbounds %"{{.*}}/runtime/internal/runtime.Defer", ptr %2, i32 0, i32 5 +// CHECK-NEXT: store ptr null, ptr %10, align 8 +// CHECK-NEXT: %11 = call i32 @{{(__)?}}sigsetjmp(ptr %1, i32 0) +// CHECK-NEXT: %12 = icmp eq i32 %11, 0 +// CHECK-NEXT: br i1 %12, label %_llgo_4, label %_llgo_5 +// CHECK-EMPTY: +// CHECK-NEXT: _llgo_1: ; preds = %_llgo_3 +// CHECK-NEXT: ret void +// CHECK-EMPTY: +// CHECK-NEXT: _llgo_2: ; preds = %_llgo_5, %_llgo_4 +// CHECK-NEXT: store ptr blockaddress(@"main.init#5", %_llgo_3), ptr %8, align 8 +// CHECK-NEXT: %13 = load i64, ptr %7, align 8 +// CHECK-NEXT: call void @"main.init#5$1"() +// CHECK-NEXT: %14 = load %"{{.*}}/runtime/internal/runtime.Defer", ptr %2, align 8 +// CHECK-NEXT: %15 = extractvalue %"{{.*}}/runtime/internal/runtime.Defer" %14, 2 +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.SetThreadDefer"(ptr %15) +// CHECK-NEXT: %16 = load ptr, ptr %9, align 8 +// CHECK-NEXT: indirectbr ptr %16, [label %_llgo_3, label %_llgo_6] +// CHECK-EMPTY: +// CHECK-NEXT: _llgo_3: ; preds = %_llgo_5, %_llgo_2 +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.Rethrow"(ptr %0) +// CHECK-NEXT: br label %_llgo_1 +// CHECK-EMPTY: +// CHECK-NEXT: _llgo_4: ; preds = %_llgo_0 +// CHECK-NEXT: call void @main.slice(i64 2) +// CHECK-NEXT: store ptr blockaddress(@"main.init#5", %_llgo_6), ptr %9, align 8 +// CHECK-NEXT: br label %_llgo_2 +// CHECK-EMPTY: +// CHECK-NEXT: _llgo_5: ; preds = %_llgo_0 +// CHECK-NEXT: store ptr blockaddress(@"main.init#5", %_llgo_3), ptr %9, align 8 +// CHECK-NEXT: %17 = load ptr, ptr %8, align 8 +// CHECK-NEXT: indirectbr ptr %17, [label %_llgo_3, label %_llgo_2] +// CHECK-EMPTY: +// CHECK-NEXT: _llgo_6: ; preds = %_llgo_2 +// CHECK-NEXT: ret void +// CHECK-NEXT: } + +// CHECK-LABEL: define void @"main.init#5$1"(){{.*}} { +// CHECK-NEXT: _llgo_0: +// CHECK-NEXT: %0 = call %"{{.*}}/runtime/internal/runtime.eface" @"{{.*}}/runtime/internal/runtime.Recover"() +// CHECK-NEXT: %1 = call i1 @"{{.*}}/runtime/internal/runtime.EfaceEqual"(%"{{.*}}/runtime/internal/runtime.eface" %0, %"{{.*}}/runtime/internal/runtime.eface" zeroinitializer) +// CHECK-NEXT: br i1 %1, label %_llgo_1, label %_llgo_2 +// CHECK-EMPTY: +// CHECK-NEXT: _llgo_1: ; preds = %_llgo_0 +// CHECK-NEXT: %2 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 16) +// CHECK-NEXT: store %"{{.*}}/runtime/internal/runtime.String" { ptr @{{[0-9]+}}, i64 18 }, ptr %2, align 8 +// CHECK-NEXT: %3 = insertvalue %"{{.*}}/runtime/internal/runtime.eface" { ptr @_llgo_string, ptr undef }, ptr %2, 1 +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.Panic"(%"{{.*}}/runtime/internal/runtime.eface" %3) +// CHECK-NEXT: unreachable +// CHECK-EMPTY: +// CHECK-NEXT: _llgo_2: ; preds = %_llgo_0 +// CHECK-NEXT: ret void +// CHECK-NEXT: } + +// CHECK-LABEL: define void @"main.init#6"(){{.*}} { +// CHECK-NEXT: _llgo_0: +// CHECK-NEXT: %0 = call ptr @"{{.*}}/runtime/internal/runtime.GetThreadDefer"() +// CHECK-NEXT: %1 = alloca i8 +// CHECK-NEXT: %2 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 48) +// CHECK-NEXT: %3 = getelementptr inbounds %"{{.*}}/runtime/internal/runtime.Defer", ptr %2, i32 0, i32 0 +// CHECK-NEXT: store ptr %1, ptr %3, align 8 +// CHECK-NEXT: %4 = getelementptr inbounds %"{{.*}}/runtime/internal/runtime.Defer", ptr %2, i32 0, i32 1 +// CHECK-NEXT: store i64 0, ptr %4, align 8 +// CHECK-NEXT: %5 = getelementptr inbounds %"{{.*}}/runtime/internal/runtime.Defer", ptr %2, i32 0, i32 2 +// CHECK-NEXT: store ptr %0, ptr %5, align 8 +// CHECK-NEXT: %6 = getelementptr inbounds %"{{.*}}/runtime/internal/runtime.Defer", ptr %2, i32 0, i32 3 +// CHECK-NEXT: store ptr blockaddress(@"main.init#6", %_llgo_2), ptr %6, align 8 +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.SetThreadDefer"(ptr %2) +// CHECK-NEXT: %7 = getelementptr inbounds %"{{.*}}/runtime/internal/runtime.Defer", ptr %2, i32 0, i32 1 +// CHECK-NEXT: %8 = getelementptr inbounds %"{{.*}}/runtime/internal/runtime.Defer", ptr %2, i32 0, i32 3 +// CHECK-NEXT: %9 = getelementptr inbounds %"{{.*}}/runtime/internal/runtime.Defer", ptr %2, i32 0, i32 4 +// CHECK-NEXT: %10 = getelementptr inbounds %"{{.*}}/runtime/internal/runtime.Defer", ptr %2, i32 0, i32 5 +// CHECK-NEXT: store ptr null, ptr %10, align 8 +// CHECK-NEXT: %11 = call i32 @{{(__)?}}sigsetjmp(ptr %1, i32 0) +// CHECK-NEXT: %12 = icmp eq i32 %11, 0 +// CHECK-NEXT: br i1 %12, label %_llgo_4, label %_llgo_5 +// CHECK-EMPTY: +// CHECK-NEXT: _llgo_1: ; preds = %_llgo_3 +// CHECK-NEXT: ret void +// CHECK-EMPTY: +// CHECK-NEXT: _llgo_2: ; preds = %_llgo_5, %_llgo_4 +// CHECK-NEXT: store ptr blockaddress(@"main.init#6", %_llgo_3), ptr %8, align 8 +// CHECK-NEXT: %13 = load i64, ptr %7, align 8 +// CHECK-NEXT: call void @"main.init#6$1"() +// CHECK-NEXT: %14 = load %"{{.*}}/runtime/internal/runtime.Defer", ptr %2, align 8 +// CHECK-NEXT: %15 = extractvalue %"{{.*}}/runtime/internal/runtime.Defer" %14, 2 +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.SetThreadDefer"(ptr %15) +// CHECK-NEXT: %16 = load ptr, ptr %9, align 8 +// CHECK-NEXT: indirectbr ptr %16, [label %_llgo_3, label %_llgo_6] +// CHECK-EMPTY: +// CHECK-NEXT: _llgo_3: ; preds = %_llgo_5, %_llgo_2 +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.Rethrow"(ptr %0) +// CHECK-NEXT: br label %_llgo_1 +// CHECK-EMPTY: +// CHECK-NEXT: _llgo_4: ; preds = %_llgo_0 +// CHECK-NEXT: call void @main.slice2(i64 2) +// CHECK-NEXT: store ptr blockaddress(@"main.init#6", %_llgo_6), ptr %9, align 8 +// CHECK-NEXT: br label %_llgo_2 +// CHECK-EMPTY: +// CHECK-NEXT: _llgo_5: ; preds = %_llgo_0 +// CHECK-NEXT: store ptr blockaddress(@"main.init#6", %_llgo_3), ptr %9, align 8 +// CHECK-NEXT: %17 = load ptr, ptr %8, align 8 +// CHECK-NEXT: indirectbr ptr %17, [label %_llgo_3, label %_llgo_2] +// CHECK-EMPTY: +// CHECK-NEXT: _llgo_6: ; preds = %_llgo_2 +// CHECK-NEXT: ret void +// CHECK-NEXT: } + +// CHECK-LABEL: define void @"main.init#6$1"(){{.*}} { +// CHECK-NEXT: _llgo_0: +// CHECK-NEXT: %0 = call %"{{.*}}/runtime/internal/runtime.eface" @"{{.*}}/runtime/internal/runtime.Recover"() +// CHECK-NEXT: %1 = call i1 @"{{.*}}/runtime/internal/runtime.EfaceEqual"(%"{{.*}}/runtime/internal/runtime.eface" %0, %"{{.*}}/runtime/internal/runtime.eface" zeroinitializer) +// CHECK-NEXT: br i1 %1, label %_llgo_1, label %_llgo_2 +// CHECK-EMPTY: +// CHECK-NEXT: _llgo_1: ; preds = %_llgo_0 +// CHECK-NEXT: %2 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 16) +// CHECK-NEXT: store %"{{.*}}/runtime/internal/runtime.String" { ptr @{{[0-9]+}}, i64 19 }, ptr %2, align 8 +// CHECK-NEXT: %3 = insertvalue %"{{.*}}/runtime/internal/runtime.eface" { ptr @_llgo_string, ptr undef }, ptr %2, 1 +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.Panic"(%"{{.*}}/runtime/internal/runtime.eface" %3) +// CHECK-NEXT: unreachable +// CHECK-EMPTY: +// CHECK-NEXT: _llgo_2: ; preds = %_llgo_0 +// CHECK-NEXT: ret void +// CHECK-NEXT: } + +// CHECK-LABEL: define void @"main.init#7"(){{.*}} { +// CHECK-NEXT: _llgo_0: +// CHECK-NEXT: %0 = call ptr @"{{.*}}/runtime/internal/runtime.GetThreadDefer"() +// CHECK-NEXT: %1 = alloca i8 +// CHECK-NEXT: %2 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 48) +// CHECK-NEXT: %3 = getelementptr inbounds %"{{.*}}/runtime/internal/runtime.Defer", ptr %2, i32 0, i32 0 +// CHECK-NEXT: store ptr %1, ptr %3, align 8 +// CHECK-NEXT: %4 = getelementptr inbounds %"{{.*}}/runtime/internal/runtime.Defer", ptr %2, i32 0, i32 1 +// CHECK-NEXT: store i64 0, ptr %4, align 8 +// CHECK-NEXT: %5 = getelementptr inbounds %"{{.*}}/runtime/internal/runtime.Defer", ptr %2, i32 0, i32 2 +// CHECK-NEXT: store ptr %0, ptr %5, align 8 +// CHECK-NEXT: %6 = getelementptr inbounds %"{{.*}}/runtime/internal/runtime.Defer", ptr %2, i32 0, i32 3 +// CHECK-NEXT: store ptr blockaddress(@"main.init#7", %_llgo_2), ptr %6, align 8 +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.SetThreadDefer"(ptr %2) +// CHECK-NEXT: %7 = getelementptr inbounds %"{{.*}}/runtime/internal/runtime.Defer", ptr %2, i32 0, i32 1 +// CHECK-NEXT: %8 = getelementptr inbounds %"{{.*}}/runtime/internal/runtime.Defer", ptr %2, i32 0, i32 3 +// CHECK-NEXT: %9 = getelementptr inbounds %"{{.*}}/runtime/internal/runtime.Defer", ptr %2, i32 0, i32 4 +// CHECK-NEXT: %10 = getelementptr inbounds %"{{.*}}/runtime/internal/runtime.Defer", ptr %2, i32 0, i32 5 +// CHECK-NEXT: store ptr null, ptr %10, align 8 +// CHECK-NEXT: %11 = call i32 @{{(__)?}}sigsetjmp(ptr %1, i32 0) +// CHECK-NEXT: %12 = icmp eq i32 %11, 0 +// CHECK-NEXT: br i1 %12, label %_llgo_4, label %_llgo_5 +// CHECK-EMPTY: +// CHECK-NEXT: _llgo_1: ; preds = %_llgo_3 +// CHECK-NEXT: ret void +// CHECK-EMPTY: +// CHECK-NEXT: _llgo_2: ; preds = %_llgo_5, %_llgo_4 +// CHECK-NEXT: store ptr blockaddress(@"main.init#7", %_llgo_3), ptr %8, align 8 +// CHECK-NEXT: %13 = load i64, ptr %7, align 8 +// CHECK-NEXT: call void @"main.init#7$1"() +// CHECK-NEXT: %14 = load %"{{.*}}/runtime/internal/runtime.Defer", ptr %2, align 8 +// CHECK-NEXT: %15 = extractvalue %"{{.*}}/runtime/internal/runtime.Defer" %14, 2 +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.SetThreadDefer"(ptr %15) +// CHECK-NEXT: %16 = load ptr, ptr %9, align 8 +// CHECK-NEXT: indirectbr ptr %16, [label %_llgo_3, label %_llgo_6] +// CHECK-EMPTY: +// CHECK-NEXT: _llgo_3: ; preds = %_llgo_5, %_llgo_2 +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.Rethrow"(ptr %0) +// CHECK-NEXT: br label %_llgo_1 +// CHECK-EMPTY: +// CHECK-NEXT: _llgo_4: ; preds = %_llgo_0 +// CHECK-NEXT: %17 = alloca [2 x i64], align 8 +// CHECK-NEXT: call void @llvm.memset.p0.i64(ptr %17, i8 0, i64 16, i1 false) +// CHECK-NEXT: %18 = getelementptr inbounds i64, ptr %17, i64 0 +// CHECK-NEXT: %19 = getelementptr inbounds i64, ptr %17, i64 1 +// CHECK-NEXT: store i64 1, ptr %18, align 8 +// CHECK-NEXT: store i64 2, ptr %19, align 8 +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.CheckIndexRange"(i1 true, i64 -1, i1 true, i64 2) +// CHECK-NEXT: %20 = getelementptr inbounds i64, ptr %17, i64 -1 +// CHECK-NEXT: %21 = load i64, ptr %20, align 8 +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.PrintInt"(i64 %21) +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.PrintByte"(i8 10) +// CHECK-NEXT: store ptr blockaddress(@"main.init#7", %_llgo_6), ptr %9, align 8 +// CHECK-NEXT: br label %_llgo_2 +// CHECK-EMPTY: +// CHECK-NEXT: _llgo_5: ; preds = %_llgo_0 +// CHECK-NEXT: store ptr blockaddress(@"main.init#7", %_llgo_3), ptr %9, align 8 +// CHECK-NEXT: %22 = load ptr, ptr %8, align 8 +// CHECK-NEXT: indirectbr ptr %22, [label %_llgo_3, label %_llgo_2] +// CHECK-EMPTY: +// CHECK-NEXT: _llgo_6: ; preds = %_llgo_2 +// CHECK-NEXT: ret void +// CHECK-NEXT: } + +// CHECK-LABEL: define void @"main.init#7$1"(){{.*}} { +// CHECK-NEXT: _llgo_0: +// CHECK-NEXT: %0 = call %"{{.*}}/runtime/internal/runtime.eface" @"{{.*}}/runtime/internal/runtime.Recover"() +// CHECK-NEXT: %1 = call i1 @"{{.*}}/runtime/internal/runtime.EfaceEqual"(%"{{.*}}/runtime/internal/runtime.eface" %0, %"{{.*}}/runtime/internal/runtime.eface" zeroinitializer) +// CHECK-NEXT: br i1 %1, label %_llgo_1, label %_llgo_2 +// CHECK-EMPTY: +// CHECK-NEXT: _llgo_1: ; preds = %_llgo_0 +// CHECK-NEXT: %2 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 16) +// CHECK-NEXT: store %"{{.*}}/runtime/internal/runtime.String" { ptr @{{[0-9]+}}, i64 12 }, ptr %2, align 8 +// CHECK-NEXT: %3 = insertvalue %"{{.*}}/runtime/internal/runtime.eface" { ptr @_llgo_string, ptr undef }, ptr %2, 1 +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.Panic"(%"{{.*}}/runtime/internal/runtime.eface" %3) +// CHECK-NEXT: unreachable +// CHECK-EMPTY: +// CHECK-NEXT: _llgo_2: ; preds = %_llgo_0 +// CHECK-NEXT: ret void +// CHECK-NEXT: } + +// CHECK-LABEL: define void @"main.init#8"(){{.*}} { +// CHECK-NEXT: _llgo_0: +// CHECK-NEXT: %0 = call ptr @"{{.*}}/runtime/internal/runtime.GetThreadDefer"() +// CHECK-NEXT: %1 = alloca i8 +// CHECK-NEXT: %2 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 48) +// CHECK-NEXT: %3 = getelementptr inbounds %"{{.*}}/runtime/internal/runtime.Defer", ptr %2, i32 0, i32 0 +// CHECK-NEXT: store ptr %1, ptr %3, align 8 +// CHECK-NEXT: %4 = getelementptr inbounds %"{{.*}}/runtime/internal/runtime.Defer", ptr %2, i32 0, i32 1 +// CHECK-NEXT: store i64 0, ptr %4, align 8 +// CHECK-NEXT: %5 = getelementptr inbounds %"{{.*}}/runtime/internal/runtime.Defer", ptr %2, i32 0, i32 2 +// CHECK-NEXT: store ptr %0, ptr %5, align 8 +// CHECK-NEXT: %6 = getelementptr inbounds %"{{.*}}/runtime/internal/runtime.Defer", ptr %2, i32 0, i32 3 +// CHECK-NEXT: store ptr blockaddress(@"main.init#8", %_llgo_2), ptr %6, align 8 +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.SetThreadDefer"(ptr %2) +// CHECK-NEXT: %7 = getelementptr inbounds %"{{.*}}/runtime/internal/runtime.Defer", ptr %2, i32 0, i32 1 +// CHECK-NEXT: %8 = getelementptr inbounds %"{{.*}}/runtime/internal/runtime.Defer", ptr %2, i32 0, i32 3 +// CHECK-NEXT: %9 = getelementptr inbounds %"{{.*}}/runtime/internal/runtime.Defer", ptr %2, i32 0, i32 4 +// CHECK-NEXT: %10 = getelementptr inbounds %"{{.*}}/runtime/internal/runtime.Defer", ptr %2, i32 0, i32 5 +// CHECK-NEXT: store ptr null, ptr %10, align 8 +// CHECK-NEXT: %11 = call i32 @{{(__)?}}sigsetjmp(ptr %1, i32 0) +// CHECK-NEXT: %12 = icmp eq i32 %11, 0 +// CHECK-NEXT: br i1 %12, label %_llgo_4, label %_llgo_5 +// CHECK-EMPTY: +// CHECK-NEXT: _llgo_1: ; preds = %_llgo_3 +// CHECK-NEXT: ret void +// CHECK-EMPTY: +// CHECK-NEXT: _llgo_2: ; preds = %_llgo_5, %_llgo_4 +// CHECK-NEXT: store ptr blockaddress(@"main.init#8", %_llgo_3), ptr %8, align 8 +// CHECK-NEXT: %13 = load i64, ptr %7, align 8 +// CHECK-NEXT: call void @"main.init#8$1"() +// CHECK-NEXT: %14 = load %"{{.*}}/runtime/internal/runtime.Defer", ptr %2, align 8 +// CHECK-NEXT: %15 = extractvalue %"{{.*}}/runtime/internal/runtime.Defer" %14, 2 +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.SetThreadDefer"(ptr %15) +// CHECK-NEXT: %16 = load ptr, ptr %9, align 8 +// CHECK-NEXT: indirectbr ptr %16, [label %_llgo_3, label %_llgo_6] +// CHECK-EMPTY: +// CHECK-NEXT: _llgo_3: ; preds = %_llgo_5, %_llgo_2 +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.Rethrow"(ptr %0) +// CHECK-NEXT: br label %_llgo_1 +// CHECK-EMPTY: +// CHECK-NEXT: _llgo_4: ; preds = %_llgo_0 +// CHECK-NEXT: %17 = alloca [2 x i64], align 8 +// CHECK-NEXT: call void @llvm.memset.p0.i64(ptr %17, i8 0, i64 16, i1 false) +// CHECK-NEXT: %18 = getelementptr inbounds i64, ptr %17, i64 0 +// CHECK-NEXT: %19 = getelementptr inbounds i64, ptr %17, i64 1 +// CHECK-NEXT: store i64 1, ptr %18, align 8 +// CHECK-NEXT: store i64 2, ptr %19, align 8 +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.CheckIndexRange"(i1 true, i64 2, i1 true, i64 2) +// CHECK-NEXT: %20 = getelementptr inbounds i64, ptr %17, i64 2 +// CHECK-NEXT: %21 = load i64, ptr %20, align 8 +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.PrintInt"(i64 %21) +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.PrintByte"(i8 10) +// CHECK-NEXT: store ptr blockaddress(@"main.init#8", %_llgo_6), ptr %9, align 8 +// CHECK-NEXT: br label %_llgo_2 +// CHECK-EMPTY: +// CHECK-NEXT: _llgo_5: ; preds = %_llgo_0 +// CHECK-NEXT: store ptr blockaddress(@"main.init#8", %_llgo_3), ptr %9, align 8 +// CHECK-NEXT: %22 = load ptr, ptr %8, align 8 +// CHECK-NEXT: indirectbr ptr %22, [label %_llgo_3, label %_llgo_2] +// CHECK-EMPTY: +// CHECK-NEXT: _llgo_6: ; preds = %_llgo_2 +// CHECK-NEXT: ret void +// CHECK-NEXT: } + +// CHECK-LABEL: define void @"main.init#8$1"(){{.*}} { +// CHECK-NEXT: _llgo_0: +// CHECK-NEXT: %0 = call %"{{.*}}/runtime/internal/runtime.eface" @"{{.*}}/runtime/internal/runtime.Recover"() +// CHECK-NEXT: %1 = call i1 @"{{.*}}/runtime/internal/runtime.EfaceEqual"(%"{{.*}}/runtime/internal/runtime.eface" %0, %"{{.*}}/runtime/internal/runtime.eface" zeroinitializer) +// CHECK-NEXT: br i1 %1, label %_llgo_1, label %_llgo_2 +// CHECK-EMPTY: +// CHECK-NEXT: _llgo_1: ; preds = %_llgo_0 +// CHECK-NEXT: %2 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 16) +// CHECK-NEXT: store %"{{.*}}/runtime/internal/runtime.String" { ptr @{{[0-9]+}}, i64 13 }, ptr %2, align 8 +// CHECK-NEXT: %3 = insertvalue %"{{.*}}/runtime/internal/runtime.eface" { ptr @_llgo_string, ptr undef }, ptr %2, 1 +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.Panic"(%"{{.*}}/runtime/internal/runtime.eface" %3) +// CHECK-NEXT: unreachable +// CHECK-EMPTY: +// CHECK-NEXT: _llgo_2: ; preds = %_llgo_0 +// CHECK-NEXT: ret void +// CHECK-NEXT: } + +// CHECK-LABEL: define void @"main.init#9"(){{.*}} { +// CHECK-NEXT: _llgo_0: +// CHECK-NEXT: %0 = call ptr @"{{.*}}/runtime/internal/runtime.GetThreadDefer"() +// CHECK-NEXT: %1 = alloca i8 +// CHECK-NEXT: %2 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 48) +// CHECK-NEXT: %3 = getelementptr inbounds %"{{.*}}/runtime/internal/runtime.Defer", ptr %2, i32 0, i32 0 +// CHECK-NEXT: store ptr %1, ptr %3, align 8 +// CHECK-NEXT: %4 = getelementptr inbounds %"{{.*}}/runtime/internal/runtime.Defer", ptr %2, i32 0, i32 1 +// CHECK-NEXT: store i64 0, ptr %4, align 8 +// CHECK-NEXT: %5 = getelementptr inbounds %"{{.*}}/runtime/internal/runtime.Defer", ptr %2, i32 0, i32 2 +// CHECK-NEXT: store ptr %0, ptr %5, align 8 +// CHECK-NEXT: %6 = getelementptr inbounds %"{{.*}}/runtime/internal/runtime.Defer", ptr %2, i32 0, i32 3 +// CHECK-NEXT: store ptr blockaddress(@"main.init#9", %_llgo_2), ptr %6, align 8 +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.SetThreadDefer"(ptr %2) +// CHECK-NEXT: %7 = getelementptr inbounds %"{{.*}}/runtime/internal/runtime.Defer", ptr %2, i32 0, i32 1 +// CHECK-NEXT: %8 = getelementptr inbounds %"{{.*}}/runtime/internal/runtime.Defer", ptr %2, i32 0, i32 3 +// CHECK-NEXT: %9 = getelementptr inbounds %"{{.*}}/runtime/internal/runtime.Defer", ptr %2, i32 0, i32 4 +// CHECK-NEXT: %10 = getelementptr inbounds %"{{.*}}/runtime/internal/runtime.Defer", ptr %2, i32 0, i32 5 +// CHECK-NEXT: store ptr null, ptr %10, align 8 +// CHECK-NEXT: %11 = call i32 @{{(__)?}}sigsetjmp(ptr %1, i32 0) +// CHECK-NEXT: %12 = icmp eq i32 %11, 0 +// CHECK-NEXT: br i1 %12, label %_llgo_4, label %_llgo_5 +// CHECK-EMPTY: +// CHECK-NEXT: _llgo_1: ; preds = %_llgo_3 +// CHECK-NEXT: ret void +// CHECK-EMPTY: +// CHECK-NEXT: _llgo_2: ; preds = %_llgo_5, %_llgo_4 +// CHECK-NEXT: store ptr blockaddress(@"main.init#9", %_llgo_3), ptr %8, align 8 +// CHECK-NEXT: %13 = load i64, ptr %7, align 8 +// CHECK-NEXT: call void @"main.init#9$1"() +// CHECK-NEXT: %14 = load %"{{.*}}/runtime/internal/runtime.Defer", ptr %2, align 8 +// CHECK-NEXT: %15 = extractvalue %"{{.*}}/runtime/internal/runtime.Defer" %14, 2 +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.SetThreadDefer"(ptr %15) +// CHECK-NEXT: %16 = load ptr, ptr %9, align 8 +// CHECK-NEXT: indirectbr ptr %16, [label %_llgo_3, label %_llgo_6] +// CHECK-EMPTY: +// CHECK-NEXT: _llgo_3: ; preds = %_llgo_5, %_llgo_2 +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.Rethrow"(ptr %0) +// CHECK-NEXT: br label %_llgo_1 +// CHECK-EMPTY: +// CHECK-NEXT: _llgo_4: ; preds = %_llgo_0 +// CHECK-NEXT: %17 = alloca [2 x i64], align 8 +// CHECK-NEXT: call void @llvm.memset.p0.i64(ptr %17, i8 0, i64 16, i1 false) +// CHECK-NEXT: %18 = getelementptr inbounds i64, ptr %17, i64 0 +// CHECK-NEXT: %19 = getelementptr inbounds i64, ptr %17, i64 1 +// CHECK-NEXT: store i64 1, ptr %18, align 8 +// CHECK-NEXT: store i64 2, ptr %19, align 8 +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.CheckIndexRange"(i1 true, i64 2, i1 false, i64 2) +// CHECK-NEXT: %20 = getelementptr inbounds i64, ptr %17, i64 2 +// CHECK-NEXT: %21 = load i64, ptr %20, align 8 +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.PrintInt"(i64 %21) +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.PrintByte"(i8 10) +// CHECK-NEXT: store ptr blockaddress(@"main.init#9", %_llgo_6), ptr %9, align 8 +// CHECK-NEXT: br label %_llgo_2 +// CHECK-EMPTY: +// CHECK-NEXT: _llgo_5: ; preds = %_llgo_0 +// CHECK-NEXT: store ptr blockaddress(@"main.init#9", %_llgo_3), ptr %9, align 8 +// CHECK-NEXT: %22 = load ptr, ptr %8, align 8 +// CHECK-NEXT: indirectbr ptr %22, [label %_llgo_3, label %_llgo_2] +// CHECK-EMPTY: +// CHECK-NEXT: _llgo_6: ; preds = %_llgo_2 +// CHECK-NEXT: ret void +// CHECK-NEXT: } + +// CHECK-LABEL: define void @"main.init#9$1"(){{.*}} { +// CHECK-NEXT: _llgo_0: +// CHECK-NEXT: %0 = call %"{{.*}}/runtime/internal/runtime.eface" @"{{.*}}/runtime/internal/runtime.Recover"() +// CHECK-NEXT: %1 = call i1 @"{{.*}}/runtime/internal/runtime.EfaceEqual"(%"{{.*}}/runtime/internal/runtime.eface" %0, %"{{.*}}/runtime/internal/runtime.eface" zeroinitializer) +// CHECK-NEXT: br i1 %1, label %_llgo_1, label %_llgo_2 +// CHECK-EMPTY: +// CHECK-NEXT: _llgo_1: ; preds = %_llgo_0 +// CHECK-NEXT: %2 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 16) +// CHECK-NEXT: store %"{{.*}}/runtime/internal/runtime.String" { ptr @{{[0-9]+}}, i64 12 }, ptr %2, align 8 +// CHECK-NEXT: %3 = insertvalue %"{{.*}}/runtime/internal/runtime.eface" { ptr @_llgo_string, ptr undef }, ptr %2, 1 +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.Panic"(%"{{.*}}/runtime/internal/runtime.eface" %3) +// CHECK-NEXT: unreachable +// CHECK-EMPTY: +// CHECK-NEXT: _llgo_2: ; preds = %_llgo_0 +// CHECK-NEXT: ret void +// CHECK-NEXT: } + +// CHECK-LABEL: define void @main.main(){{.*}} { +// CHECK-NEXT: _llgo_0: +// CHECK-NEXT: ret void +// CHECK-NEXT: } + +// CHECK-LABEL: define void @main.slice(i64 %0){{.*}} { +// CHECK-NEXT: _llgo_0: +// CHECK-NEXT: %1 = call ptr @"{{.*}}/runtime/internal/runtime.AllocZ"(i64 16) +// CHECK-NEXT: %2 = getelementptr inbounds i64, ptr %1, i64 0 +// CHECK-NEXT: store i64 1, ptr %2, align 8 +// CHECK-NEXT: %3 = getelementptr inbounds i64, ptr %1, i64 1 +// CHECK-NEXT: store i64 2, ptr %3, align 8 +// CHECK-NEXT: %4 = insertvalue %"{{.*}}/runtime/internal/runtime.Slice" undef, ptr %1, 0 +// CHECK-NEXT: %5 = insertvalue %"{{.*}}/runtime/internal/runtime.Slice" %4, i64 2, 1 +// CHECK-NEXT: %6 = insertvalue %"{{.*}}/runtime/internal/runtime.Slice" %5, i64 2, 2 +// CHECK-NEXT: %7 = extractvalue %"{{.*}}/runtime/internal/runtime.Slice" %6, 0 +// CHECK-NEXT: %8 = extractvalue %"{{.*}}/runtime/internal/runtime.Slice" %6, 1 +// CHECK-NEXT: %9 = icmp slt i64 %0, 0 +// CHECK-NEXT: %10 = icmp uge i64 %0, %8 +// CHECK-NEXT: %11 = or i1 %10, %9 +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.CheckIndexRange"(i1 %11, i64 %0, i1 true, i64 %8) +// CHECK-NEXT: %12 = getelementptr inbounds i64, ptr %7, i64 %0 +// CHECK-NEXT: %13 = load i64, ptr %12, align 8 +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.PrintInt"(i64 %13) +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.PrintByte"(i8 10) +// CHECK-NEXT: ret void +// CHECK-NEXT: } + +// CHECK-LABEL: define void @main.slice2(i64 %0){{.*}} { +// CHECK-NEXT: _llgo_0: +// CHECK-NEXT: %1 = call ptr @"{{.*}}/runtime/internal/runtime.AllocZ"(i64 16) +// CHECK-NEXT: %2 = getelementptr inbounds i64, ptr %1, i64 0 +// CHECK-NEXT: store i64 1, ptr %2, align 8 +// CHECK-NEXT: %3 = getelementptr inbounds i64, ptr %1, i64 1 +// CHECK-NEXT: store i64 2, ptr %3, align 8 +// CHECK-NEXT: %4 = insertvalue %"{{.*}}/runtime/internal/runtime.Slice" undef, ptr %1, 0 +// CHECK-NEXT: %5 = insertvalue %"{{.*}}/runtime/internal/runtime.Slice" %4, i64 2, 1 +// CHECK-NEXT: %6 = insertvalue %"{{.*}}/runtime/internal/runtime.Slice" %5, i64 2, 2 +// CHECK-NEXT: %7 = extractvalue %"{{.*}}/runtime/internal/runtime.Slice" %6, 0 +// CHECK-NEXT: %8 = extractvalue %"{{.*}}/runtime/internal/runtime.Slice" %6, 1 +// CHECK-NEXT: %9 = icmp slt i64 %0, 0 +// CHECK-NEXT: %10 = icmp uge i64 %0, %8 +// CHECK-NEXT: %11 = or i1 %10, %9 +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.CheckIndexRange"(i1 %11, i64 %0, i1 true, i64 %8) +// CHECK-NEXT: %12 = getelementptr inbounds i64, ptr %7, i64 %0 +// CHECK-NEXT: %13 = load i64, ptr %12, align 8 +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.PrintInt"(i64 %13) +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.PrintByte"(i8 10) +// CHECK-NEXT: ret void +// CHECK-NEXT: } diff --git a/cl/_testgo/makeslice/in.go b/cl/_testgo/makeslice/in.go index bf7a194d6a..de2ee3bba9 100644 --- a/cl/_testgo/makeslice/in.go +++ b/cl/_testgo/makeslice/in.go @@ -1,8 +1,8 @@ // LITTEST package main -// CHECK-DAG: call %"{{.*}}/runtime/internal/runtime.Slice" @"{{.*}}/runtime/internal/runtime.MakeSlice"({{.*}}) -// CHECK-DAG: call %"{{.*}}/runtime/internal/runtime.eface" @"{{.*}}/runtime/internal/runtime.Recover"() +// CHECK: {{^}}@{{[0-9]+}} = private unnamed_addr constant [5 x i8] c"error", align 1{{$}} +// CHECK: {{^}}@{{[0-9]+}} = private unnamed_addr constant [10 x i8] c"must error", align 1{{$}} func main() { } @@ -58,3 +58,279 @@ func init() { buf := make([]int, n) _ = buf } + +// CHECK-LABEL: define void @main.init(){{.*}} { +// CHECK-NEXT: _llgo_0: +// CHECK-NEXT: %0 = load i1, ptr @"main.init$guard", align 1 +// CHECK-NEXT: br i1 %0, label %_llgo_2, label %_llgo_1 +// CHECK-EMPTY: +// CHECK-NEXT: _llgo_1: ; preds = %_llgo_0 +// CHECK-NEXT: store i1 true, ptr @"main.init$guard", align 1 +// CHECK-NEXT: call void @"main.init#1"() +// CHECK-NEXT: call void @"main.init#2"() +// CHECK-NEXT: call void @"main.init#3"() +// CHECK-NEXT: call void @"main.init#4"() +// CHECK-NEXT: call void @"main.init#5"() +// CHECK-NEXT: br label %_llgo_2 +// CHECK-EMPTY: +// CHECK-NEXT: _llgo_2: ; preds = %_llgo_1, %_llgo_0 +// CHECK-NEXT: ret void +// CHECK-NEXT: } + +// CHECK-LABEL: define void @"main.init#1"(){{.*}} { +// CHECK-NEXT: _llgo_0: +// CHECK-NEXT: %0 = call %"{{.*}}/runtime/internal/runtime.Slice" @"{{.*}}/runtime/internal/runtime.MakeSlice"(i64 2, i64 4, i64 8) +// CHECK-NEXT: %1 = extractvalue %"{{.*}}/runtime/internal/runtime.Slice" %0, 1 +// CHECK-NEXT: %2 = icmp ne i64 %1, 2 +// CHECK-NEXT: br i1 %2, label %_llgo_1, label %_llgo_3 +// CHECK-EMPTY: +// CHECK-NEXT: _llgo_1: ; preds = %_llgo_3, %_llgo_0 +// CHECK-NEXT: %3 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 16) +// CHECK-NEXT: store %"{{.*}}/runtime/internal/runtime.String" { ptr @{{[0-9]+}}, i64 5 }, ptr %3, align 8 +// CHECK-NEXT: %4 = insertvalue %"{{.*}}/runtime/internal/runtime.eface" { ptr @_llgo_string, ptr undef }, ptr %3, 1 +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.Panic"(%"{{.*}}/runtime/internal/runtime.eface" %4) +// CHECK-NEXT: unreachable +// CHECK-EMPTY: +// CHECK-NEXT: _llgo_2: ; preds = %_llgo_3 +// CHECK-NEXT: ret void +// CHECK-EMPTY: +// CHECK-NEXT: _llgo_3: ; preds = %_llgo_0 +// CHECK-NEXT: %5 = extractvalue %"{{.*}}/runtime/internal/runtime.Slice" %0, 2 +// CHECK-NEXT: %6 = icmp ne i64 %5, 4 +// CHECK-NEXT: br i1 %6, label %_llgo_1, label %_llgo_2 +// CHECK-NEXT: } + +// CHECK-LABEL: define void @"main.init#2"(){{.*}} { +// CHECK-NEXT: _llgo_0: +// CHECK-NEXT: %0 = call %"{{.*}}/runtime/internal/runtime.Slice" @"{{.*}}/runtime/internal/runtime.MakeSlice"(i64 2, i64 4, i64 8) +// CHECK-NEXT: %1 = extractvalue %"{{.*}}/runtime/internal/runtime.Slice" %0, 1 +// CHECK-NEXT: %2 = icmp ne i64 %1, 2 +// CHECK-NEXT: br i1 %2, label %_llgo_1, label %_llgo_3 +// CHECK-EMPTY: +// CHECK-NEXT: _llgo_1: ; preds = %_llgo_3, %_llgo_0 +// CHECK-NEXT: %3 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 16) +// CHECK-NEXT: store %"{{.*}}/runtime/internal/runtime.String" { ptr @{{[0-9]+}}, i64 5 }, ptr %3, align 8 +// CHECK-NEXT: %4 = insertvalue %"{{.*}}/runtime/internal/runtime.eface" { ptr @_llgo_string, ptr undef }, ptr %3, 1 +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.Panic"(%"{{.*}}/runtime/internal/runtime.eface" %4) +// CHECK-NEXT: unreachable +// CHECK-EMPTY: +// CHECK-NEXT: _llgo_2: ; preds = %_llgo_3 +// CHECK-NEXT: ret void +// CHECK-EMPTY: +// CHECK-NEXT: _llgo_3: ; preds = %_llgo_0 +// CHECK-NEXT: %5 = extractvalue %"{{.*}}/runtime/internal/runtime.Slice" %0, 2 +// CHECK-NEXT: %6 = icmp ne i64 %5, 4 +// CHECK-NEXT: br i1 %6, label %_llgo_1, label %_llgo_2 +// CHECK-NEXT: } + +// CHECK-LABEL: define void @"main.init#3"(){{.*}} { +// CHECK-NEXT: _llgo_0: +// CHECK-NEXT: %0 = call ptr @"{{.*}}/runtime/internal/runtime.GetThreadDefer"() +// CHECK-NEXT: %1 = alloca i8 +// CHECK-NEXT: %2 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 48) +// CHECK-NEXT: %3 = getelementptr inbounds %"{{.*}}/runtime/internal/runtime.Defer", ptr %2, i32 0, i32 0 +// CHECK-NEXT: store ptr %1, ptr %3, align 8 +// CHECK-NEXT: %4 = getelementptr inbounds %"{{.*}}/runtime/internal/runtime.Defer", ptr %2, i32 0, i32 1 +// CHECK-NEXT: store i64 0, ptr %4, align 8 +// CHECK-NEXT: %5 = getelementptr inbounds %"{{.*}}/runtime/internal/runtime.Defer", ptr %2, i32 0, i32 2 +// CHECK-NEXT: store ptr %0, ptr %5, align 8 +// CHECK-NEXT: %6 = getelementptr inbounds %"{{.*}}/runtime/internal/runtime.Defer", ptr %2, i32 0, i32 3 +// CHECK-NEXT: store ptr blockaddress(@"main.init#3", %_llgo_2), ptr %6, align 8 +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.SetThreadDefer"(ptr %2) +// CHECK-NEXT: %7 = getelementptr inbounds %"{{.*}}/runtime/internal/runtime.Defer", ptr %2, i32 0, i32 1 +// CHECK-NEXT: %8 = getelementptr inbounds %"{{.*}}/runtime/internal/runtime.Defer", ptr %2, i32 0, i32 3 +// CHECK-NEXT: %9 = getelementptr inbounds %"{{.*}}/runtime/internal/runtime.Defer", ptr %2, i32 0, i32 4 +// CHECK-NEXT: %10 = getelementptr inbounds %"{{.*}}/runtime/internal/runtime.Defer", ptr %2, i32 0, i32 5 +// CHECK-NEXT: store ptr null, ptr %10, align 8 +// CHECK-NEXT: %11 = call i32 @{{(__)?}}sigsetjmp(ptr %1, i32 0) +// CHECK-NEXT: %12 = icmp eq i32 %11, 0 +// CHECK-NEXT: br i1 %12, label %_llgo_4, label %_llgo_5 +// CHECK-EMPTY: +// CHECK-NEXT: _llgo_1: ; preds = %_llgo_3 +// CHECK-NEXT: ret void +// CHECK-EMPTY: +// CHECK-NEXT: _llgo_2: ; preds = %_llgo_5, %_llgo_4 +// CHECK-NEXT: store ptr blockaddress(@"main.init#3", %_llgo_3), ptr %8, align 8 +// CHECK-NEXT: %13 = load i64, ptr %7, align 8 +// CHECK-NEXT: call void @"main.init#3$1"() +// CHECK-NEXT: %14 = load %"{{.*}}/runtime/internal/runtime.Defer", ptr %2, align 8 +// CHECK-NEXT: %15 = extractvalue %"{{.*}}/runtime/internal/runtime.Defer" %14, 2 +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.SetThreadDefer"(ptr %15) +// CHECK-NEXT: %16 = load ptr, ptr %9, align 8 +// CHECK-NEXT: indirectbr ptr %16, [label %_llgo_3, label %_llgo_6] +// CHECK-EMPTY: +// CHECK-NEXT: _llgo_3: ; preds = %_llgo_5, %_llgo_2 +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.Rethrow"(ptr %0) +// CHECK-NEXT: br label %_llgo_1 +// CHECK-EMPTY: +// CHECK-NEXT: _llgo_4: ; preds = %_llgo_0 +// CHECK-NEXT: %17 = call %"{{.*}}/runtime/internal/runtime.Slice" @"{{.*}}/runtime/internal/runtime.MakeSlice"(i64 -1, i64 -1, i64 8) +// CHECK-NEXT: store ptr blockaddress(@"main.init#3", %_llgo_6), ptr %9, align 8 +// CHECK-NEXT: br label %_llgo_2 +// CHECK-EMPTY: +// CHECK-NEXT: _llgo_5: ; preds = %_llgo_0 +// CHECK-NEXT: store ptr blockaddress(@"main.init#3", %_llgo_3), ptr %9, align 8 +// CHECK-NEXT: %18 = load ptr, ptr %8, align 8 +// CHECK-NEXT: indirectbr ptr %18, [label %_llgo_3, label %_llgo_2] +// CHECK-EMPTY: +// CHECK-NEXT: _llgo_6: ; preds = %_llgo_2 +// CHECK-NEXT: ret void +// CHECK-NEXT: } + +// CHECK-LABEL: define void @"main.init#3$1"(){{.*}} { +// CHECK-NEXT: _llgo_0: +// CHECK-NEXT: %0 = call %"{{.*}}/runtime/internal/runtime.eface" @"{{.*}}/runtime/internal/runtime.Recover"() +// CHECK-NEXT: %1 = call i1 @"{{.*}}/runtime/internal/runtime.EfaceEqual"(%"{{.*}}/runtime/internal/runtime.eface" %0, %"{{.*}}/runtime/internal/runtime.eface" zeroinitializer) +// CHECK-NEXT: br i1 %1, label %_llgo_1, label %_llgo_2 +// CHECK-EMPTY: +// CHECK-NEXT: _llgo_1: ; preds = %_llgo_0 +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.PrintString"(%"{{.*}}/runtime/internal/runtime.String" { ptr @{{[0-9]+}}, i64 10 }) +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.PrintByte"(i8 10) +// CHECK-NEXT: br label %_llgo_2 +// CHECK-EMPTY: +// CHECK-NEXT: _llgo_2: ; preds = %_llgo_1, %_llgo_0 +// CHECK-NEXT: ret void +// CHECK-NEXT: } + +// CHECK-LABEL: define void @"main.init#4"(){{.*}} { +// CHECK-NEXT: _llgo_0: +// CHECK-NEXT: %0 = call ptr @"{{.*}}/runtime/internal/runtime.GetThreadDefer"() +// CHECK-NEXT: %1 = alloca i8 +// CHECK-NEXT: %2 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 48) +// CHECK-NEXT: %3 = getelementptr inbounds %"{{.*}}/runtime/internal/runtime.Defer", ptr %2, i32 0, i32 0 +// CHECK-NEXT: store ptr %1, ptr %3, align 8 +// CHECK-NEXT: %4 = getelementptr inbounds %"{{.*}}/runtime/internal/runtime.Defer", ptr %2, i32 0, i32 1 +// CHECK-NEXT: store i64 0, ptr %4, align 8 +// CHECK-NEXT: %5 = getelementptr inbounds %"{{.*}}/runtime/internal/runtime.Defer", ptr %2, i32 0, i32 2 +// CHECK-NEXT: store ptr %0, ptr %5, align 8 +// CHECK-NEXT: %6 = getelementptr inbounds %"{{.*}}/runtime/internal/runtime.Defer", ptr %2, i32 0, i32 3 +// CHECK-NEXT: store ptr blockaddress(@"main.init#4", %_llgo_2), ptr %6, align 8 +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.SetThreadDefer"(ptr %2) +// CHECK-NEXT: %7 = getelementptr inbounds %"{{.*}}/runtime/internal/runtime.Defer", ptr %2, i32 0, i32 1 +// CHECK-NEXT: %8 = getelementptr inbounds %"{{.*}}/runtime/internal/runtime.Defer", ptr %2, i32 0, i32 3 +// CHECK-NEXT: %9 = getelementptr inbounds %"{{.*}}/runtime/internal/runtime.Defer", ptr %2, i32 0, i32 4 +// CHECK-NEXT: %10 = getelementptr inbounds %"{{.*}}/runtime/internal/runtime.Defer", ptr %2, i32 0, i32 5 +// CHECK-NEXT: store ptr null, ptr %10, align 8 +// CHECK-NEXT: %11 = call i32 @{{(__)?}}sigsetjmp(ptr %1, i32 0) +// CHECK-NEXT: %12 = icmp eq i32 %11, 0 +// CHECK-NEXT: br i1 %12, label %_llgo_4, label %_llgo_5 +// CHECK-EMPTY: +// CHECK-NEXT: _llgo_1: ; preds = %_llgo_3 +// CHECK-NEXT: ret void +// CHECK-EMPTY: +// CHECK-NEXT: _llgo_2: ; preds = %_llgo_5, %_llgo_4 +// CHECK-NEXT: store ptr blockaddress(@"main.init#4", %_llgo_3), ptr %8, align 8 +// CHECK-NEXT: %13 = load i64, ptr %7, align 8 +// CHECK-NEXT: call void @"main.init#4$1"() +// CHECK-NEXT: %14 = load %"{{.*}}/runtime/internal/runtime.Defer", ptr %2, align 8 +// CHECK-NEXT: %15 = extractvalue %"{{.*}}/runtime/internal/runtime.Defer" %14, 2 +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.SetThreadDefer"(ptr %15) +// CHECK-NEXT: %16 = load ptr, ptr %9, align 8 +// CHECK-NEXT: indirectbr ptr %16, [label %_llgo_3, label %_llgo_6] +// CHECK-EMPTY: +// CHECK-NEXT: _llgo_3: ; preds = %_llgo_5, %_llgo_2 +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.Rethrow"(ptr %0) +// CHECK-NEXT: br label %_llgo_1 +// CHECK-EMPTY: +// CHECK-NEXT: _llgo_4: ; preds = %_llgo_0 +// CHECK-NEXT: %17 = call %"{{.*}}/runtime/internal/runtime.Slice" @"{{.*}}/runtime/internal/runtime.MakeSlice"(i64 2, i64 1, i64 8) +// CHECK-NEXT: store ptr blockaddress(@"main.init#4", %_llgo_6), ptr %9, align 8 +// CHECK-NEXT: br label %_llgo_2 +// CHECK-EMPTY: +// CHECK-NEXT: _llgo_5: ; preds = %_llgo_0 +// CHECK-NEXT: store ptr blockaddress(@"main.init#4", %_llgo_3), ptr %9, align 8 +// CHECK-NEXT: %18 = load ptr, ptr %8, align 8 +// CHECK-NEXT: indirectbr ptr %18, [label %_llgo_3, label %_llgo_2] +// CHECK-EMPTY: +// CHECK-NEXT: _llgo_6: ; preds = %_llgo_2 +// CHECK-NEXT: ret void +// CHECK-NEXT: } + +// CHECK-LABEL: define void @"main.init#4$1"(){{.*}} { +// CHECK-NEXT: _llgo_0: +// CHECK-NEXT: %0 = call %"{{.*}}/runtime/internal/runtime.eface" @"{{.*}}/runtime/internal/runtime.Recover"() +// CHECK-NEXT: %1 = call i1 @"{{.*}}/runtime/internal/runtime.EfaceEqual"(%"{{.*}}/runtime/internal/runtime.eface" %0, %"{{.*}}/runtime/internal/runtime.eface" zeroinitializer) +// CHECK-NEXT: br i1 %1, label %_llgo_1, label %_llgo_2 +// CHECK-EMPTY: +// CHECK-NEXT: _llgo_1: ; preds = %_llgo_0 +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.PrintString"(%"{{.*}}/runtime/internal/runtime.String" { ptr @{{[0-9]+}}, i64 10 }) +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.PrintByte"(i8 10) +// CHECK-NEXT: br label %_llgo_2 +// CHECK-EMPTY: +// CHECK-NEXT: _llgo_2: ; preds = %_llgo_1, %_llgo_0 +// CHECK-NEXT: ret void +// CHECK-NEXT: } + +// CHECK-LABEL: define void @"main.init#5"(){{.*}} { +// CHECK-NEXT: _llgo_0: +// CHECK-NEXT: %0 = call ptr @"{{.*}}/runtime/internal/runtime.GetThreadDefer"() +// CHECK-NEXT: %1 = alloca i8 +// CHECK-NEXT: %2 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 48) +// CHECK-NEXT: %3 = getelementptr inbounds %"{{.*}}/runtime/internal/runtime.Defer", ptr %2, i32 0, i32 0 +// CHECK-NEXT: store ptr %1, ptr %3, align 8 +// CHECK-NEXT: %4 = getelementptr inbounds %"{{.*}}/runtime/internal/runtime.Defer", ptr %2, i32 0, i32 1 +// CHECK-NEXT: store i64 0, ptr %4, align 8 +// CHECK-NEXT: %5 = getelementptr inbounds %"{{.*}}/runtime/internal/runtime.Defer", ptr %2, i32 0, i32 2 +// CHECK-NEXT: store ptr %0, ptr %5, align 8 +// CHECK-NEXT: %6 = getelementptr inbounds %"{{.*}}/runtime/internal/runtime.Defer", ptr %2, i32 0, i32 3 +// CHECK-NEXT: store ptr blockaddress(@"main.init#5", %_llgo_2), ptr %6, align 8 +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.SetThreadDefer"(ptr %2) +// CHECK-NEXT: %7 = getelementptr inbounds %"{{.*}}/runtime/internal/runtime.Defer", ptr %2, i32 0, i32 1 +// CHECK-NEXT: %8 = getelementptr inbounds %"{{.*}}/runtime/internal/runtime.Defer", ptr %2, i32 0, i32 3 +// CHECK-NEXT: %9 = getelementptr inbounds %"{{.*}}/runtime/internal/runtime.Defer", ptr %2, i32 0, i32 4 +// CHECK-NEXT: %10 = getelementptr inbounds %"{{.*}}/runtime/internal/runtime.Defer", ptr %2, i32 0, i32 5 +// CHECK-NEXT: store ptr null, ptr %10, align 8 +// CHECK-NEXT: %11 = call i32 @{{(__)?}}sigsetjmp(ptr %1, i32 0) +// CHECK-NEXT: %12 = icmp eq i32 %11, 0 +// CHECK-NEXT: br i1 %12, label %_llgo_4, label %_llgo_5 +// CHECK-EMPTY: +// CHECK-NEXT: _llgo_1: ; preds = %_llgo_3 +// CHECK-NEXT: ret void +// CHECK-EMPTY: +// CHECK-NEXT: _llgo_2: ; preds = %_llgo_5, %_llgo_4 +// CHECK-NEXT: store ptr blockaddress(@"main.init#5", %_llgo_3), ptr %8, align 8 +// CHECK-NEXT: %13 = load i64, ptr %7, align 8 +// CHECK-NEXT: call void @"main.init#5$1"() +// CHECK-NEXT: %14 = load %"{{.*}}/runtime/internal/runtime.Defer", ptr %2, align 8 +// CHECK-NEXT: %15 = extractvalue %"{{.*}}/runtime/internal/runtime.Defer" %14, 2 +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.SetThreadDefer"(ptr %15) +// CHECK-NEXT: %16 = load ptr, ptr %9, align 8 +// CHECK-NEXT: indirectbr ptr %16, [label %_llgo_3, label %_llgo_6] +// CHECK-EMPTY: +// CHECK-NEXT: _llgo_3: ; preds = %_llgo_5, %_llgo_2 +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.Rethrow"(ptr %0) +// CHECK-NEXT: br label %_llgo_1 +// CHECK-EMPTY: +// CHECK-NEXT: _llgo_4: ; preds = %_llgo_0 +// CHECK-NEXT: %17 = call %"{{.*}}/runtime/internal/runtime.Slice" @"{{.*}}/runtime/internal/runtime.MakeSlice"(i64 9223372036854775807, i64 9223372036854775807, i64 8) +// CHECK-NEXT: store ptr blockaddress(@"main.init#5", %_llgo_6), ptr %9, align 8 +// CHECK-NEXT: br label %_llgo_2 +// CHECK-EMPTY: +// CHECK-NEXT: _llgo_5: ; preds = %_llgo_0 +// CHECK-NEXT: store ptr blockaddress(@"main.init#5", %_llgo_3), ptr %9, align 8 +// CHECK-NEXT: %18 = load ptr, ptr %8, align 8 +// CHECK-NEXT: indirectbr ptr %18, [label %_llgo_3, label %_llgo_2] +// CHECK-EMPTY: +// CHECK-NEXT: _llgo_6: ; preds = %_llgo_2 +// CHECK-NEXT: ret void +// CHECK-NEXT: } + +// CHECK-LABEL: define void @"main.init#5$1"(){{.*}} { +// CHECK-NEXT: _llgo_0: +// CHECK-NEXT: %0 = call %"{{.*}}/runtime/internal/runtime.eface" @"{{.*}}/runtime/internal/runtime.Recover"() +// CHECK-NEXT: %1 = call i1 @"{{.*}}/runtime/internal/runtime.EfaceEqual"(%"{{.*}}/runtime/internal/runtime.eface" %0, %"{{.*}}/runtime/internal/runtime.eface" zeroinitializer) +// CHECK-NEXT: br i1 %1, label %_llgo_1, label %_llgo_2 +// CHECK-EMPTY: +// CHECK-NEXT: _llgo_1: ; preds = %_llgo_0 +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.PrintString"(%"{{.*}}/runtime/internal/runtime.String" { ptr @{{[0-9]+}}, i64 10 }) +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.PrintByte"(i8 10) +// CHECK-NEXT: br label %_llgo_2 +// CHECK-EMPTY: +// CHECK-NEXT: _llgo_2: ; preds = %_llgo_1, %_llgo_0 +// CHECK-NEXT: ret void +// CHECK-NEXT: } + +// CHECK-LABEL: define void @main.main(){{.*}} { +// CHECK-NEXT: _llgo_0: +// CHECK-NEXT: ret void +// CHECK-NEXT: } diff --git a/cl/_testgo/reflectconv/in.go b/cl/_testgo/reflectconv/in.go index 19a30dd3a2..c1902c3320 100644 --- a/cl/_testgo/reflectconv/in.go +++ b/cl/_testgo/reflectconv/in.go @@ -1,10 +1,6 @@ // LITTEST package main -// CHECK-DAG: call i1 @reflect.Value.CanConvert({{.*}}) -// CHECK-DAG: call %reflect.Value @reflect.Value.Convert({{.*}}) -// CHECK-DAG: call void @reflect.Value.Set({{.*}}) - import ( "bytes" "fmt" @@ -15,6 +11,45 @@ import ( "unsafe" ) +// CHECK: {{^}}@{{[0-9]+}} = private unnamed_addr constant [7 x i8] c"reflect", align 1{{$}} +// CHECK: {{^}}@{{[0-9]+}} = private unnamed_addr constant [58 x i8] c"ValueOf(%T(%[1]v)).Convert(%s) = %T(%[3]v), want %T(%[4]v)", align 1{{$}} +// CHECK: {{^}}@{{[0-9]+}} = private unnamed_addr constant [59 x i8] c"ValueOf(%T(%[1]v)).Convert(%s) has internal kind %v want %v", align 1{{$}} +// CHECK: {{^}}@{{[0-9]+}} = private unnamed_addr constant [63 x i8] c"Set(ValueOf(%T(%[1]v)).Convert(%s)) = %T(%[3]v), want %T(%[4]v)", align 1{{$}} +// CHECK: {{^}}@{{[0-9]+}} = private unnamed_addr constant [35 x i8] c"table entry %v is RO, should not be", align 1{{$}} +// CHECK: {{^}}@{{[0-9]+}} = private unnamed_addr constant [46 x i8] c"self-conversion output %v is RO, should not be", align 1{{$}} +// CHECK: {{^}}@{{[0-9]+}} = private unnamed_addr constant [41 x i8] c"conversion output %v is RO, should not be", align 1{{$}} +// CHECK: {{^}}@{{[0-9]+}} = private unnamed_addr constant [46 x i8] c"set(conversion output) %v is RO, should not be", align 1{{$}} +// CHECK: {{^}}@{{[0-9]+}} = private unnamed_addr constant [41 x i8] c"(%s).ConvertibleTo(%s) = false, want true", align 1{{$}} +// CHECK: {{^}}@{{[0-9]+}} = private unnamed_addr constant [52 x i8] c"ValueOf(%T(%[1]v)).CanConvert(%s) = false, want true", align 1{{$}} +// CHECK: {{^}}@{{[0-9]+}} = private unnamed_addr constant [53 x i8] c" ValueOf(%T(%[1]v)).CanConvert(%s) = false, want true", align 1{{$}} +// CHECK: {{^}}@{{[0-9]+}} = private unnamed_addr constant [49 x i8] c"RO self-conversion output %v is not RO, should be", align 1{{$}} +// CHECK: {{^}}@{{[0-9]+}} = private unnamed_addr constant [44 x i8] c"RO conversion output %v is not RO, should be", align 1{{$}} +// CHECK: {{^}}@{{[0-9]+}} = private unnamed_addr constant [41 x i8] c"@(%s).ConvertibleTo(%s) = %v, want %v: %v", align 1{{$}} +// CHECK: {{^}}@{{[0-9]+}} = private unnamed_addr constant [47 x i8] c"store/load of sNaN not faithful, got %x want %x", align 1{{$}} +// CHECK: {{^}}@{{[0-9]+}} = private unnamed_addr constant [7 x i8] c"float32", align 1{{$}} +// CHECK: {{^}}@{{[0-9]+}} = private unnamed_addr constant [40 x i8] c"signaling nan conversion got %x, want %x", align 1{{$}} +// CHECK: {{^}}@{{[0-9]+}} = private unnamed_addr constant [40 x i8] c"[]byte should be convertible to *[8]byte", align 1{{$}} +// CHECK: {{^}}@{{[0-9]+}} = private unnamed_addr constant [57 x i8] c"slice with length 4 should not be convertible to *[8]byte", align 1{{$}} +// CHECK: {{^}}@{{[0-9]+}} = private unnamed_addr constant [77 x i8] c"reflect: cannot convert slice with length 4 to pointer to array with length 8", align 1{{$}} +// CHECK: {{^}}@{{[0-9]+}} = private unnamed_addr constant [56 x i8] c"slice with length 4 should not be convertible to [8]byte", align 1{{$}} +// CHECK: {{^}}@{{[0-9]+}} = private unnamed_addr constant [66 x i8] c"reflect: cannot convert slice with length 4 to array with length 8", align 1{{$}} +// CHECK: {{^}}@{{[0-9]+}} = private unnamed_addr constant [65 x i8] c"convert slice to non-empty array returns a addressable copy array", align 1{{$}} +// CHECK: {{^}}@{{[0-9]+}} = private unnamed_addr constant [52 x i8] c"slice (%v) mutation visible in converted result (%v)", align 1{{$}} +// CHECK: {{^}}@{{[0-9]+}} = private unnamed_addr constant [5 x i8] c"hello", align 1{{$}} +// CHECK: {{^}}@{{[0-9]+}} = private unnamed_addr constant [6 x i8] c"bytes1", align 1{{$}} +// CHECK: {{^}}@{{[0-9]+}} = private unnamed_addr constant [6 x i8] c"bytes2", align 1{{$}} +// CHECK: {{^}}@{{[0-9]+}} = private unnamed_addr constant [6 x i8] c"bytes3", align 1{{$}} +// CHECK: {{^}}@{{[0-9]+}} = private unnamed_addr constant [8 x i8] c"runes\E2\99\9D", align 1{{$}} +// CHECK: {{^}}@{{[0-9]+}} = private unnamed_addr constant [8 x i8] c"runes\E2\99\95", align 1{{$}} +// CHECK: {{^}}@{{[0-9]+}} = private unnamed_addr constant [17 x i8] c"runes\F0\9F\99\88\F0\9F\99\89\F0\9F\99\8A", align 1{{$}} +// CHECK: {{^}}@{{[0-9]+}} = private unnamed_addr constant [1 x i8] c"a", align 1{{$}} +// CHECK: {{^}}@{{[0-9]+}} = private unnamed_addr constant [3 x i8] c"\EF\BF\BD", align 1{{$}} +// CHECK: {{^}}@{{[0-9]+}} = private unnamed_addr constant [13 x i8] c"did not panic", align 1{{$}} +// CHECK: {{^}}@{{[0-9]+}} = private unnamed_addr constant [32 x i8] c"panicked with unexpected type %T", align 1{{$}} +// CHECK: {{^}}@{{[0-9]+}} = private unnamed_addr constant [44 x i8] c"panic string does not start with \22reflect\22: ", align 1{{$}} +// CHECK: {{^}}@{{[0-9]+}} = private unnamed_addr constant [31 x i8] c"panic string does not contain \22", align 1{{$}} +// CHECK: {{^}}@{{[0-9]+}} = private unnamed_addr constant [3 x i8] c"\22: ", align 1{{$}} + type Value struct { typ_ unsafe.Pointer ptr unsafe.Pointer @@ -752,3 +787,8914 @@ func shouldPanic(expect string, f func()) { }() f() } + +// CHECK-LABEL: define %reflect.Value @main.EmptyInterfaceV(%"{{.*}}/runtime/internal/runtime.eface" %0){{.*}} { +// CHECK-NEXT: _llgo_0: +// CHECK-NEXT: %1 = call ptr @"{{.*}}/runtime/internal/runtime.AllocZ"(i64 16) +// CHECK-NEXT: store %"{{.*}}/runtime/internal/runtime.eface" %0, ptr %1, align 8 +// CHECK-NEXT: %2 = load { ptr, ptr }, ptr @main.V, align 8 +// CHECK-NEXT: %3 = insertvalue %"{{.*}}/runtime/internal/runtime.eface" { ptr @"*_llgo_any", ptr undef }, ptr %1, 1 +// CHECK-NEXT: %4 = extractvalue { ptr, ptr } %2, 1 +// CHECK-NEXT: %5 = extractvalue { ptr, ptr } %2, 0 +// CHECK-NEXT: %__llgo_funcval_code = call ptr asm "", "=r,0"(ptr %5) +// CHECK-NEXT: %6 = call %reflect.Value %__llgo_funcval_code(ptr {{(nest|swiftself)}} %4, %"{{.*}}/runtime/internal/runtime.eface" %3) +// CHECK-NEXT: %7 = call %reflect.Value @reflect.Value.Elem(%reflect.Value %6) +// CHECK-NEXT: ret %reflect.Value %7 +// CHECK-NEXT: } + +// CHECK-LABEL: define i1 @main.IsRO(%reflect.Value %0){{.*}} { +// CHECK-NEXT: _llgo_0: +// CHECK-NEXT: %1 = call ptr @"{{.*}}/runtime/internal/runtime.AllocZ"(i64 24) +// CHECK-NEXT: store %reflect.Value %0, ptr %1, align 8 +// CHECK-NEXT: %2 = getelementptr inbounds %main.Value, ptr %1, i32 0, i32 2 +// CHECK-NEXT: %3 = load i64, ptr %2, align 8 +// CHECK-NEXT: %4 = and i64 %3, 32 +// CHECK-NEXT: %5 = icmp ne i64 %4, 0 +// CHECK-NEXT: ret i1 %5 +// CHECK-NEXT: } + +// CHECK-LABEL: define %reflect.Value @main.MakeRO(%reflect.Value %0){{.*}} { +// CHECK-NEXT: _llgo_0: +// CHECK-NEXT: %1 = call ptr @"{{.*}}/runtime/internal/runtime.AllocZ"(i64 24) +// CHECK-NEXT: store %reflect.Value %0, ptr %1, align 8 +// CHECK-NEXT: %2 = getelementptr inbounds %main.Value, ptr %1, i32 0, i32 2 +// CHECK-NEXT: %3 = load i64, ptr %2, align 8 +// CHECK-NEXT: %4 = or i64 %3, 32 +// CHECK-NEXT: %5 = getelementptr inbounds %main.Value, ptr %1, i32 0, i32 2 +// CHECK-NEXT: store i64 %4, ptr %5, align 8 +// CHECK-NEXT: %6 = load %reflect.Value, ptr %1, align 8 +// CHECK-NEXT: ret %reflect.Value %6 +// CHECK-NEXT: } + +// CHECK-LABEL: define %reflect.Value @main.ReadWriterV(%"{{.*}}/runtime/internal/runtime.iface" %0){{.*}} { +// CHECK-NEXT: _llgo_0: +// CHECK-NEXT: %1 = call ptr @"{{.*}}/runtime/internal/runtime.AllocZ"(i64 16) +// CHECK-NEXT: store %"{{.*}}/runtime/internal/runtime.iface" %0, ptr %1, align 8 +// CHECK-NEXT: %2 = load { ptr, ptr }, ptr @main.V, align 8 +// CHECK-NEXT: %3 = insertvalue %"{{.*}}/runtime/internal/runtime.eface" { ptr @"*_llgo_io.ReadWriter", ptr undef }, ptr %1, 1 +// CHECK-NEXT: %4 = extractvalue { ptr, ptr } %2, 1 +// CHECK-NEXT: %5 = extractvalue { ptr, ptr } %2, 0 +// CHECK-NEXT: %__llgo_funcval_code = call ptr asm "", "=r,0"(ptr %5) +// CHECK-NEXT: %6 = call %reflect.Value %__llgo_funcval_code(ptr {{(nest|swiftself)}} %4, %"{{.*}}/runtime/internal/runtime.eface" %3) +// CHECK-NEXT: %7 = call %reflect.Value @reflect.Value.Elem(%reflect.Value %6) +// CHECK-NEXT: ret %reflect.Value %7 +// CHECK-NEXT: } + +// CHECK-LABEL: define %reflect.Value @main.ReaderV(%"{{.*}}/runtime/internal/runtime.iface" %0){{.*}} { +// CHECK-NEXT: _llgo_0: +// CHECK-NEXT: %1 = call ptr @"{{.*}}/runtime/internal/runtime.AllocZ"(i64 16) +// CHECK-NEXT: store %"{{.*}}/runtime/internal/runtime.iface" %0, ptr %1, align 8 +// CHECK-NEXT: %2 = load { ptr, ptr }, ptr @main.V, align 8 +// CHECK-NEXT: %3 = insertvalue %"{{.*}}/runtime/internal/runtime.eface" { ptr @"*_llgo_io.Reader", ptr undef }, ptr %1, 1 +// CHECK-NEXT: %4 = extractvalue { ptr, ptr } %2, 1 +// CHECK-NEXT: %5 = extractvalue { ptr, ptr } %2, 0 +// CHECK-NEXT: %__llgo_funcval_code = call ptr asm "", "=r,0"(ptr %5) +// CHECK-NEXT: %6 = call %reflect.Value %__llgo_funcval_code(ptr {{(nest|swiftself)}} %4, %"{{.*}}/runtime/internal/runtime.eface" %3) +// CHECK-NEXT: %7 = call %reflect.Value @reflect.Value.Elem(%reflect.Value %6) +// CHECK-NEXT: ret %reflect.Value %7 +// CHECK-NEXT: } + +// CHECK-LABEL: define void @main.TestConvert(ptr %0){{.*}} { +// CHECK-NEXT: _llgo_0: +// CHECK-NEXT: %1 = call ptr @"{{.*}}/runtime/internal/runtime.MakeMap"(ptr @"map{{\[\[}}2]_llgo_reflect.Type]_llgo_bool", i64 0) +// CHECK-NEXT: %2 = call ptr @"{{.*}}/runtime/internal/runtime.MakeMap"(ptr @"map[_llgo_reflect.Type]_llgo_bool", i64 0) +// CHECK-NEXT: %3 = load %"{{.*}}/runtime/internal/runtime.Slice", ptr @main.convertTests, align 8 +// CHECK-NEXT: %4 = extractvalue %"{{.*}}/runtime/internal/runtime.Slice" %3, 1 +// CHECK-NEXT: br label %_llgo_1 +// CHECK-EMPTY: +// CHECK-NEXT: _llgo_1: ; preds = %_llgo_33, %_llgo_6, %_llgo_4, %_llgo_32, %_llgo_0 +// CHECK-NEXT: %5 = phi i64 [ -1, %_llgo_0 ], [ %6, %_llgo_4 ], [ %6, %_llgo_6 ], [ %6, %_llgo_32 ], [ %6, %_llgo_33 ] +// CHECK-NEXT: %6 = add i64 %5, 1 +// CHECK-NEXT: %7 = icmp slt i64 %6, %4 +// CHECK-NEXT: br i1 %7, label %_llgo_2, label %_llgo_3 +// CHECK-EMPTY: +// CHECK-NEXT: _llgo_2: ; preds = %_llgo_1 +// CHECK-NEXT: %8 = extractvalue %"{{.*}}/runtime/internal/runtime.Slice" %3, 0 +// CHECK-NEXT: %9 = extractvalue %"{{.*}}/runtime/internal/runtime.Slice" %3, 1 +// CHECK-NEXT: %10 = icmp slt i64 %6, 0 +// CHECK-NEXT: %11 = icmp uge i64 %6, %9 +// CHECK-NEXT: %12 = or i1 %11, %10 +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.CheckIndexRange"(i1 %12, i64 %6, i1 true, i64 %9) +// CHECK-NEXT: %13 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %8, i64 %6 +// CHECK-NEXT: %14 = load { %reflect.Value, %reflect.Value }, ptr %13, align 8 +// CHECK-NEXT: %15 = alloca { %reflect.Value, %reflect.Value }, align 8 +// CHECK-NEXT: call void @llvm.memset.p0.i64(ptr %15, i8 0, i64 48, i1 false) +// CHECK-NEXT: store { %reflect.Value, %reflect.Value } %14, ptr %15, align 8 +// CHECK-NEXT: %16 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %15, i32 0, i32 0 +// CHECK-NEXT: %17 = load %reflect.Value, ptr %16, align 8 +// CHECK-NEXT: %18 = call %"{{.*}}/runtime/internal/runtime.iface" @reflect.Value.Type(%reflect.Value %17) +// CHECK-NEXT: %19 = call ptr @"{{.*}}/runtime/internal/runtime.IfacePtrData"(%"{{.*}}/runtime/internal/runtime.iface" %18) +// CHECK-NEXT: %20 = extractvalue %"{{.*}}/runtime/internal/runtime.iface" %18, 0 +// CHECK-NEXT: %21 = getelementptr ptr, ptr %20, i64 10 +// CHECK-NEXT: %22 = load ptr, ptr %21, align 8 +// CHECK-NEXT: %23 = insertvalue { ptr, ptr } undef, ptr %22, 0 +// CHECK-NEXT: %24 = insertvalue { ptr, ptr } %23, ptr %19, 1 +// CHECK-NEXT: %25 = extractvalue { ptr, ptr } %24, 1 +// CHECK-NEXT: %26 = extractvalue { ptr, ptr } %24, 0 +// CHECK-NEXT: %27 = call i1 %26(ptr %25, %"{{.*}}/runtime/internal/runtime.iface" %18) +// CHECK-NEXT: br i1 %27, label %_llgo_5, label %_llgo_4 +// CHECK-EMPTY: +// CHECK-NEXT: _llgo_3: ; preds = %_llgo_1 +// CHECK-NEXT: %28 = call ptr @"{{.*}}/runtime/internal/runtime.NewMapIter"(ptr @"map[_llgo_reflect.Type]_llgo_bool", ptr %2) +// CHECK-NEXT: br label %_llgo_34 +// CHECK-EMPTY: +// CHECK-NEXT: _llgo_4: ; preds = %_llgo_2 +// CHECK-NEXT: %29 = call ptr @"{{.*}}/runtime/internal/runtime.AllocZ"(i64 32) +// CHECK-NEXT: %30 = getelementptr inbounds %"{{.*}}/runtime/internal/runtime.eface", ptr %29, i64 0 +// CHECK-NEXT: %31 = call ptr @"{{.*}}/runtime/internal/runtime.IfaceType"(%"{{.*}}/runtime/internal/runtime.iface" %18) +// CHECK-NEXT: %32 = extractvalue %"{{.*}}/runtime/internal/runtime.iface" %18, 1 +// CHECK-NEXT: %33 = insertvalue %"{{.*}}/runtime/internal/runtime.eface" undef, ptr %31, 0 +// CHECK-NEXT: %34 = insertvalue %"{{.*}}/runtime/internal/runtime.eface" %33, ptr %32, 1 +// CHECK-NEXT: store %"{{.*}}/runtime/internal/runtime.eface" %34, ptr %30, align 8 +// CHECK-NEXT: %35 = getelementptr inbounds %"{{.*}}/runtime/internal/runtime.eface", ptr %29, i64 1 +// CHECK-NEXT: %36 = call ptr @"{{.*}}/runtime/internal/runtime.IfaceType"(%"{{.*}}/runtime/internal/runtime.iface" %18) +// CHECK-NEXT: %37 = extractvalue %"{{.*}}/runtime/internal/runtime.iface" %18, 1 +// CHECK-NEXT: %38 = insertvalue %"{{.*}}/runtime/internal/runtime.eface" undef, ptr %36, 0 +// CHECK-NEXT: %39 = insertvalue %"{{.*}}/runtime/internal/runtime.eface" %38, ptr %37, 1 +// CHECK-NEXT: store %"{{.*}}/runtime/internal/runtime.eface" %39, ptr %35, align 8 +// CHECK-NEXT: %40 = insertvalue %"{{.*}}/runtime/internal/runtime.Slice" undef, ptr %29, 0 +// CHECK-NEXT: %41 = insertvalue %"{{.*}}/runtime/internal/runtime.Slice" %40, i64 2, 1 +// CHECK-NEXT: %42 = insertvalue %"{{.*}}/runtime/internal/runtime.Slice" %41, i64 2, 2 +// CHECK-NEXT: call void @"main.(*testingT).Errorf"(ptr %0, %"{{.*}}/runtime/internal/runtime.String" { ptr @{{[0-9]+}}, i64 41 }, %"{{.*}}/runtime/internal/runtime.Slice" %42) +// CHECK-NEXT: br label %_llgo_1 +// CHECK-EMPTY: +// CHECK-NEXT: _llgo_5: ; preds = %_llgo_2 +// CHECK-NEXT: %43 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %15, i32 0, i32 1 +// CHECK-NEXT: %44 = load %reflect.Value, ptr %43, align 8 +// CHECK-NEXT: %45 = call %"{{.*}}/runtime/internal/runtime.iface" @reflect.Value.Type(%reflect.Value %44) +// CHECK-NEXT: %46 = call ptr @"{{.*}}/runtime/internal/runtime.IfacePtrData"(%"{{.*}}/runtime/internal/runtime.iface" %18) +// CHECK-NEXT: %47 = extractvalue %"{{.*}}/runtime/internal/runtime.iface" %18, 0 +// CHECK-NEXT: %48 = getelementptr ptr, ptr %47, i64 10 +// CHECK-NEXT: %49 = load ptr, ptr %48, align 8 +// CHECK-NEXT: %50 = insertvalue { ptr, ptr } undef, ptr %49, 0 +// CHECK-NEXT: %51 = insertvalue { ptr, ptr } %50, ptr %46, 1 +// CHECK-NEXT: %52 = extractvalue { ptr, ptr } %51, 1 +// CHECK-NEXT: %53 = extractvalue { ptr, ptr } %51, 0 +// CHECK-NEXT: %54 = call i1 %53(ptr %52, %"{{.*}}/runtime/internal/runtime.iface" %45) +// CHECK-NEXT: br i1 %54, label %_llgo_7, label %_llgo_6 +// CHECK-EMPTY: +// CHECK-NEXT: _llgo_6: ; preds = %_llgo_5 +// CHECK-NEXT: %55 = call ptr @"{{.*}}/runtime/internal/runtime.AllocZ"(i64 32) +// CHECK-NEXT: %56 = getelementptr inbounds %"{{.*}}/runtime/internal/runtime.eface", ptr %55, i64 0 +// CHECK-NEXT: %57 = call ptr @"{{.*}}/runtime/internal/runtime.IfaceType"(%"{{.*}}/runtime/internal/runtime.iface" %18) +// CHECK-NEXT: %58 = extractvalue %"{{.*}}/runtime/internal/runtime.iface" %18, 1 +// CHECK-NEXT: %59 = insertvalue %"{{.*}}/runtime/internal/runtime.eface" undef, ptr %57, 0 +// CHECK-NEXT: %60 = insertvalue %"{{.*}}/runtime/internal/runtime.eface" %59, ptr %58, 1 +// CHECK-NEXT: store %"{{.*}}/runtime/internal/runtime.eface" %60, ptr %56, align 8 +// CHECK-NEXT: %61 = getelementptr inbounds %"{{.*}}/runtime/internal/runtime.eface", ptr %55, i64 1 +// CHECK-NEXT: %62 = call ptr @"{{.*}}/runtime/internal/runtime.IfaceType"(%"{{.*}}/runtime/internal/runtime.iface" %45) +// CHECK-NEXT: %63 = extractvalue %"{{.*}}/runtime/internal/runtime.iface" %45, 1 +// CHECK-NEXT: %64 = insertvalue %"{{.*}}/runtime/internal/runtime.eface" undef, ptr %62, 0 +// CHECK-NEXT: %65 = insertvalue %"{{.*}}/runtime/internal/runtime.eface" %64, ptr %63, 1 +// CHECK-NEXT: store %"{{.*}}/runtime/internal/runtime.eface" %65, ptr %61, align 8 +// CHECK-NEXT: %66 = insertvalue %"{{.*}}/runtime/internal/runtime.Slice" undef, ptr %55, 0 +// CHECK-NEXT: %67 = insertvalue %"{{.*}}/runtime/internal/runtime.Slice" %66, i64 2, 1 +// CHECK-NEXT: %68 = insertvalue %"{{.*}}/runtime/internal/runtime.Slice" %67, i64 2, 2 +// CHECK-NEXT: call void @"main.(*testingT).Errorf"(ptr %0, %"{{.*}}/runtime/internal/runtime.String" { ptr @{{[0-9]+}}, i64 41 }, %"{{.*}}/runtime/internal/runtime.Slice" %68) +// CHECK-NEXT: br label %_llgo_1 +// CHECK-EMPTY: +// CHECK-NEXT: _llgo_7: ; preds = %_llgo_5 +// CHECK-NEXT: %69 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 16) +// CHECK-NEXT: store %"{{.*}}/runtime/internal/runtime.iface" %18, ptr %69, align 8 +// CHECK-NEXT: %70 = call ptr @"{{.*}}/runtime/internal/runtime.MapAssign"(ptr @"map[_llgo_reflect.Type]_llgo_bool", ptr %2, ptr %69) +// CHECK-NEXT: store i1 true, ptr %70, align 1 +// CHECK-NEXT: %71 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 16) +// CHECK-NEXT: store %"{{.*}}/runtime/internal/runtime.iface" %45, ptr %71, align 8 +// CHECK-NEXT: %72 = call ptr @"{{.*}}/runtime/internal/runtime.MapAssign"(ptr @"map[_llgo_reflect.Type]_llgo_bool", ptr %2, ptr %71) +// CHECK-NEXT: store i1 true, ptr %72, align 1 +// CHECK-NEXT: %73 = alloca [2 x %"{{.*}}/runtime/internal/runtime.iface"], align 8 +// CHECK-NEXT: call void @llvm.memset.p0.i64(ptr %73, i8 0, i64 32, i1 false) +// CHECK-NEXT: %74 = getelementptr inbounds %"{{.*}}/runtime/internal/runtime.iface", ptr %73, i64 0 +// CHECK-NEXT: %75 = getelementptr inbounds %"{{.*}}/runtime/internal/runtime.iface", ptr %73, i64 1 +// CHECK-NEXT: store %"{{.*}}/runtime/internal/runtime.iface" %18, ptr %74, align 8 +// CHECK-NEXT: store %"{{.*}}/runtime/internal/runtime.iface" %45, ptr %75, align 8 +// CHECK-NEXT: %76 = load [2 x %"{{.*}}/runtime/internal/runtime.iface"], ptr %73, align 8 +// CHECK-NEXT: %77 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 32) +// CHECK-NEXT: store [2 x %"{{.*}}/runtime/internal/runtime.iface"] %76, ptr %77, align 8 +// CHECK-NEXT: %78 = call ptr @"{{.*}}/runtime/internal/runtime.MapAssign"(ptr @"map{{\[\[}}2]_llgo_reflect.Type]_llgo_bool", ptr %1, ptr %77) +// CHECK-NEXT: store i1 true, ptr %78, align 1 +// CHECK-NEXT: %79 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %15, i32 0, i32 0 +// CHECK-NEXT: %80 = load %reflect.Value, ptr %79, align 8 +// CHECK-NEXT: %81 = call i1 @reflect.Value.CanConvert(%reflect.Value %80, %"{{.*}}/runtime/internal/runtime.iface" %18) +// CHECK-NEXT: br i1 %81, label %_llgo_9, label %_llgo_8 +// CHECK-EMPTY: +// CHECK-NEXT: _llgo_8: ; preds = %_llgo_7 +// CHECK-NEXT: %82 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %15, i32 0, i32 0 +// CHECK-NEXT: %83 = load %reflect.Value, ptr %82, align 8 +// CHECK-NEXT: %84 = call %"{{.*}}/runtime/internal/runtime.eface" @reflect.Value.Interface(%reflect.Value %83) +// CHECK-NEXT: %85 = call ptr @"{{.*}}/runtime/internal/runtime.AllocZ"(i64 32) +// CHECK-NEXT: %86 = getelementptr inbounds %"{{.*}}/runtime/internal/runtime.eface", ptr %85, i64 0 +// CHECK-NEXT: store %"{{.*}}/runtime/internal/runtime.eface" %84, ptr %86, align 8 +// CHECK-NEXT: %87 = getelementptr inbounds %"{{.*}}/runtime/internal/runtime.eface", ptr %85, i64 1 +// CHECK-NEXT: %88 = call ptr @"{{.*}}/runtime/internal/runtime.IfaceType"(%"{{.*}}/runtime/internal/runtime.iface" %18) +// CHECK-NEXT: %89 = extractvalue %"{{.*}}/runtime/internal/runtime.iface" %18, 1 +// CHECK-NEXT: %90 = insertvalue %"{{.*}}/runtime/internal/runtime.eface" undef, ptr %88, 0 +// CHECK-NEXT: %91 = insertvalue %"{{.*}}/runtime/internal/runtime.eface" %90, ptr %89, 1 +// CHECK-NEXT: store %"{{.*}}/runtime/internal/runtime.eface" %91, ptr %87, align 8 +// CHECK-NEXT: %92 = insertvalue %"{{.*}}/runtime/internal/runtime.Slice" undef, ptr %85, 0 +// CHECK-NEXT: %93 = insertvalue %"{{.*}}/runtime/internal/runtime.Slice" %92, i64 2, 1 +// CHECK-NEXT: %94 = insertvalue %"{{.*}}/runtime/internal/runtime.Slice" %93, i64 2, 2 +// CHECK-NEXT: call void @"main.(*testingT).Errorf"(ptr %0, %"{{.*}}/runtime/internal/runtime.String" { ptr @{{[0-9]+}}, i64 52 }, %"{{.*}}/runtime/internal/runtime.Slice" %94) +// CHECK-NEXT: br label %_llgo_9 +// CHECK-EMPTY: +// CHECK-NEXT: _llgo_9: ; preds = %_llgo_8, %_llgo_7 +// CHECK-NEXT: %95 = call %reflect.Value @reflect.Value.Convert(%reflect.Value %80, %"{{.*}}/runtime/internal/runtime.iface" %18) +// CHECK-NEXT: %96 = call %"{{.*}}/runtime/internal/runtime.eface" @reflect.Value.Interface(%reflect.Value %95) +// CHECK-NEXT: %97 = call %"{{.*}}/runtime/internal/runtime.iface" @reflect.Value.Type(%reflect.Value %95) +// CHECK-NEXT: %98 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %15, i32 0, i32 0 +// CHECK-NEXT: %99 = load %reflect.Value, ptr %98, align 8 +// CHECK-NEXT: %100 = call %"{{.*}}/runtime/internal/runtime.iface" @reflect.Value.Type(%reflect.Value %99) +// CHECK-NEXT: %101 = call ptr @"{{.*}}/runtime/internal/runtime.IfaceType"(%"{{.*}}/runtime/internal/runtime.iface" %97) +// CHECK-NEXT: %102 = extractvalue %"{{.*}}/runtime/internal/runtime.iface" %97, 1 +// CHECK-NEXT: %103 = insertvalue %"{{.*}}/runtime/internal/runtime.eface" undef, ptr %101, 0 +// CHECK-NEXT: %104 = insertvalue %"{{.*}}/runtime/internal/runtime.eface" %103, ptr %102, 1 +// CHECK-NEXT: %105 = call ptr @"{{.*}}/runtime/internal/runtime.IfaceType"(%"{{.*}}/runtime/internal/runtime.iface" %100) +// CHECK-NEXT: %106 = extractvalue %"{{.*}}/runtime/internal/runtime.iface" %100, 1 +// CHECK-NEXT: %107 = insertvalue %"{{.*}}/runtime/internal/runtime.eface" undef, ptr %105, 0 +// CHECK-NEXT: %108 = insertvalue %"{{.*}}/runtime/internal/runtime.eface" %107, ptr %106, 1 +// CHECK-NEXT: %109 = call i1 @"{{.*}}/runtime/internal/runtime.EfaceEqual"(%"{{.*}}/runtime/internal/runtime.eface" %104, %"{{.*}}/runtime/internal/runtime.eface" %108) +// CHECK-NEXT: %110 = xor i1 %109, true +// CHECK-NEXT: br i1 %110, label %_llgo_10, label %_llgo_12 +// CHECK-EMPTY: +// CHECK-NEXT: _llgo_10: ; preds = %_llgo_12, %_llgo_9 +// CHECK-NEXT: %111 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %15, i32 0, i32 0 +// CHECK-NEXT: %112 = load %reflect.Value, ptr %111, align 8 +// CHECK-NEXT: %113 = call %"{{.*}}/runtime/internal/runtime.eface" @reflect.Value.Interface(%reflect.Value %112) +// CHECK-NEXT: %114 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %15, i32 0, i32 0 +// CHECK-NEXT: %115 = load %reflect.Value, ptr %114, align 8 +// CHECK-NEXT: %116 = call %"{{.*}}/runtime/internal/runtime.eface" @reflect.Value.Interface(%reflect.Value %115) +// CHECK-NEXT: %117 = call ptr @"{{.*}}/runtime/internal/runtime.AllocZ"(i64 64) +// CHECK-NEXT: %118 = getelementptr inbounds %"{{.*}}/runtime/internal/runtime.eface", ptr %117, i64 0 +// CHECK-NEXT: store %"{{.*}}/runtime/internal/runtime.eface" %113, ptr %118, align 8 +// CHECK-NEXT: %119 = getelementptr inbounds %"{{.*}}/runtime/internal/runtime.eface", ptr %117, i64 1 +// CHECK-NEXT: %120 = call ptr @"{{.*}}/runtime/internal/runtime.IfaceType"(%"{{.*}}/runtime/internal/runtime.iface" %18) +// CHECK-NEXT: %121 = extractvalue %"{{.*}}/runtime/internal/runtime.iface" %18, 1 +// CHECK-NEXT: %122 = insertvalue %"{{.*}}/runtime/internal/runtime.eface" undef, ptr %120, 0 +// CHECK-NEXT: %123 = insertvalue %"{{.*}}/runtime/internal/runtime.eface" %122, ptr %121, 1 +// CHECK-NEXT: store %"{{.*}}/runtime/internal/runtime.eface" %123, ptr %119, align 8 +// CHECK-NEXT: %124 = getelementptr inbounds %"{{.*}}/runtime/internal/runtime.eface", ptr %117, i64 2 +// CHECK-NEXT: store %"{{.*}}/runtime/internal/runtime.eface" %96, ptr %124, align 8 +// CHECK-NEXT: %125 = getelementptr inbounds %"{{.*}}/runtime/internal/runtime.eface", ptr %117, i64 3 +// CHECK-NEXT: store %"{{.*}}/runtime/internal/runtime.eface" %116, ptr %125, align 8 +// CHECK-NEXT: %126 = insertvalue %"{{.*}}/runtime/internal/runtime.Slice" undef, ptr %117, 0 +// CHECK-NEXT: %127 = insertvalue %"{{.*}}/runtime/internal/runtime.Slice" %126, i64 4, 1 +// CHECK-NEXT: %128 = insertvalue %"{{.*}}/runtime/internal/runtime.Slice" %127, i64 4, 2 +// CHECK-NEXT: call void @"main.(*testingT).Errorf"(ptr %0, %"{{.*}}/runtime/internal/runtime.String" { ptr @{{[0-9]+}}, i64 58 }, %"{{.*}}/runtime/internal/runtime.Slice" %128) +// CHECK-NEXT: br label %_llgo_11 +// CHECK-EMPTY: +// CHECK-NEXT: _llgo_11: ; preds = %_llgo_12, %_llgo_10 +// CHECK-NEXT: %129 = call i1 @reflect.Value.CanConvert(%reflect.Value %80, %"{{.*}}/runtime/internal/runtime.iface" %45) +// CHECK-NEXT: br i1 %129, label %_llgo_14, label %_llgo_13 +// CHECK-EMPTY: +// CHECK-NEXT: _llgo_12: ; preds = %_llgo_9 +// CHECK-NEXT: %130 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %15, i32 0, i32 0 +// CHECK-NEXT: %131 = load %reflect.Value, ptr %130, align 8 +// CHECK-NEXT: %132 = call %"{{.*}}/runtime/internal/runtime.eface" @reflect.Value.Interface(%reflect.Value %131) +// CHECK-NEXT: %133 = call i1 @reflect.DeepEqual(%"{{.*}}/runtime/internal/runtime.eface" %96, %"{{.*}}/runtime/internal/runtime.eface" %132) +// CHECK-NEXT: br i1 %133, label %_llgo_11, label %_llgo_10 +// CHECK-EMPTY: +// CHECK-NEXT: _llgo_13: ; preds = %_llgo_11 +// CHECK-NEXT: %134 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %15, i32 0, i32 0 +// CHECK-NEXT: %135 = load %reflect.Value, ptr %134, align 8 +// CHECK-NEXT: %136 = call %"{{.*}}/runtime/internal/runtime.eface" @reflect.Value.Interface(%reflect.Value %135) +// CHECK-NEXT: %137 = call ptr @"{{.*}}/runtime/internal/runtime.AllocZ"(i64 32) +// CHECK-NEXT: %138 = getelementptr inbounds %"{{.*}}/runtime/internal/runtime.eface", ptr %137, i64 0 +// CHECK-NEXT: store %"{{.*}}/runtime/internal/runtime.eface" %136, ptr %138, align 8 +// CHECK-NEXT: %139 = getelementptr inbounds %"{{.*}}/runtime/internal/runtime.eface", ptr %137, i64 1 +// CHECK-NEXT: %140 = call ptr @"{{.*}}/runtime/internal/runtime.IfaceType"(%"{{.*}}/runtime/internal/runtime.iface" %45) +// CHECK-NEXT: %141 = extractvalue %"{{.*}}/runtime/internal/runtime.iface" %45, 1 +// CHECK-NEXT: %142 = insertvalue %"{{.*}}/runtime/internal/runtime.eface" undef, ptr %140, 0 +// CHECK-NEXT: %143 = insertvalue %"{{.*}}/runtime/internal/runtime.eface" %142, ptr %141, 1 +// CHECK-NEXT: store %"{{.*}}/runtime/internal/runtime.eface" %143, ptr %139, align 8 +// CHECK-NEXT: %144 = insertvalue %"{{.*}}/runtime/internal/runtime.Slice" undef, ptr %137, 0 +// CHECK-NEXT: %145 = insertvalue %"{{.*}}/runtime/internal/runtime.Slice" %144, i64 2, 1 +// CHECK-NEXT: %146 = insertvalue %"{{.*}}/runtime/internal/runtime.Slice" %145, i64 2, 2 +// CHECK-NEXT: call void @"main.(*testingT).Errorf"(ptr %0, %"{{.*}}/runtime/internal/runtime.String" { ptr @{{[0-9]+}}, i64 53 }, %"{{.*}}/runtime/internal/runtime.Slice" %146) +// CHECK-NEXT: br label %_llgo_14 +// CHECK-EMPTY: +// CHECK-NEXT: _llgo_14: ; preds = %_llgo_13, %_llgo_11 +// CHECK-NEXT: %147 = call %reflect.Value @reflect.Value.Convert(%reflect.Value %80, %"{{.*}}/runtime/internal/runtime.iface" %45) +// CHECK-NEXT: %148 = call %"{{.*}}/runtime/internal/runtime.eface" @reflect.Value.Interface(%reflect.Value %147) +// CHECK-NEXT: %149 = call %"{{.*}}/runtime/internal/runtime.iface" @reflect.Value.Type(%reflect.Value %147) +// CHECK-NEXT: %150 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %15, i32 0, i32 1 +// CHECK-NEXT: %151 = load %reflect.Value, ptr %150, align 8 +// CHECK-NEXT: %152 = call %"{{.*}}/runtime/internal/runtime.iface" @reflect.Value.Type(%reflect.Value %151) +// CHECK-NEXT: %153 = call ptr @"{{.*}}/runtime/internal/runtime.IfaceType"(%"{{.*}}/runtime/internal/runtime.iface" %149) +// CHECK-NEXT: %154 = extractvalue %"{{.*}}/runtime/internal/runtime.iface" %149, 1 +// CHECK-NEXT: %155 = insertvalue %"{{.*}}/runtime/internal/runtime.eface" undef, ptr %153, 0 +// CHECK-NEXT: %156 = insertvalue %"{{.*}}/runtime/internal/runtime.eface" %155, ptr %154, 1 +// CHECK-NEXT: %157 = call ptr @"{{.*}}/runtime/internal/runtime.IfaceType"(%"{{.*}}/runtime/internal/runtime.iface" %152) +// CHECK-NEXT: %158 = extractvalue %"{{.*}}/runtime/internal/runtime.iface" %152, 1 +// CHECK-NEXT: %159 = insertvalue %"{{.*}}/runtime/internal/runtime.eface" undef, ptr %157, 0 +// CHECK-NEXT: %160 = insertvalue %"{{.*}}/runtime/internal/runtime.eface" %159, ptr %158, 1 +// CHECK-NEXT: %161 = call i1 @"{{.*}}/runtime/internal/runtime.EfaceEqual"(%"{{.*}}/runtime/internal/runtime.eface" %156, %"{{.*}}/runtime/internal/runtime.eface" %160) +// CHECK-NEXT: %162 = xor i1 %161, true +// CHECK-NEXT: br i1 %162, label %_llgo_15, label %_llgo_17 +// CHECK-EMPTY: +// CHECK-NEXT: _llgo_15: ; preds = %_llgo_17, %_llgo_14 +// CHECK-NEXT: %163 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %15, i32 0, i32 0 +// CHECK-NEXT: %164 = load %reflect.Value, ptr %163, align 8 +// CHECK-NEXT: %165 = call %"{{.*}}/runtime/internal/runtime.eface" @reflect.Value.Interface(%reflect.Value %164) +// CHECK-NEXT: %166 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %15, i32 0, i32 1 +// CHECK-NEXT: %167 = load %reflect.Value, ptr %166, align 8 +// CHECK-NEXT: %168 = call %"{{.*}}/runtime/internal/runtime.eface" @reflect.Value.Interface(%reflect.Value %167) +// CHECK-NEXT: %169 = call ptr @"{{.*}}/runtime/internal/runtime.AllocZ"(i64 64) +// CHECK-NEXT: %170 = getelementptr inbounds %"{{.*}}/runtime/internal/runtime.eface", ptr %169, i64 0 +// CHECK-NEXT: store %"{{.*}}/runtime/internal/runtime.eface" %165, ptr %170, align 8 +// CHECK-NEXT: %171 = getelementptr inbounds %"{{.*}}/runtime/internal/runtime.eface", ptr %169, i64 1 +// CHECK-NEXT: %172 = call ptr @"{{.*}}/runtime/internal/runtime.IfaceType"(%"{{.*}}/runtime/internal/runtime.iface" %45) +// CHECK-NEXT: %173 = extractvalue %"{{.*}}/runtime/internal/runtime.iface" %45, 1 +// CHECK-NEXT: %174 = insertvalue %"{{.*}}/runtime/internal/runtime.eface" undef, ptr %172, 0 +// CHECK-NEXT: %175 = insertvalue %"{{.*}}/runtime/internal/runtime.eface" %174, ptr %173, 1 +// CHECK-NEXT: store %"{{.*}}/runtime/internal/runtime.eface" %175, ptr %171, align 8 +// CHECK-NEXT: %176 = getelementptr inbounds %"{{.*}}/runtime/internal/runtime.eface", ptr %169, i64 2 +// CHECK-NEXT: store %"{{.*}}/runtime/internal/runtime.eface" %148, ptr %176, align 8 +// CHECK-NEXT: %177 = getelementptr inbounds %"{{.*}}/runtime/internal/runtime.eface", ptr %169, i64 3 +// CHECK-NEXT: store %"{{.*}}/runtime/internal/runtime.eface" %168, ptr %177, align 8 +// CHECK-NEXT: %178 = insertvalue %"{{.*}}/runtime/internal/runtime.Slice" undef, ptr %169, 0 +// CHECK-NEXT: %179 = insertvalue %"{{.*}}/runtime/internal/runtime.Slice" %178, i64 4, 1 +// CHECK-NEXT: %180 = insertvalue %"{{.*}}/runtime/internal/runtime.Slice" %179, i64 4, 2 +// CHECK-NEXT: call void @"main.(*testingT).Errorf"(ptr %0, %"{{.*}}/runtime/internal/runtime.String" { ptr @{{[0-9]+}}, i64 58 }, %"{{.*}}/runtime/internal/runtime.Slice" %180) +// CHECK-NEXT: br label %_llgo_16 +// CHECK-EMPTY: +// CHECK-NEXT: _llgo_16: ; preds = %_llgo_17, %_llgo_15 +// CHECK-NEXT: %181 = call i64 @reflect.Value.Kind(%reflect.Value %147) +// CHECK-NEXT: %182 = call %"{{.*}}/runtime/internal/runtime.iface" @reflect.Value.Type(%reflect.Value %147) +// CHECK-NEXT: %183 = call ptr @"{{.*}}/runtime/internal/runtime.IfacePtrData"(%"{{.*}}/runtime/internal/runtime.iface" %182) +// CHECK-NEXT: %184 = extractvalue %"{{.*}}/runtime/internal/runtime.iface" %182, 0 +// CHECK-NEXT: %185 = getelementptr ptr, ptr %184, i64 {{(21|23)}} +// CHECK-NEXT: %186 = load ptr, ptr %185, align 8 +// CHECK-NEXT: %187 = insertvalue { ptr, ptr } undef, ptr %186, 0 +// CHECK-NEXT: %188 = insertvalue { ptr, ptr } %187, ptr %183, 1 +// CHECK-NEXT: %189 = extractvalue { ptr, ptr } %188, 1 +// CHECK-NEXT: %190 = extractvalue { ptr, ptr } %188, 0 +// CHECK-NEXT: %191 = call i64 %190(ptr %189) +// CHECK-NEXT: %192 = icmp ne i64 %181, %191 +// CHECK-NEXT: br i1 %192, label %_llgo_18, label %_llgo_19 +// CHECK-EMPTY: +// CHECK-NEXT: _llgo_17: ; preds = %_llgo_14 +// CHECK-NEXT: %193 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %15, i32 0, i32 1 +// CHECK-NEXT: %194 = load %reflect.Value, ptr %193, align 8 +// CHECK-NEXT: %195 = call %"{{.*}}/runtime/internal/runtime.eface" @reflect.Value.Interface(%reflect.Value %194) +// CHECK-NEXT: %196 = call i1 @reflect.DeepEqual(%"{{.*}}/runtime/internal/runtime.eface" %148, %"{{.*}}/runtime/internal/runtime.eface" %195) +// CHECK-NEXT: br i1 %196, label %_llgo_16, label %_llgo_15 +// CHECK-EMPTY: +// CHECK-NEXT: _llgo_18: ; preds = %_llgo_16 +// CHECK-NEXT: %197 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %15, i32 0, i32 0 +// CHECK-NEXT: %198 = load %reflect.Value, ptr %197, align 8 +// CHECK-NEXT: %199 = call %"{{.*}}/runtime/internal/runtime.eface" @reflect.Value.Interface(%reflect.Value %198) +// CHECK-NEXT: %200 = call ptr @"{{.*}}/runtime/internal/runtime.AllocZ"(i64 64) +// CHECK-NEXT: %201 = getelementptr inbounds %"{{.*}}/runtime/internal/runtime.eface", ptr %200, i64 0 +// CHECK-NEXT: store %"{{.*}}/runtime/internal/runtime.eface" %199, ptr %201, align 8 +// CHECK-NEXT: %202 = getelementptr inbounds %"{{.*}}/runtime/internal/runtime.eface", ptr %200, i64 1 +// CHECK-NEXT: %203 = call ptr @"{{.*}}/runtime/internal/runtime.IfaceType"(%"{{.*}}/runtime/internal/runtime.iface" %18) +// CHECK-NEXT: %204 = extractvalue %"{{.*}}/runtime/internal/runtime.iface" %18, 1 +// CHECK-NEXT: %205 = insertvalue %"{{.*}}/runtime/internal/runtime.eface" undef, ptr %203, 0 +// CHECK-NEXT: %206 = insertvalue %"{{.*}}/runtime/internal/runtime.eface" %205, ptr %204, 1 +// CHECK-NEXT: store %"{{.*}}/runtime/internal/runtime.eface" %206, ptr %202, align 8 +// CHECK-NEXT: %207 = getelementptr inbounds %"{{.*}}/runtime/internal/runtime.eface", ptr %200, i64 2 +// CHECK-NEXT: %208 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 8) +// CHECK-NEXT: store i64 %181, ptr %208, align 8 +// CHECK-NEXT: %209 = insertvalue %"{{.*}}/runtime/internal/runtime.eface" { ptr @_llgo_reflect.Kind, ptr undef }, ptr %208, 1 +// CHECK-NEXT: store %"{{.*}}/runtime/internal/runtime.eface" %209, ptr %207, align 8 +// CHECK-NEXT: %210 = getelementptr inbounds %"{{.*}}/runtime/internal/runtime.eface", ptr %200, i64 3 +// CHECK-NEXT: %211 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 8) +// CHECK-NEXT: store i64 %191, ptr %211, align 8 +// CHECK-NEXT: %212 = insertvalue %"{{.*}}/runtime/internal/runtime.eface" { ptr @_llgo_reflect.Kind, ptr undef }, ptr %211, 1 +// CHECK-NEXT: store %"{{.*}}/runtime/internal/runtime.eface" %212, ptr %210, align 8 +// CHECK-NEXT: %213 = insertvalue %"{{.*}}/runtime/internal/runtime.Slice" undef, ptr %200, 0 +// CHECK-NEXT: %214 = insertvalue %"{{.*}}/runtime/internal/runtime.Slice" %213, i64 4, 1 +// CHECK-NEXT: %215 = insertvalue %"{{.*}}/runtime/internal/runtime.Slice" %214, i64 4, 2 +// CHECK-NEXT: call void @"main.(*testingT).Errorf"(ptr %0, %"{{.*}}/runtime/internal/runtime.String" { ptr @{{[0-9]+}}, i64 59 }, %"{{.*}}/runtime/internal/runtime.Slice" %215) +// CHECK-NEXT: br label %_llgo_19 +// CHECK-EMPTY: +// CHECK-NEXT: _llgo_19: ; preds = %_llgo_18, %_llgo_16 +// CHECK-NEXT: %216 = call %reflect.Value @reflect.New(%"{{.*}}/runtime/internal/runtime.iface" %45) +// CHECK-NEXT: %217 = call %reflect.Value @reflect.Value.Elem(%reflect.Value %216) +// CHECK-NEXT: call void @reflect.Value.Set(%reflect.Value %217, %reflect.Value %147) +// CHECK-NEXT: %218 = call %"{{.*}}/runtime/internal/runtime.eface" @reflect.Value.Interface(%reflect.Value %217) +// CHECK-NEXT: %219 = call %"{{.*}}/runtime/internal/runtime.iface" @reflect.Value.Type(%reflect.Value %217) +// CHECK-NEXT: %220 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %15, i32 0, i32 1 +// CHECK-NEXT: %221 = load %reflect.Value, ptr %220, align 8 +// CHECK-NEXT: %222 = call %"{{.*}}/runtime/internal/runtime.iface" @reflect.Value.Type(%reflect.Value %221) +// CHECK-NEXT: %223 = call ptr @"{{.*}}/runtime/internal/runtime.IfaceType"(%"{{.*}}/runtime/internal/runtime.iface" %219) +// CHECK-NEXT: %224 = extractvalue %"{{.*}}/runtime/internal/runtime.iface" %219, 1 +// CHECK-NEXT: %225 = insertvalue %"{{.*}}/runtime/internal/runtime.eface" undef, ptr %223, 0 +// CHECK-NEXT: %226 = insertvalue %"{{.*}}/runtime/internal/runtime.eface" %225, ptr %224, 1 +// CHECK-NEXT: %227 = call ptr @"{{.*}}/runtime/internal/runtime.IfaceType"(%"{{.*}}/runtime/internal/runtime.iface" %222) +// CHECK-NEXT: %228 = extractvalue %"{{.*}}/runtime/internal/runtime.iface" %222, 1 +// CHECK-NEXT: %229 = insertvalue %"{{.*}}/runtime/internal/runtime.eface" undef, ptr %227, 0 +// CHECK-NEXT: %230 = insertvalue %"{{.*}}/runtime/internal/runtime.eface" %229, ptr %228, 1 +// CHECK-NEXT: %231 = call i1 @"{{.*}}/runtime/internal/runtime.EfaceEqual"(%"{{.*}}/runtime/internal/runtime.eface" %226, %"{{.*}}/runtime/internal/runtime.eface" %230) +// CHECK-NEXT: %232 = xor i1 %231, true +// CHECK-NEXT: br i1 %232, label %_llgo_20, label %_llgo_22 +// CHECK-EMPTY: +// CHECK-NEXT: _llgo_20: ; preds = %_llgo_22, %_llgo_19 +// CHECK-NEXT: %233 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %15, i32 0, i32 0 +// CHECK-NEXT: %234 = load %reflect.Value, ptr %233, align 8 +// CHECK-NEXT: %235 = call %"{{.*}}/runtime/internal/runtime.eface" @reflect.Value.Interface(%reflect.Value %234) +// CHECK-NEXT: %236 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %15, i32 0, i32 1 +// CHECK-NEXT: %237 = load %reflect.Value, ptr %236, align 8 +// CHECK-NEXT: %238 = call %"{{.*}}/runtime/internal/runtime.eface" @reflect.Value.Interface(%reflect.Value %237) +// CHECK-NEXT: %239 = call ptr @"{{.*}}/runtime/internal/runtime.AllocZ"(i64 64) +// CHECK-NEXT: %240 = getelementptr inbounds %"{{.*}}/runtime/internal/runtime.eface", ptr %239, i64 0 +// CHECK-NEXT: store %"{{.*}}/runtime/internal/runtime.eface" %235, ptr %240, align 8 +// CHECK-NEXT: %241 = getelementptr inbounds %"{{.*}}/runtime/internal/runtime.eface", ptr %239, i64 1 +// CHECK-NEXT: %242 = call ptr @"{{.*}}/runtime/internal/runtime.IfaceType"(%"{{.*}}/runtime/internal/runtime.iface" %45) +// CHECK-NEXT: %243 = extractvalue %"{{.*}}/runtime/internal/runtime.iface" %45, 1 +// CHECK-NEXT: %244 = insertvalue %"{{.*}}/runtime/internal/runtime.eface" undef, ptr %242, 0 +// CHECK-NEXT: %245 = insertvalue %"{{.*}}/runtime/internal/runtime.eface" %244, ptr %243, 1 +// CHECK-NEXT: store %"{{.*}}/runtime/internal/runtime.eface" %245, ptr %241, align 8 +// CHECK-NEXT: %246 = getelementptr inbounds %"{{.*}}/runtime/internal/runtime.eface", ptr %239, i64 2 +// CHECK-NEXT: store %"{{.*}}/runtime/internal/runtime.eface" %218, ptr %246, align 8 +// CHECK-NEXT: %247 = getelementptr inbounds %"{{.*}}/runtime/internal/runtime.eface", ptr %239, i64 3 +// CHECK-NEXT: store %"{{.*}}/runtime/internal/runtime.eface" %238, ptr %247, align 8 +// CHECK-NEXT: %248 = insertvalue %"{{.*}}/runtime/internal/runtime.Slice" undef, ptr %239, 0 +// CHECK-NEXT: %249 = insertvalue %"{{.*}}/runtime/internal/runtime.Slice" %248, i64 4, 1 +// CHECK-NEXT: %250 = insertvalue %"{{.*}}/runtime/internal/runtime.Slice" %249, i64 4, 2 +// CHECK-NEXT: call void @"main.(*testingT).Errorf"(ptr %0, %"{{.*}}/runtime/internal/runtime.String" { ptr @{{[0-9]+}}, i64 63 }, %"{{.*}}/runtime/internal/runtime.Slice" %250) +// CHECK-NEXT: br label %_llgo_21 +// CHECK-EMPTY: +// CHECK-NEXT: _llgo_21: ; preds = %_llgo_22, %_llgo_20 +// CHECK-NEXT: %251 = call i1 @main.IsRO(%reflect.Value %80) +// CHECK-NEXT: br i1 %251, label %_llgo_23, label %_llgo_24 +// CHECK-EMPTY: +// CHECK-NEXT: _llgo_22: ; preds = %_llgo_19 +// CHECK-NEXT: %252 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %15, i32 0, i32 1 +// CHECK-NEXT: %253 = load %reflect.Value, ptr %252, align 8 +// CHECK-NEXT: %254 = call %"{{.*}}/runtime/internal/runtime.eface" @reflect.Value.Interface(%reflect.Value %253) +// CHECK-NEXT: %255 = call i1 @reflect.DeepEqual(%"{{.*}}/runtime/internal/runtime.eface" %218, %"{{.*}}/runtime/internal/runtime.eface" %254) +// CHECK-NEXT: br i1 %255, label %_llgo_21, label %_llgo_20 +// CHECK-EMPTY: +// CHECK-NEXT: _llgo_23: ; preds = %_llgo_21 +// CHECK-NEXT: %256 = call ptr @"{{.*}}/runtime/internal/runtime.AllocZ"(i64 16) +// CHECK-NEXT: %257 = getelementptr inbounds %"{{.*}}/runtime/internal/runtime.eface", ptr %256, i64 0 +// CHECK-NEXT: %258 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 24) +// CHECK-NEXT: store %reflect.Value %80, ptr %258, align 8 +// CHECK-NEXT: %259 = insertvalue %"{{.*}}/runtime/internal/runtime.eface" { ptr @_llgo_reflect.Value, ptr undef }, ptr %258, 1 +// CHECK-NEXT: store %"{{.*}}/runtime/internal/runtime.eface" %259, ptr %257, align 8 +// CHECK-NEXT: %260 = insertvalue %"{{.*}}/runtime/internal/runtime.Slice" undef, ptr %256, 0 +// CHECK-NEXT: %261 = insertvalue %"{{.*}}/runtime/internal/runtime.Slice" %260, i64 1, 1 +// CHECK-NEXT: %262 = insertvalue %"{{.*}}/runtime/internal/runtime.Slice" %261, i64 1, 2 +// CHECK-NEXT: call void @"main.(*testingT).Errorf"(ptr %0, %"{{.*}}/runtime/internal/runtime.String" { ptr @{{[0-9]+}}, i64 35 }, %"{{.*}}/runtime/internal/runtime.Slice" %262) +// CHECK-NEXT: br label %_llgo_24 +// CHECK-EMPTY: +// CHECK-NEXT: _llgo_24: ; preds = %_llgo_23, %_llgo_21 +// CHECK-NEXT: %263 = call i1 @main.IsRO(%reflect.Value %95) +// CHECK-NEXT: br i1 %263, label %_llgo_25, label %_llgo_26 +// CHECK-EMPTY: +// CHECK-NEXT: _llgo_25: ; preds = %_llgo_24 +// CHECK-NEXT: %264 = call ptr @"{{.*}}/runtime/internal/runtime.AllocZ"(i64 16) +// CHECK-NEXT: %265 = getelementptr inbounds %"{{.*}}/runtime/internal/runtime.eface", ptr %264, i64 0 +// CHECK-NEXT: %266 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 24) +// CHECK-NEXT: store %reflect.Value %95, ptr %266, align 8 +// CHECK-NEXT: %267 = insertvalue %"{{.*}}/runtime/internal/runtime.eface" { ptr @_llgo_reflect.Value, ptr undef }, ptr %266, 1 +// CHECK-NEXT: store %"{{.*}}/runtime/internal/runtime.eface" %267, ptr %265, align 8 +// CHECK-NEXT: %268 = insertvalue %"{{.*}}/runtime/internal/runtime.Slice" undef, ptr %264, 0 +// CHECK-NEXT: %269 = insertvalue %"{{.*}}/runtime/internal/runtime.Slice" %268, i64 1, 1 +// CHECK-NEXT: %270 = insertvalue %"{{.*}}/runtime/internal/runtime.Slice" %269, i64 1, 2 +// CHECK-NEXT: call void @"main.(*testingT).Errorf"(ptr %0, %"{{.*}}/runtime/internal/runtime.String" { ptr @{{[0-9]+}}, i64 46 }, %"{{.*}}/runtime/internal/runtime.Slice" %270) +// CHECK-NEXT: br label %_llgo_26 +// CHECK-EMPTY: +// CHECK-NEXT: _llgo_26: ; preds = %_llgo_25, %_llgo_24 +// CHECK-NEXT: %271 = call i1 @main.IsRO(%reflect.Value %147) +// CHECK-NEXT: br i1 %271, label %_llgo_27, label %_llgo_28 +// CHECK-EMPTY: +// CHECK-NEXT: _llgo_27: ; preds = %_llgo_26 +// CHECK-NEXT: %272 = call ptr @"{{.*}}/runtime/internal/runtime.AllocZ"(i64 16) +// CHECK-NEXT: %273 = getelementptr inbounds %"{{.*}}/runtime/internal/runtime.eface", ptr %272, i64 0 +// CHECK-NEXT: %274 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 24) +// CHECK-NEXT: store %reflect.Value %147, ptr %274, align 8 +// CHECK-NEXT: %275 = insertvalue %"{{.*}}/runtime/internal/runtime.eface" { ptr @_llgo_reflect.Value, ptr undef }, ptr %274, 1 +// CHECK-NEXT: store %"{{.*}}/runtime/internal/runtime.eface" %275, ptr %273, align 8 +// CHECK-NEXT: %276 = insertvalue %"{{.*}}/runtime/internal/runtime.Slice" undef, ptr %272, 0 +// CHECK-NEXT: %277 = insertvalue %"{{.*}}/runtime/internal/runtime.Slice" %276, i64 1, 1 +// CHECK-NEXT: %278 = insertvalue %"{{.*}}/runtime/internal/runtime.Slice" %277, i64 1, 2 +// CHECK-NEXT: call void @"main.(*testingT).Errorf"(ptr %0, %"{{.*}}/runtime/internal/runtime.String" { ptr @{{[0-9]+}}, i64 41 }, %"{{.*}}/runtime/internal/runtime.Slice" %278) +// CHECK-NEXT: br label %_llgo_28 +// CHECK-EMPTY: +// CHECK-NEXT: _llgo_28: ; preds = %_llgo_27, %_llgo_26 +// CHECK-NEXT: %279 = call i1 @main.IsRO(%reflect.Value %217) +// CHECK-NEXT: br i1 %279, label %_llgo_29, label %_llgo_30 +// CHECK-EMPTY: +// CHECK-NEXT: _llgo_29: ; preds = %_llgo_28 +// CHECK-NEXT: %280 = call ptr @"{{.*}}/runtime/internal/runtime.AllocZ"(i64 16) +// CHECK-NEXT: %281 = getelementptr inbounds %"{{.*}}/runtime/internal/runtime.eface", ptr %280, i64 0 +// CHECK-NEXT: %282 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 24) +// CHECK-NEXT: store %reflect.Value %217, ptr %282, align 8 +// CHECK-NEXT: %283 = insertvalue %"{{.*}}/runtime/internal/runtime.eface" { ptr @_llgo_reflect.Value, ptr undef }, ptr %282, 1 +// CHECK-NEXT: store %"{{.*}}/runtime/internal/runtime.eface" %283, ptr %281, align 8 +// CHECK-NEXT: %284 = insertvalue %"{{.*}}/runtime/internal/runtime.Slice" undef, ptr %280, 0 +// CHECK-NEXT: %285 = insertvalue %"{{.*}}/runtime/internal/runtime.Slice" %284, i64 1, 1 +// CHECK-NEXT: %286 = insertvalue %"{{.*}}/runtime/internal/runtime.Slice" %285, i64 1, 2 +// CHECK-NEXT: call void @"main.(*testingT).Errorf"(ptr %0, %"{{.*}}/runtime/internal/runtime.String" { ptr @{{[0-9]+}}, i64 46 }, %"{{.*}}/runtime/internal/runtime.Slice" %286) +// CHECK-NEXT: br label %_llgo_30 +// CHECK-EMPTY: +// CHECK-NEXT: _llgo_30: ; preds = %_llgo_29, %_llgo_28 +// CHECK-NEXT: %287 = call %reflect.Value @main.MakeRO(%reflect.Value %80) +// CHECK-NEXT: %288 = call %reflect.Value @reflect.Value.Convert(%reflect.Value %287, %"{{.*}}/runtime/internal/runtime.iface" %18) +// CHECK-NEXT: %289 = call i1 @main.IsRO(%reflect.Value %288) +// CHECK-NEXT: br i1 %289, label %_llgo_32, label %_llgo_31 +// CHECK-EMPTY: +// CHECK-NEXT: _llgo_31: ; preds = %_llgo_30 +// CHECK-NEXT: %290 = call ptr @"{{.*}}/runtime/internal/runtime.AllocZ"(i64 16) +// CHECK-NEXT: %291 = getelementptr inbounds %"{{.*}}/runtime/internal/runtime.eface", ptr %290, i64 0 +// CHECK-NEXT: %292 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 24) +// CHECK-NEXT: store %reflect.Value %80, ptr %292, align 8 +// CHECK-NEXT: %293 = insertvalue %"{{.*}}/runtime/internal/runtime.eface" { ptr @_llgo_reflect.Value, ptr undef }, ptr %292, 1 +// CHECK-NEXT: store %"{{.*}}/runtime/internal/runtime.eface" %293, ptr %291, align 8 +// CHECK-NEXT: %294 = insertvalue %"{{.*}}/runtime/internal/runtime.Slice" undef, ptr %290, 0 +// CHECK-NEXT: %295 = insertvalue %"{{.*}}/runtime/internal/runtime.Slice" %294, i64 1, 1 +// CHECK-NEXT: %296 = insertvalue %"{{.*}}/runtime/internal/runtime.Slice" %295, i64 1, 2 +// CHECK-NEXT: call void @"main.(*testingT).Errorf"(ptr %0, %"{{.*}}/runtime/internal/runtime.String" { ptr @{{[0-9]+}}, i64 49 }, %"{{.*}}/runtime/internal/runtime.Slice" %296) +// CHECK-NEXT: br label %_llgo_32 +// CHECK-EMPTY: +// CHECK-NEXT: _llgo_32: ; preds = %_llgo_31, %_llgo_30 +// CHECK-NEXT: %297 = call %reflect.Value @main.MakeRO(%reflect.Value %80) +// CHECK-NEXT: %298 = call %reflect.Value @reflect.Value.Convert(%reflect.Value %297, %"{{.*}}/runtime/internal/runtime.iface" %45) +// CHECK-NEXT: %299 = call i1 @main.IsRO(%reflect.Value %298) +// CHECK-NEXT: br i1 %299, label %_llgo_1, label %_llgo_33 +// CHECK-EMPTY: +// CHECK-NEXT: _llgo_33: ; preds = %_llgo_32 +// CHECK-NEXT: %300 = call ptr @"{{.*}}/runtime/internal/runtime.AllocZ"(i64 16) +// CHECK-NEXT: %301 = getelementptr inbounds %"{{.*}}/runtime/internal/runtime.eface", ptr %300, i64 0 +// CHECK-NEXT: %302 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 24) +// CHECK-NEXT: store %reflect.Value %80, ptr %302, align 8 +// CHECK-NEXT: %303 = insertvalue %"{{.*}}/runtime/internal/runtime.eface" { ptr @_llgo_reflect.Value, ptr undef }, ptr %302, 1 +// CHECK-NEXT: store %"{{.*}}/runtime/internal/runtime.eface" %303, ptr %301, align 8 +// CHECK-NEXT: %304 = insertvalue %"{{.*}}/runtime/internal/runtime.Slice" undef, ptr %300, 0 +// CHECK-NEXT: %305 = insertvalue %"{{.*}}/runtime/internal/runtime.Slice" %304, i64 1, 1 +// CHECK-NEXT: %306 = insertvalue %"{{.*}}/runtime/internal/runtime.Slice" %305, i64 1, 2 +// CHECK-NEXT: call void @"main.(*testingT).Errorf"(ptr %0, %"{{.*}}/runtime/internal/runtime.String" { ptr @{{[0-9]+}}, i64 44 }, %"{{.*}}/runtime/internal/runtime.Slice" %306) +// CHECK-NEXT: br label %_llgo_1 +// CHECK-EMPTY: +// CHECK-NEXT: _llgo_34: ; preds = %_llgo_50, %_llgo_3 +// CHECK-NEXT: %307 = call { i1, ptr, ptr } @"{{.*}}/runtime/internal/runtime.MapIterNext"(ptr %28) +// CHECK-NEXT: %308 = extractvalue { i1, ptr, ptr } %307, 0 +// CHECK-NEXT: br i1 %308, label %_llgo_45, label %_llgo_46 +// CHECK-EMPTY: +// CHECK-NEXT: _llgo_35: ; preds = %_llgo_47 +// CHECK-NEXT: %309 = extractvalue { i1, %"{{.*}}/runtime/internal/runtime.iface", i1 } %398, 1 +// CHECK-NEXT: %310 = call ptr @"{{.*}}/runtime/internal/runtime.NewMapIter"(ptr @"map[_llgo_reflect.Type]_llgo_bool", ptr %2) +// CHECK-NEXT: br label %_llgo_37 +// CHECK-EMPTY: +// CHECK-NEXT: _llgo_36: ; preds = %_llgo_47 +// CHECK-NEXT: ret void +// CHECK-EMPTY: +// CHECK-NEXT: _llgo_37: ; preds = %_llgo_44, %_llgo_40, %_llgo_35 +// CHECK-NEXT: %311 = call { i1, ptr, ptr } @"{{.*}}/runtime/internal/runtime.MapIterNext"(ptr %310) +// CHECK-NEXT: %312 = extractvalue { i1, ptr, ptr } %311, 0 +// CHECK-NEXT: br i1 %312, label %_llgo_48, label %_llgo_49 +// CHECK-EMPTY: +// CHECK-NEXT: _llgo_38: ; preds = %_llgo_50 +// CHECK-NEXT: %313 = extractvalue { i1, %"{{.*}}/runtime/internal/runtime.iface", i1 } %406, 1 +// CHECK-NEXT: %314 = call ptr @"{{.*}}/runtime/internal/runtime.IfaceType"(%"{{.*}}/runtime/internal/runtime.iface" %309) +// CHECK-NEXT: %315 = extractvalue %"{{.*}}/runtime/internal/runtime.iface" %309, 1 +// CHECK-NEXT: %316 = insertvalue %"{{.*}}/runtime/internal/runtime.eface" undef, ptr %314, 0 +// CHECK-NEXT: %317 = insertvalue %"{{.*}}/runtime/internal/runtime.eface" %316, ptr %315, 1 +// CHECK-NEXT: %318 = call ptr @"{{.*}}/runtime/internal/runtime.IfaceType"(%"{{.*}}/runtime/internal/runtime.iface" %313) +// CHECK-NEXT: %319 = extractvalue %"{{.*}}/runtime/internal/runtime.iface" %313, 1 +// CHECK-NEXT: %320 = insertvalue %"{{.*}}/runtime/internal/runtime.eface" undef, ptr %318, 0 +// CHECK-NEXT: %321 = insertvalue %"{{.*}}/runtime/internal/runtime.eface" %320, ptr %319, 1 +// CHECK-NEXT: %322 = call i1 @"{{.*}}/runtime/internal/runtime.EfaceEqual"(%"{{.*}}/runtime/internal/runtime.eface" %317, %"{{.*}}/runtime/internal/runtime.eface" %321) +// CHECK-NEXT: br i1 %322, label %_llgo_40, label %_llgo_41 +// CHECK-EMPTY: +// CHECK-NEXT: _llgo_39: ; preds = %_llgo_41 +// CHECK-NEXT: %323 = call ptr @"{{.*}}/runtime/internal/runtime.IfacePtrData"(%"{{.*}}/runtime/internal/runtime.iface" %313) +// CHECK-NEXT: %324 = extractvalue %"{{.*}}/runtime/internal/runtime.iface" %313, 0 +// CHECK-NEXT: %325 = getelementptr ptr, ptr %324, i64 {{(21|23)}} +// CHECK-NEXT: %326 = load ptr, ptr %325, align 8 +// CHECK-NEXT: %327 = insertvalue { ptr, ptr } undef, ptr %326, 0 +// CHECK-NEXT: %328 = insertvalue { ptr, ptr } %327, ptr %323, 1 +// CHECK-NEXT: %329 = extractvalue { ptr, ptr } %328, 1 +// CHECK-NEXT: %330 = extractvalue { ptr, ptr } %328, 0 +// CHECK-NEXT: %331 = call i64 %330(ptr %329) +// CHECK-NEXT: %332 = icmp eq i64 %331, 20 +// CHECK-NEXT: br i1 %332, label %_llgo_42, label %_llgo_43 +// CHECK-EMPTY: +// CHECK-NEXT: _llgo_40: ; preds = %_llgo_43, %_llgo_41, %_llgo_38 +// CHECK-NEXT: %333 = phi i1 [ true, %_llgo_38 ], [ true, %_llgo_41 ], [ %361, %_llgo_43 ] +// CHECK-NEXT: %334 = call ptr @"{{.*}}/runtime/internal/runtime.IfacePtrData"(%"{{.*}}/runtime/internal/runtime.iface" %309) +// CHECK-NEXT: %335 = extractvalue %"{{.*}}/runtime/internal/runtime.iface" %309, 0 +// CHECK-NEXT: %336 = getelementptr ptr, ptr %335, i64 10 +// CHECK-NEXT: %337 = load ptr, ptr %336, align 8 +// CHECK-NEXT: %338 = insertvalue { ptr, ptr } undef, ptr %337, 0 +// CHECK-NEXT: %339 = insertvalue { ptr, ptr } %338, ptr %334, 1 +// CHECK-NEXT: %340 = extractvalue { ptr, ptr } %339, 1 +// CHECK-NEXT: %341 = extractvalue { ptr, ptr } %339, 0 +// CHECK-NEXT: %342 = call i1 %341(ptr %340, %"{{.*}}/runtime/internal/runtime.iface" %313) +// CHECK-NEXT: %343 = icmp ne i1 %342, %333 +// CHECK-NEXT: br i1 %343, label %_llgo_44, label %_llgo_37 +// CHECK-EMPTY: +// CHECK-NEXT: _llgo_41: ; preds = %_llgo_38 +// CHECK-NEXT: %344 = alloca [2 x %"{{.*}}/runtime/internal/runtime.iface"], align 8 +// CHECK-NEXT: call void @llvm.memset.p0.i64(ptr %344, i8 0, i64 32, i1 false) +// CHECK-NEXT: %345 = getelementptr inbounds %"{{.*}}/runtime/internal/runtime.iface", ptr %344, i64 0 +// CHECK-NEXT: %346 = getelementptr inbounds %"{{.*}}/runtime/internal/runtime.iface", ptr %344, i64 1 +// CHECK-NEXT: store %"{{.*}}/runtime/internal/runtime.iface" %309, ptr %345, align 8 +// CHECK-NEXT: store %"{{.*}}/runtime/internal/runtime.iface" %313, ptr %346, align 8 +// CHECK-NEXT: %347 = load [2 x %"{{.*}}/runtime/internal/runtime.iface"], ptr %344, align 8 +// CHECK-NEXT: %348 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 32) +// CHECK-NEXT: store [2 x %"{{.*}}/runtime/internal/runtime.iface"] %347, ptr %348, align 8 +// CHECK-NEXT: %349 = call ptr @"{{.*}}/runtime/internal/runtime.MapAccess1"(ptr @"map{{\[\[}}2]_llgo_reflect.Type]_llgo_bool", ptr %1, ptr %348) +// CHECK-NEXT: %350 = load i1, ptr %349, align 1 +// CHECK-NEXT: br i1 %350, label %_llgo_40, label %_llgo_39 +// CHECK-EMPTY: +// CHECK-NEXT: _llgo_42: ; preds = %_llgo_39 +// CHECK-NEXT: %351 = call ptr @"{{.*}}/runtime/internal/runtime.IfacePtrData"(%"{{.*}}/runtime/internal/runtime.iface" %313) +// CHECK-NEXT: %352 = extractvalue %"{{.*}}/runtime/internal/runtime.iface" %313, 0 +// CHECK-NEXT: %353 = getelementptr ptr, ptr %352, i64 {{(28|31)}} +// CHECK-NEXT: %354 = load ptr, ptr %353, align 8 +// CHECK-NEXT: %355 = insertvalue { ptr, ptr } undef, ptr %354, 0 +// CHECK-NEXT: %356 = insertvalue { ptr, ptr } %355, ptr %351, 1 +// CHECK-NEXT: %357 = extractvalue { ptr, ptr } %356, 1 +// CHECK-NEXT: %358 = extractvalue { ptr, ptr } %356, 0 +// CHECK-NEXT: %359 = call i64 %358(ptr %357) +// CHECK-NEXT: %360 = icmp eq i64 %359, 0 +// CHECK-NEXT: br label %_llgo_43 +// CHECK-EMPTY: +// CHECK-NEXT: _llgo_43: ; preds = %_llgo_42, %_llgo_39 +// CHECK-NEXT: %361 = phi i1 [ false, %_llgo_39 ], [ %360, %_llgo_42 ] +// CHECK-NEXT: br label %_llgo_40 +// CHECK-EMPTY: +// CHECK-NEXT: _llgo_44: ; preds = %_llgo_40 +// CHECK-NEXT: %362 = alloca [2 x %"{{.*}}/runtime/internal/runtime.iface"], align 8 +// CHECK-NEXT: call void @llvm.memset.p0.i64(ptr %362, i8 0, i64 32, i1 false) +// CHECK-NEXT: %363 = getelementptr inbounds %"{{.*}}/runtime/internal/runtime.iface", ptr %362, i64 0 +// CHECK-NEXT: %364 = getelementptr inbounds %"{{.*}}/runtime/internal/runtime.iface", ptr %362, i64 1 +// CHECK-NEXT: store %"{{.*}}/runtime/internal/runtime.iface" %309, ptr %363, align 8 +// CHECK-NEXT: store %"{{.*}}/runtime/internal/runtime.iface" %313, ptr %364, align 8 +// CHECK-NEXT: %365 = load [2 x %"{{.*}}/runtime/internal/runtime.iface"], ptr %362, align 8 +// CHECK-NEXT: %366 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 32) +// CHECK-NEXT: store [2 x %"{{.*}}/runtime/internal/runtime.iface"] %365, ptr %366, align 8 +// CHECK-NEXT: %367 = call ptr @"{{.*}}/runtime/internal/runtime.MapAccess1"(ptr @"map{{\[\[}}2]_llgo_reflect.Type]_llgo_bool", ptr %1, ptr %366) +// CHECK-NEXT: %368 = load i1, ptr %367, align 1 +// CHECK-NEXT: %369 = call ptr @"{{.*}}/runtime/internal/runtime.AllocZ"(i64 80) +// CHECK-NEXT: %370 = getelementptr inbounds %"{{.*}}/runtime/internal/runtime.eface", ptr %369, i64 0 +// CHECK-NEXT: %371 = call ptr @"{{.*}}/runtime/internal/runtime.IfaceType"(%"{{.*}}/runtime/internal/runtime.iface" %309) +// CHECK-NEXT: %372 = extractvalue %"{{.*}}/runtime/internal/runtime.iface" %309, 1 +// CHECK-NEXT: %373 = insertvalue %"{{.*}}/runtime/internal/runtime.eface" undef, ptr %371, 0 +// CHECK-NEXT: %374 = insertvalue %"{{.*}}/runtime/internal/runtime.eface" %373, ptr %372, 1 +// CHECK-NEXT: store %"{{.*}}/runtime/internal/runtime.eface" %374, ptr %370, align 8 +// CHECK-NEXT: %375 = getelementptr inbounds %"{{.*}}/runtime/internal/runtime.eface", ptr %369, i64 1 +// CHECK-NEXT: %376 = call ptr @"{{.*}}/runtime/internal/runtime.IfaceType"(%"{{.*}}/runtime/internal/runtime.iface" %313) +// CHECK-NEXT: %377 = extractvalue %"{{.*}}/runtime/internal/runtime.iface" %313, 1 +// CHECK-NEXT: %378 = insertvalue %"{{.*}}/runtime/internal/runtime.eface" undef, ptr %376, 0 +// CHECK-NEXT: %379 = insertvalue %"{{.*}}/runtime/internal/runtime.eface" %378, ptr %377, 1 +// CHECK-NEXT: store %"{{.*}}/runtime/internal/runtime.eface" %379, ptr %375, align 8 +// CHECK-NEXT: %380 = getelementptr inbounds %"{{.*}}/runtime/internal/runtime.eface", ptr %369, i64 2 +// CHECK-NEXT: %381 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 1) +// CHECK-NEXT: store i1 %342, ptr %381, align 1 +// CHECK-NEXT: %382 = insertvalue %"{{.*}}/runtime/internal/runtime.eface" { ptr @_llgo_bool, ptr undef }, ptr %381, 1 +// CHECK-NEXT: store %"{{.*}}/runtime/internal/runtime.eface" %382, ptr %380, align 8 +// CHECK-NEXT: %383 = getelementptr inbounds %"{{.*}}/runtime/internal/runtime.eface", ptr %369, i64 3 +// CHECK-NEXT: %384 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 1) +// CHECK-NEXT: store i1 %333, ptr %384, align 1 +// CHECK-NEXT: %385 = insertvalue %"{{.*}}/runtime/internal/runtime.eface" { ptr @_llgo_bool, ptr undef }, ptr %384, 1 +// CHECK-NEXT: store %"{{.*}}/runtime/internal/runtime.eface" %385, ptr %383, align 8 +// CHECK-NEXT: %386 = getelementptr inbounds %"{{.*}}/runtime/internal/runtime.eface", ptr %369, i64 4 +// CHECK-NEXT: %387 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 1) +// CHECK-NEXT: store i1 %368, ptr %387, align 1 +// CHECK-NEXT: %388 = insertvalue %"{{.*}}/runtime/internal/runtime.eface" { ptr @_llgo_bool, ptr undef }, ptr %387, 1 +// CHECK-NEXT: store %"{{.*}}/runtime/internal/runtime.eface" %388, ptr %386, align 8 +// CHECK-NEXT: %389 = insertvalue %"{{.*}}/runtime/internal/runtime.Slice" undef, ptr %369, 0 +// CHECK-NEXT: %390 = insertvalue %"{{.*}}/runtime/internal/runtime.Slice" %389, i64 5, 1 +// CHECK-NEXT: %391 = insertvalue %"{{.*}}/runtime/internal/runtime.Slice" %390, i64 5, 2 +// CHECK-NEXT: call void @"main.(*testingT).Errorf"(ptr %0, %"{{.*}}/runtime/internal/runtime.String" { ptr @{{[0-9]+}}, i64 41 }, %"{{.*}}/runtime/internal/runtime.Slice" %391) +// CHECK-NEXT: br label %_llgo_37 +// CHECK-EMPTY: +// CHECK-NEXT: _llgo_45: ; preds = %_llgo_34 +// CHECK-NEXT: %392 = extractvalue { i1, ptr, ptr } %307, 1 +// CHECK-NEXT: %393 = extractvalue { i1, ptr, ptr } %307, 2 +// CHECK-NEXT: %394 = load %"{{.*}}/runtime/internal/runtime.iface", ptr %392, align 8 +// CHECK-NEXT: %395 = load i1, ptr %393, align 1 +// CHECK-NEXT: %396 = insertvalue { i1, %"{{.*}}/runtime/internal/runtime.iface", i1 } { i1 true, %"{{.*}}/runtime/internal/runtime.iface" undef, i1 undef }, %"{{.*}}/runtime/internal/runtime.iface" %394, 1 +// CHECK-NEXT: %397 = insertvalue { i1, %"{{.*}}/runtime/internal/runtime.iface", i1 } %396, i1 %395, 2 +// CHECK-NEXT: br label %_llgo_47 +// CHECK-EMPTY: +// CHECK-NEXT: _llgo_46: ; preds = %_llgo_34 +// CHECK-NEXT: br label %_llgo_47 +// CHECK-EMPTY: +// CHECK-NEXT: _llgo_47: ; preds = %_llgo_46, %_llgo_45 +// CHECK-NEXT: %398 = phi { i1, %"{{.*}}/runtime/internal/runtime.iface", i1 } [ %397, %_llgo_45 ], [ zeroinitializer, %_llgo_46 ] +// CHECK-NEXT: %399 = extractvalue { i1, %"{{.*}}/runtime/internal/runtime.iface", i1 } %398, 0 +// CHECK-NEXT: br i1 %399, label %_llgo_35, label %_llgo_36 +// CHECK-EMPTY: +// CHECK-NEXT: _llgo_48: ; preds = %_llgo_37 +// CHECK-NEXT: %400 = extractvalue { i1, ptr, ptr } %311, 1 +// CHECK-NEXT: %401 = extractvalue { i1, ptr, ptr } %311, 2 +// CHECK-NEXT: %402 = load %"{{.*}}/runtime/internal/runtime.iface", ptr %400, align 8 +// CHECK-NEXT: %403 = load i1, ptr %401, align 1 +// CHECK-NEXT: %404 = insertvalue { i1, %"{{.*}}/runtime/internal/runtime.iface", i1 } { i1 true, %"{{.*}}/runtime/internal/runtime.iface" undef, i1 undef }, %"{{.*}}/runtime/internal/runtime.iface" %402, 1 +// CHECK-NEXT: %405 = insertvalue { i1, %"{{.*}}/runtime/internal/runtime.iface", i1 } %404, i1 %403, 2 +// CHECK-NEXT: br label %_llgo_50 +// CHECK-EMPTY: +// CHECK-NEXT: _llgo_49: ; preds = %_llgo_37 +// CHECK-NEXT: br label %_llgo_50 +// CHECK-EMPTY: +// CHECK-NEXT: _llgo_50: ; preds = %_llgo_49, %_llgo_48 +// CHECK-NEXT: %406 = phi { i1, %"{{.*}}/runtime/internal/runtime.iface", i1 } [ %405, %_llgo_48 ], [ zeroinitializer, %_llgo_49 ] +// CHECK-NEXT: %407 = extractvalue { i1, %"{{.*}}/runtime/internal/runtime.iface", i1 } %406, 0 +// CHECK-NEXT: br i1 %407, label %_llgo_38, label %_llgo_34 +// CHECK-NEXT: } + +// CHECK-LABEL: define void @main.TestConvertNaNs(ptr %0){{.*}} { +// CHECK-NEXT: _llgo_0: +// CHECK-NEXT: %1 = call float @math.Float32frombits(i32 2139095041) +// CHECK-NEXT: store float %1, ptr @main.gFloat32, align 4 +// CHECK-NEXT: %2 = load float, ptr @main.gFloat32, align 4 +// CHECK-NEXT: %3 = call i32 @math.Float32bits(float %2) +// CHECK-NEXT: %4 = icmp ne i32 %3, 2139095041 +// CHECK-NEXT: br i1 %4, label %_llgo_1, label %_llgo_2 +// CHECK-EMPTY: +// CHECK-NEXT: _llgo_1: ; preds = %_llgo_0 +// CHECK-NEXT: %5 = call ptr @"{{.*}}/runtime/internal/runtime.AllocZ"(i64 32) +// CHECK-NEXT: %6 = getelementptr inbounds %"{{.*}}/runtime/internal/runtime.eface", ptr %5, i64 0 +// CHECK-NEXT: %7 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 4) +// CHECK-NEXT: store i32 %3, ptr %7, align 4 +// CHECK-NEXT: %8 = insertvalue %"{{.*}}/runtime/internal/runtime.eface" { ptr @_llgo_uint32, ptr undef }, ptr %7, 1 +// CHECK-NEXT: store %"{{.*}}/runtime/internal/runtime.eface" %8, ptr %6, align 8 +// CHECK-NEXT: %9 = getelementptr inbounds %"{{.*}}/runtime/internal/runtime.eface", ptr %5, i64 1 +// CHECK-NEXT: %10 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 4) +// CHECK-NEXT: store i32 2139095041, ptr %10, align 4 +// CHECK-NEXT: %11 = insertvalue %"{{.*}}/runtime/internal/runtime.eface" { ptr @_llgo_uint32, ptr undef }, ptr %10, 1 +// CHECK-NEXT: store %"{{.*}}/runtime/internal/runtime.eface" %11, ptr %9, align 8 +// CHECK-NEXT: %12 = insertvalue %"{{.*}}/runtime/internal/runtime.Slice" undef, ptr %5, 0 +// CHECK-NEXT: %13 = insertvalue %"{{.*}}/runtime/internal/runtime.Slice" %12, i64 2, 1 +// CHECK-NEXT: %14 = insertvalue %"{{.*}}/runtime/internal/runtime.Slice" %13, i64 2, 2 +// CHECK-NEXT: call void @"main.(*testingT).Errorf"(ptr %0, %"{{.*}}/runtime/internal/runtime.String" { ptr @{{[0-9]+}}, i64 47 }, %"{{.*}}/runtime/internal/runtime.Slice" %14) +// CHECK-NEXT: br label %_llgo_2 +// CHECK-EMPTY: +// CHECK-NEXT: _llgo_2: ; preds = %_llgo_1, %_llgo_0 +// CHECK-NEXT: %15 = load { ptr, ptr }, ptr @main.V, align 8 +// CHECK-NEXT: %16 = call float @math.Float32frombits(i32 2139095041) +// CHECK-NEXT: %17 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 4) +// CHECK-NEXT: store float %16, ptr %17, align 4 +// CHECK-NEXT: %18 = insertvalue %"{{.*}}/runtime/internal/runtime.eface" { ptr @_llgo_main.myFloat32.14.0, ptr undef }, ptr %17, 1 +// CHECK-NEXT: %19 = extractvalue { ptr, ptr } %15, 1 +// CHECK-NEXT: %20 = extractvalue { ptr, ptr } %15, 0 +// CHECK-NEXT: %__llgo_funcval_code = call ptr asm "", "=r,0"(ptr %20) +// CHECK-NEXT: %21 = call %reflect.Value %__llgo_funcval_code(ptr {{(nest|swiftself)}} %19, %"{{.*}}/runtime/internal/runtime.eface" %18) +// CHECK-NEXT: %22 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 4) +// CHECK-NEXT: store float 0.000000e+00, ptr %22, align 4 +// CHECK-NEXT: %23 = insertvalue %"{{.*}}/runtime/internal/runtime.eface" { ptr @_llgo_float32, ptr undef }, ptr %22, 1 +// CHECK-NEXT: %24 = call %"{{.*}}/runtime/internal/runtime.iface" @reflect.TypeOf(%"{{.*}}/runtime/internal/runtime.eface" %23) +// CHECK-NEXT: %25 = call %reflect.Value @reflect.Value.Convert(%reflect.Value %21, %"{{.*}}/runtime/internal/runtime.iface" %24) +// CHECK-NEXT: %26 = call %"{{.*}}/runtime/internal/runtime.eface" @reflect.Value.Interface(%reflect.Value %25) +// CHECK-NEXT: %27 = extractvalue %"{{.*}}/runtime/internal/runtime.eface" %26, 0 +// CHECK-NEXT: %28 = icmp eq ptr %27, @_llgo_float32 +// CHECK-NEXT: br i1 %28, label %_llgo_5, label %_llgo_6 +// CHECK-EMPTY: +// CHECK-NEXT: _llgo_3: ; preds = %_llgo_5 +// CHECK-NEXT: %29 = call ptr @"{{.*}}/runtime/internal/runtime.AllocZ"(i64 32) +// CHECK-NEXT: %30 = getelementptr inbounds %"{{.*}}/runtime/internal/runtime.eface", ptr %29, i64 0 +// CHECK-NEXT: %31 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 4) +// CHECK-NEXT: store i32 %41, ptr %31, align 4 +// CHECK-NEXT: %32 = insertvalue %"{{.*}}/runtime/internal/runtime.eface" { ptr @_llgo_uint32, ptr undef }, ptr %31, 1 +// CHECK-NEXT: store %"{{.*}}/runtime/internal/runtime.eface" %32, ptr %30, align 8 +// CHECK-NEXT: %33 = getelementptr inbounds %"{{.*}}/runtime/internal/runtime.eface", ptr %29, i64 1 +// CHECK-NEXT: %34 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 4) +// CHECK-NEXT: store i32 2139095041, ptr %34, align 4 +// CHECK-NEXT: %35 = insertvalue %"{{.*}}/runtime/internal/runtime.eface" { ptr @_llgo_uint32, ptr undef }, ptr %34, 1 +// CHECK-NEXT: store %"{{.*}}/runtime/internal/runtime.eface" %35, ptr %33, align 8 +// CHECK-NEXT: %36 = insertvalue %"{{.*}}/runtime/internal/runtime.Slice" undef, ptr %29, 0 +// CHECK-NEXT: %37 = insertvalue %"{{.*}}/runtime/internal/runtime.Slice" %36, i64 2, 1 +// CHECK-NEXT: %38 = insertvalue %"{{.*}}/runtime/internal/runtime.Slice" %37, i64 2, 2 +// CHECK-NEXT: call void @"main.(*testingT).Errorf"(ptr %0, %"{{.*}}/runtime/internal/runtime.String" { ptr @{{[0-9]+}}, i64 40 }, %"{{.*}}/runtime/internal/runtime.Slice" %38) +// CHECK-NEXT: br label %_llgo_4 +// CHECK-EMPTY: +// CHECK-NEXT: _llgo_4: ; preds = %_llgo_3, %_llgo_5 +// CHECK-NEXT: ret void +// CHECK-EMPTY: +// CHECK-NEXT: _llgo_5: ; preds = %_llgo_2 +// CHECK-NEXT: %39 = extractvalue %"{{.*}}/runtime/internal/runtime.eface" %26, 1 +// CHECK-NEXT: %40 = load float, ptr %39, align 4 +// CHECK-NEXT: %41 = call i32 @math.Float32bits(float %40) +// CHECK-NEXT: %42 = icmp ne i32 %41, 2139095041 +// CHECK-NEXT: br i1 %42, label %_llgo_3, label %_llgo_4 +// CHECK-EMPTY: +// CHECK-NEXT: _llgo_6: ; preds = %_llgo_2 +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.PanicTypeAssert"(ptr %27, %"{{.*}}/runtime/internal/runtime.String" { ptr @{{[0-9]+}}, i64 7 }, %"{{.*}}/runtime/internal/runtime.String" zeroinitializer) +// CHECK-NEXT: unreachable +// CHECK-NEXT: } + +// CHECK-LABEL: define void @main.TestConvertPanic(ptr %0){{.*}} { +// CHECK-NEXT: _llgo_0: +// CHECK-NEXT: %1 = call ptr @"{{.*}}/runtime/internal/runtime.AllocZ"(i64 4) +// CHECK-NEXT: %2 = call %"{{.*}}/runtime/internal/runtime.Slice" @"{{.*}}/runtime/internal/runtime.NewSlice2"(ptr %1, i64 1, i64 4, i64 0, i64 4, i1 true, i1 true, i1 true) +// CHECK-NEXT: %3 = call ptr @"{{.*}}/runtime/internal/runtime.AllocZ"(i64 8) +// CHECK-NEXT: %4 = call ptr @"{{.*}}/runtime/internal/runtime.AllocZ"(i64 24) +// CHECK-NEXT: %5 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 24) +// CHECK-NEXT: store %"{{.*}}/runtime/internal/runtime.Slice" %2, ptr %5, align 8 +// CHECK-NEXT: %6 = insertvalue %"{{.*}}/runtime/internal/runtime.eface" { ptr @"[]_llgo_uint8", ptr undef }, ptr %5, 1 +// CHECK-NEXT: %7 = call %reflect.Value @reflect.ValueOf(%"{{.*}}/runtime/internal/runtime.eface" %6) +// CHECK-NEXT: store %reflect.Value %7, ptr %4, align 8 +// CHECK-NEXT: %8 = call ptr @"{{.*}}/runtime/internal/runtime.AllocZ"(i64 16) +// CHECK-NEXT: %9 = insertvalue %"{{.*}}/runtime/internal/runtime.eface" { ptr @"*[8]_llgo_uint8", ptr undef }, ptr %3, 1 +// CHECK-NEXT: %10 = call %"{{.*}}/runtime/internal/runtime.iface" @reflect.TypeOf(%"{{.*}}/runtime/internal/runtime.eface" %9) +// CHECK-NEXT: store %"{{.*}}/runtime/internal/runtime.iface" %10, ptr %8, align 8 +// CHECK-NEXT: %11 = load %reflect.Value, ptr %4, align 8 +// CHECK-NEXT: %12 = call %"{{.*}}/runtime/internal/runtime.iface" @reflect.Value.Type(%reflect.Value %11) +// CHECK-NEXT: %13 = load %"{{.*}}/runtime/internal/runtime.iface", ptr %8, align 8 +// CHECK-NEXT: %14 = call ptr @"{{.*}}/runtime/internal/runtime.IfacePtrData"(%"{{.*}}/runtime/internal/runtime.iface" %12) +// CHECK-NEXT: %15 = extractvalue %"{{.*}}/runtime/internal/runtime.iface" %12, 0 +// CHECK-NEXT: %16 = getelementptr ptr, ptr %15, i64 10 +// CHECK-NEXT: %17 = load ptr, ptr %16, align 8 +// CHECK-NEXT: %18 = insertvalue { ptr, ptr } undef, ptr %17, 0 +// CHECK-NEXT: %19 = insertvalue { ptr, ptr } %18, ptr %14, 1 +// CHECK-NEXT: %20 = extractvalue { ptr, ptr } %19, 1 +// CHECK-NEXT: %21 = extractvalue { ptr, ptr } %19, 0 +// CHECK-NEXT: %22 = call i1 %21(ptr %20, %"{{.*}}/runtime/internal/runtime.iface" %13) +// CHECK-NEXT: br i1 %22, label %_llgo_2, label %_llgo_1 +// CHECK-EMPTY: +// CHECK-NEXT: _llgo_1: ; preds = %_llgo_0 +// CHECK-NEXT: call void @"main.(*testingT).Errorf"(ptr %0, %"{{.*}}/runtime/internal/runtime.String" { ptr @{{[0-9]+}}, i64 40 }, %"{{.*}}/runtime/internal/runtime.Slice" zeroinitializer) +// CHECK-NEXT: br label %_llgo_2 +// CHECK-EMPTY: +// CHECK-NEXT: _llgo_2: ; preds = %_llgo_1, %_llgo_0 +// CHECK-NEXT: %23 = load %reflect.Value, ptr %4, align 8 +// CHECK-NEXT: %24 = load %"{{.*}}/runtime/internal/runtime.iface", ptr %8, align 8 +// CHECK-NEXT: %25 = call i1 @reflect.Value.CanConvert(%reflect.Value %23, %"{{.*}}/runtime/internal/runtime.iface" %24) +// CHECK-NEXT: br i1 %25, label %_llgo_3, label %_llgo_4 +// CHECK-EMPTY: +// CHECK-NEXT: _llgo_3: ; preds = %_llgo_2 +// CHECK-NEXT: call void @"main.(*testingT).Errorf"(ptr %0, %"{{.*}}/runtime/internal/runtime.String" { ptr @{{[0-9]+}}, i64 57 }, %"{{.*}}/runtime/internal/runtime.Slice" zeroinitializer) +// CHECK-NEXT: br label %_llgo_4 +// CHECK-EMPTY: +// CHECK-NEXT: _llgo_4: ; preds = %_llgo_3, %_llgo_2 +// CHECK-NEXT: %26 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 16) +// CHECK-NEXT: %27 = getelementptr inbounds { ptr, ptr }, ptr %26, i32 0, i32 0 +// CHECK-NEXT: store ptr %4, ptr %27, align 8 +// CHECK-NEXT: %28 = getelementptr inbounds { ptr, ptr }, ptr %26, i32 0, i32 1 +// CHECK-NEXT: store ptr %8, ptr %28, align 8 +// CHECK-NEXT: %29 = insertvalue { ptr, ptr } { ptr @"main.TestConvertPanic$1", ptr undef }, ptr %26, 1 +// CHECK-NEXT: call void @main.shouldPanic(%"{{.*}}/runtime/internal/runtime.String" { ptr @{{[0-9]+}}, i64 77 }, { ptr, ptr } %29) +// CHECK-NEXT: %30 = load %reflect.Value, ptr %4, align 8 +// CHECK-NEXT: %31 = load %"{{.*}}/runtime/internal/runtime.iface", ptr %8, align 8 +// CHECK-NEXT: %32 = call ptr @"{{.*}}/runtime/internal/runtime.IfacePtrData"(%"{{.*}}/runtime/internal/runtime.iface" %31) +// CHECK-NEXT: %33 = extractvalue %"{{.*}}/runtime/internal/runtime.iface" %31, 0 +// CHECK-NEXT: %34 = getelementptr ptr, ptr %33, i64 11 +// CHECK-NEXT: %35 = load ptr, ptr %34, align 8 +// CHECK-NEXT: %36 = insertvalue { ptr, ptr } undef, ptr %35, 0 +// CHECK-NEXT: %37 = insertvalue { ptr, ptr } %36, ptr %32, 1 +// CHECK-NEXT: %38 = extractvalue { ptr, ptr } %37, 1 +// CHECK-NEXT: %39 = extractvalue { ptr, ptr } %37, 0 +// CHECK-NEXT: %40 = call %"{{.*}}/runtime/internal/runtime.iface" %39(ptr %38) +// CHECK-NEXT: %41 = call i1 @reflect.Value.CanConvert(%reflect.Value %30, %"{{.*}}/runtime/internal/runtime.iface" %40) +// CHECK-NEXT: br i1 %41, label %_llgo_5, label %_llgo_6 +// CHECK-EMPTY: +// CHECK-NEXT: _llgo_5: ; preds = %_llgo_4 +// CHECK-NEXT: call void @"main.(*testingT).Errorf"(ptr %0, %"{{.*}}/runtime/internal/runtime.String" { ptr @{{[0-9]+}}, i64 56 }, %"{{.*}}/runtime/internal/runtime.Slice" zeroinitializer) +// CHECK-NEXT: br label %_llgo_6 +// CHECK-EMPTY: +// CHECK-NEXT: _llgo_6: ; preds = %_llgo_5, %_llgo_4 +// CHECK-NEXT: %42 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 16) +// CHECK-NEXT: %43 = getelementptr inbounds { ptr, ptr }, ptr %42, i32 0, i32 0 +// CHECK-NEXT: store ptr %4, ptr %43, align 8 +// CHECK-NEXT: %44 = getelementptr inbounds { ptr, ptr }, ptr %42, i32 0, i32 1 +// CHECK-NEXT: store ptr %8, ptr %44, align 8 +// CHECK-NEXT: %45 = insertvalue { ptr, ptr } { ptr @"main.TestConvertPanic$2", ptr undef }, ptr %42, 1 +// CHECK-NEXT: call void @main.shouldPanic(%"{{.*}}/runtime/internal/runtime.String" { ptr @{{[0-9]+}}, i64 66 }, { ptr, ptr } %45) +// CHECK-NEXT: ret void +// CHECK-NEXT: } + +// CHECK-LABEL: define void @"main.TestConvertPanic$1"(ptr {{(nest|swiftself)}} %0){{.*}} { +// CHECK-NEXT: _llgo_0: +// CHECK-NEXT: %1 = load { ptr, ptr }, ptr %0, align 8 +// CHECK-NEXT: %2 = extractvalue { ptr, ptr } %1, 0 +// CHECK-NEXT: %3 = call ptr @"{{.*}}/runtime/internal/runtime.AssertNilDerefPtr"(ptr %2) +// CHECK-NEXT: %4 = load %reflect.Value, ptr %3, align 8 +// CHECK-NEXT: %5 = extractvalue { ptr, ptr } %1, 1 +// CHECK-NEXT: %6 = load %"{{.*}}/runtime/internal/runtime.iface", ptr %5, align 8 +// CHECK-NEXT: %7 = call %reflect.Value @reflect.Value.Convert(%reflect.Value %4, %"{{.*}}/runtime/internal/runtime.iface" %6) +// CHECK-NEXT: ret void +// CHECK-NEXT: } + +// CHECK-LABEL: define void @"main.TestConvertPanic$2"(ptr {{(nest|swiftself)}} %0){{.*}} { +// CHECK-NEXT: _llgo_0: +// CHECK-NEXT: %1 = load { ptr, ptr }, ptr %0, align 8 +// CHECK-NEXT: %2 = extractvalue { ptr, ptr } %1, 0 +// CHECK-NEXT: %3 = call ptr @"{{.*}}/runtime/internal/runtime.AssertNilDerefPtr"(ptr %2) +// CHECK-NEXT: %4 = load %reflect.Value, ptr %3, align 8 +// CHECK-NEXT: %5 = extractvalue { ptr, ptr } %1, 1 +// CHECK-NEXT: %6 = load %"{{.*}}/runtime/internal/runtime.iface", ptr %5, align 8 +// CHECK-NEXT: %7 = call ptr @"{{.*}}/runtime/internal/runtime.IfacePtrData"(%"{{.*}}/runtime/internal/runtime.iface" %6) +// CHECK-NEXT: %8 = extractvalue %"{{.*}}/runtime/internal/runtime.iface" %6, 0 +// CHECK-NEXT: %9 = getelementptr ptr, ptr %8, i64 11 +// CHECK-NEXT: %10 = load ptr, ptr %9, align 8 +// CHECK-NEXT: %11 = insertvalue { ptr, ptr } undef, ptr %10, 0 +// CHECK-NEXT: %12 = insertvalue { ptr, ptr } %11, ptr %7, 1 +// CHECK-NEXT: %13 = extractvalue { ptr, ptr } %12, 1 +// CHECK-NEXT: %14 = extractvalue { ptr, ptr } %12, 0 +// CHECK-NEXT: %15 = call %"{{.*}}/runtime/internal/runtime.iface" %14(ptr %13) +// CHECK-NEXT: %16 = call %reflect.Value @reflect.Value.Convert(%reflect.Value %4, %"{{.*}}/runtime/internal/runtime.iface" %15) +// CHECK-NEXT: ret void +// CHECK-NEXT: } + +// CHECK-LABEL: define void @main.TestConvertSlice2Array(ptr %0){{.*}} { +// CHECK-NEXT: _llgo_0: +// CHECK-NEXT: %1 = call ptr @"{{.*}}/runtime/internal/runtime.AllocZ"(i64 32) +// CHECK-NEXT: %2 = call %"{{.*}}/runtime/internal/runtime.Slice" @"{{.*}}/runtime/internal/runtime.NewSlice2"(ptr %1, i64 8, i64 4, i64 0, i64 4, i1 true, i1 true, i1 true) +// CHECK-NEXT: %3 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 32) +// CHECK-NEXT: store [4 x i64] zeroinitializer, ptr %3, align 8 +// CHECK-NEXT: %4 = insertvalue %"{{.*}}/runtime/internal/runtime.eface" { ptr @"[4]_llgo_int", ptr undef }, ptr %3, 1 +// CHECK-NEXT: %5 = call %"{{.*}}/runtime/internal/runtime.iface" @reflect.TypeOf(%"{{.*}}/runtime/internal/runtime.eface" %4) +// CHECK-NEXT: %6 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 24) +// CHECK-NEXT: store %"{{.*}}/runtime/internal/runtime.Slice" %2, ptr %6, align 8 +// CHECK-NEXT: %7 = insertvalue %"{{.*}}/runtime/internal/runtime.eface" { ptr @"[]_llgo_int", ptr undef }, ptr %6, 1 +// CHECK-NEXT: %8 = call %reflect.Value @reflect.ValueOf(%"{{.*}}/runtime/internal/runtime.eface" %7) +// CHECK-NEXT: %9 = call %reflect.Value @reflect.Value.Convert(%reflect.Value %8, %"{{.*}}/runtime/internal/runtime.iface" %5) +// CHECK-NEXT: %10 = call i1 @reflect.Value.CanAddr(%reflect.Value %9) +// CHECK-NEXT: br i1 %10, label %_llgo_1, label %_llgo_2 +// CHECK-EMPTY: +// CHECK-NEXT: _llgo_1: ; preds = %_llgo_0 +// CHECK-NEXT: call void @"main.(*testingT).Fatalf"(ptr %0, %"{{.*}}/runtime/internal/runtime.String" { ptr @{{[0-9]+}}, i64 65 }, %"{{.*}}/runtime/internal/runtime.Slice" zeroinitializer) +// CHECK-NEXT: br label %_llgo_2 +// CHECK-EMPTY: +// CHECK-NEXT: _llgo_2: ; preds = %_llgo_1, %_llgo_0 +// CHECK-NEXT: %11 = extractvalue %"{{.*}}/runtime/internal/runtime.Slice" %2, 1 +// CHECK-NEXT: br label %_llgo_3 +// CHECK-EMPTY: +// CHECK-NEXT: _llgo_3: ; preds = %_llgo_4, %_llgo_2 +// CHECK-NEXT: %12 = phi i64 [ -1, %_llgo_2 ], [ %13, %_llgo_4 ] +// CHECK-NEXT: %13 = add i64 %12, 1 +// CHECK-NEXT: %14 = icmp slt i64 %13, %11 +// CHECK-NEXT: br i1 %14, label %_llgo_4, label %_llgo_5 +// CHECK-EMPTY: +// CHECK-NEXT: _llgo_4: ; preds = %_llgo_3 +// CHECK-NEXT: %15 = call %reflect.Value @reflect.Value.Index(%reflect.Value %8, i64 %13) +// CHECK-NEXT: %16 = add i64 %13, 1 +// CHECK-NEXT: %17 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 8) +// CHECK-NEXT: store i64 %16, ptr %17, align 8 +// CHECK-NEXT: %18 = insertvalue %"{{.*}}/runtime/internal/runtime.eface" { ptr @_llgo_int, ptr undef }, ptr %17, 1 +// CHECK-NEXT: %19 = call %reflect.Value @reflect.ValueOf(%"{{.*}}/runtime/internal/runtime.eface" %18) +// CHECK-NEXT: call void @reflect.Value.Set(%reflect.Value %15, %reflect.Value %19) +// CHECK-NEXT: br label %_llgo_3 +// CHECK-EMPTY: +// CHECK-NEXT: _llgo_5: ; preds = %_llgo_3 +// CHECK-NEXT: %20 = extractvalue %"{{.*}}/runtime/internal/runtime.Slice" %2, 1 +// CHECK-NEXT: br label %_llgo_6 +// CHECK-EMPTY: +// CHECK-NEXT: _llgo_6: ; preds = %_llgo_9, %_llgo_7, %_llgo_5 +// CHECK-NEXT: %21 = phi i64 [ -1, %_llgo_5 ], [ %22, %_llgo_7 ], [ %22, %_llgo_9 ] +// CHECK-NEXT: %22 = add i64 %21, 1 +// CHECK-NEXT: %23 = icmp slt i64 %22, %20 +// CHECK-NEXT: br i1 %23, label %_llgo_7, label %_llgo_8 +// CHECK-EMPTY: +// CHECK-NEXT: _llgo_7: ; preds = %_llgo_6 +// CHECK-NEXT: %24 = call %reflect.Value @reflect.Value.Index(%reflect.Value %9, i64 %22) +// CHECK-NEXT: %25 = call i64 @reflect.Value.Int(%reflect.Value %24) +// CHECK-NEXT: %26 = icmp ne i64 %25, 0 +// CHECK-NEXT: br i1 %26, label %_llgo_9, label %_llgo_6 +// CHECK-EMPTY: +// CHECK-NEXT: _llgo_8: ; preds = %_llgo_6 +// CHECK-NEXT: ret void +// CHECK-EMPTY: +// CHECK-NEXT: _llgo_9: ; preds = %_llgo_7 +// CHECK-NEXT: %27 = call ptr @"{{.*}}/runtime/internal/runtime.AllocZ"(i64 32) +// CHECK-NEXT: %28 = getelementptr inbounds %"{{.*}}/runtime/internal/runtime.eface", ptr %27, i64 0 +// CHECK-NEXT: %29 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 24) +// CHECK-NEXT: store %reflect.Value %8, ptr %29, align 8 +// CHECK-NEXT: %30 = insertvalue %"{{.*}}/runtime/internal/runtime.eface" { ptr @_llgo_reflect.Value, ptr undef }, ptr %29, 1 +// CHECK-NEXT: store %"{{.*}}/runtime/internal/runtime.eface" %30, ptr %28, align 8 +// CHECK-NEXT: %31 = getelementptr inbounds %"{{.*}}/runtime/internal/runtime.eface", ptr %27, i64 1 +// CHECK-NEXT: %32 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 24) +// CHECK-NEXT: store %reflect.Value %9, ptr %32, align 8 +// CHECK-NEXT: %33 = insertvalue %"{{.*}}/runtime/internal/runtime.eface" { ptr @_llgo_reflect.Value, ptr undef }, ptr %32, 1 +// CHECK-NEXT: store %"{{.*}}/runtime/internal/runtime.eface" %33, ptr %31, align 8 +// CHECK-NEXT: %34 = insertvalue %"{{.*}}/runtime/internal/runtime.Slice" undef, ptr %27, 0 +// CHECK-NEXT: %35 = insertvalue %"{{.*}}/runtime/internal/runtime.Slice" %34, i64 2, 1 +// CHECK-NEXT: %36 = insertvalue %"{{.*}}/runtime/internal/runtime.Slice" %35, i64 2, 2 +// CHECK-NEXT: call void @"main.(*testingT).Fatalf"(ptr %0, %"{{.*}}/runtime/internal/runtime.String" { ptr @{{[0-9]+}}, i64 52 }, %"{{.*}}/runtime/internal/runtime.Slice" %36) +// CHECK-NEXT: br label %_llgo_6 +// CHECK-NEXT: } + +// CHECK-LABEL: define void @main.init(){{.*}} { +// CHECK-NEXT: _llgo_0: +// CHECK-NEXT: %0 = load i1, ptr @"main.init$guard", align 1 +// CHECK-NEXT: br i1 %0, label %_llgo_2, label %_llgo_1 +// CHECK-EMPTY: +// CHECK-NEXT: _llgo_1: ; preds = %_llgo_0 +// CHECK-NEXT: store i1 true, ptr @"main.init$guard", align 1 +// CHECK-NEXT: call void @bytes.init() +// CHECK-NEXT: call void @fmt.init() +// CHECK-NEXT: call void @io.init() +// CHECK-NEXT: call void @math.init() +// CHECK-NEXT: call void @reflect.init() +// CHECK-NEXT: call void @strings.init() +// CHECK-NEXT: store { ptr, ptr } { ptr @reflect.ValueOf, ptr null }, ptr @main.V, align 8 +// CHECK-NEXT: %1 = call ptr @"{{.*}}/runtime/internal/runtime.AllocZ"(i64 17808) +// CHECK-NEXT: %2 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %1, i64 0 +// CHECK-NEXT: %3 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %2, i32 0, i32 0 +// CHECK-NEXT: %4 = load { ptr, ptr }, ptr @main.V, align 8 +// CHECK-NEXT: %5 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 1) +// CHECK-NEXT: store i8 0, ptr %5, align 1 +// CHECK-NEXT: %6 = insertvalue %"{{.*}}/runtime/internal/runtime.eface" { ptr @_llgo_uint8, ptr undef }, ptr %5, 1 +// CHECK-NEXT: %7 = extractvalue { ptr, ptr } %4, 1 +// CHECK-NEXT: %8 = extractvalue { ptr, ptr } %4, 0 +// CHECK-NEXT: %__llgo_funcval_code = call ptr asm "", "=r,0"(ptr %8) +// CHECK-NEXT: %9 = call %reflect.Value %__llgo_funcval_code(ptr {{(nest|swiftself)}} %7, %"{{.*}}/runtime/internal/runtime.eface" %6) +// CHECK-NEXT: %10 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %2, i32 0, i32 1 +// CHECK-NEXT: %11 = load { ptr, ptr }, ptr @main.V, align 8 +// CHECK-NEXT: %12 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 1) +// CHECK-NEXT: store i8 0, ptr %12, align 1 +// CHECK-NEXT: %13 = insertvalue %"{{.*}}/runtime/internal/runtime.eface" { ptr @_llgo_uint8, ptr undef }, ptr %12, 1 +// CHECK-NEXT: %14 = extractvalue { ptr, ptr } %11, 1 +// CHECK-NEXT: %15 = extractvalue { ptr, ptr } %11, 0 +// CHECK-NEXT: %__llgo_funcval_code1 = call ptr asm "", "=r,0"(ptr %15) +// CHECK-NEXT: %16 = call %reflect.Value %__llgo_funcval_code1(ptr {{(nest|swiftself)}} %14, %"{{.*}}/runtime/internal/runtime.eface" %13) +// CHECK-NEXT: store %reflect.Value %9, ptr %3, align 8 +// CHECK-NEXT: store %reflect.Value %16, ptr %10, align 8 +// CHECK-NEXT: %17 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %1, i64 1 +// CHECK-NEXT: %18 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %17, i32 0, i32 0 +// CHECK-NEXT: %19 = load { ptr, ptr }, ptr @main.V, align 8 +// CHECK-NEXT: %20 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 1) +// CHECK-NEXT: store i8 1, ptr %20, align 1 +// CHECK-NEXT: %21 = insertvalue %"{{.*}}/runtime/internal/runtime.eface" { ptr @_llgo_int8, ptr undef }, ptr %20, 1 +// CHECK-NEXT: %22 = extractvalue { ptr, ptr } %19, 1 +// CHECK-NEXT: %23 = extractvalue { ptr, ptr } %19, 0 +// CHECK-NEXT: %__llgo_funcval_code2 = call ptr asm "", "=r,0"(ptr %23) +// CHECK-NEXT: %24 = call %reflect.Value %__llgo_funcval_code2(ptr {{(nest|swiftself)}} %22, %"{{.*}}/runtime/internal/runtime.eface" %21) +// CHECK-NEXT: %25 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %17, i32 0, i32 1 +// CHECK-NEXT: %26 = load { ptr, ptr }, ptr @main.V, align 8 +// CHECK-NEXT: %27 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 1) +// CHECK-NEXT: store i8 1, ptr %27, align 1 +// CHECK-NEXT: %28 = insertvalue %"{{.*}}/runtime/internal/runtime.eface" { ptr @_llgo_int8, ptr undef }, ptr %27, 1 +// CHECK-NEXT: %29 = extractvalue { ptr, ptr } %26, 1 +// CHECK-NEXT: %30 = extractvalue { ptr, ptr } %26, 0 +// CHECK-NEXT: %__llgo_funcval_code3 = call ptr asm "", "=r,0"(ptr %30) +// CHECK-NEXT: %31 = call %reflect.Value %__llgo_funcval_code3(ptr {{(nest|swiftself)}} %29, %"{{.*}}/runtime/internal/runtime.eface" %28) +// CHECK-NEXT: store %reflect.Value %24, ptr %18, align 8 +// CHECK-NEXT: store %reflect.Value %31, ptr %25, align 8 +// CHECK-NEXT: %32 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %1, i64 2 +// CHECK-NEXT: %33 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %32, i32 0, i32 0 +// CHECK-NEXT: %34 = load { ptr, ptr }, ptr @main.V, align 8 +// CHECK-NEXT: %35 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 1) +// CHECK-NEXT: store i8 2, ptr %35, align 1 +// CHECK-NEXT: %36 = insertvalue %"{{.*}}/runtime/internal/runtime.eface" { ptr @_llgo_int8, ptr undef }, ptr %35, 1 +// CHECK-NEXT: %37 = extractvalue { ptr, ptr } %34, 1 +// CHECK-NEXT: %38 = extractvalue { ptr, ptr } %34, 0 +// CHECK-NEXT: %__llgo_funcval_code4 = call ptr asm "", "=r,0"(ptr %38) +// CHECK-NEXT: %39 = call %reflect.Value %__llgo_funcval_code4(ptr {{(nest|swiftself)}} %37, %"{{.*}}/runtime/internal/runtime.eface" %36) +// CHECK-NEXT: %40 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %32, i32 0, i32 1 +// CHECK-NEXT: %41 = load { ptr, ptr }, ptr @main.V, align 8 +// CHECK-NEXT: %42 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 1) +// CHECK-NEXT: store i8 2, ptr %42, align 1 +// CHECK-NEXT: %43 = insertvalue %"{{.*}}/runtime/internal/runtime.eface" { ptr @_llgo_uint8, ptr undef }, ptr %42, 1 +// CHECK-NEXT: %44 = extractvalue { ptr, ptr } %41, 1 +// CHECK-NEXT: %45 = extractvalue { ptr, ptr } %41, 0 +// CHECK-NEXT: %__llgo_funcval_code5 = call ptr asm "", "=r,0"(ptr %45) +// CHECK-NEXT: %46 = call %reflect.Value %__llgo_funcval_code5(ptr {{(nest|swiftself)}} %44, %"{{.*}}/runtime/internal/runtime.eface" %43) +// CHECK-NEXT: store %reflect.Value %39, ptr %33, align 8 +// CHECK-NEXT: store %reflect.Value %46, ptr %40, align 8 +// CHECK-NEXT: %47 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %1, i64 3 +// CHECK-NEXT: %48 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %47, i32 0, i32 0 +// CHECK-NEXT: %49 = load { ptr, ptr }, ptr @main.V, align 8 +// CHECK-NEXT: %50 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 1) +// CHECK-NEXT: store i8 3, ptr %50, align 1 +// CHECK-NEXT: %51 = insertvalue %"{{.*}}/runtime/internal/runtime.eface" { ptr @_llgo_uint8, ptr undef }, ptr %50, 1 +// CHECK-NEXT: %52 = extractvalue { ptr, ptr } %49, 1 +// CHECK-NEXT: %53 = extractvalue { ptr, ptr } %49, 0 +// CHECK-NEXT: %__llgo_funcval_code6 = call ptr asm "", "=r,0"(ptr %53) +// CHECK-NEXT: %54 = call %reflect.Value %__llgo_funcval_code6(ptr {{(nest|swiftself)}} %52, %"{{.*}}/runtime/internal/runtime.eface" %51) +// CHECK-NEXT: %55 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %47, i32 0, i32 1 +// CHECK-NEXT: %56 = load { ptr, ptr }, ptr @main.V, align 8 +// CHECK-NEXT: %57 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 1) +// CHECK-NEXT: store i8 3, ptr %57, align 1 +// CHECK-NEXT: %58 = insertvalue %"{{.*}}/runtime/internal/runtime.eface" { ptr @_llgo_int8, ptr undef }, ptr %57, 1 +// CHECK-NEXT: %59 = extractvalue { ptr, ptr } %56, 1 +// CHECK-NEXT: %60 = extractvalue { ptr, ptr } %56, 0 +// CHECK-NEXT: %__llgo_funcval_code7 = call ptr asm "", "=r,0"(ptr %60) +// CHECK-NEXT: %61 = call %reflect.Value %__llgo_funcval_code7(ptr {{(nest|swiftself)}} %59, %"{{.*}}/runtime/internal/runtime.eface" %58) +// CHECK-NEXT: store %reflect.Value %54, ptr %48, align 8 +// CHECK-NEXT: store %reflect.Value %61, ptr %55, align 8 +// CHECK-NEXT: %62 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %1, i64 4 +// CHECK-NEXT: %63 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %62, i32 0, i32 0 +// CHECK-NEXT: %64 = load { ptr, ptr }, ptr @main.V, align 8 +// CHECK-NEXT: %65 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 1) +// CHECK-NEXT: store i8 4, ptr %65, align 1 +// CHECK-NEXT: %66 = insertvalue %"{{.*}}/runtime/internal/runtime.eface" { ptr @_llgo_int8, ptr undef }, ptr %65, 1 +// CHECK-NEXT: %67 = extractvalue { ptr, ptr } %64, 1 +// CHECK-NEXT: %68 = extractvalue { ptr, ptr } %64, 0 +// CHECK-NEXT: %__llgo_funcval_code8 = call ptr asm "", "=r,0"(ptr %68) +// CHECK-NEXT: %69 = call %reflect.Value %__llgo_funcval_code8(ptr {{(nest|swiftself)}} %67, %"{{.*}}/runtime/internal/runtime.eface" %66) +// CHECK-NEXT: %70 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %62, i32 0, i32 1 +// CHECK-NEXT: %71 = load { ptr, ptr }, ptr @main.V, align 8 +// CHECK-NEXT: %72 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 2) +// CHECK-NEXT: store i16 4, ptr %72, align 2 +// CHECK-NEXT: %73 = insertvalue %"{{.*}}/runtime/internal/runtime.eface" { ptr @_llgo_int16, ptr undef }, ptr %72, 1 +// CHECK-NEXT: %74 = extractvalue { ptr, ptr } %71, 1 +// CHECK-NEXT: %75 = extractvalue { ptr, ptr } %71, 0 +// CHECK-NEXT: %__llgo_funcval_code9 = call ptr asm "", "=r,0"(ptr %75) +// CHECK-NEXT: %76 = call %reflect.Value %__llgo_funcval_code9(ptr {{(nest|swiftself)}} %74, %"{{.*}}/runtime/internal/runtime.eface" %73) +// CHECK-NEXT: store %reflect.Value %69, ptr %63, align 8 +// CHECK-NEXT: store %reflect.Value %76, ptr %70, align 8 +// CHECK-NEXT: %77 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %1, i64 5 +// CHECK-NEXT: %78 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %77, i32 0, i32 0 +// CHECK-NEXT: %79 = load { ptr, ptr }, ptr @main.V, align 8 +// CHECK-NEXT: %80 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 2) +// CHECK-NEXT: store i16 5, ptr %80, align 2 +// CHECK-NEXT: %81 = insertvalue %"{{.*}}/runtime/internal/runtime.eface" { ptr @_llgo_int16, ptr undef }, ptr %80, 1 +// CHECK-NEXT: %82 = extractvalue { ptr, ptr } %79, 1 +// CHECK-NEXT: %83 = extractvalue { ptr, ptr } %79, 0 +// CHECK-NEXT: %__llgo_funcval_code10 = call ptr asm "", "=r,0"(ptr %83) +// CHECK-NEXT: %84 = call %reflect.Value %__llgo_funcval_code10(ptr {{(nest|swiftself)}} %82, %"{{.*}}/runtime/internal/runtime.eface" %81) +// CHECK-NEXT: %85 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %77, i32 0, i32 1 +// CHECK-NEXT: %86 = load { ptr, ptr }, ptr @main.V, align 8 +// CHECK-NEXT: %87 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 1) +// CHECK-NEXT: store i8 5, ptr %87, align 1 +// CHECK-NEXT: %88 = insertvalue %"{{.*}}/runtime/internal/runtime.eface" { ptr @_llgo_int8, ptr undef }, ptr %87, 1 +// CHECK-NEXT: %89 = extractvalue { ptr, ptr } %86, 1 +// CHECK-NEXT: %90 = extractvalue { ptr, ptr } %86, 0 +// CHECK-NEXT: %__llgo_funcval_code11 = call ptr asm "", "=r,0"(ptr %90) +// CHECK-NEXT: %91 = call %reflect.Value %__llgo_funcval_code11(ptr {{(nest|swiftself)}} %89, %"{{.*}}/runtime/internal/runtime.eface" %88) +// CHECK-NEXT: store %reflect.Value %84, ptr %78, align 8 +// CHECK-NEXT: store %reflect.Value %91, ptr %85, align 8 +// CHECK-NEXT: %92 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %1, i64 6 +// CHECK-NEXT: %93 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %92, i32 0, i32 0 +// CHECK-NEXT: %94 = load { ptr, ptr }, ptr @main.V, align 8 +// CHECK-NEXT: %95 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 1) +// CHECK-NEXT: store i8 6, ptr %95, align 1 +// CHECK-NEXT: %96 = insertvalue %"{{.*}}/runtime/internal/runtime.eface" { ptr @_llgo_int8, ptr undef }, ptr %95, 1 +// CHECK-NEXT: %97 = extractvalue { ptr, ptr } %94, 1 +// CHECK-NEXT: %98 = extractvalue { ptr, ptr } %94, 0 +// CHECK-NEXT: %__llgo_funcval_code12 = call ptr asm "", "=r,0"(ptr %98) +// CHECK-NEXT: %99 = call %reflect.Value %__llgo_funcval_code12(ptr {{(nest|swiftself)}} %97, %"{{.*}}/runtime/internal/runtime.eface" %96) +// CHECK-NEXT: %100 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %92, i32 0, i32 1 +// CHECK-NEXT: %101 = load { ptr, ptr }, ptr @main.V, align 8 +// CHECK-NEXT: %102 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 2) +// CHECK-NEXT: store i16 6, ptr %102, align 2 +// CHECK-NEXT: %103 = insertvalue %"{{.*}}/runtime/internal/runtime.eface" { ptr @_llgo_uint16, ptr undef }, ptr %102, 1 +// CHECK-NEXT: %104 = extractvalue { ptr, ptr } %101, 1 +// CHECK-NEXT: %105 = extractvalue { ptr, ptr } %101, 0 +// CHECK-NEXT: %__llgo_funcval_code13 = call ptr asm "", "=r,0"(ptr %105) +// CHECK-NEXT: %106 = call %reflect.Value %__llgo_funcval_code13(ptr {{(nest|swiftself)}} %104, %"{{.*}}/runtime/internal/runtime.eface" %103) +// CHECK-NEXT: store %reflect.Value %99, ptr %93, align 8 +// CHECK-NEXT: store %reflect.Value %106, ptr %100, align 8 +// CHECK-NEXT: %107 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %1, i64 7 +// CHECK-NEXT: %108 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %107, i32 0, i32 0 +// CHECK-NEXT: %109 = load { ptr, ptr }, ptr @main.V, align 8 +// CHECK-NEXT: %110 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 2) +// CHECK-NEXT: store i16 7, ptr %110, align 2 +// CHECK-NEXT: %111 = insertvalue %"{{.*}}/runtime/internal/runtime.eface" { ptr @_llgo_uint16, ptr undef }, ptr %110, 1 +// CHECK-NEXT: %112 = extractvalue { ptr, ptr } %109, 1 +// CHECK-NEXT: %113 = extractvalue { ptr, ptr } %109, 0 +// CHECK-NEXT: %__llgo_funcval_code14 = call ptr asm "", "=r,0"(ptr %113) +// CHECK-NEXT: %114 = call %reflect.Value %__llgo_funcval_code14(ptr {{(nest|swiftself)}} %112, %"{{.*}}/runtime/internal/runtime.eface" %111) +// CHECK-NEXT: %115 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %107, i32 0, i32 1 +// CHECK-NEXT: %116 = load { ptr, ptr }, ptr @main.V, align 8 +// CHECK-NEXT: %117 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 1) +// CHECK-NEXT: store i8 7, ptr %117, align 1 +// CHECK-NEXT: %118 = insertvalue %"{{.*}}/runtime/internal/runtime.eface" { ptr @_llgo_int8, ptr undef }, ptr %117, 1 +// CHECK-NEXT: %119 = extractvalue { ptr, ptr } %116, 1 +// CHECK-NEXT: %120 = extractvalue { ptr, ptr } %116, 0 +// CHECK-NEXT: %__llgo_funcval_code15 = call ptr asm "", "=r,0"(ptr %120) +// CHECK-NEXT: %121 = call %reflect.Value %__llgo_funcval_code15(ptr {{(nest|swiftself)}} %119, %"{{.*}}/runtime/internal/runtime.eface" %118) +// CHECK-NEXT: store %reflect.Value %114, ptr %108, align 8 +// CHECK-NEXT: store %reflect.Value %121, ptr %115, align 8 +// CHECK-NEXT: %122 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %1, i64 8 +// CHECK-NEXT: %123 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %122, i32 0, i32 0 +// CHECK-NEXT: %124 = load { ptr, ptr }, ptr @main.V, align 8 +// CHECK-NEXT: %125 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 1) +// CHECK-NEXT: store i8 8, ptr %125, align 1 +// CHECK-NEXT: %126 = insertvalue %"{{.*}}/runtime/internal/runtime.eface" { ptr @_llgo_int8, ptr undef }, ptr %125, 1 +// CHECK-NEXT: %127 = extractvalue { ptr, ptr } %124, 1 +// CHECK-NEXT: %128 = extractvalue { ptr, ptr } %124, 0 +// CHECK-NEXT: %__llgo_funcval_code16 = call ptr asm "", "=r,0"(ptr %128) +// CHECK-NEXT: %129 = call %reflect.Value %__llgo_funcval_code16(ptr {{(nest|swiftself)}} %127, %"{{.*}}/runtime/internal/runtime.eface" %126) +// CHECK-NEXT: %130 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %122, i32 0, i32 1 +// CHECK-NEXT: %131 = load { ptr, ptr }, ptr @main.V, align 8 +// CHECK-NEXT: %132 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 4) +// CHECK-NEXT: store i32 8, ptr %132, align 4 +// CHECK-NEXT: %133 = insertvalue %"{{.*}}/runtime/internal/runtime.eface" { ptr @_llgo_int32, ptr undef }, ptr %132, 1 +// CHECK-NEXT: %134 = extractvalue { ptr, ptr } %131, 1 +// CHECK-NEXT: %135 = extractvalue { ptr, ptr } %131, 0 +// CHECK-NEXT: %__llgo_funcval_code17 = call ptr asm "", "=r,0"(ptr %135) +// CHECK-NEXT: %136 = call %reflect.Value %__llgo_funcval_code17(ptr {{(nest|swiftself)}} %134, %"{{.*}}/runtime/internal/runtime.eface" %133) +// CHECK-NEXT: store %reflect.Value %129, ptr %123, align 8 +// CHECK-NEXT: store %reflect.Value %136, ptr %130, align 8 +// CHECK-NEXT: %137 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %1, i64 9 +// CHECK-NEXT: %138 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %137, i32 0, i32 0 +// CHECK-NEXT: %139 = load { ptr, ptr }, ptr @main.V, align 8 +// CHECK-NEXT: %140 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 4) +// CHECK-NEXT: store i32 9, ptr %140, align 4 +// CHECK-NEXT: %141 = insertvalue %"{{.*}}/runtime/internal/runtime.eface" { ptr @_llgo_int32, ptr undef }, ptr %140, 1 +// CHECK-NEXT: %142 = extractvalue { ptr, ptr } %139, 1 +// CHECK-NEXT: %143 = extractvalue { ptr, ptr } %139, 0 +// CHECK-NEXT: %__llgo_funcval_code18 = call ptr asm "", "=r,0"(ptr %143) +// CHECK-NEXT: %144 = call %reflect.Value %__llgo_funcval_code18(ptr {{(nest|swiftself)}} %142, %"{{.*}}/runtime/internal/runtime.eface" %141) +// CHECK-NEXT: %145 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %137, i32 0, i32 1 +// CHECK-NEXT: %146 = load { ptr, ptr }, ptr @main.V, align 8 +// CHECK-NEXT: %147 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 1) +// CHECK-NEXT: store i8 9, ptr %147, align 1 +// CHECK-NEXT: %148 = insertvalue %"{{.*}}/runtime/internal/runtime.eface" { ptr @_llgo_int8, ptr undef }, ptr %147, 1 +// CHECK-NEXT: %149 = extractvalue { ptr, ptr } %146, 1 +// CHECK-NEXT: %150 = extractvalue { ptr, ptr } %146, 0 +// CHECK-NEXT: %__llgo_funcval_code19 = call ptr asm "", "=r,0"(ptr %150) +// CHECK-NEXT: %151 = call %reflect.Value %__llgo_funcval_code19(ptr {{(nest|swiftself)}} %149, %"{{.*}}/runtime/internal/runtime.eface" %148) +// CHECK-NEXT: store %reflect.Value %144, ptr %138, align 8 +// CHECK-NEXT: store %reflect.Value %151, ptr %145, align 8 +// CHECK-NEXT: %152 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %1, i64 10 +// CHECK-NEXT: %153 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %152, i32 0, i32 0 +// CHECK-NEXT: %154 = load { ptr, ptr }, ptr @main.V, align 8 +// CHECK-NEXT: %155 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 1) +// CHECK-NEXT: store i8 10, ptr %155, align 1 +// CHECK-NEXT: %156 = insertvalue %"{{.*}}/runtime/internal/runtime.eface" { ptr @_llgo_int8, ptr undef }, ptr %155, 1 +// CHECK-NEXT: %157 = extractvalue { ptr, ptr } %154, 1 +// CHECK-NEXT: %158 = extractvalue { ptr, ptr } %154, 0 +// CHECK-NEXT: %__llgo_funcval_code20 = call ptr asm "", "=r,0"(ptr %158) +// CHECK-NEXT: %159 = call %reflect.Value %__llgo_funcval_code20(ptr {{(nest|swiftself)}} %157, %"{{.*}}/runtime/internal/runtime.eface" %156) +// CHECK-NEXT: %160 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %152, i32 0, i32 1 +// CHECK-NEXT: %161 = load { ptr, ptr }, ptr @main.V, align 8 +// CHECK-NEXT: %162 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 4) +// CHECK-NEXT: store i32 10, ptr %162, align 4 +// CHECK-NEXT: %163 = insertvalue %"{{.*}}/runtime/internal/runtime.eface" { ptr @_llgo_uint32, ptr undef }, ptr %162, 1 +// CHECK-NEXT: %164 = extractvalue { ptr, ptr } %161, 1 +// CHECK-NEXT: %165 = extractvalue { ptr, ptr } %161, 0 +// CHECK-NEXT: %__llgo_funcval_code21 = call ptr asm "", "=r,0"(ptr %165) +// CHECK-NEXT: %166 = call %reflect.Value %__llgo_funcval_code21(ptr {{(nest|swiftself)}} %164, %"{{.*}}/runtime/internal/runtime.eface" %163) +// CHECK-NEXT: store %reflect.Value %159, ptr %153, align 8 +// CHECK-NEXT: store %reflect.Value %166, ptr %160, align 8 +// CHECK-NEXT: %167 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %1, i64 11 +// CHECK-NEXT: %168 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %167, i32 0, i32 0 +// CHECK-NEXT: %169 = load { ptr, ptr }, ptr @main.V, align 8 +// CHECK-NEXT: %170 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 4) +// CHECK-NEXT: store i32 11, ptr %170, align 4 +// CHECK-NEXT: %171 = insertvalue %"{{.*}}/runtime/internal/runtime.eface" { ptr @_llgo_uint32, ptr undef }, ptr %170, 1 +// CHECK-NEXT: %172 = extractvalue { ptr, ptr } %169, 1 +// CHECK-NEXT: %173 = extractvalue { ptr, ptr } %169, 0 +// CHECK-NEXT: %__llgo_funcval_code22 = call ptr asm "", "=r,0"(ptr %173) +// CHECK-NEXT: %174 = call %reflect.Value %__llgo_funcval_code22(ptr {{(nest|swiftself)}} %172, %"{{.*}}/runtime/internal/runtime.eface" %171) +// CHECK-NEXT: %175 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %167, i32 0, i32 1 +// CHECK-NEXT: %176 = load { ptr, ptr }, ptr @main.V, align 8 +// CHECK-NEXT: %177 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 1) +// CHECK-NEXT: store i8 11, ptr %177, align 1 +// CHECK-NEXT: %178 = insertvalue %"{{.*}}/runtime/internal/runtime.eface" { ptr @_llgo_int8, ptr undef }, ptr %177, 1 +// CHECK-NEXT: %179 = extractvalue { ptr, ptr } %176, 1 +// CHECK-NEXT: %180 = extractvalue { ptr, ptr } %176, 0 +// CHECK-NEXT: %__llgo_funcval_code23 = call ptr asm "", "=r,0"(ptr %180) +// CHECK-NEXT: %181 = call %reflect.Value %__llgo_funcval_code23(ptr {{(nest|swiftself)}} %179, %"{{.*}}/runtime/internal/runtime.eface" %178) +// CHECK-NEXT: store %reflect.Value %174, ptr %168, align 8 +// CHECK-NEXT: store %reflect.Value %181, ptr %175, align 8 +// CHECK-NEXT: %182 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %1, i64 12 +// CHECK-NEXT: %183 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %182, i32 0, i32 0 +// CHECK-NEXT: %184 = load { ptr, ptr }, ptr @main.V, align 8 +// CHECK-NEXT: %185 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 1) +// CHECK-NEXT: store i8 12, ptr %185, align 1 +// CHECK-NEXT: %186 = insertvalue %"{{.*}}/runtime/internal/runtime.eface" { ptr @_llgo_int8, ptr undef }, ptr %185, 1 +// CHECK-NEXT: %187 = extractvalue { ptr, ptr } %184, 1 +// CHECK-NEXT: %188 = extractvalue { ptr, ptr } %184, 0 +// CHECK-NEXT: %__llgo_funcval_code24 = call ptr asm "", "=r,0"(ptr %188) +// CHECK-NEXT: %189 = call %reflect.Value %__llgo_funcval_code24(ptr {{(nest|swiftself)}} %187, %"{{.*}}/runtime/internal/runtime.eface" %186) +// CHECK-NEXT: %190 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %182, i32 0, i32 1 +// CHECK-NEXT: %191 = load { ptr, ptr }, ptr @main.V, align 8 +// CHECK-NEXT: %192 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 8) +// CHECK-NEXT: store i64 12, ptr %192, align 8 +// CHECK-NEXT: %193 = insertvalue %"{{.*}}/runtime/internal/runtime.eface" { ptr @_llgo_int64, ptr undef }, ptr %192, 1 +// CHECK-NEXT: %194 = extractvalue { ptr, ptr } %191, 1 +// CHECK-NEXT: %195 = extractvalue { ptr, ptr } %191, 0 +// CHECK-NEXT: %__llgo_funcval_code25 = call ptr asm "", "=r,0"(ptr %195) +// CHECK-NEXT: %196 = call %reflect.Value %__llgo_funcval_code25(ptr {{(nest|swiftself)}} %194, %"{{.*}}/runtime/internal/runtime.eface" %193) +// CHECK-NEXT: store %reflect.Value %189, ptr %183, align 8 +// CHECK-NEXT: store %reflect.Value %196, ptr %190, align 8 +// CHECK-NEXT: %197 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %1, i64 13 +// CHECK-NEXT: %198 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %197, i32 0, i32 0 +// CHECK-NEXT: %199 = load { ptr, ptr }, ptr @main.V, align 8 +// CHECK-NEXT: %200 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 8) +// CHECK-NEXT: store i64 13, ptr %200, align 8 +// CHECK-NEXT: %201 = insertvalue %"{{.*}}/runtime/internal/runtime.eface" { ptr @_llgo_int64, ptr undef }, ptr %200, 1 +// CHECK-NEXT: %202 = extractvalue { ptr, ptr } %199, 1 +// CHECK-NEXT: %203 = extractvalue { ptr, ptr } %199, 0 +// CHECK-NEXT: %__llgo_funcval_code26 = call ptr asm "", "=r,0"(ptr %203) +// CHECK-NEXT: %204 = call %reflect.Value %__llgo_funcval_code26(ptr {{(nest|swiftself)}} %202, %"{{.*}}/runtime/internal/runtime.eface" %201) +// CHECK-NEXT: %205 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %197, i32 0, i32 1 +// CHECK-NEXT: %206 = load { ptr, ptr }, ptr @main.V, align 8 +// CHECK-NEXT: %207 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 1) +// CHECK-NEXT: store i8 13, ptr %207, align 1 +// CHECK-NEXT: %208 = insertvalue %"{{.*}}/runtime/internal/runtime.eface" { ptr @_llgo_int8, ptr undef }, ptr %207, 1 +// CHECK-NEXT: %209 = extractvalue { ptr, ptr } %206, 1 +// CHECK-NEXT: %210 = extractvalue { ptr, ptr } %206, 0 +// CHECK-NEXT: %__llgo_funcval_code27 = call ptr asm "", "=r,0"(ptr %210) +// CHECK-NEXT: %211 = call %reflect.Value %__llgo_funcval_code27(ptr {{(nest|swiftself)}} %209, %"{{.*}}/runtime/internal/runtime.eface" %208) +// CHECK-NEXT: store %reflect.Value %204, ptr %198, align 8 +// CHECK-NEXT: store %reflect.Value %211, ptr %205, align 8 +// CHECK-NEXT: %212 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %1, i64 14 +// CHECK-NEXT: %213 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %212, i32 0, i32 0 +// CHECK-NEXT: %214 = load { ptr, ptr }, ptr @main.V, align 8 +// CHECK-NEXT: %215 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 1) +// CHECK-NEXT: store i8 14, ptr %215, align 1 +// CHECK-NEXT: %216 = insertvalue %"{{.*}}/runtime/internal/runtime.eface" { ptr @_llgo_int8, ptr undef }, ptr %215, 1 +// CHECK-NEXT: %217 = extractvalue { ptr, ptr } %214, 1 +// CHECK-NEXT: %218 = extractvalue { ptr, ptr } %214, 0 +// CHECK-NEXT: %__llgo_funcval_code28 = call ptr asm "", "=r,0"(ptr %218) +// CHECK-NEXT: %219 = call %reflect.Value %__llgo_funcval_code28(ptr {{(nest|swiftself)}} %217, %"{{.*}}/runtime/internal/runtime.eface" %216) +// CHECK-NEXT: %220 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %212, i32 0, i32 1 +// CHECK-NEXT: %221 = load { ptr, ptr }, ptr @main.V, align 8 +// CHECK-NEXT: %222 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 8) +// CHECK-NEXT: store i64 14, ptr %222, align 8 +// CHECK-NEXT: %223 = insertvalue %"{{.*}}/runtime/internal/runtime.eface" { ptr @_llgo_uint64, ptr undef }, ptr %222, 1 +// CHECK-NEXT: %224 = extractvalue { ptr, ptr } %221, 1 +// CHECK-NEXT: %225 = extractvalue { ptr, ptr } %221, 0 +// CHECK-NEXT: %__llgo_funcval_code29 = call ptr asm "", "=r,0"(ptr %225) +// CHECK-NEXT: %226 = call %reflect.Value %__llgo_funcval_code29(ptr {{(nest|swiftself)}} %224, %"{{.*}}/runtime/internal/runtime.eface" %223) +// CHECK-NEXT: store %reflect.Value %219, ptr %213, align 8 +// CHECK-NEXT: store %reflect.Value %226, ptr %220, align 8 +// CHECK-NEXT: %227 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %1, i64 15 +// CHECK-NEXT: %228 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %227, i32 0, i32 0 +// CHECK-NEXT: %229 = load { ptr, ptr }, ptr @main.V, align 8 +// CHECK-NEXT: %230 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 8) +// CHECK-NEXT: store i64 15, ptr %230, align 8 +// CHECK-NEXT: %231 = insertvalue %"{{.*}}/runtime/internal/runtime.eface" { ptr @_llgo_uint64, ptr undef }, ptr %230, 1 +// CHECK-NEXT: %232 = extractvalue { ptr, ptr } %229, 1 +// CHECK-NEXT: %233 = extractvalue { ptr, ptr } %229, 0 +// CHECK-NEXT: %__llgo_funcval_code30 = call ptr asm "", "=r,0"(ptr %233) +// CHECK-NEXT: %234 = call %reflect.Value %__llgo_funcval_code30(ptr {{(nest|swiftself)}} %232, %"{{.*}}/runtime/internal/runtime.eface" %231) +// CHECK-NEXT: %235 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %227, i32 0, i32 1 +// CHECK-NEXT: %236 = load { ptr, ptr }, ptr @main.V, align 8 +// CHECK-NEXT: %237 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 1) +// CHECK-NEXT: store i8 15, ptr %237, align 1 +// CHECK-NEXT: %238 = insertvalue %"{{.*}}/runtime/internal/runtime.eface" { ptr @_llgo_int8, ptr undef }, ptr %237, 1 +// CHECK-NEXT: %239 = extractvalue { ptr, ptr } %236, 1 +// CHECK-NEXT: %240 = extractvalue { ptr, ptr } %236, 0 +// CHECK-NEXT: %__llgo_funcval_code31 = call ptr asm "", "=r,0"(ptr %240) +// CHECK-NEXT: %241 = call %reflect.Value %__llgo_funcval_code31(ptr {{(nest|swiftself)}} %239, %"{{.*}}/runtime/internal/runtime.eface" %238) +// CHECK-NEXT: store %reflect.Value %234, ptr %228, align 8 +// CHECK-NEXT: store %reflect.Value %241, ptr %235, align 8 +// CHECK-NEXT: %242 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %1, i64 16 +// CHECK-NEXT: %243 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %242, i32 0, i32 0 +// CHECK-NEXT: %244 = load { ptr, ptr }, ptr @main.V, align 8 +// CHECK-NEXT: %245 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 1) +// CHECK-NEXT: store i8 16, ptr %245, align 1 +// CHECK-NEXT: %246 = insertvalue %"{{.*}}/runtime/internal/runtime.eface" { ptr @_llgo_int8, ptr undef }, ptr %245, 1 +// CHECK-NEXT: %247 = extractvalue { ptr, ptr } %244, 1 +// CHECK-NEXT: %248 = extractvalue { ptr, ptr } %244, 0 +// CHECK-NEXT: %__llgo_funcval_code32 = call ptr asm "", "=r,0"(ptr %248) +// CHECK-NEXT: %249 = call %reflect.Value %__llgo_funcval_code32(ptr {{(nest|swiftself)}} %247, %"{{.*}}/runtime/internal/runtime.eface" %246) +// CHECK-NEXT: %250 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %242, i32 0, i32 1 +// CHECK-NEXT: %251 = load { ptr, ptr }, ptr @main.V, align 8 +// CHECK-NEXT: %252 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 8) +// CHECK-NEXT: store i64 16, ptr %252, align 8 +// CHECK-NEXT: %253 = insertvalue %"{{.*}}/runtime/internal/runtime.eface" { ptr @_llgo_int, ptr undef }, ptr %252, 1 +// CHECK-NEXT: %254 = extractvalue { ptr, ptr } %251, 1 +// CHECK-NEXT: %255 = extractvalue { ptr, ptr } %251, 0 +// CHECK-NEXT: %__llgo_funcval_code33 = call ptr asm "", "=r,0"(ptr %255) +// CHECK-NEXT: %256 = call %reflect.Value %__llgo_funcval_code33(ptr {{(nest|swiftself)}} %254, %"{{.*}}/runtime/internal/runtime.eface" %253) +// CHECK-NEXT: store %reflect.Value %249, ptr %243, align 8 +// CHECK-NEXT: store %reflect.Value %256, ptr %250, align 8 +// CHECK-NEXT: %257 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %1, i64 17 +// CHECK-NEXT: %258 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %257, i32 0, i32 0 +// CHECK-NEXT: %259 = load { ptr, ptr }, ptr @main.V, align 8 +// CHECK-NEXT: %260 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 8) +// CHECK-NEXT: store i64 17, ptr %260, align 8 +// CHECK-NEXT: %261 = insertvalue %"{{.*}}/runtime/internal/runtime.eface" { ptr @_llgo_int, ptr undef }, ptr %260, 1 +// CHECK-NEXT: %262 = extractvalue { ptr, ptr } %259, 1 +// CHECK-NEXT: %263 = extractvalue { ptr, ptr } %259, 0 +// CHECK-NEXT: %__llgo_funcval_code34 = call ptr asm "", "=r,0"(ptr %263) +// CHECK-NEXT: %264 = call %reflect.Value %__llgo_funcval_code34(ptr {{(nest|swiftself)}} %262, %"{{.*}}/runtime/internal/runtime.eface" %261) +// CHECK-NEXT: %265 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %257, i32 0, i32 1 +// CHECK-NEXT: %266 = load { ptr, ptr }, ptr @main.V, align 8 +// CHECK-NEXT: %267 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 1) +// CHECK-NEXT: store i8 17, ptr %267, align 1 +// CHECK-NEXT: %268 = insertvalue %"{{.*}}/runtime/internal/runtime.eface" { ptr @_llgo_int8, ptr undef }, ptr %267, 1 +// CHECK-NEXT: %269 = extractvalue { ptr, ptr } %266, 1 +// CHECK-NEXT: %270 = extractvalue { ptr, ptr } %266, 0 +// CHECK-NEXT: %__llgo_funcval_code35 = call ptr asm "", "=r,0"(ptr %270) +// CHECK-NEXT: %271 = call %reflect.Value %__llgo_funcval_code35(ptr {{(nest|swiftself)}} %269, %"{{.*}}/runtime/internal/runtime.eface" %268) +// CHECK-NEXT: store %reflect.Value %264, ptr %258, align 8 +// CHECK-NEXT: store %reflect.Value %271, ptr %265, align 8 +// CHECK-NEXT: %272 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %1, i64 18 +// CHECK-NEXT: %273 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %272, i32 0, i32 0 +// CHECK-NEXT: %274 = load { ptr, ptr }, ptr @main.V, align 8 +// CHECK-NEXT: %275 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 1) +// CHECK-NEXT: store i8 18, ptr %275, align 1 +// CHECK-NEXT: %276 = insertvalue %"{{.*}}/runtime/internal/runtime.eface" { ptr @_llgo_int8, ptr undef }, ptr %275, 1 +// CHECK-NEXT: %277 = extractvalue { ptr, ptr } %274, 1 +// CHECK-NEXT: %278 = extractvalue { ptr, ptr } %274, 0 +// CHECK-NEXT: %__llgo_funcval_code36 = call ptr asm "", "=r,0"(ptr %278) +// CHECK-NEXT: %279 = call %reflect.Value %__llgo_funcval_code36(ptr {{(nest|swiftself)}} %277, %"{{.*}}/runtime/internal/runtime.eface" %276) +// CHECK-NEXT: %280 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %272, i32 0, i32 1 +// CHECK-NEXT: %281 = load { ptr, ptr }, ptr @main.V, align 8 +// CHECK-NEXT: %282 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 8) +// CHECK-NEXT: store i64 18, ptr %282, align 8 +// CHECK-NEXT: %283 = insertvalue %"{{.*}}/runtime/internal/runtime.eface" { ptr @_llgo_uint, ptr undef }, ptr %282, 1 +// CHECK-NEXT: %284 = extractvalue { ptr, ptr } %281, 1 +// CHECK-NEXT: %285 = extractvalue { ptr, ptr } %281, 0 +// CHECK-NEXT: %__llgo_funcval_code37 = call ptr asm "", "=r,0"(ptr %285) +// CHECK-NEXT: %286 = call %reflect.Value %__llgo_funcval_code37(ptr {{(nest|swiftself)}} %284, %"{{.*}}/runtime/internal/runtime.eface" %283) +// CHECK-NEXT: store %reflect.Value %279, ptr %273, align 8 +// CHECK-NEXT: store %reflect.Value %286, ptr %280, align 8 +// CHECK-NEXT: %287 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %1, i64 19 +// CHECK-NEXT: %288 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %287, i32 0, i32 0 +// CHECK-NEXT: %289 = load { ptr, ptr }, ptr @main.V, align 8 +// CHECK-NEXT: %290 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 8) +// CHECK-NEXT: store i64 19, ptr %290, align 8 +// CHECK-NEXT: %291 = insertvalue %"{{.*}}/runtime/internal/runtime.eface" { ptr @_llgo_uint, ptr undef }, ptr %290, 1 +// CHECK-NEXT: %292 = extractvalue { ptr, ptr } %289, 1 +// CHECK-NEXT: %293 = extractvalue { ptr, ptr } %289, 0 +// CHECK-NEXT: %__llgo_funcval_code38 = call ptr asm "", "=r,0"(ptr %293) +// CHECK-NEXT: %294 = call %reflect.Value %__llgo_funcval_code38(ptr {{(nest|swiftself)}} %292, %"{{.*}}/runtime/internal/runtime.eface" %291) +// CHECK-NEXT: %295 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %287, i32 0, i32 1 +// CHECK-NEXT: %296 = load { ptr, ptr }, ptr @main.V, align 8 +// CHECK-NEXT: %297 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 1) +// CHECK-NEXT: store i8 19, ptr %297, align 1 +// CHECK-NEXT: %298 = insertvalue %"{{.*}}/runtime/internal/runtime.eface" { ptr @_llgo_int8, ptr undef }, ptr %297, 1 +// CHECK-NEXT: %299 = extractvalue { ptr, ptr } %296, 1 +// CHECK-NEXT: %300 = extractvalue { ptr, ptr } %296, 0 +// CHECK-NEXT: %__llgo_funcval_code39 = call ptr asm "", "=r,0"(ptr %300) +// CHECK-NEXT: %301 = call %reflect.Value %__llgo_funcval_code39(ptr {{(nest|swiftself)}} %299, %"{{.*}}/runtime/internal/runtime.eface" %298) +// CHECK-NEXT: store %reflect.Value %294, ptr %288, align 8 +// CHECK-NEXT: store %reflect.Value %301, ptr %295, align 8 +// CHECK-NEXT: %302 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %1, i64 20 +// CHECK-NEXT: %303 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %302, i32 0, i32 0 +// CHECK-NEXT: %304 = load { ptr, ptr }, ptr @main.V, align 8 +// CHECK-NEXT: %305 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 1) +// CHECK-NEXT: store i8 20, ptr %305, align 1 +// CHECK-NEXT: %306 = insertvalue %"{{.*}}/runtime/internal/runtime.eface" { ptr @_llgo_int8, ptr undef }, ptr %305, 1 +// CHECK-NEXT: %307 = extractvalue { ptr, ptr } %304, 1 +// CHECK-NEXT: %308 = extractvalue { ptr, ptr } %304, 0 +// CHECK-NEXT: %__llgo_funcval_code40 = call ptr asm "", "=r,0"(ptr %308) +// CHECK-NEXT: %309 = call %reflect.Value %__llgo_funcval_code40(ptr {{(nest|swiftself)}} %307, %"{{.*}}/runtime/internal/runtime.eface" %306) +// CHECK-NEXT: %310 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %302, i32 0, i32 1 +// CHECK-NEXT: %311 = load { ptr, ptr }, ptr @main.V, align 8 +// CHECK-NEXT: %312 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 8) +// CHECK-NEXT: store i64 20, ptr %312, align 8 +// CHECK-NEXT: %313 = insertvalue %"{{.*}}/runtime/internal/runtime.eface" { ptr @_llgo_uintptr, ptr undef }, ptr %312, 1 +// CHECK-NEXT: %314 = extractvalue { ptr, ptr } %311, 1 +// CHECK-NEXT: %315 = extractvalue { ptr, ptr } %311, 0 +// CHECK-NEXT: %__llgo_funcval_code41 = call ptr asm "", "=r,0"(ptr %315) +// CHECK-NEXT: %316 = call %reflect.Value %__llgo_funcval_code41(ptr {{(nest|swiftself)}} %314, %"{{.*}}/runtime/internal/runtime.eface" %313) +// CHECK-NEXT: store %reflect.Value %309, ptr %303, align 8 +// CHECK-NEXT: store %reflect.Value %316, ptr %310, align 8 +// CHECK-NEXT: %317 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %1, i64 21 +// CHECK-NEXT: %318 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %317, i32 0, i32 0 +// CHECK-NEXT: %319 = load { ptr, ptr }, ptr @main.V, align 8 +// CHECK-NEXT: %320 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 8) +// CHECK-NEXT: store i64 21, ptr %320, align 8 +// CHECK-NEXT: %321 = insertvalue %"{{.*}}/runtime/internal/runtime.eface" { ptr @_llgo_uintptr, ptr undef }, ptr %320, 1 +// CHECK-NEXT: %322 = extractvalue { ptr, ptr } %319, 1 +// CHECK-NEXT: %323 = extractvalue { ptr, ptr } %319, 0 +// CHECK-NEXT: %__llgo_funcval_code42 = call ptr asm "", "=r,0"(ptr %323) +// CHECK-NEXT: %324 = call %reflect.Value %__llgo_funcval_code42(ptr {{(nest|swiftself)}} %322, %"{{.*}}/runtime/internal/runtime.eface" %321) +// CHECK-NEXT: %325 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %317, i32 0, i32 1 +// CHECK-NEXT: %326 = load { ptr, ptr }, ptr @main.V, align 8 +// CHECK-NEXT: %327 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 1) +// CHECK-NEXT: store i8 21, ptr %327, align 1 +// CHECK-NEXT: %328 = insertvalue %"{{.*}}/runtime/internal/runtime.eface" { ptr @_llgo_int8, ptr undef }, ptr %327, 1 +// CHECK-NEXT: %329 = extractvalue { ptr, ptr } %326, 1 +// CHECK-NEXT: %330 = extractvalue { ptr, ptr } %326, 0 +// CHECK-NEXT: %__llgo_funcval_code43 = call ptr asm "", "=r,0"(ptr %330) +// CHECK-NEXT: %331 = call %reflect.Value %__llgo_funcval_code43(ptr {{(nest|swiftself)}} %329, %"{{.*}}/runtime/internal/runtime.eface" %328) +// CHECK-NEXT: store %reflect.Value %324, ptr %318, align 8 +// CHECK-NEXT: store %reflect.Value %331, ptr %325, align 8 +// CHECK-NEXT: %332 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %1, i64 22 +// CHECK-NEXT: %333 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %332, i32 0, i32 0 +// CHECK-NEXT: %334 = load { ptr, ptr }, ptr @main.V, align 8 +// CHECK-NEXT: %335 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 1) +// CHECK-NEXT: store i8 22, ptr %335, align 1 +// CHECK-NEXT: %336 = insertvalue %"{{.*}}/runtime/internal/runtime.eface" { ptr @_llgo_int8, ptr undef }, ptr %335, 1 +// CHECK-NEXT: %337 = extractvalue { ptr, ptr } %334, 1 +// CHECK-NEXT: %338 = extractvalue { ptr, ptr } %334, 0 +// CHECK-NEXT: %__llgo_funcval_code44 = call ptr asm "", "=r,0"(ptr %338) +// CHECK-NEXT: %339 = call %reflect.Value %__llgo_funcval_code44(ptr {{(nest|swiftself)}} %337, %"{{.*}}/runtime/internal/runtime.eface" %336) +// CHECK-NEXT: %340 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %332, i32 0, i32 1 +// CHECK-NEXT: %341 = load { ptr, ptr }, ptr @main.V, align 8 +// CHECK-NEXT: %342 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 4) +// CHECK-NEXT: store float 2.200000e+01, ptr %342, align 4 +// CHECK-NEXT: %343 = insertvalue %"{{.*}}/runtime/internal/runtime.eface" { ptr @_llgo_float32, ptr undef }, ptr %342, 1 +// CHECK-NEXT: %344 = extractvalue { ptr, ptr } %341, 1 +// CHECK-NEXT: %345 = extractvalue { ptr, ptr } %341, 0 +// CHECK-NEXT: %__llgo_funcval_code45 = call ptr asm "", "=r,0"(ptr %345) +// CHECK-NEXT: %346 = call %reflect.Value %__llgo_funcval_code45(ptr {{(nest|swiftself)}} %344, %"{{.*}}/runtime/internal/runtime.eface" %343) +// CHECK-NEXT: store %reflect.Value %339, ptr %333, align 8 +// CHECK-NEXT: store %reflect.Value %346, ptr %340, align 8 +// CHECK-NEXT: %347 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %1, i64 23 +// CHECK-NEXT: %348 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %347, i32 0, i32 0 +// CHECK-NEXT: %349 = load { ptr, ptr }, ptr @main.V, align 8 +// CHECK-NEXT: %350 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 4) +// CHECK-NEXT: store float 2.300000e+01, ptr %350, align 4 +// CHECK-NEXT: %351 = insertvalue %"{{.*}}/runtime/internal/runtime.eface" { ptr @_llgo_float32, ptr undef }, ptr %350, 1 +// CHECK-NEXT: %352 = extractvalue { ptr, ptr } %349, 1 +// CHECK-NEXT: %353 = extractvalue { ptr, ptr } %349, 0 +// CHECK-NEXT: %__llgo_funcval_code46 = call ptr asm "", "=r,0"(ptr %353) +// CHECK-NEXT: %354 = call %reflect.Value %__llgo_funcval_code46(ptr {{(nest|swiftself)}} %352, %"{{.*}}/runtime/internal/runtime.eface" %351) +// CHECK-NEXT: %355 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %347, i32 0, i32 1 +// CHECK-NEXT: %356 = load { ptr, ptr }, ptr @main.V, align 8 +// CHECK-NEXT: %357 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 1) +// CHECK-NEXT: store i8 23, ptr %357, align 1 +// CHECK-NEXT: %358 = insertvalue %"{{.*}}/runtime/internal/runtime.eface" { ptr @_llgo_int8, ptr undef }, ptr %357, 1 +// CHECK-NEXT: %359 = extractvalue { ptr, ptr } %356, 1 +// CHECK-NEXT: %360 = extractvalue { ptr, ptr } %356, 0 +// CHECK-NEXT: %__llgo_funcval_code47 = call ptr asm "", "=r,0"(ptr %360) +// CHECK-NEXT: %361 = call %reflect.Value %__llgo_funcval_code47(ptr {{(nest|swiftself)}} %359, %"{{.*}}/runtime/internal/runtime.eface" %358) +// CHECK-NEXT: store %reflect.Value %354, ptr %348, align 8 +// CHECK-NEXT: store %reflect.Value %361, ptr %355, align 8 +// CHECK-NEXT: %362 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %1, i64 24 +// CHECK-NEXT: %363 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %362, i32 0, i32 0 +// CHECK-NEXT: %364 = load { ptr, ptr }, ptr @main.V, align 8 +// CHECK-NEXT: %365 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 1) +// CHECK-NEXT: store i8 24, ptr %365, align 1 +// CHECK-NEXT: %366 = insertvalue %"{{.*}}/runtime/internal/runtime.eface" { ptr @_llgo_int8, ptr undef }, ptr %365, 1 +// CHECK-NEXT: %367 = extractvalue { ptr, ptr } %364, 1 +// CHECK-NEXT: %368 = extractvalue { ptr, ptr } %364, 0 +// CHECK-NEXT: %__llgo_funcval_code48 = call ptr asm "", "=r,0"(ptr %368) +// CHECK-NEXT: %369 = call %reflect.Value %__llgo_funcval_code48(ptr {{(nest|swiftself)}} %367, %"{{.*}}/runtime/internal/runtime.eface" %366) +// CHECK-NEXT: %370 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %362, i32 0, i32 1 +// CHECK-NEXT: %371 = load { ptr, ptr }, ptr @main.V, align 8 +// CHECK-NEXT: %372 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 8) +// CHECK-NEXT: store double 2.400000e+01, ptr %372, align 8 +// CHECK-NEXT: %373 = insertvalue %"{{.*}}/runtime/internal/runtime.eface" { ptr @_llgo_float64, ptr undef }, ptr %372, 1 +// CHECK-NEXT: %374 = extractvalue { ptr, ptr } %371, 1 +// CHECK-NEXT: %375 = extractvalue { ptr, ptr } %371, 0 +// CHECK-NEXT: %__llgo_funcval_code49 = call ptr asm "", "=r,0"(ptr %375) +// CHECK-NEXT: %376 = call %reflect.Value %__llgo_funcval_code49(ptr {{(nest|swiftself)}} %374, %"{{.*}}/runtime/internal/runtime.eface" %373) +// CHECK-NEXT: store %reflect.Value %369, ptr %363, align 8 +// CHECK-NEXT: store %reflect.Value %376, ptr %370, align 8 +// CHECK-NEXT: %377 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %1, i64 25 +// CHECK-NEXT: %378 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %377, i32 0, i32 0 +// CHECK-NEXT: %379 = load { ptr, ptr }, ptr @main.V, align 8 +// CHECK-NEXT: %380 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 8) +// CHECK-NEXT: store double 2.500000e+01, ptr %380, align 8 +// CHECK-NEXT: %381 = insertvalue %"{{.*}}/runtime/internal/runtime.eface" { ptr @_llgo_float64, ptr undef }, ptr %380, 1 +// CHECK-NEXT: %382 = extractvalue { ptr, ptr } %379, 1 +// CHECK-NEXT: %383 = extractvalue { ptr, ptr } %379, 0 +// CHECK-NEXT: %__llgo_funcval_code50 = call ptr asm "", "=r,0"(ptr %383) +// CHECK-NEXT: %384 = call %reflect.Value %__llgo_funcval_code50(ptr {{(nest|swiftself)}} %382, %"{{.*}}/runtime/internal/runtime.eface" %381) +// CHECK-NEXT: %385 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %377, i32 0, i32 1 +// CHECK-NEXT: %386 = load { ptr, ptr }, ptr @main.V, align 8 +// CHECK-NEXT: %387 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 1) +// CHECK-NEXT: store i8 25, ptr %387, align 1 +// CHECK-NEXT: %388 = insertvalue %"{{.*}}/runtime/internal/runtime.eface" { ptr @_llgo_int8, ptr undef }, ptr %387, 1 +// CHECK-NEXT: %389 = extractvalue { ptr, ptr } %386, 1 +// CHECK-NEXT: %390 = extractvalue { ptr, ptr } %386, 0 +// CHECK-NEXT: %__llgo_funcval_code51 = call ptr asm "", "=r,0"(ptr %390) +// CHECK-NEXT: %391 = call %reflect.Value %__llgo_funcval_code51(ptr {{(nest|swiftself)}} %389, %"{{.*}}/runtime/internal/runtime.eface" %388) +// CHECK-NEXT: store %reflect.Value %384, ptr %378, align 8 +// CHECK-NEXT: store %reflect.Value %391, ptr %385, align 8 +// CHECK-NEXT: %392 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %1, i64 26 +// CHECK-NEXT: %393 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %392, i32 0, i32 0 +// CHECK-NEXT: %394 = load { ptr, ptr }, ptr @main.V, align 8 +// CHECK-NEXT: %395 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 1) +// CHECK-NEXT: store i8 26, ptr %395, align 1 +// CHECK-NEXT: %396 = insertvalue %"{{.*}}/runtime/internal/runtime.eface" { ptr @_llgo_uint8, ptr undef }, ptr %395, 1 +// CHECK-NEXT: %397 = extractvalue { ptr, ptr } %394, 1 +// CHECK-NEXT: %398 = extractvalue { ptr, ptr } %394, 0 +// CHECK-NEXT: %__llgo_funcval_code52 = call ptr asm "", "=r,0"(ptr %398) +// CHECK-NEXT: %399 = call %reflect.Value %__llgo_funcval_code52(ptr {{(nest|swiftself)}} %397, %"{{.*}}/runtime/internal/runtime.eface" %396) +// CHECK-NEXT: %400 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %392, i32 0, i32 1 +// CHECK-NEXT: %401 = load { ptr, ptr }, ptr @main.V, align 8 +// CHECK-NEXT: %402 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 1) +// CHECK-NEXT: store i8 26, ptr %402, align 1 +// CHECK-NEXT: %403 = insertvalue %"{{.*}}/runtime/internal/runtime.eface" { ptr @_llgo_uint8, ptr undef }, ptr %402, 1 +// CHECK-NEXT: %404 = extractvalue { ptr, ptr } %401, 1 +// CHECK-NEXT: %405 = extractvalue { ptr, ptr } %401, 0 +// CHECK-NEXT: %__llgo_funcval_code53 = call ptr asm "", "=r,0"(ptr %405) +// CHECK-NEXT: %406 = call %reflect.Value %__llgo_funcval_code53(ptr {{(nest|swiftself)}} %404, %"{{.*}}/runtime/internal/runtime.eface" %403) +// CHECK-NEXT: store %reflect.Value %399, ptr %393, align 8 +// CHECK-NEXT: store %reflect.Value %406, ptr %400, align 8 +// CHECK-NEXT: %407 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %1, i64 27 +// CHECK-NEXT: %408 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %407, i32 0, i32 0 +// CHECK-NEXT: %409 = load { ptr, ptr }, ptr @main.V, align 8 +// CHECK-NEXT: %410 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 1) +// CHECK-NEXT: store i8 27, ptr %410, align 1 +// CHECK-NEXT: %411 = insertvalue %"{{.*}}/runtime/internal/runtime.eface" { ptr @_llgo_uint8, ptr undef }, ptr %410, 1 +// CHECK-NEXT: %412 = extractvalue { ptr, ptr } %409, 1 +// CHECK-NEXT: %413 = extractvalue { ptr, ptr } %409, 0 +// CHECK-NEXT: %__llgo_funcval_code54 = call ptr asm "", "=r,0"(ptr %413) +// CHECK-NEXT: %414 = call %reflect.Value %__llgo_funcval_code54(ptr {{(nest|swiftself)}} %412, %"{{.*}}/runtime/internal/runtime.eface" %411) +// CHECK-NEXT: %415 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %407, i32 0, i32 1 +// CHECK-NEXT: %416 = load { ptr, ptr }, ptr @main.V, align 8 +// CHECK-NEXT: %417 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 2) +// CHECK-NEXT: store i16 27, ptr %417, align 2 +// CHECK-NEXT: %418 = insertvalue %"{{.*}}/runtime/internal/runtime.eface" { ptr @_llgo_int16, ptr undef }, ptr %417, 1 +// CHECK-NEXT: %419 = extractvalue { ptr, ptr } %416, 1 +// CHECK-NEXT: %420 = extractvalue { ptr, ptr } %416, 0 +// CHECK-NEXT: %__llgo_funcval_code55 = call ptr asm "", "=r,0"(ptr %420) +// CHECK-NEXT: %421 = call %reflect.Value %__llgo_funcval_code55(ptr {{(nest|swiftself)}} %419, %"{{.*}}/runtime/internal/runtime.eface" %418) +// CHECK-NEXT: store %reflect.Value %414, ptr %408, align 8 +// CHECK-NEXT: store %reflect.Value %421, ptr %415, align 8 +// CHECK-NEXT: %422 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %1, i64 28 +// CHECK-NEXT: %423 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %422, i32 0, i32 0 +// CHECK-NEXT: %424 = load { ptr, ptr }, ptr @main.V, align 8 +// CHECK-NEXT: %425 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 2) +// CHECK-NEXT: store i16 28, ptr %425, align 2 +// CHECK-NEXT: %426 = insertvalue %"{{.*}}/runtime/internal/runtime.eface" { ptr @_llgo_int16, ptr undef }, ptr %425, 1 +// CHECK-NEXT: %427 = extractvalue { ptr, ptr } %424, 1 +// CHECK-NEXT: %428 = extractvalue { ptr, ptr } %424, 0 +// CHECK-NEXT: %__llgo_funcval_code56 = call ptr asm "", "=r,0"(ptr %428) +// CHECK-NEXT: %429 = call %reflect.Value %__llgo_funcval_code56(ptr {{(nest|swiftself)}} %427, %"{{.*}}/runtime/internal/runtime.eface" %426) +// CHECK-NEXT: %430 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %422, i32 0, i32 1 +// CHECK-NEXT: %431 = load { ptr, ptr }, ptr @main.V, align 8 +// CHECK-NEXT: %432 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 1) +// CHECK-NEXT: store i8 28, ptr %432, align 1 +// CHECK-NEXT: %433 = insertvalue %"{{.*}}/runtime/internal/runtime.eface" { ptr @_llgo_uint8, ptr undef }, ptr %432, 1 +// CHECK-NEXT: %434 = extractvalue { ptr, ptr } %431, 1 +// CHECK-NEXT: %435 = extractvalue { ptr, ptr } %431, 0 +// CHECK-NEXT: %__llgo_funcval_code57 = call ptr asm "", "=r,0"(ptr %435) +// CHECK-NEXT: %436 = call %reflect.Value %__llgo_funcval_code57(ptr {{(nest|swiftself)}} %434, %"{{.*}}/runtime/internal/runtime.eface" %433) +// CHECK-NEXT: store %reflect.Value %429, ptr %423, align 8 +// CHECK-NEXT: store %reflect.Value %436, ptr %430, align 8 +// CHECK-NEXT: %437 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %1, i64 29 +// CHECK-NEXT: %438 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %437, i32 0, i32 0 +// CHECK-NEXT: %439 = load { ptr, ptr }, ptr @main.V, align 8 +// CHECK-NEXT: %440 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 1) +// CHECK-NEXT: store i8 29, ptr %440, align 1 +// CHECK-NEXT: %441 = insertvalue %"{{.*}}/runtime/internal/runtime.eface" { ptr @_llgo_uint8, ptr undef }, ptr %440, 1 +// CHECK-NEXT: %442 = extractvalue { ptr, ptr } %439, 1 +// CHECK-NEXT: %443 = extractvalue { ptr, ptr } %439, 0 +// CHECK-NEXT: %__llgo_funcval_code58 = call ptr asm "", "=r,0"(ptr %443) +// CHECK-NEXT: %444 = call %reflect.Value %__llgo_funcval_code58(ptr {{(nest|swiftself)}} %442, %"{{.*}}/runtime/internal/runtime.eface" %441) +// CHECK-NEXT: %445 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %437, i32 0, i32 1 +// CHECK-NEXT: %446 = load { ptr, ptr }, ptr @main.V, align 8 +// CHECK-NEXT: %447 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 2) +// CHECK-NEXT: store i16 29, ptr %447, align 2 +// CHECK-NEXT: %448 = insertvalue %"{{.*}}/runtime/internal/runtime.eface" { ptr @_llgo_uint16, ptr undef }, ptr %447, 1 +// CHECK-NEXT: %449 = extractvalue { ptr, ptr } %446, 1 +// CHECK-NEXT: %450 = extractvalue { ptr, ptr } %446, 0 +// CHECK-NEXT: %__llgo_funcval_code59 = call ptr asm "", "=r,0"(ptr %450) +// CHECK-NEXT: %451 = call %reflect.Value %__llgo_funcval_code59(ptr {{(nest|swiftself)}} %449, %"{{.*}}/runtime/internal/runtime.eface" %448) +// CHECK-NEXT: store %reflect.Value %444, ptr %438, align 8 +// CHECK-NEXT: store %reflect.Value %451, ptr %445, align 8 +// CHECK-NEXT: %452 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %1, i64 30 +// CHECK-NEXT: %453 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %452, i32 0, i32 0 +// CHECK-NEXT: %454 = load { ptr, ptr }, ptr @main.V, align 8 +// CHECK-NEXT: %455 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 2) +// CHECK-NEXT: store i16 30, ptr %455, align 2 +// CHECK-NEXT: %456 = insertvalue %"{{.*}}/runtime/internal/runtime.eface" { ptr @_llgo_uint16, ptr undef }, ptr %455, 1 +// CHECK-NEXT: %457 = extractvalue { ptr, ptr } %454, 1 +// CHECK-NEXT: %458 = extractvalue { ptr, ptr } %454, 0 +// CHECK-NEXT: %__llgo_funcval_code60 = call ptr asm "", "=r,0"(ptr %458) +// CHECK-NEXT: %459 = call %reflect.Value %__llgo_funcval_code60(ptr {{(nest|swiftself)}} %457, %"{{.*}}/runtime/internal/runtime.eface" %456) +// CHECK-NEXT: %460 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %452, i32 0, i32 1 +// CHECK-NEXT: %461 = load { ptr, ptr }, ptr @main.V, align 8 +// CHECK-NEXT: %462 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 1) +// CHECK-NEXT: store i8 30, ptr %462, align 1 +// CHECK-NEXT: %463 = insertvalue %"{{.*}}/runtime/internal/runtime.eface" { ptr @_llgo_uint8, ptr undef }, ptr %462, 1 +// CHECK-NEXT: %464 = extractvalue { ptr, ptr } %461, 1 +// CHECK-NEXT: %465 = extractvalue { ptr, ptr } %461, 0 +// CHECK-NEXT: %__llgo_funcval_code61 = call ptr asm "", "=r,0"(ptr %465) +// CHECK-NEXT: %466 = call %reflect.Value %__llgo_funcval_code61(ptr {{(nest|swiftself)}} %464, %"{{.*}}/runtime/internal/runtime.eface" %463) +// CHECK-NEXT: store %reflect.Value %459, ptr %453, align 8 +// CHECK-NEXT: store %reflect.Value %466, ptr %460, align 8 +// CHECK-NEXT: %467 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %1, i64 31 +// CHECK-NEXT: %468 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %467, i32 0, i32 0 +// CHECK-NEXT: %469 = load { ptr, ptr }, ptr @main.V, align 8 +// CHECK-NEXT: %470 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 1) +// CHECK-NEXT: store i8 31, ptr %470, align 1 +// CHECK-NEXT: %471 = insertvalue %"{{.*}}/runtime/internal/runtime.eface" { ptr @_llgo_uint8, ptr undef }, ptr %470, 1 +// CHECK-NEXT: %472 = extractvalue { ptr, ptr } %469, 1 +// CHECK-NEXT: %473 = extractvalue { ptr, ptr } %469, 0 +// CHECK-NEXT: %__llgo_funcval_code62 = call ptr asm "", "=r,0"(ptr %473) +// CHECK-NEXT: %474 = call %reflect.Value %__llgo_funcval_code62(ptr {{(nest|swiftself)}} %472, %"{{.*}}/runtime/internal/runtime.eface" %471) +// CHECK-NEXT: %475 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %467, i32 0, i32 1 +// CHECK-NEXT: %476 = load { ptr, ptr }, ptr @main.V, align 8 +// CHECK-NEXT: %477 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 4) +// CHECK-NEXT: store i32 31, ptr %477, align 4 +// CHECK-NEXT: %478 = insertvalue %"{{.*}}/runtime/internal/runtime.eface" { ptr @_llgo_int32, ptr undef }, ptr %477, 1 +// CHECK-NEXT: %479 = extractvalue { ptr, ptr } %476, 1 +// CHECK-NEXT: %480 = extractvalue { ptr, ptr } %476, 0 +// CHECK-NEXT: %__llgo_funcval_code63 = call ptr asm "", "=r,0"(ptr %480) +// CHECK-NEXT: %481 = call %reflect.Value %__llgo_funcval_code63(ptr {{(nest|swiftself)}} %479, %"{{.*}}/runtime/internal/runtime.eface" %478) +// CHECK-NEXT: store %reflect.Value %474, ptr %468, align 8 +// CHECK-NEXT: store %reflect.Value %481, ptr %475, align 8 +// CHECK-NEXT: %482 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %1, i64 32 +// CHECK-NEXT: %483 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %482, i32 0, i32 0 +// CHECK-NEXT: %484 = load { ptr, ptr }, ptr @main.V, align 8 +// CHECK-NEXT: %485 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 4) +// CHECK-NEXT: store i32 32, ptr %485, align 4 +// CHECK-NEXT: %486 = insertvalue %"{{.*}}/runtime/internal/runtime.eface" { ptr @_llgo_int32, ptr undef }, ptr %485, 1 +// CHECK-NEXT: %487 = extractvalue { ptr, ptr } %484, 1 +// CHECK-NEXT: %488 = extractvalue { ptr, ptr } %484, 0 +// CHECK-NEXT: %__llgo_funcval_code64 = call ptr asm "", "=r,0"(ptr %488) +// CHECK-NEXT: %489 = call %reflect.Value %__llgo_funcval_code64(ptr {{(nest|swiftself)}} %487, %"{{.*}}/runtime/internal/runtime.eface" %486) +// CHECK-NEXT: %490 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %482, i32 0, i32 1 +// CHECK-NEXT: %491 = load { ptr, ptr }, ptr @main.V, align 8 +// CHECK-NEXT: %492 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 1) +// CHECK-NEXT: store i8 32, ptr %492, align 1 +// CHECK-NEXT: %493 = insertvalue %"{{.*}}/runtime/internal/runtime.eface" { ptr @_llgo_uint8, ptr undef }, ptr %492, 1 +// CHECK-NEXT: %494 = extractvalue { ptr, ptr } %491, 1 +// CHECK-NEXT: %495 = extractvalue { ptr, ptr } %491, 0 +// CHECK-NEXT: %__llgo_funcval_code65 = call ptr asm "", "=r,0"(ptr %495) +// CHECK-NEXT: %496 = call %reflect.Value %__llgo_funcval_code65(ptr {{(nest|swiftself)}} %494, %"{{.*}}/runtime/internal/runtime.eface" %493) +// CHECK-NEXT: store %reflect.Value %489, ptr %483, align 8 +// CHECK-NEXT: store %reflect.Value %496, ptr %490, align 8 +// CHECK-NEXT: %497 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %1, i64 33 +// CHECK-NEXT: %498 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %497, i32 0, i32 0 +// CHECK-NEXT: %499 = load { ptr, ptr }, ptr @main.V, align 8 +// CHECK-NEXT: %500 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 1) +// CHECK-NEXT: store i8 33, ptr %500, align 1 +// CHECK-NEXT: %501 = insertvalue %"{{.*}}/runtime/internal/runtime.eface" { ptr @_llgo_uint8, ptr undef }, ptr %500, 1 +// CHECK-NEXT: %502 = extractvalue { ptr, ptr } %499, 1 +// CHECK-NEXT: %503 = extractvalue { ptr, ptr } %499, 0 +// CHECK-NEXT: %__llgo_funcval_code66 = call ptr asm "", "=r,0"(ptr %503) +// CHECK-NEXT: %504 = call %reflect.Value %__llgo_funcval_code66(ptr {{(nest|swiftself)}} %502, %"{{.*}}/runtime/internal/runtime.eface" %501) +// CHECK-NEXT: %505 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %497, i32 0, i32 1 +// CHECK-NEXT: %506 = load { ptr, ptr }, ptr @main.V, align 8 +// CHECK-NEXT: %507 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 4) +// CHECK-NEXT: store i32 33, ptr %507, align 4 +// CHECK-NEXT: %508 = insertvalue %"{{.*}}/runtime/internal/runtime.eface" { ptr @_llgo_uint32, ptr undef }, ptr %507, 1 +// CHECK-NEXT: %509 = extractvalue { ptr, ptr } %506, 1 +// CHECK-NEXT: %510 = extractvalue { ptr, ptr } %506, 0 +// CHECK-NEXT: %__llgo_funcval_code67 = call ptr asm "", "=r,0"(ptr %510) +// CHECK-NEXT: %511 = call %reflect.Value %__llgo_funcval_code67(ptr {{(nest|swiftself)}} %509, %"{{.*}}/runtime/internal/runtime.eface" %508) +// CHECK-NEXT: store %reflect.Value %504, ptr %498, align 8 +// CHECK-NEXT: store %reflect.Value %511, ptr %505, align 8 +// CHECK-NEXT: %512 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %1, i64 34 +// CHECK-NEXT: %513 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %512, i32 0, i32 0 +// CHECK-NEXT: %514 = load { ptr, ptr }, ptr @main.V, align 8 +// CHECK-NEXT: %515 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 4) +// CHECK-NEXT: store i32 34, ptr %515, align 4 +// CHECK-NEXT: %516 = insertvalue %"{{.*}}/runtime/internal/runtime.eface" { ptr @_llgo_uint32, ptr undef }, ptr %515, 1 +// CHECK-NEXT: %517 = extractvalue { ptr, ptr } %514, 1 +// CHECK-NEXT: %518 = extractvalue { ptr, ptr } %514, 0 +// CHECK-NEXT: %__llgo_funcval_code68 = call ptr asm "", "=r,0"(ptr %518) +// CHECK-NEXT: %519 = call %reflect.Value %__llgo_funcval_code68(ptr {{(nest|swiftself)}} %517, %"{{.*}}/runtime/internal/runtime.eface" %516) +// CHECK-NEXT: %520 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %512, i32 0, i32 1 +// CHECK-NEXT: %521 = load { ptr, ptr }, ptr @main.V, align 8 +// CHECK-NEXT: %522 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 1) +// CHECK-NEXT: store i8 34, ptr %522, align 1 +// CHECK-NEXT: %523 = insertvalue %"{{.*}}/runtime/internal/runtime.eface" { ptr @_llgo_uint8, ptr undef }, ptr %522, 1 +// CHECK-NEXT: %524 = extractvalue { ptr, ptr } %521, 1 +// CHECK-NEXT: %525 = extractvalue { ptr, ptr } %521, 0 +// CHECK-NEXT: %__llgo_funcval_code69 = call ptr asm "", "=r,0"(ptr %525) +// CHECK-NEXT: %526 = call %reflect.Value %__llgo_funcval_code69(ptr {{(nest|swiftself)}} %524, %"{{.*}}/runtime/internal/runtime.eface" %523) +// CHECK-NEXT: store %reflect.Value %519, ptr %513, align 8 +// CHECK-NEXT: store %reflect.Value %526, ptr %520, align 8 +// CHECK-NEXT: %527 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %1, i64 35 +// CHECK-NEXT: %528 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %527, i32 0, i32 0 +// CHECK-NEXT: %529 = load { ptr, ptr }, ptr @main.V, align 8 +// CHECK-NEXT: %530 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 1) +// CHECK-NEXT: store i8 35, ptr %530, align 1 +// CHECK-NEXT: %531 = insertvalue %"{{.*}}/runtime/internal/runtime.eface" { ptr @_llgo_uint8, ptr undef }, ptr %530, 1 +// CHECK-NEXT: %532 = extractvalue { ptr, ptr } %529, 1 +// CHECK-NEXT: %533 = extractvalue { ptr, ptr } %529, 0 +// CHECK-NEXT: %__llgo_funcval_code70 = call ptr asm "", "=r,0"(ptr %533) +// CHECK-NEXT: %534 = call %reflect.Value %__llgo_funcval_code70(ptr {{(nest|swiftself)}} %532, %"{{.*}}/runtime/internal/runtime.eface" %531) +// CHECK-NEXT: %535 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %527, i32 0, i32 1 +// CHECK-NEXT: %536 = load { ptr, ptr }, ptr @main.V, align 8 +// CHECK-NEXT: %537 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 8) +// CHECK-NEXT: store i64 35, ptr %537, align 8 +// CHECK-NEXT: %538 = insertvalue %"{{.*}}/runtime/internal/runtime.eface" { ptr @_llgo_int64, ptr undef }, ptr %537, 1 +// CHECK-NEXT: %539 = extractvalue { ptr, ptr } %536, 1 +// CHECK-NEXT: %540 = extractvalue { ptr, ptr } %536, 0 +// CHECK-NEXT: %__llgo_funcval_code71 = call ptr asm "", "=r,0"(ptr %540) +// CHECK-NEXT: %541 = call %reflect.Value %__llgo_funcval_code71(ptr {{(nest|swiftself)}} %539, %"{{.*}}/runtime/internal/runtime.eface" %538) +// CHECK-NEXT: store %reflect.Value %534, ptr %528, align 8 +// CHECK-NEXT: store %reflect.Value %541, ptr %535, align 8 +// CHECK-NEXT: %542 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %1, i64 36 +// CHECK-NEXT: %543 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %542, i32 0, i32 0 +// CHECK-NEXT: %544 = load { ptr, ptr }, ptr @main.V, align 8 +// CHECK-NEXT: %545 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 8) +// CHECK-NEXT: store i64 36, ptr %545, align 8 +// CHECK-NEXT: %546 = insertvalue %"{{.*}}/runtime/internal/runtime.eface" { ptr @_llgo_int64, ptr undef }, ptr %545, 1 +// CHECK-NEXT: %547 = extractvalue { ptr, ptr } %544, 1 +// CHECK-NEXT: %548 = extractvalue { ptr, ptr } %544, 0 +// CHECK-NEXT: %__llgo_funcval_code72 = call ptr asm "", "=r,0"(ptr %548) +// CHECK-NEXT: %549 = call %reflect.Value %__llgo_funcval_code72(ptr {{(nest|swiftself)}} %547, %"{{.*}}/runtime/internal/runtime.eface" %546) +// CHECK-NEXT: %550 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %542, i32 0, i32 1 +// CHECK-NEXT: %551 = load { ptr, ptr }, ptr @main.V, align 8 +// CHECK-NEXT: %552 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 1) +// CHECK-NEXT: store i8 36, ptr %552, align 1 +// CHECK-NEXT: %553 = insertvalue %"{{.*}}/runtime/internal/runtime.eface" { ptr @_llgo_uint8, ptr undef }, ptr %552, 1 +// CHECK-NEXT: %554 = extractvalue { ptr, ptr } %551, 1 +// CHECK-NEXT: %555 = extractvalue { ptr, ptr } %551, 0 +// CHECK-NEXT: %__llgo_funcval_code73 = call ptr asm "", "=r,0"(ptr %555) +// CHECK-NEXT: %556 = call %reflect.Value %__llgo_funcval_code73(ptr {{(nest|swiftself)}} %554, %"{{.*}}/runtime/internal/runtime.eface" %553) +// CHECK-NEXT: store %reflect.Value %549, ptr %543, align 8 +// CHECK-NEXT: store %reflect.Value %556, ptr %550, align 8 +// CHECK-NEXT: %557 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %1, i64 37 +// CHECK-NEXT: %558 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %557, i32 0, i32 0 +// CHECK-NEXT: %559 = load { ptr, ptr }, ptr @main.V, align 8 +// CHECK-NEXT: %560 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 1) +// CHECK-NEXT: store i8 37, ptr %560, align 1 +// CHECK-NEXT: %561 = insertvalue %"{{.*}}/runtime/internal/runtime.eface" { ptr @_llgo_uint8, ptr undef }, ptr %560, 1 +// CHECK-NEXT: %562 = extractvalue { ptr, ptr } %559, 1 +// CHECK-NEXT: %563 = extractvalue { ptr, ptr } %559, 0 +// CHECK-NEXT: %__llgo_funcval_code74 = call ptr asm "", "=r,0"(ptr %563) +// CHECK-NEXT: %564 = call %reflect.Value %__llgo_funcval_code74(ptr {{(nest|swiftself)}} %562, %"{{.*}}/runtime/internal/runtime.eface" %561) +// CHECK-NEXT: %565 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %557, i32 0, i32 1 +// CHECK-NEXT: %566 = load { ptr, ptr }, ptr @main.V, align 8 +// CHECK-NEXT: %567 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 8) +// CHECK-NEXT: store i64 37, ptr %567, align 8 +// CHECK-NEXT: %568 = insertvalue %"{{.*}}/runtime/internal/runtime.eface" { ptr @_llgo_uint64, ptr undef }, ptr %567, 1 +// CHECK-NEXT: %569 = extractvalue { ptr, ptr } %566, 1 +// CHECK-NEXT: %570 = extractvalue { ptr, ptr } %566, 0 +// CHECK-NEXT: %__llgo_funcval_code75 = call ptr asm "", "=r,0"(ptr %570) +// CHECK-NEXT: %571 = call %reflect.Value %__llgo_funcval_code75(ptr {{(nest|swiftself)}} %569, %"{{.*}}/runtime/internal/runtime.eface" %568) +// CHECK-NEXT: store %reflect.Value %564, ptr %558, align 8 +// CHECK-NEXT: store %reflect.Value %571, ptr %565, align 8 +// CHECK-NEXT: %572 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %1, i64 38 +// CHECK-NEXT: %573 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %572, i32 0, i32 0 +// CHECK-NEXT: %574 = load { ptr, ptr }, ptr @main.V, align 8 +// CHECK-NEXT: %575 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 8) +// CHECK-NEXT: store i64 38, ptr %575, align 8 +// CHECK-NEXT: %576 = insertvalue %"{{.*}}/runtime/internal/runtime.eface" { ptr @_llgo_uint64, ptr undef }, ptr %575, 1 +// CHECK-NEXT: %577 = extractvalue { ptr, ptr } %574, 1 +// CHECK-NEXT: %578 = extractvalue { ptr, ptr } %574, 0 +// CHECK-NEXT: %__llgo_funcval_code76 = call ptr asm "", "=r,0"(ptr %578) +// CHECK-NEXT: %579 = call %reflect.Value %__llgo_funcval_code76(ptr {{(nest|swiftself)}} %577, %"{{.*}}/runtime/internal/runtime.eface" %576) +// CHECK-NEXT: %580 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %572, i32 0, i32 1 +// CHECK-NEXT: %581 = load { ptr, ptr }, ptr @main.V, align 8 +// CHECK-NEXT: %582 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 1) +// CHECK-NEXT: store i8 38, ptr %582, align 1 +// CHECK-NEXT: %583 = insertvalue %"{{.*}}/runtime/internal/runtime.eface" { ptr @_llgo_uint8, ptr undef }, ptr %582, 1 +// CHECK-NEXT: %584 = extractvalue { ptr, ptr } %581, 1 +// CHECK-NEXT: %585 = extractvalue { ptr, ptr } %581, 0 +// CHECK-NEXT: %__llgo_funcval_code77 = call ptr asm "", "=r,0"(ptr %585) +// CHECK-NEXT: %586 = call %reflect.Value %__llgo_funcval_code77(ptr {{(nest|swiftself)}} %584, %"{{.*}}/runtime/internal/runtime.eface" %583) +// CHECK-NEXT: store %reflect.Value %579, ptr %573, align 8 +// CHECK-NEXT: store %reflect.Value %586, ptr %580, align 8 +// CHECK-NEXT: %587 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %1, i64 39 +// CHECK-NEXT: %588 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %587, i32 0, i32 0 +// CHECK-NEXT: %589 = load { ptr, ptr }, ptr @main.V, align 8 +// CHECK-NEXT: %590 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 1) +// CHECK-NEXT: store i8 39, ptr %590, align 1 +// CHECK-NEXT: %591 = insertvalue %"{{.*}}/runtime/internal/runtime.eface" { ptr @_llgo_uint8, ptr undef }, ptr %590, 1 +// CHECK-NEXT: %592 = extractvalue { ptr, ptr } %589, 1 +// CHECK-NEXT: %593 = extractvalue { ptr, ptr } %589, 0 +// CHECK-NEXT: %__llgo_funcval_code78 = call ptr asm "", "=r,0"(ptr %593) +// CHECK-NEXT: %594 = call %reflect.Value %__llgo_funcval_code78(ptr {{(nest|swiftself)}} %592, %"{{.*}}/runtime/internal/runtime.eface" %591) +// CHECK-NEXT: %595 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %587, i32 0, i32 1 +// CHECK-NEXT: %596 = load { ptr, ptr }, ptr @main.V, align 8 +// CHECK-NEXT: %597 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 8) +// CHECK-NEXT: store i64 39, ptr %597, align 8 +// CHECK-NEXT: %598 = insertvalue %"{{.*}}/runtime/internal/runtime.eface" { ptr @_llgo_int, ptr undef }, ptr %597, 1 +// CHECK-NEXT: %599 = extractvalue { ptr, ptr } %596, 1 +// CHECK-NEXT: %600 = extractvalue { ptr, ptr } %596, 0 +// CHECK-NEXT: %__llgo_funcval_code79 = call ptr asm "", "=r,0"(ptr %600) +// CHECK-NEXT: %601 = call %reflect.Value %__llgo_funcval_code79(ptr {{(nest|swiftself)}} %599, %"{{.*}}/runtime/internal/runtime.eface" %598) +// CHECK-NEXT: store %reflect.Value %594, ptr %588, align 8 +// CHECK-NEXT: store %reflect.Value %601, ptr %595, align 8 +// CHECK-NEXT: %602 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %1, i64 40 +// CHECK-NEXT: %603 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %602, i32 0, i32 0 +// CHECK-NEXT: %604 = load { ptr, ptr }, ptr @main.V, align 8 +// CHECK-NEXT: %605 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 8) +// CHECK-NEXT: store i64 40, ptr %605, align 8 +// CHECK-NEXT: %606 = insertvalue %"{{.*}}/runtime/internal/runtime.eface" { ptr @_llgo_int, ptr undef }, ptr %605, 1 +// CHECK-NEXT: %607 = extractvalue { ptr, ptr } %604, 1 +// CHECK-NEXT: %608 = extractvalue { ptr, ptr } %604, 0 +// CHECK-NEXT: %__llgo_funcval_code80 = call ptr asm "", "=r,0"(ptr %608) +// CHECK-NEXT: %609 = call %reflect.Value %__llgo_funcval_code80(ptr {{(nest|swiftself)}} %607, %"{{.*}}/runtime/internal/runtime.eface" %606) +// CHECK-NEXT: %610 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %602, i32 0, i32 1 +// CHECK-NEXT: %611 = load { ptr, ptr }, ptr @main.V, align 8 +// CHECK-NEXT: %612 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 1) +// CHECK-NEXT: store i8 40, ptr %612, align 1 +// CHECK-NEXT: %613 = insertvalue %"{{.*}}/runtime/internal/runtime.eface" { ptr @_llgo_uint8, ptr undef }, ptr %612, 1 +// CHECK-NEXT: %614 = extractvalue { ptr, ptr } %611, 1 +// CHECK-NEXT: %615 = extractvalue { ptr, ptr } %611, 0 +// CHECK-NEXT: %__llgo_funcval_code81 = call ptr asm "", "=r,0"(ptr %615) +// CHECK-NEXT: %616 = call %reflect.Value %__llgo_funcval_code81(ptr {{(nest|swiftself)}} %614, %"{{.*}}/runtime/internal/runtime.eface" %613) +// CHECK-NEXT: store %reflect.Value %609, ptr %603, align 8 +// CHECK-NEXT: store %reflect.Value %616, ptr %610, align 8 +// CHECK-NEXT: %617 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %1, i64 41 +// CHECK-NEXT: %618 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %617, i32 0, i32 0 +// CHECK-NEXT: %619 = load { ptr, ptr }, ptr @main.V, align 8 +// CHECK-NEXT: %620 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 1) +// CHECK-NEXT: store i8 41, ptr %620, align 1 +// CHECK-NEXT: %621 = insertvalue %"{{.*}}/runtime/internal/runtime.eface" { ptr @_llgo_uint8, ptr undef }, ptr %620, 1 +// CHECK-NEXT: %622 = extractvalue { ptr, ptr } %619, 1 +// CHECK-NEXT: %623 = extractvalue { ptr, ptr } %619, 0 +// CHECK-NEXT: %__llgo_funcval_code82 = call ptr asm "", "=r,0"(ptr %623) +// CHECK-NEXT: %624 = call %reflect.Value %__llgo_funcval_code82(ptr {{(nest|swiftself)}} %622, %"{{.*}}/runtime/internal/runtime.eface" %621) +// CHECK-NEXT: %625 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %617, i32 0, i32 1 +// CHECK-NEXT: %626 = load { ptr, ptr }, ptr @main.V, align 8 +// CHECK-NEXT: %627 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 8) +// CHECK-NEXT: store i64 41, ptr %627, align 8 +// CHECK-NEXT: %628 = insertvalue %"{{.*}}/runtime/internal/runtime.eface" { ptr @_llgo_uint, ptr undef }, ptr %627, 1 +// CHECK-NEXT: %629 = extractvalue { ptr, ptr } %626, 1 +// CHECK-NEXT: %630 = extractvalue { ptr, ptr } %626, 0 +// CHECK-NEXT: %__llgo_funcval_code83 = call ptr asm "", "=r,0"(ptr %630) +// CHECK-NEXT: %631 = call %reflect.Value %__llgo_funcval_code83(ptr {{(nest|swiftself)}} %629, %"{{.*}}/runtime/internal/runtime.eface" %628) +// CHECK-NEXT: store %reflect.Value %624, ptr %618, align 8 +// CHECK-NEXT: store %reflect.Value %631, ptr %625, align 8 +// CHECK-NEXT: %632 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %1, i64 42 +// CHECK-NEXT: %633 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %632, i32 0, i32 0 +// CHECK-NEXT: %634 = load { ptr, ptr }, ptr @main.V, align 8 +// CHECK-NEXT: %635 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 8) +// CHECK-NEXT: store i64 42, ptr %635, align 8 +// CHECK-NEXT: %636 = insertvalue %"{{.*}}/runtime/internal/runtime.eface" { ptr @_llgo_uint, ptr undef }, ptr %635, 1 +// CHECK-NEXT: %637 = extractvalue { ptr, ptr } %634, 1 +// CHECK-NEXT: %638 = extractvalue { ptr, ptr } %634, 0 +// CHECK-NEXT: %__llgo_funcval_code84 = call ptr asm "", "=r,0"(ptr %638) +// CHECK-NEXT: %639 = call %reflect.Value %__llgo_funcval_code84(ptr {{(nest|swiftself)}} %637, %"{{.*}}/runtime/internal/runtime.eface" %636) +// CHECK-NEXT: %640 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %632, i32 0, i32 1 +// CHECK-NEXT: %641 = load { ptr, ptr }, ptr @main.V, align 8 +// CHECK-NEXT: %642 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 1) +// CHECK-NEXT: store i8 42, ptr %642, align 1 +// CHECK-NEXT: %643 = insertvalue %"{{.*}}/runtime/internal/runtime.eface" { ptr @_llgo_uint8, ptr undef }, ptr %642, 1 +// CHECK-NEXT: %644 = extractvalue { ptr, ptr } %641, 1 +// CHECK-NEXT: %645 = extractvalue { ptr, ptr } %641, 0 +// CHECK-NEXT: %__llgo_funcval_code85 = call ptr asm "", "=r,0"(ptr %645) +// CHECK-NEXT: %646 = call %reflect.Value %__llgo_funcval_code85(ptr {{(nest|swiftself)}} %644, %"{{.*}}/runtime/internal/runtime.eface" %643) +// CHECK-NEXT: store %reflect.Value %639, ptr %633, align 8 +// CHECK-NEXT: store %reflect.Value %646, ptr %640, align 8 +// CHECK-NEXT: %647 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %1, i64 43 +// CHECK-NEXT: %648 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %647, i32 0, i32 0 +// CHECK-NEXT: %649 = load { ptr, ptr }, ptr @main.V, align 8 +// CHECK-NEXT: %650 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 1) +// CHECK-NEXT: store i8 43, ptr %650, align 1 +// CHECK-NEXT: %651 = insertvalue %"{{.*}}/runtime/internal/runtime.eface" { ptr @_llgo_uint8, ptr undef }, ptr %650, 1 +// CHECK-NEXT: %652 = extractvalue { ptr, ptr } %649, 1 +// CHECK-NEXT: %653 = extractvalue { ptr, ptr } %649, 0 +// CHECK-NEXT: %__llgo_funcval_code86 = call ptr asm "", "=r,0"(ptr %653) +// CHECK-NEXT: %654 = call %reflect.Value %__llgo_funcval_code86(ptr {{(nest|swiftself)}} %652, %"{{.*}}/runtime/internal/runtime.eface" %651) +// CHECK-NEXT: %655 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %647, i32 0, i32 1 +// CHECK-NEXT: %656 = load { ptr, ptr }, ptr @main.V, align 8 +// CHECK-NEXT: %657 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 8) +// CHECK-NEXT: store i64 43, ptr %657, align 8 +// CHECK-NEXT: %658 = insertvalue %"{{.*}}/runtime/internal/runtime.eface" { ptr @_llgo_uintptr, ptr undef }, ptr %657, 1 +// CHECK-NEXT: %659 = extractvalue { ptr, ptr } %656, 1 +// CHECK-NEXT: %660 = extractvalue { ptr, ptr } %656, 0 +// CHECK-NEXT: %__llgo_funcval_code87 = call ptr asm "", "=r,0"(ptr %660) +// CHECK-NEXT: %661 = call %reflect.Value %__llgo_funcval_code87(ptr {{(nest|swiftself)}} %659, %"{{.*}}/runtime/internal/runtime.eface" %658) +// CHECK-NEXT: store %reflect.Value %654, ptr %648, align 8 +// CHECK-NEXT: store %reflect.Value %661, ptr %655, align 8 +// CHECK-NEXT: %662 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %1, i64 44 +// CHECK-NEXT: %663 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %662, i32 0, i32 0 +// CHECK-NEXT: %664 = load { ptr, ptr }, ptr @main.V, align 8 +// CHECK-NEXT: %665 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 8) +// CHECK-NEXT: store i64 44, ptr %665, align 8 +// CHECK-NEXT: %666 = insertvalue %"{{.*}}/runtime/internal/runtime.eface" { ptr @_llgo_uintptr, ptr undef }, ptr %665, 1 +// CHECK-NEXT: %667 = extractvalue { ptr, ptr } %664, 1 +// CHECK-NEXT: %668 = extractvalue { ptr, ptr } %664, 0 +// CHECK-NEXT: %__llgo_funcval_code88 = call ptr asm "", "=r,0"(ptr %668) +// CHECK-NEXT: %669 = call %reflect.Value %__llgo_funcval_code88(ptr {{(nest|swiftself)}} %667, %"{{.*}}/runtime/internal/runtime.eface" %666) +// CHECK-NEXT: %670 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %662, i32 0, i32 1 +// CHECK-NEXT: %671 = load { ptr, ptr }, ptr @main.V, align 8 +// CHECK-NEXT: %672 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 1) +// CHECK-NEXT: store i8 44, ptr %672, align 1 +// CHECK-NEXT: %673 = insertvalue %"{{.*}}/runtime/internal/runtime.eface" { ptr @_llgo_uint8, ptr undef }, ptr %672, 1 +// CHECK-NEXT: %674 = extractvalue { ptr, ptr } %671, 1 +// CHECK-NEXT: %675 = extractvalue { ptr, ptr } %671, 0 +// CHECK-NEXT: %__llgo_funcval_code89 = call ptr asm "", "=r,0"(ptr %675) +// CHECK-NEXT: %676 = call %reflect.Value %__llgo_funcval_code89(ptr {{(nest|swiftself)}} %674, %"{{.*}}/runtime/internal/runtime.eface" %673) +// CHECK-NEXT: store %reflect.Value %669, ptr %663, align 8 +// CHECK-NEXT: store %reflect.Value %676, ptr %670, align 8 +// CHECK-NEXT: %677 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %1, i64 45 +// CHECK-NEXT: %678 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %677, i32 0, i32 0 +// CHECK-NEXT: %679 = load { ptr, ptr }, ptr @main.V, align 8 +// CHECK-NEXT: %680 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 1) +// CHECK-NEXT: store i8 45, ptr %680, align 1 +// CHECK-NEXT: %681 = insertvalue %"{{.*}}/runtime/internal/runtime.eface" { ptr @_llgo_uint8, ptr undef }, ptr %680, 1 +// CHECK-NEXT: %682 = extractvalue { ptr, ptr } %679, 1 +// CHECK-NEXT: %683 = extractvalue { ptr, ptr } %679, 0 +// CHECK-NEXT: %__llgo_funcval_code90 = call ptr asm "", "=r,0"(ptr %683) +// CHECK-NEXT: %684 = call %reflect.Value %__llgo_funcval_code90(ptr {{(nest|swiftself)}} %682, %"{{.*}}/runtime/internal/runtime.eface" %681) +// CHECK-NEXT: %685 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %677, i32 0, i32 1 +// CHECK-NEXT: %686 = load { ptr, ptr }, ptr @main.V, align 8 +// CHECK-NEXT: %687 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 4) +// CHECK-NEXT: store float 4.500000e+01, ptr %687, align 4 +// CHECK-NEXT: %688 = insertvalue %"{{.*}}/runtime/internal/runtime.eface" { ptr @_llgo_float32, ptr undef }, ptr %687, 1 +// CHECK-NEXT: %689 = extractvalue { ptr, ptr } %686, 1 +// CHECK-NEXT: %690 = extractvalue { ptr, ptr } %686, 0 +// CHECK-NEXT: %__llgo_funcval_code91 = call ptr asm "", "=r,0"(ptr %690) +// CHECK-NEXT: %691 = call %reflect.Value %__llgo_funcval_code91(ptr {{(nest|swiftself)}} %689, %"{{.*}}/runtime/internal/runtime.eface" %688) +// CHECK-NEXT: store %reflect.Value %684, ptr %678, align 8 +// CHECK-NEXT: store %reflect.Value %691, ptr %685, align 8 +// CHECK-NEXT: %692 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %1, i64 46 +// CHECK-NEXT: %693 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %692, i32 0, i32 0 +// CHECK-NEXT: %694 = load { ptr, ptr }, ptr @main.V, align 8 +// CHECK-NEXT: %695 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 4) +// CHECK-NEXT: store float 4.600000e+01, ptr %695, align 4 +// CHECK-NEXT: %696 = insertvalue %"{{.*}}/runtime/internal/runtime.eface" { ptr @_llgo_float32, ptr undef }, ptr %695, 1 +// CHECK-NEXT: %697 = extractvalue { ptr, ptr } %694, 1 +// CHECK-NEXT: %698 = extractvalue { ptr, ptr } %694, 0 +// CHECK-NEXT: %__llgo_funcval_code92 = call ptr asm "", "=r,0"(ptr %698) +// CHECK-NEXT: %699 = call %reflect.Value %__llgo_funcval_code92(ptr {{(nest|swiftself)}} %697, %"{{.*}}/runtime/internal/runtime.eface" %696) +// CHECK-NEXT: %700 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %692, i32 0, i32 1 +// CHECK-NEXT: %701 = load { ptr, ptr }, ptr @main.V, align 8 +// CHECK-NEXT: %702 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 1) +// CHECK-NEXT: store i8 46, ptr %702, align 1 +// CHECK-NEXT: %703 = insertvalue %"{{.*}}/runtime/internal/runtime.eface" { ptr @_llgo_uint8, ptr undef }, ptr %702, 1 +// CHECK-NEXT: %704 = extractvalue { ptr, ptr } %701, 1 +// CHECK-NEXT: %705 = extractvalue { ptr, ptr } %701, 0 +// CHECK-NEXT: %__llgo_funcval_code93 = call ptr asm "", "=r,0"(ptr %705) +// CHECK-NEXT: %706 = call %reflect.Value %__llgo_funcval_code93(ptr {{(nest|swiftself)}} %704, %"{{.*}}/runtime/internal/runtime.eface" %703) +// CHECK-NEXT: store %reflect.Value %699, ptr %693, align 8 +// CHECK-NEXT: store %reflect.Value %706, ptr %700, align 8 +// CHECK-NEXT: %707 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %1, i64 47 +// CHECK-NEXT: %708 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %707, i32 0, i32 0 +// CHECK-NEXT: %709 = load { ptr, ptr }, ptr @main.V, align 8 +// CHECK-NEXT: %710 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 1) +// CHECK-NEXT: store i8 47, ptr %710, align 1 +// CHECK-NEXT: %711 = insertvalue %"{{.*}}/runtime/internal/runtime.eface" { ptr @_llgo_uint8, ptr undef }, ptr %710, 1 +// CHECK-NEXT: %712 = extractvalue { ptr, ptr } %709, 1 +// CHECK-NEXT: %713 = extractvalue { ptr, ptr } %709, 0 +// CHECK-NEXT: %__llgo_funcval_code94 = call ptr asm "", "=r,0"(ptr %713) +// CHECK-NEXT: %714 = call %reflect.Value %__llgo_funcval_code94(ptr {{(nest|swiftself)}} %712, %"{{.*}}/runtime/internal/runtime.eface" %711) +// CHECK-NEXT: %715 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %707, i32 0, i32 1 +// CHECK-NEXT: %716 = load { ptr, ptr }, ptr @main.V, align 8 +// CHECK-NEXT: %717 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 8) +// CHECK-NEXT: store double 4.700000e+01, ptr %717, align 8 +// CHECK-NEXT: %718 = insertvalue %"{{.*}}/runtime/internal/runtime.eface" { ptr @_llgo_float64, ptr undef }, ptr %717, 1 +// CHECK-NEXT: %719 = extractvalue { ptr, ptr } %716, 1 +// CHECK-NEXT: %720 = extractvalue { ptr, ptr } %716, 0 +// CHECK-NEXT: %__llgo_funcval_code95 = call ptr asm "", "=r,0"(ptr %720) +// CHECK-NEXT: %721 = call %reflect.Value %__llgo_funcval_code95(ptr {{(nest|swiftself)}} %719, %"{{.*}}/runtime/internal/runtime.eface" %718) +// CHECK-NEXT: store %reflect.Value %714, ptr %708, align 8 +// CHECK-NEXT: store %reflect.Value %721, ptr %715, align 8 +// CHECK-NEXT: %722 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %1, i64 48 +// CHECK-NEXT: %723 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %722, i32 0, i32 0 +// CHECK-NEXT: %724 = load { ptr, ptr }, ptr @main.V, align 8 +// CHECK-NEXT: %725 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 8) +// CHECK-NEXT: store double 4.800000e+01, ptr %725, align 8 +// CHECK-NEXT: %726 = insertvalue %"{{.*}}/runtime/internal/runtime.eface" { ptr @_llgo_float64, ptr undef }, ptr %725, 1 +// CHECK-NEXT: %727 = extractvalue { ptr, ptr } %724, 1 +// CHECK-NEXT: %728 = extractvalue { ptr, ptr } %724, 0 +// CHECK-NEXT: %__llgo_funcval_code96 = call ptr asm "", "=r,0"(ptr %728) +// CHECK-NEXT: %729 = call %reflect.Value %__llgo_funcval_code96(ptr {{(nest|swiftself)}} %727, %"{{.*}}/runtime/internal/runtime.eface" %726) +// CHECK-NEXT: %730 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %722, i32 0, i32 1 +// CHECK-NEXT: %731 = load { ptr, ptr }, ptr @main.V, align 8 +// CHECK-NEXT: %732 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 1) +// CHECK-NEXT: store i8 48, ptr %732, align 1 +// CHECK-NEXT: %733 = insertvalue %"{{.*}}/runtime/internal/runtime.eface" { ptr @_llgo_uint8, ptr undef }, ptr %732, 1 +// CHECK-NEXT: %734 = extractvalue { ptr, ptr } %731, 1 +// CHECK-NEXT: %735 = extractvalue { ptr, ptr } %731, 0 +// CHECK-NEXT: %__llgo_funcval_code97 = call ptr asm "", "=r,0"(ptr %735) +// CHECK-NEXT: %736 = call %reflect.Value %__llgo_funcval_code97(ptr {{(nest|swiftself)}} %734, %"{{.*}}/runtime/internal/runtime.eface" %733) +// CHECK-NEXT: store %reflect.Value %729, ptr %723, align 8 +// CHECK-NEXT: store %reflect.Value %736, ptr %730, align 8 +// CHECK-NEXT: %737 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %1, i64 49 +// CHECK-NEXT: %738 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %737, i32 0, i32 0 +// CHECK-NEXT: %739 = load { ptr, ptr }, ptr @main.V, align 8 +// CHECK-NEXT: %740 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 2) +// CHECK-NEXT: store i16 49, ptr %740, align 2 +// CHECK-NEXT: %741 = insertvalue %"{{.*}}/runtime/internal/runtime.eface" { ptr @_llgo_int16, ptr undef }, ptr %740, 1 +// CHECK-NEXT: %742 = extractvalue { ptr, ptr } %739, 1 +// CHECK-NEXT: %743 = extractvalue { ptr, ptr } %739, 0 +// CHECK-NEXT: %__llgo_funcval_code98 = call ptr asm "", "=r,0"(ptr %743) +// CHECK-NEXT: %744 = call %reflect.Value %__llgo_funcval_code98(ptr {{(nest|swiftself)}} %742, %"{{.*}}/runtime/internal/runtime.eface" %741) +// CHECK-NEXT: %745 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %737, i32 0, i32 1 +// CHECK-NEXT: %746 = load { ptr, ptr }, ptr @main.V, align 8 +// CHECK-NEXT: %747 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 2) +// CHECK-NEXT: store i16 49, ptr %747, align 2 +// CHECK-NEXT: %748 = insertvalue %"{{.*}}/runtime/internal/runtime.eface" { ptr @_llgo_int16, ptr undef }, ptr %747, 1 +// CHECK-NEXT: %749 = extractvalue { ptr, ptr } %746, 1 +// CHECK-NEXT: %750 = extractvalue { ptr, ptr } %746, 0 +// CHECK-NEXT: %__llgo_funcval_code99 = call ptr asm "", "=r,0"(ptr %750) +// CHECK-NEXT: %751 = call %reflect.Value %__llgo_funcval_code99(ptr {{(nest|swiftself)}} %749, %"{{.*}}/runtime/internal/runtime.eface" %748) +// CHECK-NEXT: store %reflect.Value %744, ptr %738, align 8 +// CHECK-NEXT: store %reflect.Value %751, ptr %745, align 8 +// CHECK-NEXT: %752 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %1, i64 50 +// CHECK-NEXT: %753 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %752, i32 0, i32 0 +// CHECK-NEXT: %754 = load { ptr, ptr }, ptr @main.V, align 8 +// CHECK-NEXT: %755 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 2) +// CHECK-NEXT: store i16 50, ptr %755, align 2 +// CHECK-NEXT: %756 = insertvalue %"{{.*}}/runtime/internal/runtime.eface" { ptr @_llgo_int16, ptr undef }, ptr %755, 1 +// CHECK-NEXT: %757 = extractvalue { ptr, ptr } %754, 1 +// CHECK-NEXT: %758 = extractvalue { ptr, ptr } %754, 0 +// CHECK-NEXT: %__llgo_funcval_code100 = call ptr asm "", "=r,0"(ptr %758) +// CHECK-NEXT: %759 = call %reflect.Value %__llgo_funcval_code100(ptr {{(nest|swiftself)}} %757, %"{{.*}}/runtime/internal/runtime.eface" %756) +// CHECK-NEXT: %760 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %752, i32 0, i32 1 +// CHECK-NEXT: %761 = load { ptr, ptr }, ptr @main.V, align 8 +// CHECK-NEXT: %762 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 2) +// CHECK-NEXT: store i16 50, ptr %762, align 2 +// CHECK-NEXT: %763 = insertvalue %"{{.*}}/runtime/internal/runtime.eface" { ptr @_llgo_uint16, ptr undef }, ptr %762, 1 +// CHECK-NEXT: %764 = extractvalue { ptr, ptr } %761, 1 +// CHECK-NEXT: %765 = extractvalue { ptr, ptr } %761, 0 +// CHECK-NEXT: %__llgo_funcval_code101 = call ptr asm "", "=r,0"(ptr %765) +// CHECK-NEXT: %766 = call %reflect.Value %__llgo_funcval_code101(ptr {{(nest|swiftself)}} %764, %"{{.*}}/runtime/internal/runtime.eface" %763) +// CHECK-NEXT: store %reflect.Value %759, ptr %753, align 8 +// CHECK-NEXT: store %reflect.Value %766, ptr %760, align 8 +// CHECK-NEXT: %767 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %1, i64 51 +// CHECK-NEXT: %768 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %767, i32 0, i32 0 +// CHECK-NEXT: %769 = load { ptr, ptr }, ptr @main.V, align 8 +// CHECK-NEXT: %770 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 2) +// CHECK-NEXT: store i16 51, ptr %770, align 2 +// CHECK-NEXT: %771 = insertvalue %"{{.*}}/runtime/internal/runtime.eface" { ptr @_llgo_uint16, ptr undef }, ptr %770, 1 +// CHECK-NEXT: %772 = extractvalue { ptr, ptr } %769, 1 +// CHECK-NEXT: %773 = extractvalue { ptr, ptr } %769, 0 +// CHECK-NEXT: %__llgo_funcval_code102 = call ptr asm "", "=r,0"(ptr %773) +// CHECK-NEXT: %774 = call %reflect.Value %__llgo_funcval_code102(ptr {{(nest|swiftself)}} %772, %"{{.*}}/runtime/internal/runtime.eface" %771) +// CHECK-NEXT: %775 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %767, i32 0, i32 1 +// CHECK-NEXT: %776 = load { ptr, ptr }, ptr @main.V, align 8 +// CHECK-NEXT: %777 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 2) +// CHECK-NEXT: store i16 51, ptr %777, align 2 +// CHECK-NEXT: %778 = insertvalue %"{{.*}}/runtime/internal/runtime.eface" { ptr @_llgo_int16, ptr undef }, ptr %777, 1 +// CHECK-NEXT: %779 = extractvalue { ptr, ptr } %776, 1 +// CHECK-NEXT: %780 = extractvalue { ptr, ptr } %776, 0 +// CHECK-NEXT: %__llgo_funcval_code103 = call ptr asm "", "=r,0"(ptr %780) +// CHECK-NEXT: %781 = call %reflect.Value %__llgo_funcval_code103(ptr {{(nest|swiftself)}} %779, %"{{.*}}/runtime/internal/runtime.eface" %778) +// CHECK-NEXT: store %reflect.Value %774, ptr %768, align 8 +// CHECK-NEXT: store %reflect.Value %781, ptr %775, align 8 +// CHECK-NEXT: %782 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %1, i64 52 +// CHECK-NEXT: %783 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %782, i32 0, i32 0 +// CHECK-NEXT: %784 = load { ptr, ptr }, ptr @main.V, align 8 +// CHECK-NEXT: %785 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 2) +// CHECK-NEXT: store i16 52, ptr %785, align 2 +// CHECK-NEXT: %786 = insertvalue %"{{.*}}/runtime/internal/runtime.eface" { ptr @_llgo_int16, ptr undef }, ptr %785, 1 +// CHECK-NEXT: %787 = extractvalue { ptr, ptr } %784, 1 +// CHECK-NEXT: %788 = extractvalue { ptr, ptr } %784, 0 +// CHECK-NEXT: %__llgo_funcval_code104 = call ptr asm "", "=r,0"(ptr %788) +// CHECK-NEXT: %789 = call %reflect.Value %__llgo_funcval_code104(ptr {{(nest|swiftself)}} %787, %"{{.*}}/runtime/internal/runtime.eface" %786) +// CHECK-NEXT: %790 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %782, i32 0, i32 1 +// CHECK-NEXT: %791 = load { ptr, ptr }, ptr @main.V, align 8 +// CHECK-NEXT: %792 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 4) +// CHECK-NEXT: store i32 52, ptr %792, align 4 +// CHECK-NEXT: %793 = insertvalue %"{{.*}}/runtime/internal/runtime.eface" { ptr @_llgo_int32, ptr undef }, ptr %792, 1 +// CHECK-NEXT: %794 = extractvalue { ptr, ptr } %791, 1 +// CHECK-NEXT: %795 = extractvalue { ptr, ptr } %791, 0 +// CHECK-NEXT: %__llgo_funcval_code105 = call ptr asm "", "=r,0"(ptr %795) +// CHECK-NEXT: %796 = call %reflect.Value %__llgo_funcval_code105(ptr {{(nest|swiftself)}} %794, %"{{.*}}/runtime/internal/runtime.eface" %793) +// CHECK-NEXT: store %reflect.Value %789, ptr %783, align 8 +// CHECK-NEXT: store %reflect.Value %796, ptr %790, align 8 +// CHECK-NEXT: %797 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %1, i64 53 +// CHECK-NEXT: %798 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %797, i32 0, i32 0 +// CHECK-NEXT: %799 = load { ptr, ptr }, ptr @main.V, align 8 +// CHECK-NEXT: %800 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 4) +// CHECK-NEXT: store i32 53, ptr %800, align 4 +// CHECK-NEXT: %801 = insertvalue %"{{.*}}/runtime/internal/runtime.eface" { ptr @_llgo_int32, ptr undef }, ptr %800, 1 +// CHECK-NEXT: %802 = extractvalue { ptr, ptr } %799, 1 +// CHECK-NEXT: %803 = extractvalue { ptr, ptr } %799, 0 +// CHECK-NEXT: %__llgo_funcval_code106 = call ptr asm "", "=r,0"(ptr %803) +// CHECK-NEXT: %804 = call %reflect.Value %__llgo_funcval_code106(ptr {{(nest|swiftself)}} %802, %"{{.*}}/runtime/internal/runtime.eface" %801) +// CHECK-NEXT: %805 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %797, i32 0, i32 1 +// CHECK-NEXT: %806 = load { ptr, ptr }, ptr @main.V, align 8 +// CHECK-NEXT: %807 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 2) +// CHECK-NEXT: store i16 53, ptr %807, align 2 +// CHECK-NEXT: %808 = insertvalue %"{{.*}}/runtime/internal/runtime.eface" { ptr @_llgo_int16, ptr undef }, ptr %807, 1 +// CHECK-NEXT: %809 = extractvalue { ptr, ptr } %806, 1 +// CHECK-NEXT: %810 = extractvalue { ptr, ptr } %806, 0 +// CHECK-NEXT: %__llgo_funcval_code107 = call ptr asm "", "=r,0"(ptr %810) +// CHECK-NEXT: %811 = call %reflect.Value %__llgo_funcval_code107(ptr {{(nest|swiftself)}} %809, %"{{.*}}/runtime/internal/runtime.eface" %808) +// CHECK-NEXT: store %reflect.Value %804, ptr %798, align 8 +// CHECK-NEXT: store %reflect.Value %811, ptr %805, align 8 +// CHECK-NEXT: %812 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %1, i64 54 +// CHECK-NEXT: %813 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %812, i32 0, i32 0 +// CHECK-NEXT: %814 = load { ptr, ptr }, ptr @main.V, align 8 +// CHECK-NEXT: %815 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 2) +// CHECK-NEXT: store i16 54, ptr %815, align 2 +// CHECK-NEXT: %816 = insertvalue %"{{.*}}/runtime/internal/runtime.eface" { ptr @_llgo_int16, ptr undef }, ptr %815, 1 +// CHECK-NEXT: %817 = extractvalue { ptr, ptr } %814, 1 +// CHECK-NEXT: %818 = extractvalue { ptr, ptr } %814, 0 +// CHECK-NEXT: %__llgo_funcval_code108 = call ptr asm "", "=r,0"(ptr %818) +// CHECK-NEXT: %819 = call %reflect.Value %__llgo_funcval_code108(ptr {{(nest|swiftself)}} %817, %"{{.*}}/runtime/internal/runtime.eface" %816) +// CHECK-NEXT: %820 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %812, i32 0, i32 1 +// CHECK-NEXT: %821 = load { ptr, ptr }, ptr @main.V, align 8 +// CHECK-NEXT: %822 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 4) +// CHECK-NEXT: store i32 54, ptr %822, align 4 +// CHECK-NEXT: %823 = insertvalue %"{{.*}}/runtime/internal/runtime.eface" { ptr @_llgo_uint32, ptr undef }, ptr %822, 1 +// CHECK-NEXT: %824 = extractvalue { ptr, ptr } %821, 1 +// CHECK-NEXT: %825 = extractvalue { ptr, ptr } %821, 0 +// CHECK-NEXT: %__llgo_funcval_code109 = call ptr asm "", "=r,0"(ptr %825) +// CHECK-NEXT: %826 = call %reflect.Value %__llgo_funcval_code109(ptr {{(nest|swiftself)}} %824, %"{{.*}}/runtime/internal/runtime.eface" %823) +// CHECK-NEXT: store %reflect.Value %819, ptr %813, align 8 +// CHECK-NEXT: store %reflect.Value %826, ptr %820, align 8 +// CHECK-NEXT: %827 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %1, i64 55 +// CHECK-NEXT: %828 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %827, i32 0, i32 0 +// CHECK-NEXT: %829 = load { ptr, ptr }, ptr @main.V, align 8 +// CHECK-NEXT: %830 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 4) +// CHECK-NEXT: store i32 55, ptr %830, align 4 +// CHECK-NEXT: %831 = insertvalue %"{{.*}}/runtime/internal/runtime.eface" { ptr @_llgo_uint32, ptr undef }, ptr %830, 1 +// CHECK-NEXT: %832 = extractvalue { ptr, ptr } %829, 1 +// CHECK-NEXT: %833 = extractvalue { ptr, ptr } %829, 0 +// CHECK-NEXT: %__llgo_funcval_code110 = call ptr asm "", "=r,0"(ptr %833) +// CHECK-NEXT: %834 = call %reflect.Value %__llgo_funcval_code110(ptr {{(nest|swiftself)}} %832, %"{{.*}}/runtime/internal/runtime.eface" %831) +// CHECK-NEXT: %835 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %827, i32 0, i32 1 +// CHECK-NEXT: %836 = load { ptr, ptr }, ptr @main.V, align 8 +// CHECK-NEXT: %837 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 2) +// CHECK-NEXT: store i16 55, ptr %837, align 2 +// CHECK-NEXT: %838 = insertvalue %"{{.*}}/runtime/internal/runtime.eface" { ptr @_llgo_int16, ptr undef }, ptr %837, 1 +// CHECK-NEXT: %839 = extractvalue { ptr, ptr } %836, 1 +// CHECK-NEXT: %840 = extractvalue { ptr, ptr } %836, 0 +// CHECK-NEXT: %__llgo_funcval_code111 = call ptr asm "", "=r,0"(ptr %840) +// CHECK-NEXT: %841 = call %reflect.Value %__llgo_funcval_code111(ptr {{(nest|swiftself)}} %839, %"{{.*}}/runtime/internal/runtime.eface" %838) +// CHECK-NEXT: store %reflect.Value %834, ptr %828, align 8 +// CHECK-NEXT: store %reflect.Value %841, ptr %835, align 8 +// CHECK-NEXT: %842 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %1, i64 56 +// CHECK-NEXT: %843 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %842, i32 0, i32 0 +// CHECK-NEXT: %844 = load { ptr, ptr }, ptr @main.V, align 8 +// CHECK-NEXT: %845 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 2) +// CHECK-NEXT: store i16 56, ptr %845, align 2 +// CHECK-NEXT: %846 = insertvalue %"{{.*}}/runtime/internal/runtime.eface" { ptr @_llgo_int16, ptr undef }, ptr %845, 1 +// CHECK-NEXT: %847 = extractvalue { ptr, ptr } %844, 1 +// CHECK-NEXT: %848 = extractvalue { ptr, ptr } %844, 0 +// CHECK-NEXT: %__llgo_funcval_code112 = call ptr asm "", "=r,0"(ptr %848) +// CHECK-NEXT: %849 = call %reflect.Value %__llgo_funcval_code112(ptr {{(nest|swiftself)}} %847, %"{{.*}}/runtime/internal/runtime.eface" %846) +// CHECK-NEXT: %850 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %842, i32 0, i32 1 +// CHECK-NEXT: %851 = load { ptr, ptr }, ptr @main.V, align 8 +// CHECK-NEXT: %852 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 8) +// CHECK-NEXT: store i64 56, ptr %852, align 8 +// CHECK-NEXT: %853 = insertvalue %"{{.*}}/runtime/internal/runtime.eface" { ptr @_llgo_int64, ptr undef }, ptr %852, 1 +// CHECK-NEXT: %854 = extractvalue { ptr, ptr } %851, 1 +// CHECK-NEXT: %855 = extractvalue { ptr, ptr } %851, 0 +// CHECK-NEXT: %__llgo_funcval_code113 = call ptr asm "", "=r,0"(ptr %855) +// CHECK-NEXT: %856 = call %reflect.Value %__llgo_funcval_code113(ptr {{(nest|swiftself)}} %854, %"{{.*}}/runtime/internal/runtime.eface" %853) +// CHECK-NEXT: store %reflect.Value %849, ptr %843, align 8 +// CHECK-NEXT: store %reflect.Value %856, ptr %850, align 8 +// CHECK-NEXT: %857 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %1, i64 57 +// CHECK-NEXT: %858 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %857, i32 0, i32 0 +// CHECK-NEXT: %859 = load { ptr, ptr }, ptr @main.V, align 8 +// CHECK-NEXT: %860 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 8) +// CHECK-NEXT: store i64 57, ptr %860, align 8 +// CHECK-NEXT: %861 = insertvalue %"{{.*}}/runtime/internal/runtime.eface" { ptr @_llgo_int64, ptr undef }, ptr %860, 1 +// CHECK-NEXT: %862 = extractvalue { ptr, ptr } %859, 1 +// CHECK-NEXT: %863 = extractvalue { ptr, ptr } %859, 0 +// CHECK-NEXT: %__llgo_funcval_code114 = call ptr asm "", "=r,0"(ptr %863) +// CHECK-NEXT: %864 = call %reflect.Value %__llgo_funcval_code114(ptr {{(nest|swiftself)}} %862, %"{{.*}}/runtime/internal/runtime.eface" %861) +// CHECK-NEXT: %865 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %857, i32 0, i32 1 +// CHECK-NEXT: %866 = load { ptr, ptr }, ptr @main.V, align 8 +// CHECK-NEXT: %867 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 2) +// CHECK-NEXT: store i16 57, ptr %867, align 2 +// CHECK-NEXT: %868 = insertvalue %"{{.*}}/runtime/internal/runtime.eface" { ptr @_llgo_int16, ptr undef }, ptr %867, 1 +// CHECK-NEXT: %869 = extractvalue { ptr, ptr } %866, 1 +// CHECK-NEXT: %870 = extractvalue { ptr, ptr } %866, 0 +// CHECK-NEXT: %__llgo_funcval_code115 = call ptr asm "", "=r,0"(ptr %870) +// CHECK-NEXT: %871 = call %reflect.Value %__llgo_funcval_code115(ptr {{(nest|swiftself)}} %869, %"{{.*}}/runtime/internal/runtime.eface" %868) +// CHECK-NEXT: store %reflect.Value %864, ptr %858, align 8 +// CHECK-NEXT: store %reflect.Value %871, ptr %865, align 8 +// CHECK-NEXT: %872 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %1, i64 58 +// CHECK-NEXT: %873 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %872, i32 0, i32 0 +// CHECK-NEXT: %874 = load { ptr, ptr }, ptr @main.V, align 8 +// CHECK-NEXT: %875 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 2) +// CHECK-NEXT: store i16 58, ptr %875, align 2 +// CHECK-NEXT: %876 = insertvalue %"{{.*}}/runtime/internal/runtime.eface" { ptr @_llgo_int16, ptr undef }, ptr %875, 1 +// CHECK-NEXT: %877 = extractvalue { ptr, ptr } %874, 1 +// CHECK-NEXT: %878 = extractvalue { ptr, ptr } %874, 0 +// CHECK-NEXT: %__llgo_funcval_code116 = call ptr asm "", "=r,0"(ptr %878) +// CHECK-NEXT: %879 = call %reflect.Value %__llgo_funcval_code116(ptr {{(nest|swiftself)}} %877, %"{{.*}}/runtime/internal/runtime.eface" %876) +// CHECK-NEXT: %880 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %872, i32 0, i32 1 +// CHECK-NEXT: %881 = load { ptr, ptr }, ptr @main.V, align 8 +// CHECK-NEXT: %882 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 8) +// CHECK-NEXT: store i64 58, ptr %882, align 8 +// CHECK-NEXT: %883 = insertvalue %"{{.*}}/runtime/internal/runtime.eface" { ptr @_llgo_uint64, ptr undef }, ptr %882, 1 +// CHECK-NEXT: %884 = extractvalue { ptr, ptr } %881, 1 +// CHECK-NEXT: %885 = extractvalue { ptr, ptr } %881, 0 +// CHECK-NEXT: %__llgo_funcval_code117 = call ptr asm "", "=r,0"(ptr %885) +// CHECK-NEXT: %886 = call %reflect.Value %__llgo_funcval_code117(ptr {{(nest|swiftself)}} %884, %"{{.*}}/runtime/internal/runtime.eface" %883) +// CHECK-NEXT: store %reflect.Value %879, ptr %873, align 8 +// CHECK-NEXT: store %reflect.Value %886, ptr %880, align 8 +// CHECK-NEXT: %887 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %1, i64 59 +// CHECK-NEXT: %888 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %887, i32 0, i32 0 +// CHECK-NEXT: %889 = load { ptr, ptr }, ptr @main.V, align 8 +// CHECK-NEXT: %890 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 8) +// CHECK-NEXT: store i64 59, ptr %890, align 8 +// CHECK-NEXT: %891 = insertvalue %"{{.*}}/runtime/internal/runtime.eface" { ptr @_llgo_uint64, ptr undef }, ptr %890, 1 +// CHECK-NEXT: %892 = extractvalue { ptr, ptr } %889, 1 +// CHECK-NEXT: %893 = extractvalue { ptr, ptr } %889, 0 +// CHECK-NEXT: %__llgo_funcval_code118 = call ptr asm "", "=r,0"(ptr %893) +// CHECK-NEXT: %894 = call %reflect.Value %__llgo_funcval_code118(ptr {{(nest|swiftself)}} %892, %"{{.*}}/runtime/internal/runtime.eface" %891) +// CHECK-NEXT: %895 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %887, i32 0, i32 1 +// CHECK-NEXT: %896 = load { ptr, ptr }, ptr @main.V, align 8 +// CHECK-NEXT: %897 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 2) +// CHECK-NEXT: store i16 59, ptr %897, align 2 +// CHECK-NEXT: %898 = insertvalue %"{{.*}}/runtime/internal/runtime.eface" { ptr @_llgo_int16, ptr undef }, ptr %897, 1 +// CHECK-NEXT: %899 = extractvalue { ptr, ptr } %896, 1 +// CHECK-NEXT: %900 = extractvalue { ptr, ptr } %896, 0 +// CHECK-NEXT: %__llgo_funcval_code119 = call ptr asm "", "=r,0"(ptr %900) +// CHECK-NEXT: %901 = call %reflect.Value %__llgo_funcval_code119(ptr {{(nest|swiftself)}} %899, %"{{.*}}/runtime/internal/runtime.eface" %898) +// CHECK-NEXT: store %reflect.Value %894, ptr %888, align 8 +// CHECK-NEXT: store %reflect.Value %901, ptr %895, align 8 +// CHECK-NEXT: %902 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %1, i64 60 +// CHECK-NEXT: %903 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %902, i32 0, i32 0 +// CHECK-NEXT: %904 = load { ptr, ptr }, ptr @main.V, align 8 +// CHECK-NEXT: %905 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 2) +// CHECK-NEXT: store i16 60, ptr %905, align 2 +// CHECK-NEXT: %906 = insertvalue %"{{.*}}/runtime/internal/runtime.eface" { ptr @_llgo_int16, ptr undef }, ptr %905, 1 +// CHECK-NEXT: %907 = extractvalue { ptr, ptr } %904, 1 +// CHECK-NEXT: %908 = extractvalue { ptr, ptr } %904, 0 +// CHECK-NEXT: %__llgo_funcval_code120 = call ptr asm "", "=r,0"(ptr %908) +// CHECK-NEXT: %909 = call %reflect.Value %__llgo_funcval_code120(ptr {{(nest|swiftself)}} %907, %"{{.*}}/runtime/internal/runtime.eface" %906) +// CHECK-NEXT: %910 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %902, i32 0, i32 1 +// CHECK-NEXT: %911 = load { ptr, ptr }, ptr @main.V, align 8 +// CHECK-NEXT: %912 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 8) +// CHECK-NEXT: store i64 60, ptr %912, align 8 +// CHECK-NEXT: %913 = insertvalue %"{{.*}}/runtime/internal/runtime.eface" { ptr @_llgo_int, ptr undef }, ptr %912, 1 +// CHECK-NEXT: %914 = extractvalue { ptr, ptr } %911, 1 +// CHECK-NEXT: %915 = extractvalue { ptr, ptr } %911, 0 +// CHECK-NEXT: %__llgo_funcval_code121 = call ptr asm "", "=r,0"(ptr %915) +// CHECK-NEXT: %916 = call %reflect.Value %__llgo_funcval_code121(ptr {{(nest|swiftself)}} %914, %"{{.*}}/runtime/internal/runtime.eface" %913) +// CHECK-NEXT: store %reflect.Value %909, ptr %903, align 8 +// CHECK-NEXT: store %reflect.Value %916, ptr %910, align 8 +// CHECK-NEXT: %917 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %1, i64 61 +// CHECK-NEXT: %918 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %917, i32 0, i32 0 +// CHECK-NEXT: %919 = load { ptr, ptr }, ptr @main.V, align 8 +// CHECK-NEXT: %920 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 8) +// CHECK-NEXT: store i64 61, ptr %920, align 8 +// CHECK-NEXT: %921 = insertvalue %"{{.*}}/runtime/internal/runtime.eface" { ptr @_llgo_int, ptr undef }, ptr %920, 1 +// CHECK-NEXT: %922 = extractvalue { ptr, ptr } %919, 1 +// CHECK-NEXT: %923 = extractvalue { ptr, ptr } %919, 0 +// CHECK-NEXT: %__llgo_funcval_code122 = call ptr asm "", "=r,0"(ptr %923) +// CHECK-NEXT: %924 = call %reflect.Value %__llgo_funcval_code122(ptr {{(nest|swiftself)}} %922, %"{{.*}}/runtime/internal/runtime.eface" %921) +// CHECK-NEXT: %925 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %917, i32 0, i32 1 +// CHECK-NEXT: %926 = load { ptr, ptr }, ptr @main.V, align 8 +// CHECK-NEXT: %927 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 2) +// CHECK-NEXT: store i16 61, ptr %927, align 2 +// CHECK-NEXT: %928 = insertvalue %"{{.*}}/runtime/internal/runtime.eface" { ptr @_llgo_int16, ptr undef }, ptr %927, 1 +// CHECK-NEXT: %929 = extractvalue { ptr, ptr } %926, 1 +// CHECK-NEXT: %930 = extractvalue { ptr, ptr } %926, 0 +// CHECK-NEXT: %__llgo_funcval_code123 = call ptr asm "", "=r,0"(ptr %930) +// CHECK-NEXT: %931 = call %reflect.Value %__llgo_funcval_code123(ptr {{(nest|swiftself)}} %929, %"{{.*}}/runtime/internal/runtime.eface" %928) +// CHECK-NEXT: store %reflect.Value %924, ptr %918, align 8 +// CHECK-NEXT: store %reflect.Value %931, ptr %925, align 8 +// CHECK-NEXT: %932 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %1, i64 62 +// CHECK-NEXT: %933 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %932, i32 0, i32 0 +// CHECK-NEXT: %934 = load { ptr, ptr }, ptr @main.V, align 8 +// CHECK-NEXT: %935 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 2) +// CHECK-NEXT: store i16 62, ptr %935, align 2 +// CHECK-NEXT: %936 = insertvalue %"{{.*}}/runtime/internal/runtime.eface" { ptr @_llgo_int16, ptr undef }, ptr %935, 1 +// CHECK-NEXT: %937 = extractvalue { ptr, ptr } %934, 1 +// CHECK-NEXT: %938 = extractvalue { ptr, ptr } %934, 0 +// CHECK-NEXT: %__llgo_funcval_code124 = call ptr asm "", "=r,0"(ptr %938) +// CHECK-NEXT: %939 = call %reflect.Value %__llgo_funcval_code124(ptr {{(nest|swiftself)}} %937, %"{{.*}}/runtime/internal/runtime.eface" %936) +// CHECK-NEXT: %940 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %932, i32 0, i32 1 +// CHECK-NEXT: %941 = load { ptr, ptr }, ptr @main.V, align 8 +// CHECK-NEXT: %942 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 8) +// CHECK-NEXT: store i64 62, ptr %942, align 8 +// CHECK-NEXT: %943 = insertvalue %"{{.*}}/runtime/internal/runtime.eface" { ptr @_llgo_uint, ptr undef }, ptr %942, 1 +// CHECK-NEXT: %944 = extractvalue { ptr, ptr } %941, 1 +// CHECK-NEXT: %945 = extractvalue { ptr, ptr } %941, 0 +// CHECK-NEXT: %__llgo_funcval_code125 = call ptr asm "", "=r,0"(ptr %945) +// CHECK-NEXT: %946 = call %reflect.Value %__llgo_funcval_code125(ptr {{(nest|swiftself)}} %944, %"{{.*}}/runtime/internal/runtime.eface" %943) +// CHECK-NEXT: store %reflect.Value %939, ptr %933, align 8 +// CHECK-NEXT: store %reflect.Value %946, ptr %940, align 8 +// CHECK-NEXT: %947 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %1, i64 63 +// CHECK-NEXT: %948 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %947, i32 0, i32 0 +// CHECK-NEXT: %949 = load { ptr, ptr }, ptr @main.V, align 8 +// CHECK-NEXT: %950 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 8) +// CHECK-NEXT: store i64 63, ptr %950, align 8 +// CHECK-NEXT: %951 = insertvalue %"{{.*}}/runtime/internal/runtime.eface" { ptr @_llgo_uint, ptr undef }, ptr %950, 1 +// CHECK-NEXT: %952 = extractvalue { ptr, ptr } %949, 1 +// CHECK-NEXT: %953 = extractvalue { ptr, ptr } %949, 0 +// CHECK-NEXT: %__llgo_funcval_code126 = call ptr asm "", "=r,0"(ptr %953) +// CHECK-NEXT: %954 = call %reflect.Value %__llgo_funcval_code126(ptr {{(nest|swiftself)}} %952, %"{{.*}}/runtime/internal/runtime.eface" %951) +// CHECK-NEXT: %955 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %947, i32 0, i32 1 +// CHECK-NEXT: %956 = load { ptr, ptr }, ptr @main.V, align 8 +// CHECK-NEXT: %957 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 2) +// CHECK-NEXT: store i16 63, ptr %957, align 2 +// CHECK-NEXT: %958 = insertvalue %"{{.*}}/runtime/internal/runtime.eface" { ptr @_llgo_int16, ptr undef }, ptr %957, 1 +// CHECK-NEXT: %959 = extractvalue { ptr, ptr } %956, 1 +// CHECK-NEXT: %960 = extractvalue { ptr, ptr } %956, 0 +// CHECK-NEXT: %__llgo_funcval_code127 = call ptr asm "", "=r,0"(ptr %960) +// CHECK-NEXT: %961 = call %reflect.Value %__llgo_funcval_code127(ptr {{(nest|swiftself)}} %959, %"{{.*}}/runtime/internal/runtime.eface" %958) +// CHECK-NEXT: store %reflect.Value %954, ptr %948, align 8 +// CHECK-NEXT: store %reflect.Value %961, ptr %955, align 8 +// CHECK-NEXT: %962 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %1, i64 64 +// CHECK-NEXT: %963 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %962, i32 0, i32 0 +// CHECK-NEXT: %964 = load { ptr, ptr }, ptr @main.V, align 8 +// CHECK-NEXT: %965 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 2) +// CHECK-NEXT: store i16 64, ptr %965, align 2 +// CHECK-NEXT: %966 = insertvalue %"{{.*}}/runtime/internal/runtime.eface" { ptr @_llgo_int16, ptr undef }, ptr %965, 1 +// CHECK-NEXT: %967 = extractvalue { ptr, ptr } %964, 1 +// CHECK-NEXT: %968 = extractvalue { ptr, ptr } %964, 0 +// CHECK-NEXT: %__llgo_funcval_code128 = call ptr asm "", "=r,0"(ptr %968) +// CHECK-NEXT: %969 = call %reflect.Value %__llgo_funcval_code128(ptr {{(nest|swiftself)}} %967, %"{{.*}}/runtime/internal/runtime.eface" %966) +// CHECK-NEXT: %970 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %962, i32 0, i32 1 +// CHECK-NEXT: %971 = load { ptr, ptr }, ptr @main.V, align 8 +// CHECK-NEXT: %972 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 8) +// CHECK-NEXT: store i64 64, ptr %972, align 8 +// CHECK-NEXT: %973 = insertvalue %"{{.*}}/runtime/internal/runtime.eface" { ptr @_llgo_uintptr, ptr undef }, ptr %972, 1 +// CHECK-NEXT: %974 = extractvalue { ptr, ptr } %971, 1 +// CHECK-NEXT: %975 = extractvalue { ptr, ptr } %971, 0 +// CHECK-NEXT: %__llgo_funcval_code129 = call ptr asm "", "=r,0"(ptr %975) +// CHECK-NEXT: %976 = call %reflect.Value %__llgo_funcval_code129(ptr {{(nest|swiftself)}} %974, %"{{.*}}/runtime/internal/runtime.eface" %973) +// CHECK-NEXT: store %reflect.Value %969, ptr %963, align 8 +// CHECK-NEXT: store %reflect.Value %976, ptr %970, align 8 +// CHECK-NEXT: %977 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %1, i64 65 +// CHECK-NEXT: %978 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %977, i32 0, i32 0 +// CHECK-NEXT: %979 = load { ptr, ptr }, ptr @main.V, align 8 +// CHECK-NEXT: %980 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 8) +// CHECK-NEXT: store i64 65, ptr %980, align 8 +// CHECK-NEXT: %981 = insertvalue %"{{.*}}/runtime/internal/runtime.eface" { ptr @_llgo_uintptr, ptr undef }, ptr %980, 1 +// CHECK-NEXT: %982 = extractvalue { ptr, ptr } %979, 1 +// CHECK-NEXT: %983 = extractvalue { ptr, ptr } %979, 0 +// CHECK-NEXT: %__llgo_funcval_code130 = call ptr asm "", "=r,0"(ptr %983) +// CHECK-NEXT: %984 = call %reflect.Value %__llgo_funcval_code130(ptr {{(nest|swiftself)}} %982, %"{{.*}}/runtime/internal/runtime.eface" %981) +// CHECK-NEXT: %985 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %977, i32 0, i32 1 +// CHECK-NEXT: %986 = load { ptr, ptr }, ptr @main.V, align 8 +// CHECK-NEXT: %987 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 2) +// CHECK-NEXT: store i16 65, ptr %987, align 2 +// CHECK-NEXT: %988 = insertvalue %"{{.*}}/runtime/internal/runtime.eface" { ptr @_llgo_int16, ptr undef }, ptr %987, 1 +// CHECK-NEXT: %989 = extractvalue { ptr, ptr } %986, 1 +// CHECK-NEXT: %990 = extractvalue { ptr, ptr } %986, 0 +// CHECK-NEXT: %__llgo_funcval_code131 = call ptr asm "", "=r,0"(ptr %990) +// CHECK-NEXT: %991 = call %reflect.Value %__llgo_funcval_code131(ptr {{(nest|swiftself)}} %989, %"{{.*}}/runtime/internal/runtime.eface" %988) +// CHECK-NEXT: store %reflect.Value %984, ptr %978, align 8 +// CHECK-NEXT: store %reflect.Value %991, ptr %985, align 8 +// CHECK-NEXT: %992 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %1, i64 66 +// CHECK-NEXT: %993 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %992, i32 0, i32 0 +// CHECK-NEXT: %994 = load { ptr, ptr }, ptr @main.V, align 8 +// CHECK-NEXT: %995 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 2) +// CHECK-NEXT: store i16 66, ptr %995, align 2 +// CHECK-NEXT: %996 = insertvalue %"{{.*}}/runtime/internal/runtime.eface" { ptr @_llgo_int16, ptr undef }, ptr %995, 1 +// CHECK-NEXT: %997 = extractvalue { ptr, ptr } %994, 1 +// CHECK-NEXT: %998 = extractvalue { ptr, ptr } %994, 0 +// CHECK-NEXT: %__llgo_funcval_code132 = call ptr asm "", "=r,0"(ptr %998) +// CHECK-NEXT: %999 = call %reflect.Value %__llgo_funcval_code132(ptr {{(nest|swiftself)}} %997, %"{{.*}}/runtime/internal/runtime.eface" %996) +// CHECK-NEXT: %1000 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %992, i32 0, i32 1 +// CHECK-NEXT: %1001 = load { ptr, ptr }, ptr @main.V, align 8 +// CHECK-NEXT: %1002 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 4) +// CHECK-NEXT: store float 6.600000e+01, ptr %1002, align 4 +// CHECK-NEXT: %1003 = insertvalue %"{{.*}}/runtime/internal/runtime.eface" { ptr @_llgo_float32, ptr undef }, ptr %1002, 1 +// CHECK-NEXT: %1004 = extractvalue { ptr, ptr } %1001, 1 +// CHECK-NEXT: %1005 = extractvalue { ptr, ptr } %1001, 0 +// CHECK-NEXT: %__llgo_funcval_code133 = call ptr asm "", "=r,0"(ptr %1005) +// CHECK-NEXT: %1006 = call %reflect.Value %__llgo_funcval_code133(ptr {{(nest|swiftself)}} %1004, %"{{.*}}/runtime/internal/runtime.eface" %1003) +// CHECK-NEXT: store %reflect.Value %999, ptr %993, align 8 +// CHECK-NEXT: store %reflect.Value %1006, ptr %1000, align 8 +// CHECK-NEXT: %1007 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %1, i64 67 +// CHECK-NEXT: %1008 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %1007, i32 0, i32 0 +// CHECK-NEXT: %1009 = load { ptr, ptr }, ptr @main.V, align 8 +// CHECK-NEXT: %1010 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 4) +// CHECK-NEXT: store float 6.700000e+01, ptr %1010, align 4 +// CHECK-NEXT: %1011 = insertvalue %"{{.*}}/runtime/internal/runtime.eface" { ptr @_llgo_float32, ptr undef }, ptr %1010, 1 +// CHECK-NEXT: %1012 = extractvalue { ptr, ptr } %1009, 1 +// CHECK-NEXT: %1013 = extractvalue { ptr, ptr } %1009, 0 +// CHECK-NEXT: %__llgo_funcval_code134 = call ptr asm "", "=r,0"(ptr %1013) +// CHECK-NEXT: %1014 = call %reflect.Value %__llgo_funcval_code134(ptr {{(nest|swiftself)}} %1012, %"{{.*}}/runtime/internal/runtime.eface" %1011) +// CHECK-NEXT: %1015 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %1007, i32 0, i32 1 +// CHECK-NEXT: %1016 = load { ptr, ptr }, ptr @main.V, align 8 +// CHECK-NEXT: %1017 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 2) +// CHECK-NEXT: store i16 67, ptr %1017, align 2 +// CHECK-NEXT: %1018 = insertvalue %"{{.*}}/runtime/internal/runtime.eface" { ptr @_llgo_int16, ptr undef }, ptr %1017, 1 +// CHECK-NEXT: %1019 = extractvalue { ptr, ptr } %1016, 1 +// CHECK-NEXT: %1020 = extractvalue { ptr, ptr } %1016, 0 +// CHECK-NEXT: %__llgo_funcval_code135 = call ptr asm "", "=r,0"(ptr %1020) +// CHECK-NEXT: %1021 = call %reflect.Value %__llgo_funcval_code135(ptr {{(nest|swiftself)}} %1019, %"{{.*}}/runtime/internal/runtime.eface" %1018) +// CHECK-NEXT: store %reflect.Value %1014, ptr %1008, align 8 +// CHECK-NEXT: store %reflect.Value %1021, ptr %1015, align 8 +// CHECK-NEXT: %1022 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %1, i64 68 +// CHECK-NEXT: %1023 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %1022, i32 0, i32 0 +// CHECK-NEXT: %1024 = load { ptr, ptr }, ptr @main.V, align 8 +// CHECK-NEXT: %1025 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 2) +// CHECK-NEXT: store i16 68, ptr %1025, align 2 +// CHECK-NEXT: %1026 = insertvalue %"{{.*}}/runtime/internal/runtime.eface" { ptr @_llgo_int16, ptr undef }, ptr %1025, 1 +// CHECK-NEXT: %1027 = extractvalue { ptr, ptr } %1024, 1 +// CHECK-NEXT: %1028 = extractvalue { ptr, ptr } %1024, 0 +// CHECK-NEXT: %__llgo_funcval_code136 = call ptr asm "", "=r,0"(ptr %1028) +// CHECK-NEXT: %1029 = call %reflect.Value %__llgo_funcval_code136(ptr {{(nest|swiftself)}} %1027, %"{{.*}}/runtime/internal/runtime.eface" %1026) +// CHECK-NEXT: %1030 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %1022, i32 0, i32 1 +// CHECK-NEXT: %1031 = load { ptr, ptr }, ptr @main.V, align 8 +// CHECK-NEXT: %1032 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 8) +// CHECK-NEXT: store double 6.800000e+01, ptr %1032, align 8 +// CHECK-NEXT: %1033 = insertvalue %"{{.*}}/runtime/internal/runtime.eface" { ptr @_llgo_float64, ptr undef }, ptr %1032, 1 +// CHECK-NEXT: %1034 = extractvalue { ptr, ptr } %1031, 1 +// CHECK-NEXT: %1035 = extractvalue { ptr, ptr } %1031, 0 +// CHECK-NEXT: %__llgo_funcval_code137 = call ptr asm "", "=r,0"(ptr %1035) +// CHECK-NEXT: %1036 = call %reflect.Value %__llgo_funcval_code137(ptr {{(nest|swiftself)}} %1034, %"{{.*}}/runtime/internal/runtime.eface" %1033) +// CHECK-NEXT: store %reflect.Value %1029, ptr %1023, align 8 +// CHECK-NEXT: store %reflect.Value %1036, ptr %1030, align 8 +// CHECK-NEXT: %1037 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %1, i64 69 +// CHECK-NEXT: %1038 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %1037, i32 0, i32 0 +// CHECK-NEXT: %1039 = load { ptr, ptr }, ptr @main.V, align 8 +// CHECK-NEXT: %1040 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 8) +// CHECK-NEXT: store double 6.900000e+01, ptr %1040, align 8 +// CHECK-NEXT: %1041 = insertvalue %"{{.*}}/runtime/internal/runtime.eface" { ptr @_llgo_float64, ptr undef }, ptr %1040, 1 +// CHECK-NEXT: %1042 = extractvalue { ptr, ptr } %1039, 1 +// CHECK-NEXT: %1043 = extractvalue { ptr, ptr } %1039, 0 +// CHECK-NEXT: %__llgo_funcval_code138 = call ptr asm "", "=r,0"(ptr %1043) +// CHECK-NEXT: %1044 = call %reflect.Value %__llgo_funcval_code138(ptr {{(nest|swiftself)}} %1042, %"{{.*}}/runtime/internal/runtime.eface" %1041) +// CHECK-NEXT: %1045 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %1037, i32 0, i32 1 +// CHECK-NEXT: %1046 = load { ptr, ptr }, ptr @main.V, align 8 +// CHECK-NEXT: %1047 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 2) +// CHECK-NEXT: store i16 69, ptr %1047, align 2 +// CHECK-NEXT: %1048 = insertvalue %"{{.*}}/runtime/internal/runtime.eface" { ptr @_llgo_int16, ptr undef }, ptr %1047, 1 +// CHECK-NEXT: %1049 = extractvalue { ptr, ptr } %1046, 1 +// CHECK-NEXT: %1050 = extractvalue { ptr, ptr } %1046, 0 +// CHECK-NEXT: %__llgo_funcval_code139 = call ptr asm "", "=r,0"(ptr %1050) +// CHECK-NEXT: %1051 = call %reflect.Value %__llgo_funcval_code139(ptr {{(nest|swiftself)}} %1049, %"{{.*}}/runtime/internal/runtime.eface" %1048) +// CHECK-NEXT: store %reflect.Value %1044, ptr %1038, align 8 +// CHECK-NEXT: store %reflect.Value %1051, ptr %1045, align 8 +// CHECK-NEXT: %1052 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %1, i64 70 +// CHECK-NEXT: %1053 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %1052, i32 0, i32 0 +// CHECK-NEXT: %1054 = load { ptr, ptr }, ptr @main.V, align 8 +// CHECK-NEXT: %1055 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 2) +// CHECK-NEXT: store i16 70, ptr %1055, align 2 +// CHECK-NEXT: %1056 = insertvalue %"{{.*}}/runtime/internal/runtime.eface" { ptr @_llgo_uint16, ptr undef }, ptr %1055, 1 +// CHECK-NEXT: %1057 = extractvalue { ptr, ptr } %1054, 1 +// CHECK-NEXT: %1058 = extractvalue { ptr, ptr } %1054, 0 +// CHECK-NEXT: %__llgo_funcval_code140 = call ptr asm "", "=r,0"(ptr %1058) +// CHECK-NEXT: %1059 = call %reflect.Value %__llgo_funcval_code140(ptr {{(nest|swiftself)}} %1057, %"{{.*}}/runtime/internal/runtime.eface" %1056) +// CHECK-NEXT: %1060 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %1052, i32 0, i32 1 +// CHECK-NEXT: %1061 = load { ptr, ptr }, ptr @main.V, align 8 +// CHECK-NEXT: %1062 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 2) +// CHECK-NEXT: store i16 70, ptr %1062, align 2 +// CHECK-NEXT: %1063 = insertvalue %"{{.*}}/runtime/internal/runtime.eface" { ptr @_llgo_uint16, ptr undef }, ptr %1062, 1 +// CHECK-NEXT: %1064 = extractvalue { ptr, ptr } %1061, 1 +// CHECK-NEXT: %1065 = extractvalue { ptr, ptr } %1061, 0 +// CHECK-NEXT: %__llgo_funcval_code141 = call ptr asm "", "=r,0"(ptr %1065) +// CHECK-NEXT: %1066 = call %reflect.Value %__llgo_funcval_code141(ptr {{(nest|swiftself)}} %1064, %"{{.*}}/runtime/internal/runtime.eface" %1063) +// CHECK-NEXT: store %reflect.Value %1059, ptr %1053, align 8 +// CHECK-NEXT: store %reflect.Value %1066, ptr %1060, align 8 +// CHECK-NEXT: %1067 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %1, i64 71 +// CHECK-NEXT: %1068 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %1067, i32 0, i32 0 +// CHECK-NEXT: %1069 = load { ptr, ptr }, ptr @main.V, align 8 +// CHECK-NEXT: %1070 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 2) +// CHECK-NEXT: store i16 71, ptr %1070, align 2 +// CHECK-NEXT: %1071 = insertvalue %"{{.*}}/runtime/internal/runtime.eface" { ptr @_llgo_uint16, ptr undef }, ptr %1070, 1 +// CHECK-NEXT: %1072 = extractvalue { ptr, ptr } %1069, 1 +// CHECK-NEXT: %1073 = extractvalue { ptr, ptr } %1069, 0 +// CHECK-NEXT: %__llgo_funcval_code142 = call ptr asm "", "=r,0"(ptr %1073) +// CHECK-NEXT: %1074 = call %reflect.Value %__llgo_funcval_code142(ptr {{(nest|swiftself)}} %1072, %"{{.*}}/runtime/internal/runtime.eface" %1071) +// CHECK-NEXT: %1075 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %1067, i32 0, i32 1 +// CHECK-NEXT: %1076 = load { ptr, ptr }, ptr @main.V, align 8 +// CHECK-NEXT: %1077 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 4) +// CHECK-NEXT: store i32 71, ptr %1077, align 4 +// CHECK-NEXT: %1078 = insertvalue %"{{.*}}/runtime/internal/runtime.eface" { ptr @_llgo_int32, ptr undef }, ptr %1077, 1 +// CHECK-NEXT: %1079 = extractvalue { ptr, ptr } %1076, 1 +// CHECK-NEXT: %1080 = extractvalue { ptr, ptr } %1076, 0 +// CHECK-NEXT: %__llgo_funcval_code143 = call ptr asm "", "=r,0"(ptr %1080) +// CHECK-NEXT: %1081 = call %reflect.Value %__llgo_funcval_code143(ptr {{(nest|swiftself)}} %1079, %"{{.*}}/runtime/internal/runtime.eface" %1078) +// CHECK-NEXT: store %reflect.Value %1074, ptr %1068, align 8 +// CHECK-NEXT: store %reflect.Value %1081, ptr %1075, align 8 +// CHECK-NEXT: %1082 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %1, i64 72 +// CHECK-NEXT: %1083 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %1082, i32 0, i32 0 +// CHECK-NEXT: %1084 = load { ptr, ptr }, ptr @main.V, align 8 +// CHECK-NEXT: %1085 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 4) +// CHECK-NEXT: store i32 72, ptr %1085, align 4 +// CHECK-NEXT: %1086 = insertvalue %"{{.*}}/runtime/internal/runtime.eface" { ptr @_llgo_int32, ptr undef }, ptr %1085, 1 +// CHECK-NEXT: %1087 = extractvalue { ptr, ptr } %1084, 1 +// CHECK-NEXT: %1088 = extractvalue { ptr, ptr } %1084, 0 +// CHECK-NEXT: %__llgo_funcval_code144 = call ptr asm "", "=r,0"(ptr %1088) +// CHECK-NEXT: %1089 = call %reflect.Value %__llgo_funcval_code144(ptr {{(nest|swiftself)}} %1087, %"{{.*}}/runtime/internal/runtime.eface" %1086) +// CHECK-NEXT: %1090 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %1082, i32 0, i32 1 +// CHECK-NEXT: %1091 = load { ptr, ptr }, ptr @main.V, align 8 +// CHECK-NEXT: %1092 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 2) +// CHECK-NEXT: store i16 72, ptr %1092, align 2 +// CHECK-NEXT: %1093 = insertvalue %"{{.*}}/runtime/internal/runtime.eface" { ptr @_llgo_uint16, ptr undef }, ptr %1092, 1 +// CHECK-NEXT: %1094 = extractvalue { ptr, ptr } %1091, 1 +// CHECK-NEXT: %1095 = extractvalue { ptr, ptr } %1091, 0 +// CHECK-NEXT: %__llgo_funcval_code145 = call ptr asm "", "=r,0"(ptr %1095) +// CHECK-NEXT: %1096 = call %reflect.Value %__llgo_funcval_code145(ptr {{(nest|swiftself)}} %1094, %"{{.*}}/runtime/internal/runtime.eface" %1093) +// CHECK-NEXT: store %reflect.Value %1089, ptr %1083, align 8 +// CHECK-NEXT: store %reflect.Value %1096, ptr %1090, align 8 +// CHECK-NEXT: %1097 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %1, i64 73 +// CHECK-NEXT: %1098 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %1097, i32 0, i32 0 +// CHECK-NEXT: %1099 = load { ptr, ptr }, ptr @main.V, align 8 +// CHECK-NEXT: %1100 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 2) +// CHECK-NEXT: store i16 73, ptr %1100, align 2 +// CHECK-NEXT: %1101 = insertvalue %"{{.*}}/runtime/internal/runtime.eface" { ptr @_llgo_uint16, ptr undef }, ptr %1100, 1 +// CHECK-NEXT: %1102 = extractvalue { ptr, ptr } %1099, 1 +// CHECK-NEXT: %1103 = extractvalue { ptr, ptr } %1099, 0 +// CHECK-NEXT: %__llgo_funcval_code146 = call ptr asm "", "=r,0"(ptr %1103) +// CHECK-NEXT: %1104 = call %reflect.Value %__llgo_funcval_code146(ptr {{(nest|swiftself)}} %1102, %"{{.*}}/runtime/internal/runtime.eface" %1101) +// CHECK-NEXT: %1105 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %1097, i32 0, i32 1 +// CHECK-NEXT: %1106 = load { ptr, ptr }, ptr @main.V, align 8 +// CHECK-NEXT: %1107 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 4) +// CHECK-NEXT: store i32 73, ptr %1107, align 4 +// CHECK-NEXT: %1108 = insertvalue %"{{.*}}/runtime/internal/runtime.eface" { ptr @_llgo_uint32, ptr undef }, ptr %1107, 1 +// CHECK-NEXT: %1109 = extractvalue { ptr, ptr } %1106, 1 +// CHECK-NEXT: %1110 = extractvalue { ptr, ptr } %1106, 0 +// CHECK-NEXT: %__llgo_funcval_code147 = call ptr asm "", "=r,0"(ptr %1110) +// CHECK-NEXT: %1111 = call %reflect.Value %__llgo_funcval_code147(ptr {{(nest|swiftself)}} %1109, %"{{.*}}/runtime/internal/runtime.eface" %1108) +// CHECK-NEXT: store %reflect.Value %1104, ptr %1098, align 8 +// CHECK-NEXT: store %reflect.Value %1111, ptr %1105, align 8 +// CHECK-NEXT: %1112 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %1, i64 74 +// CHECK-NEXT: %1113 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %1112, i32 0, i32 0 +// CHECK-NEXT: %1114 = load { ptr, ptr }, ptr @main.V, align 8 +// CHECK-NEXT: %1115 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 4) +// CHECK-NEXT: store i32 74, ptr %1115, align 4 +// CHECK-NEXT: %1116 = insertvalue %"{{.*}}/runtime/internal/runtime.eface" { ptr @_llgo_uint32, ptr undef }, ptr %1115, 1 +// CHECK-NEXT: %1117 = extractvalue { ptr, ptr } %1114, 1 +// CHECK-NEXT: %1118 = extractvalue { ptr, ptr } %1114, 0 +// CHECK-NEXT: %__llgo_funcval_code148 = call ptr asm "", "=r,0"(ptr %1118) +// CHECK-NEXT: %1119 = call %reflect.Value %__llgo_funcval_code148(ptr {{(nest|swiftself)}} %1117, %"{{.*}}/runtime/internal/runtime.eface" %1116) +// CHECK-NEXT: %1120 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %1112, i32 0, i32 1 +// CHECK-NEXT: %1121 = load { ptr, ptr }, ptr @main.V, align 8 +// CHECK-NEXT: %1122 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 2) +// CHECK-NEXT: store i16 74, ptr %1122, align 2 +// CHECK-NEXT: %1123 = insertvalue %"{{.*}}/runtime/internal/runtime.eface" { ptr @_llgo_uint16, ptr undef }, ptr %1122, 1 +// CHECK-NEXT: %1124 = extractvalue { ptr, ptr } %1121, 1 +// CHECK-NEXT: %1125 = extractvalue { ptr, ptr } %1121, 0 +// CHECK-NEXT: %__llgo_funcval_code149 = call ptr asm "", "=r,0"(ptr %1125) +// CHECK-NEXT: %1126 = call %reflect.Value %__llgo_funcval_code149(ptr {{(nest|swiftself)}} %1124, %"{{.*}}/runtime/internal/runtime.eface" %1123) +// CHECK-NEXT: store %reflect.Value %1119, ptr %1113, align 8 +// CHECK-NEXT: store %reflect.Value %1126, ptr %1120, align 8 +// CHECK-NEXT: %1127 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %1, i64 75 +// CHECK-NEXT: %1128 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %1127, i32 0, i32 0 +// CHECK-NEXT: %1129 = load { ptr, ptr }, ptr @main.V, align 8 +// CHECK-NEXT: %1130 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 2) +// CHECK-NEXT: store i16 75, ptr %1130, align 2 +// CHECK-NEXT: %1131 = insertvalue %"{{.*}}/runtime/internal/runtime.eface" { ptr @_llgo_uint16, ptr undef }, ptr %1130, 1 +// CHECK-NEXT: %1132 = extractvalue { ptr, ptr } %1129, 1 +// CHECK-NEXT: %1133 = extractvalue { ptr, ptr } %1129, 0 +// CHECK-NEXT: %__llgo_funcval_code150 = call ptr asm "", "=r,0"(ptr %1133) +// CHECK-NEXT: %1134 = call %reflect.Value %__llgo_funcval_code150(ptr {{(nest|swiftself)}} %1132, %"{{.*}}/runtime/internal/runtime.eface" %1131) +// CHECK-NEXT: %1135 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %1127, i32 0, i32 1 +// CHECK-NEXT: %1136 = load { ptr, ptr }, ptr @main.V, align 8 +// CHECK-NEXT: %1137 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 8) +// CHECK-NEXT: store i64 75, ptr %1137, align 8 +// CHECK-NEXT: %1138 = insertvalue %"{{.*}}/runtime/internal/runtime.eface" { ptr @_llgo_int64, ptr undef }, ptr %1137, 1 +// CHECK-NEXT: %1139 = extractvalue { ptr, ptr } %1136, 1 +// CHECK-NEXT: %1140 = extractvalue { ptr, ptr } %1136, 0 +// CHECK-NEXT: %__llgo_funcval_code151 = call ptr asm "", "=r,0"(ptr %1140) +// CHECK-NEXT: %1141 = call %reflect.Value %__llgo_funcval_code151(ptr {{(nest|swiftself)}} %1139, %"{{.*}}/runtime/internal/runtime.eface" %1138) +// CHECK-NEXT: store %reflect.Value %1134, ptr %1128, align 8 +// CHECK-NEXT: store %reflect.Value %1141, ptr %1135, align 8 +// CHECK-NEXT: %1142 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %1, i64 76 +// CHECK-NEXT: %1143 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %1142, i32 0, i32 0 +// CHECK-NEXT: %1144 = load { ptr, ptr }, ptr @main.V, align 8 +// CHECK-NEXT: %1145 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 8) +// CHECK-NEXT: store i64 76, ptr %1145, align 8 +// CHECK-NEXT: %1146 = insertvalue %"{{.*}}/runtime/internal/runtime.eface" { ptr @_llgo_int64, ptr undef }, ptr %1145, 1 +// CHECK-NEXT: %1147 = extractvalue { ptr, ptr } %1144, 1 +// CHECK-NEXT: %1148 = extractvalue { ptr, ptr } %1144, 0 +// CHECK-NEXT: %__llgo_funcval_code152 = call ptr asm "", "=r,0"(ptr %1148) +// CHECK-NEXT: %1149 = call %reflect.Value %__llgo_funcval_code152(ptr {{(nest|swiftself)}} %1147, %"{{.*}}/runtime/internal/runtime.eface" %1146) +// CHECK-NEXT: %1150 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %1142, i32 0, i32 1 +// CHECK-NEXT: %1151 = load { ptr, ptr }, ptr @main.V, align 8 +// CHECK-NEXT: %1152 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 2) +// CHECK-NEXT: store i16 76, ptr %1152, align 2 +// CHECK-NEXT: %1153 = insertvalue %"{{.*}}/runtime/internal/runtime.eface" { ptr @_llgo_uint16, ptr undef }, ptr %1152, 1 +// CHECK-NEXT: %1154 = extractvalue { ptr, ptr } %1151, 1 +// CHECK-NEXT: %1155 = extractvalue { ptr, ptr } %1151, 0 +// CHECK-NEXT: %__llgo_funcval_code153 = call ptr asm "", "=r,0"(ptr %1155) +// CHECK-NEXT: %1156 = call %reflect.Value %__llgo_funcval_code153(ptr {{(nest|swiftself)}} %1154, %"{{.*}}/runtime/internal/runtime.eface" %1153) +// CHECK-NEXT: store %reflect.Value %1149, ptr %1143, align 8 +// CHECK-NEXT: store %reflect.Value %1156, ptr %1150, align 8 +// CHECK-NEXT: %1157 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %1, i64 77 +// CHECK-NEXT: %1158 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %1157, i32 0, i32 0 +// CHECK-NEXT: %1159 = load { ptr, ptr }, ptr @main.V, align 8 +// CHECK-NEXT: %1160 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 2) +// CHECK-NEXT: store i16 77, ptr %1160, align 2 +// CHECK-NEXT: %1161 = insertvalue %"{{.*}}/runtime/internal/runtime.eface" { ptr @_llgo_uint16, ptr undef }, ptr %1160, 1 +// CHECK-NEXT: %1162 = extractvalue { ptr, ptr } %1159, 1 +// CHECK-NEXT: %1163 = extractvalue { ptr, ptr } %1159, 0 +// CHECK-NEXT: %__llgo_funcval_code154 = call ptr asm "", "=r,0"(ptr %1163) +// CHECK-NEXT: %1164 = call %reflect.Value %__llgo_funcval_code154(ptr {{(nest|swiftself)}} %1162, %"{{.*}}/runtime/internal/runtime.eface" %1161) +// CHECK-NEXT: %1165 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %1157, i32 0, i32 1 +// CHECK-NEXT: %1166 = load { ptr, ptr }, ptr @main.V, align 8 +// CHECK-NEXT: %1167 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 8) +// CHECK-NEXT: store i64 77, ptr %1167, align 8 +// CHECK-NEXT: %1168 = insertvalue %"{{.*}}/runtime/internal/runtime.eface" { ptr @_llgo_uint64, ptr undef }, ptr %1167, 1 +// CHECK-NEXT: %1169 = extractvalue { ptr, ptr } %1166, 1 +// CHECK-NEXT: %1170 = extractvalue { ptr, ptr } %1166, 0 +// CHECK-NEXT: %__llgo_funcval_code155 = call ptr asm "", "=r,0"(ptr %1170) +// CHECK-NEXT: %1171 = call %reflect.Value %__llgo_funcval_code155(ptr {{(nest|swiftself)}} %1169, %"{{.*}}/runtime/internal/runtime.eface" %1168) +// CHECK-NEXT: store %reflect.Value %1164, ptr %1158, align 8 +// CHECK-NEXT: store %reflect.Value %1171, ptr %1165, align 8 +// CHECK-NEXT: %1172 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %1, i64 78 +// CHECK-NEXT: %1173 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %1172, i32 0, i32 0 +// CHECK-NEXT: %1174 = load { ptr, ptr }, ptr @main.V, align 8 +// CHECK-NEXT: %1175 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 8) +// CHECK-NEXT: store i64 78, ptr %1175, align 8 +// CHECK-NEXT: %1176 = insertvalue %"{{.*}}/runtime/internal/runtime.eface" { ptr @_llgo_uint64, ptr undef }, ptr %1175, 1 +// CHECK-NEXT: %1177 = extractvalue { ptr, ptr } %1174, 1 +// CHECK-NEXT: %1178 = extractvalue { ptr, ptr } %1174, 0 +// CHECK-NEXT: %__llgo_funcval_code156 = call ptr asm "", "=r,0"(ptr %1178) +// CHECK-NEXT: %1179 = call %reflect.Value %__llgo_funcval_code156(ptr {{(nest|swiftself)}} %1177, %"{{.*}}/runtime/internal/runtime.eface" %1176) +// CHECK-NEXT: %1180 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %1172, i32 0, i32 1 +// CHECK-NEXT: %1181 = load { ptr, ptr }, ptr @main.V, align 8 +// CHECK-NEXT: %1182 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 2) +// CHECK-NEXT: store i16 78, ptr %1182, align 2 +// CHECK-NEXT: %1183 = insertvalue %"{{.*}}/runtime/internal/runtime.eface" { ptr @_llgo_uint16, ptr undef }, ptr %1182, 1 +// CHECK-NEXT: %1184 = extractvalue { ptr, ptr } %1181, 1 +// CHECK-NEXT: %1185 = extractvalue { ptr, ptr } %1181, 0 +// CHECK-NEXT: %__llgo_funcval_code157 = call ptr asm "", "=r,0"(ptr %1185) +// CHECK-NEXT: %1186 = call %reflect.Value %__llgo_funcval_code157(ptr {{(nest|swiftself)}} %1184, %"{{.*}}/runtime/internal/runtime.eface" %1183) +// CHECK-NEXT: store %reflect.Value %1179, ptr %1173, align 8 +// CHECK-NEXT: store %reflect.Value %1186, ptr %1180, align 8 +// CHECK-NEXT: %1187 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %1, i64 79 +// CHECK-NEXT: %1188 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %1187, i32 0, i32 0 +// CHECK-NEXT: %1189 = load { ptr, ptr }, ptr @main.V, align 8 +// CHECK-NEXT: %1190 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 2) +// CHECK-NEXT: store i16 79, ptr %1190, align 2 +// CHECK-NEXT: %1191 = insertvalue %"{{.*}}/runtime/internal/runtime.eface" { ptr @_llgo_uint16, ptr undef }, ptr %1190, 1 +// CHECK-NEXT: %1192 = extractvalue { ptr, ptr } %1189, 1 +// CHECK-NEXT: %1193 = extractvalue { ptr, ptr } %1189, 0 +// CHECK-NEXT: %__llgo_funcval_code158 = call ptr asm "", "=r,0"(ptr %1193) +// CHECK-NEXT: %1194 = call %reflect.Value %__llgo_funcval_code158(ptr {{(nest|swiftself)}} %1192, %"{{.*}}/runtime/internal/runtime.eface" %1191) +// CHECK-NEXT: %1195 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %1187, i32 0, i32 1 +// CHECK-NEXT: %1196 = load { ptr, ptr }, ptr @main.V, align 8 +// CHECK-NEXT: %1197 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 8) +// CHECK-NEXT: store i64 79, ptr %1197, align 8 +// CHECK-NEXT: %1198 = insertvalue %"{{.*}}/runtime/internal/runtime.eface" { ptr @_llgo_int, ptr undef }, ptr %1197, 1 +// CHECK-NEXT: %1199 = extractvalue { ptr, ptr } %1196, 1 +// CHECK-NEXT: %1200 = extractvalue { ptr, ptr } %1196, 0 +// CHECK-NEXT: %__llgo_funcval_code159 = call ptr asm "", "=r,0"(ptr %1200) +// CHECK-NEXT: %1201 = call %reflect.Value %__llgo_funcval_code159(ptr {{(nest|swiftself)}} %1199, %"{{.*}}/runtime/internal/runtime.eface" %1198) +// CHECK-NEXT: store %reflect.Value %1194, ptr %1188, align 8 +// CHECK-NEXT: store %reflect.Value %1201, ptr %1195, align 8 +// CHECK-NEXT: %1202 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %1, i64 80 +// CHECK-NEXT: %1203 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %1202, i32 0, i32 0 +// CHECK-NEXT: %1204 = load { ptr, ptr }, ptr @main.V, align 8 +// CHECK-NEXT: %1205 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 8) +// CHECK-NEXT: store i64 80, ptr %1205, align 8 +// CHECK-NEXT: %1206 = insertvalue %"{{.*}}/runtime/internal/runtime.eface" { ptr @_llgo_int, ptr undef }, ptr %1205, 1 +// CHECK-NEXT: %1207 = extractvalue { ptr, ptr } %1204, 1 +// CHECK-NEXT: %1208 = extractvalue { ptr, ptr } %1204, 0 +// CHECK-NEXT: %__llgo_funcval_code160 = call ptr asm "", "=r,0"(ptr %1208) +// CHECK-NEXT: %1209 = call %reflect.Value %__llgo_funcval_code160(ptr {{(nest|swiftself)}} %1207, %"{{.*}}/runtime/internal/runtime.eface" %1206) +// CHECK-NEXT: %1210 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %1202, i32 0, i32 1 +// CHECK-NEXT: %1211 = load { ptr, ptr }, ptr @main.V, align 8 +// CHECK-NEXT: %1212 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 2) +// CHECK-NEXT: store i16 80, ptr %1212, align 2 +// CHECK-NEXT: %1213 = insertvalue %"{{.*}}/runtime/internal/runtime.eface" { ptr @_llgo_uint16, ptr undef }, ptr %1212, 1 +// CHECK-NEXT: %1214 = extractvalue { ptr, ptr } %1211, 1 +// CHECK-NEXT: %1215 = extractvalue { ptr, ptr } %1211, 0 +// CHECK-NEXT: %__llgo_funcval_code161 = call ptr asm "", "=r,0"(ptr %1215) +// CHECK-NEXT: %1216 = call %reflect.Value %__llgo_funcval_code161(ptr {{(nest|swiftself)}} %1214, %"{{.*}}/runtime/internal/runtime.eface" %1213) +// CHECK-NEXT: store %reflect.Value %1209, ptr %1203, align 8 +// CHECK-NEXT: store %reflect.Value %1216, ptr %1210, align 8 +// CHECK-NEXT: %1217 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %1, i64 81 +// CHECK-NEXT: %1218 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %1217, i32 0, i32 0 +// CHECK-NEXT: %1219 = load { ptr, ptr }, ptr @main.V, align 8 +// CHECK-NEXT: %1220 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 2) +// CHECK-NEXT: store i16 81, ptr %1220, align 2 +// CHECK-NEXT: %1221 = insertvalue %"{{.*}}/runtime/internal/runtime.eface" { ptr @_llgo_uint16, ptr undef }, ptr %1220, 1 +// CHECK-NEXT: %1222 = extractvalue { ptr, ptr } %1219, 1 +// CHECK-NEXT: %1223 = extractvalue { ptr, ptr } %1219, 0 +// CHECK-NEXT: %__llgo_funcval_code162 = call ptr asm "", "=r,0"(ptr %1223) +// CHECK-NEXT: %1224 = call %reflect.Value %__llgo_funcval_code162(ptr {{(nest|swiftself)}} %1222, %"{{.*}}/runtime/internal/runtime.eface" %1221) +// CHECK-NEXT: %1225 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %1217, i32 0, i32 1 +// CHECK-NEXT: %1226 = load { ptr, ptr }, ptr @main.V, align 8 +// CHECK-NEXT: %1227 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 8) +// CHECK-NEXT: store i64 81, ptr %1227, align 8 +// CHECK-NEXT: %1228 = insertvalue %"{{.*}}/runtime/internal/runtime.eface" { ptr @_llgo_uint, ptr undef }, ptr %1227, 1 +// CHECK-NEXT: %1229 = extractvalue { ptr, ptr } %1226, 1 +// CHECK-NEXT: %1230 = extractvalue { ptr, ptr } %1226, 0 +// CHECK-NEXT: %__llgo_funcval_code163 = call ptr asm "", "=r,0"(ptr %1230) +// CHECK-NEXT: %1231 = call %reflect.Value %__llgo_funcval_code163(ptr {{(nest|swiftself)}} %1229, %"{{.*}}/runtime/internal/runtime.eface" %1228) +// CHECK-NEXT: store %reflect.Value %1224, ptr %1218, align 8 +// CHECK-NEXT: store %reflect.Value %1231, ptr %1225, align 8 +// CHECK-NEXT: %1232 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %1, i64 82 +// CHECK-NEXT: %1233 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %1232, i32 0, i32 0 +// CHECK-NEXT: %1234 = load { ptr, ptr }, ptr @main.V, align 8 +// CHECK-NEXT: %1235 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 8) +// CHECK-NEXT: store i64 82, ptr %1235, align 8 +// CHECK-NEXT: %1236 = insertvalue %"{{.*}}/runtime/internal/runtime.eface" { ptr @_llgo_uint, ptr undef }, ptr %1235, 1 +// CHECK-NEXT: %1237 = extractvalue { ptr, ptr } %1234, 1 +// CHECK-NEXT: %1238 = extractvalue { ptr, ptr } %1234, 0 +// CHECK-NEXT: %__llgo_funcval_code164 = call ptr asm "", "=r,0"(ptr %1238) +// CHECK-NEXT: %1239 = call %reflect.Value %__llgo_funcval_code164(ptr {{(nest|swiftself)}} %1237, %"{{.*}}/runtime/internal/runtime.eface" %1236) +// CHECK-NEXT: %1240 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %1232, i32 0, i32 1 +// CHECK-NEXT: %1241 = load { ptr, ptr }, ptr @main.V, align 8 +// CHECK-NEXT: %1242 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 2) +// CHECK-NEXT: store i16 82, ptr %1242, align 2 +// CHECK-NEXT: %1243 = insertvalue %"{{.*}}/runtime/internal/runtime.eface" { ptr @_llgo_uint16, ptr undef }, ptr %1242, 1 +// CHECK-NEXT: %1244 = extractvalue { ptr, ptr } %1241, 1 +// CHECK-NEXT: %1245 = extractvalue { ptr, ptr } %1241, 0 +// CHECK-NEXT: %__llgo_funcval_code165 = call ptr asm "", "=r,0"(ptr %1245) +// CHECK-NEXT: %1246 = call %reflect.Value %__llgo_funcval_code165(ptr {{(nest|swiftself)}} %1244, %"{{.*}}/runtime/internal/runtime.eface" %1243) +// CHECK-NEXT: store %reflect.Value %1239, ptr %1233, align 8 +// CHECK-NEXT: store %reflect.Value %1246, ptr %1240, align 8 +// CHECK-NEXT: %1247 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %1, i64 83 +// CHECK-NEXT: %1248 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %1247, i32 0, i32 0 +// CHECK-NEXT: %1249 = load { ptr, ptr }, ptr @main.V, align 8 +// CHECK-NEXT: %1250 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 2) +// CHECK-NEXT: store i16 83, ptr %1250, align 2 +// CHECK-NEXT: %1251 = insertvalue %"{{.*}}/runtime/internal/runtime.eface" { ptr @_llgo_uint16, ptr undef }, ptr %1250, 1 +// CHECK-NEXT: %1252 = extractvalue { ptr, ptr } %1249, 1 +// CHECK-NEXT: %1253 = extractvalue { ptr, ptr } %1249, 0 +// CHECK-NEXT: %__llgo_funcval_code166 = call ptr asm "", "=r,0"(ptr %1253) +// CHECK-NEXT: %1254 = call %reflect.Value %__llgo_funcval_code166(ptr {{(nest|swiftself)}} %1252, %"{{.*}}/runtime/internal/runtime.eface" %1251) +// CHECK-NEXT: %1255 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %1247, i32 0, i32 1 +// CHECK-NEXT: %1256 = load { ptr, ptr }, ptr @main.V, align 8 +// CHECK-NEXT: %1257 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 8) +// CHECK-NEXT: store i64 83, ptr %1257, align 8 +// CHECK-NEXT: %1258 = insertvalue %"{{.*}}/runtime/internal/runtime.eface" { ptr @_llgo_uintptr, ptr undef }, ptr %1257, 1 +// CHECK-NEXT: %1259 = extractvalue { ptr, ptr } %1256, 1 +// CHECK-NEXT: %1260 = extractvalue { ptr, ptr } %1256, 0 +// CHECK-NEXT: %__llgo_funcval_code167 = call ptr asm "", "=r,0"(ptr %1260) +// CHECK-NEXT: %1261 = call %reflect.Value %__llgo_funcval_code167(ptr {{(nest|swiftself)}} %1259, %"{{.*}}/runtime/internal/runtime.eface" %1258) +// CHECK-NEXT: store %reflect.Value %1254, ptr %1248, align 8 +// CHECK-NEXT: store %reflect.Value %1261, ptr %1255, align 8 +// CHECK-NEXT: %1262 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %1, i64 84 +// CHECK-NEXT: %1263 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %1262, i32 0, i32 0 +// CHECK-NEXT: %1264 = load { ptr, ptr }, ptr @main.V, align 8 +// CHECK-NEXT: %1265 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 8) +// CHECK-NEXT: store i64 84, ptr %1265, align 8 +// CHECK-NEXT: %1266 = insertvalue %"{{.*}}/runtime/internal/runtime.eface" { ptr @_llgo_uintptr, ptr undef }, ptr %1265, 1 +// CHECK-NEXT: %1267 = extractvalue { ptr, ptr } %1264, 1 +// CHECK-NEXT: %1268 = extractvalue { ptr, ptr } %1264, 0 +// CHECK-NEXT: %__llgo_funcval_code168 = call ptr asm "", "=r,0"(ptr %1268) +// CHECK-NEXT: %1269 = call %reflect.Value %__llgo_funcval_code168(ptr {{(nest|swiftself)}} %1267, %"{{.*}}/runtime/internal/runtime.eface" %1266) +// CHECK-NEXT: %1270 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %1262, i32 0, i32 1 +// CHECK-NEXT: %1271 = load { ptr, ptr }, ptr @main.V, align 8 +// CHECK-NEXT: %1272 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 2) +// CHECK-NEXT: store i16 84, ptr %1272, align 2 +// CHECK-NEXT: %1273 = insertvalue %"{{.*}}/runtime/internal/runtime.eface" { ptr @_llgo_uint16, ptr undef }, ptr %1272, 1 +// CHECK-NEXT: %1274 = extractvalue { ptr, ptr } %1271, 1 +// CHECK-NEXT: %1275 = extractvalue { ptr, ptr } %1271, 0 +// CHECK-NEXT: %__llgo_funcval_code169 = call ptr asm "", "=r,0"(ptr %1275) +// CHECK-NEXT: %1276 = call %reflect.Value %__llgo_funcval_code169(ptr {{(nest|swiftself)}} %1274, %"{{.*}}/runtime/internal/runtime.eface" %1273) +// CHECK-NEXT: store %reflect.Value %1269, ptr %1263, align 8 +// CHECK-NEXT: store %reflect.Value %1276, ptr %1270, align 8 +// CHECK-NEXT: %1277 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %1, i64 85 +// CHECK-NEXT: %1278 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %1277, i32 0, i32 0 +// CHECK-NEXT: %1279 = load { ptr, ptr }, ptr @main.V, align 8 +// CHECK-NEXT: %1280 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 2) +// CHECK-NEXT: store i16 85, ptr %1280, align 2 +// CHECK-NEXT: %1281 = insertvalue %"{{.*}}/runtime/internal/runtime.eface" { ptr @_llgo_uint16, ptr undef }, ptr %1280, 1 +// CHECK-NEXT: %1282 = extractvalue { ptr, ptr } %1279, 1 +// CHECK-NEXT: %1283 = extractvalue { ptr, ptr } %1279, 0 +// CHECK-NEXT: %__llgo_funcval_code170 = call ptr asm "", "=r,0"(ptr %1283) +// CHECK-NEXT: %1284 = call %reflect.Value %__llgo_funcval_code170(ptr {{(nest|swiftself)}} %1282, %"{{.*}}/runtime/internal/runtime.eface" %1281) +// CHECK-NEXT: %1285 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %1277, i32 0, i32 1 +// CHECK-NEXT: %1286 = load { ptr, ptr }, ptr @main.V, align 8 +// CHECK-NEXT: %1287 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 4) +// CHECK-NEXT: store float 8.500000e+01, ptr %1287, align 4 +// CHECK-NEXT: %1288 = insertvalue %"{{.*}}/runtime/internal/runtime.eface" { ptr @_llgo_float32, ptr undef }, ptr %1287, 1 +// CHECK-NEXT: %1289 = extractvalue { ptr, ptr } %1286, 1 +// CHECK-NEXT: %1290 = extractvalue { ptr, ptr } %1286, 0 +// CHECK-NEXT: %__llgo_funcval_code171 = call ptr asm "", "=r,0"(ptr %1290) +// CHECK-NEXT: %1291 = call %reflect.Value %__llgo_funcval_code171(ptr {{(nest|swiftself)}} %1289, %"{{.*}}/runtime/internal/runtime.eface" %1288) +// CHECK-NEXT: store %reflect.Value %1284, ptr %1278, align 8 +// CHECK-NEXT: store %reflect.Value %1291, ptr %1285, align 8 +// CHECK-NEXT: %1292 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %1, i64 86 +// CHECK-NEXT: %1293 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %1292, i32 0, i32 0 +// CHECK-NEXT: %1294 = load { ptr, ptr }, ptr @main.V, align 8 +// CHECK-NEXT: %1295 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 4) +// CHECK-NEXT: store float 8.600000e+01, ptr %1295, align 4 +// CHECK-NEXT: %1296 = insertvalue %"{{.*}}/runtime/internal/runtime.eface" { ptr @_llgo_float32, ptr undef }, ptr %1295, 1 +// CHECK-NEXT: %1297 = extractvalue { ptr, ptr } %1294, 1 +// CHECK-NEXT: %1298 = extractvalue { ptr, ptr } %1294, 0 +// CHECK-NEXT: %__llgo_funcval_code172 = call ptr asm "", "=r,0"(ptr %1298) +// CHECK-NEXT: %1299 = call %reflect.Value %__llgo_funcval_code172(ptr {{(nest|swiftself)}} %1297, %"{{.*}}/runtime/internal/runtime.eface" %1296) +// CHECK-NEXT: %1300 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %1292, i32 0, i32 1 +// CHECK-NEXT: %1301 = load { ptr, ptr }, ptr @main.V, align 8 +// CHECK-NEXT: %1302 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 2) +// CHECK-NEXT: store i16 86, ptr %1302, align 2 +// CHECK-NEXT: %1303 = insertvalue %"{{.*}}/runtime/internal/runtime.eface" { ptr @_llgo_uint16, ptr undef }, ptr %1302, 1 +// CHECK-NEXT: %1304 = extractvalue { ptr, ptr } %1301, 1 +// CHECK-NEXT: %1305 = extractvalue { ptr, ptr } %1301, 0 +// CHECK-NEXT: %__llgo_funcval_code173 = call ptr asm "", "=r,0"(ptr %1305) +// CHECK-NEXT: %1306 = call %reflect.Value %__llgo_funcval_code173(ptr {{(nest|swiftself)}} %1304, %"{{.*}}/runtime/internal/runtime.eface" %1303) +// CHECK-NEXT: store %reflect.Value %1299, ptr %1293, align 8 +// CHECK-NEXT: store %reflect.Value %1306, ptr %1300, align 8 +// CHECK-NEXT: %1307 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %1, i64 87 +// CHECK-NEXT: %1308 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %1307, i32 0, i32 0 +// CHECK-NEXT: %1309 = load { ptr, ptr }, ptr @main.V, align 8 +// CHECK-NEXT: %1310 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 2) +// CHECK-NEXT: store i16 87, ptr %1310, align 2 +// CHECK-NEXT: %1311 = insertvalue %"{{.*}}/runtime/internal/runtime.eface" { ptr @_llgo_uint16, ptr undef }, ptr %1310, 1 +// CHECK-NEXT: %1312 = extractvalue { ptr, ptr } %1309, 1 +// CHECK-NEXT: %1313 = extractvalue { ptr, ptr } %1309, 0 +// CHECK-NEXT: %__llgo_funcval_code174 = call ptr asm "", "=r,0"(ptr %1313) +// CHECK-NEXT: %1314 = call %reflect.Value %__llgo_funcval_code174(ptr {{(nest|swiftself)}} %1312, %"{{.*}}/runtime/internal/runtime.eface" %1311) +// CHECK-NEXT: %1315 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %1307, i32 0, i32 1 +// CHECK-NEXT: %1316 = load { ptr, ptr }, ptr @main.V, align 8 +// CHECK-NEXT: %1317 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 8) +// CHECK-NEXT: store double 8.700000e+01, ptr %1317, align 8 +// CHECK-NEXT: %1318 = insertvalue %"{{.*}}/runtime/internal/runtime.eface" { ptr @_llgo_float64, ptr undef }, ptr %1317, 1 +// CHECK-NEXT: %1319 = extractvalue { ptr, ptr } %1316, 1 +// CHECK-NEXT: %1320 = extractvalue { ptr, ptr } %1316, 0 +// CHECK-NEXT: %__llgo_funcval_code175 = call ptr asm "", "=r,0"(ptr %1320) +// CHECK-NEXT: %1321 = call %reflect.Value %__llgo_funcval_code175(ptr {{(nest|swiftself)}} %1319, %"{{.*}}/runtime/internal/runtime.eface" %1318) +// CHECK-NEXT: store %reflect.Value %1314, ptr %1308, align 8 +// CHECK-NEXT: store %reflect.Value %1321, ptr %1315, align 8 +// CHECK-NEXT: %1322 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %1, i64 88 +// CHECK-NEXT: %1323 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %1322, i32 0, i32 0 +// CHECK-NEXT: %1324 = load { ptr, ptr }, ptr @main.V, align 8 +// CHECK-NEXT: %1325 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 8) +// CHECK-NEXT: store double 8.800000e+01, ptr %1325, align 8 +// CHECK-NEXT: %1326 = insertvalue %"{{.*}}/runtime/internal/runtime.eface" { ptr @_llgo_float64, ptr undef }, ptr %1325, 1 +// CHECK-NEXT: %1327 = extractvalue { ptr, ptr } %1324, 1 +// CHECK-NEXT: %1328 = extractvalue { ptr, ptr } %1324, 0 +// CHECK-NEXT: %__llgo_funcval_code176 = call ptr asm "", "=r,0"(ptr %1328) +// CHECK-NEXT: %1329 = call %reflect.Value %__llgo_funcval_code176(ptr {{(nest|swiftself)}} %1327, %"{{.*}}/runtime/internal/runtime.eface" %1326) +// CHECK-NEXT: %1330 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %1322, i32 0, i32 1 +// CHECK-NEXT: %1331 = load { ptr, ptr }, ptr @main.V, align 8 +// CHECK-NEXT: %1332 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 2) +// CHECK-NEXT: store i16 88, ptr %1332, align 2 +// CHECK-NEXT: %1333 = insertvalue %"{{.*}}/runtime/internal/runtime.eface" { ptr @_llgo_uint16, ptr undef }, ptr %1332, 1 +// CHECK-NEXT: %1334 = extractvalue { ptr, ptr } %1331, 1 +// CHECK-NEXT: %1335 = extractvalue { ptr, ptr } %1331, 0 +// CHECK-NEXT: %__llgo_funcval_code177 = call ptr asm "", "=r,0"(ptr %1335) +// CHECK-NEXT: %1336 = call %reflect.Value %__llgo_funcval_code177(ptr {{(nest|swiftself)}} %1334, %"{{.*}}/runtime/internal/runtime.eface" %1333) +// CHECK-NEXT: store %reflect.Value %1329, ptr %1323, align 8 +// CHECK-NEXT: store %reflect.Value %1336, ptr %1330, align 8 +// CHECK-NEXT: %1337 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %1, i64 89 +// CHECK-NEXT: %1338 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %1337, i32 0, i32 0 +// CHECK-NEXT: %1339 = load { ptr, ptr }, ptr @main.V, align 8 +// CHECK-NEXT: %1340 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 4) +// CHECK-NEXT: store i32 89, ptr %1340, align 4 +// CHECK-NEXT: %1341 = insertvalue %"{{.*}}/runtime/internal/runtime.eface" { ptr @_llgo_int32, ptr undef }, ptr %1340, 1 +// CHECK-NEXT: %1342 = extractvalue { ptr, ptr } %1339, 1 +// CHECK-NEXT: %1343 = extractvalue { ptr, ptr } %1339, 0 +// CHECK-NEXT: %__llgo_funcval_code178 = call ptr asm "", "=r,0"(ptr %1343) +// CHECK-NEXT: %1344 = call %reflect.Value %__llgo_funcval_code178(ptr {{(nest|swiftself)}} %1342, %"{{.*}}/runtime/internal/runtime.eface" %1341) +// CHECK-NEXT: %1345 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %1337, i32 0, i32 1 +// CHECK-NEXT: %1346 = load { ptr, ptr }, ptr @main.V, align 8 +// CHECK-NEXT: %1347 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 4) +// CHECK-NEXT: store i32 89, ptr %1347, align 4 +// CHECK-NEXT: %1348 = insertvalue %"{{.*}}/runtime/internal/runtime.eface" { ptr @_llgo_int32, ptr undef }, ptr %1347, 1 +// CHECK-NEXT: %1349 = extractvalue { ptr, ptr } %1346, 1 +// CHECK-NEXT: %1350 = extractvalue { ptr, ptr } %1346, 0 +// CHECK-NEXT: %__llgo_funcval_code179 = call ptr asm "", "=r,0"(ptr %1350) +// CHECK-NEXT: %1351 = call %reflect.Value %__llgo_funcval_code179(ptr {{(nest|swiftself)}} %1349, %"{{.*}}/runtime/internal/runtime.eface" %1348) +// CHECK-NEXT: store %reflect.Value %1344, ptr %1338, align 8 +// CHECK-NEXT: store %reflect.Value %1351, ptr %1345, align 8 +// CHECK-NEXT: %1352 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %1, i64 90 +// CHECK-NEXT: %1353 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %1352, i32 0, i32 0 +// CHECK-NEXT: %1354 = load { ptr, ptr }, ptr @main.V, align 8 +// CHECK-NEXT: %1355 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 4) +// CHECK-NEXT: store i32 90, ptr %1355, align 4 +// CHECK-NEXT: %1356 = insertvalue %"{{.*}}/runtime/internal/runtime.eface" { ptr @_llgo_int32, ptr undef }, ptr %1355, 1 +// CHECK-NEXT: %1357 = extractvalue { ptr, ptr } %1354, 1 +// CHECK-NEXT: %1358 = extractvalue { ptr, ptr } %1354, 0 +// CHECK-NEXT: %__llgo_funcval_code180 = call ptr asm "", "=r,0"(ptr %1358) +// CHECK-NEXT: %1359 = call %reflect.Value %__llgo_funcval_code180(ptr {{(nest|swiftself)}} %1357, %"{{.*}}/runtime/internal/runtime.eface" %1356) +// CHECK-NEXT: %1360 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %1352, i32 0, i32 1 +// CHECK-NEXT: %1361 = load { ptr, ptr }, ptr @main.V, align 8 +// CHECK-NEXT: %1362 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 4) +// CHECK-NEXT: store i32 90, ptr %1362, align 4 +// CHECK-NEXT: %1363 = insertvalue %"{{.*}}/runtime/internal/runtime.eface" { ptr @_llgo_uint32, ptr undef }, ptr %1362, 1 +// CHECK-NEXT: %1364 = extractvalue { ptr, ptr } %1361, 1 +// CHECK-NEXT: %1365 = extractvalue { ptr, ptr } %1361, 0 +// CHECK-NEXT: %__llgo_funcval_code181 = call ptr asm "", "=r,0"(ptr %1365) +// CHECK-NEXT: %1366 = call %reflect.Value %__llgo_funcval_code181(ptr {{(nest|swiftself)}} %1364, %"{{.*}}/runtime/internal/runtime.eface" %1363) +// CHECK-NEXT: store %reflect.Value %1359, ptr %1353, align 8 +// CHECK-NEXT: store %reflect.Value %1366, ptr %1360, align 8 +// CHECK-NEXT: %1367 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %1, i64 91 +// CHECK-NEXT: %1368 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %1367, i32 0, i32 0 +// CHECK-NEXT: %1369 = load { ptr, ptr }, ptr @main.V, align 8 +// CHECK-NEXT: %1370 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 4) +// CHECK-NEXT: store i32 91, ptr %1370, align 4 +// CHECK-NEXT: %1371 = insertvalue %"{{.*}}/runtime/internal/runtime.eface" { ptr @_llgo_uint32, ptr undef }, ptr %1370, 1 +// CHECK-NEXT: %1372 = extractvalue { ptr, ptr } %1369, 1 +// CHECK-NEXT: %1373 = extractvalue { ptr, ptr } %1369, 0 +// CHECK-NEXT: %__llgo_funcval_code182 = call ptr asm "", "=r,0"(ptr %1373) +// CHECK-NEXT: %1374 = call %reflect.Value %__llgo_funcval_code182(ptr {{(nest|swiftself)}} %1372, %"{{.*}}/runtime/internal/runtime.eface" %1371) +// CHECK-NEXT: %1375 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %1367, i32 0, i32 1 +// CHECK-NEXT: %1376 = load { ptr, ptr }, ptr @main.V, align 8 +// CHECK-NEXT: %1377 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 4) +// CHECK-NEXT: store i32 91, ptr %1377, align 4 +// CHECK-NEXT: %1378 = insertvalue %"{{.*}}/runtime/internal/runtime.eface" { ptr @_llgo_int32, ptr undef }, ptr %1377, 1 +// CHECK-NEXT: %1379 = extractvalue { ptr, ptr } %1376, 1 +// CHECK-NEXT: %1380 = extractvalue { ptr, ptr } %1376, 0 +// CHECK-NEXT: %__llgo_funcval_code183 = call ptr asm "", "=r,0"(ptr %1380) +// CHECK-NEXT: %1381 = call %reflect.Value %__llgo_funcval_code183(ptr {{(nest|swiftself)}} %1379, %"{{.*}}/runtime/internal/runtime.eface" %1378) +// CHECK-NEXT: store %reflect.Value %1374, ptr %1368, align 8 +// CHECK-NEXT: store %reflect.Value %1381, ptr %1375, align 8 +// CHECK-NEXT: %1382 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %1, i64 92 +// CHECK-NEXT: %1383 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %1382, i32 0, i32 0 +// CHECK-NEXT: %1384 = load { ptr, ptr }, ptr @main.V, align 8 +// CHECK-NEXT: %1385 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 4) +// CHECK-NEXT: store i32 92, ptr %1385, align 4 +// CHECK-NEXT: %1386 = insertvalue %"{{.*}}/runtime/internal/runtime.eface" { ptr @_llgo_int32, ptr undef }, ptr %1385, 1 +// CHECK-NEXT: %1387 = extractvalue { ptr, ptr } %1384, 1 +// CHECK-NEXT: %1388 = extractvalue { ptr, ptr } %1384, 0 +// CHECK-NEXT: %__llgo_funcval_code184 = call ptr asm "", "=r,0"(ptr %1388) +// CHECK-NEXT: %1389 = call %reflect.Value %__llgo_funcval_code184(ptr {{(nest|swiftself)}} %1387, %"{{.*}}/runtime/internal/runtime.eface" %1386) +// CHECK-NEXT: %1390 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %1382, i32 0, i32 1 +// CHECK-NEXT: %1391 = load { ptr, ptr }, ptr @main.V, align 8 +// CHECK-NEXT: %1392 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 8) +// CHECK-NEXT: store i64 92, ptr %1392, align 8 +// CHECK-NEXT: %1393 = insertvalue %"{{.*}}/runtime/internal/runtime.eface" { ptr @_llgo_int64, ptr undef }, ptr %1392, 1 +// CHECK-NEXT: %1394 = extractvalue { ptr, ptr } %1391, 1 +// CHECK-NEXT: %1395 = extractvalue { ptr, ptr } %1391, 0 +// CHECK-NEXT: %__llgo_funcval_code185 = call ptr asm "", "=r,0"(ptr %1395) +// CHECK-NEXT: %1396 = call %reflect.Value %__llgo_funcval_code185(ptr {{(nest|swiftself)}} %1394, %"{{.*}}/runtime/internal/runtime.eface" %1393) +// CHECK-NEXT: store %reflect.Value %1389, ptr %1383, align 8 +// CHECK-NEXT: store %reflect.Value %1396, ptr %1390, align 8 +// CHECK-NEXT: %1397 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %1, i64 93 +// CHECK-NEXT: %1398 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %1397, i32 0, i32 0 +// CHECK-NEXT: %1399 = load { ptr, ptr }, ptr @main.V, align 8 +// CHECK-NEXT: %1400 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 8) +// CHECK-NEXT: store i64 93, ptr %1400, align 8 +// CHECK-NEXT: %1401 = insertvalue %"{{.*}}/runtime/internal/runtime.eface" { ptr @_llgo_int64, ptr undef }, ptr %1400, 1 +// CHECK-NEXT: %1402 = extractvalue { ptr, ptr } %1399, 1 +// CHECK-NEXT: %1403 = extractvalue { ptr, ptr } %1399, 0 +// CHECK-NEXT: %__llgo_funcval_code186 = call ptr asm "", "=r,0"(ptr %1403) +// CHECK-NEXT: %1404 = call %reflect.Value %__llgo_funcval_code186(ptr {{(nest|swiftself)}} %1402, %"{{.*}}/runtime/internal/runtime.eface" %1401) +// CHECK-NEXT: %1405 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %1397, i32 0, i32 1 +// CHECK-NEXT: %1406 = load { ptr, ptr }, ptr @main.V, align 8 +// CHECK-NEXT: %1407 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 4) +// CHECK-NEXT: store i32 93, ptr %1407, align 4 +// CHECK-NEXT: %1408 = insertvalue %"{{.*}}/runtime/internal/runtime.eface" { ptr @_llgo_int32, ptr undef }, ptr %1407, 1 +// CHECK-NEXT: %1409 = extractvalue { ptr, ptr } %1406, 1 +// CHECK-NEXT: %1410 = extractvalue { ptr, ptr } %1406, 0 +// CHECK-NEXT: %__llgo_funcval_code187 = call ptr asm "", "=r,0"(ptr %1410) +// CHECK-NEXT: %1411 = call %reflect.Value %__llgo_funcval_code187(ptr {{(nest|swiftself)}} %1409, %"{{.*}}/runtime/internal/runtime.eface" %1408) +// CHECK-NEXT: store %reflect.Value %1404, ptr %1398, align 8 +// CHECK-NEXT: store %reflect.Value %1411, ptr %1405, align 8 +// CHECK-NEXT: %1412 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %1, i64 94 +// CHECK-NEXT: %1413 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %1412, i32 0, i32 0 +// CHECK-NEXT: %1414 = load { ptr, ptr }, ptr @main.V, align 8 +// CHECK-NEXT: %1415 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 4) +// CHECK-NEXT: store i32 94, ptr %1415, align 4 +// CHECK-NEXT: %1416 = insertvalue %"{{.*}}/runtime/internal/runtime.eface" { ptr @_llgo_int32, ptr undef }, ptr %1415, 1 +// CHECK-NEXT: %1417 = extractvalue { ptr, ptr } %1414, 1 +// CHECK-NEXT: %1418 = extractvalue { ptr, ptr } %1414, 0 +// CHECK-NEXT: %__llgo_funcval_code188 = call ptr asm "", "=r,0"(ptr %1418) +// CHECK-NEXT: %1419 = call %reflect.Value %__llgo_funcval_code188(ptr {{(nest|swiftself)}} %1417, %"{{.*}}/runtime/internal/runtime.eface" %1416) +// CHECK-NEXT: %1420 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %1412, i32 0, i32 1 +// CHECK-NEXT: %1421 = load { ptr, ptr }, ptr @main.V, align 8 +// CHECK-NEXT: %1422 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 8) +// CHECK-NEXT: store i64 94, ptr %1422, align 8 +// CHECK-NEXT: %1423 = insertvalue %"{{.*}}/runtime/internal/runtime.eface" { ptr @_llgo_uint64, ptr undef }, ptr %1422, 1 +// CHECK-NEXT: %1424 = extractvalue { ptr, ptr } %1421, 1 +// CHECK-NEXT: %1425 = extractvalue { ptr, ptr } %1421, 0 +// CHECK-NEXT: %__llgo_funcval_code189 = call ptr asm "", "=r,0"(ptr %1425) +// CHECK-NEXT: %1426 = call %reflect.Value %__llgo_funcval_code189(ptr {{(nest|swiftself)}} %1424, %"{{.*}}/runtime/internal/runtime.eface" %1423) +// CHECK-NEXT: store %reflect.Value %1419, ptr %1413, align 8 +// CHECK-NEXT: store %reflect.Value %1426, ptr %1420, align 8 +// CHECK-NEXT: %1427 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %1, i64 95 +// CHECK-NEXT: %1428 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %1427, i32 0, i32 0 +// CHECK-NEXT: %1429 = load { ptr, ptr }, ptr @main.V, align 8 +// CHECK-NEXT: %1430 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 8) +// CHECK-NEXT: store i64 95, ptr %1430, align 8 +// CHECK-NEXT: %1431 = insertvalue %"{{.*}}/runtime/internal/runtime.eface" { ptr @_llgo_uint64, ptr undef }, ptr %1430, 1 +// CHECK-NEXT: %1432 = extractvalue { ptr, ptr } %1429, 1 +// CHECK-NEXT: %1433 = extractvalue { ptr, ptr } %1429, 0 +// CHECK-NEXT: %__llgo_funcval_code190 = call ptr asm "", "=r,0"(ptr %1433) +// CHECK-NEXT: %1434 = call %reflect.Value %__llgo_funcval_code190(ptr {{(nest|swiftself)}} %1432, %"{{.*}}/runtime/internal/runtime.eface" %1431) +// CHECK-NEXT: %1435 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %1427, i32 0, i32 1 +// CHECK-NEXT: %1436 = load { ptr, ptr }, ptr @main.V, align 8 +// CHECK-NEXT: %1437 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 4) +// CHECK-NEXT: store i32 95, ptr %1437, align 4 +// CHECK-NEXT: %1438 = insertvalue %"{{.*}}/runtime/internal/runtime.eface" { ptr @_llgo_int32, ptr undef }, ptr %1437, 1 +// CHECK-NEXT: %1439 = extractvalue { ptr, ptr } %1436, 1 +// CHECK-NEXT: %1440 = extractvalue { ptr, ptr } %1436, 0 +// CHECK-NEXT: %__llgo_funcval_code191 = call ptr asm "", "=r,0"(ptr %1440) +// CHECK-NEXT: %1441 = call %reflect.Value %__llgo_funcval_code191(ptr {{(nest|swiftself)}} %1439, %"{{.*}}/runtime/internal/runtime.eface" %1438) +// CHECK-NEXT: store %reflect.Value %1434, ptr %1428, align 8 +// CHECK-NEXT: store %reflect.Value %1441, ptr %1435, align 8 +// CHECK-NEXT: %1442 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %1, i64 96 +// CHECK-NEXT: %1443 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %1442, i32 0, i32 0 +// CHECK-NEXT: %1444 = load { ptr, ptr }, ptr @main.V, align 8 +// CHECK-NEXT: %1445 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 4) +// CHECK-NEXT: store i32 96, ptr %1445, align 4 +// CHECK-NEXT: %1446 = insertvalue %"{{.*}}/runtime/internal/runtime.eface" { ptr @_llgo_int32, ptr undef }, ptr %1445, 1 +// CHECK-NEXT: %1447 = extractvalue { ptr, ptr } %1444, 1 +// CHECK-NEXT: %1448 = extractvalue { ptr, ptr } %1444, 0 +// CHECK-NEXT: %__llgo_funcval_code192 = call ptr asm "", "=r,0"(ptr %1448) +// CHECK-NEXT: %1449 = call %reflect.Value %__llgo_funcval_code192(ptr {{(nest|swiftself)}} %1447, %"{{.*}}/runtime/internal/runtime.eface" %1446) +// CHECK-NEXT: %1450 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %1442, i32 0, i32 1 +// CHECK-NEXT: %1451 = load { ptr, ptr }, ptr @main.V, align 8 +// CHECK-NEXT: %1452 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 8) +// CHECK-NEXT: store i64 96, ptr %1452, align 8 +// CHECK-NEXT: %1453 = insertvalue %"{{.*}}/runtime/internal/runtime.eface" { ptr @_llgo_int, ptr undef }, ptr %1452, 1 +// CHECK-NEXT: %1454 = extractvalue { ptr, ptr } %1451, 1 +// CHECK-NEXT: %1455 = extractvalue { ptr, ptr } %1451, 0 +// CHECK-NEXT: %__llgo_funcval_code193 = call ptr asm "", "=r,0"(ptr %1455) +// CHECK-NEXT: %1456 = call %reflect.Value %__llgo_funcval_code193(ptr {{(nest|swiftself)}} %1454, %"{{.*}}/runtime/internal/runtime.eface" %1453) +// CHECK-NEXT: store %reflect.Value %1449, ptr %1443, align 8 +// CHECK-NEXT: store %reflect.Value %1456, ptr %1450, align 8 +// CHECK-NEXT: %1457 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %1, i64 97 +// CHECK-NEXT: %1458 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %1457, i32 0, i32 0 +// CHECK-NEXT: %1459 = load { ptr, ptr }, ptr @main.V, align 8 +// CHECK-NEXT: %1460 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 8) +// CHECK-NEXT: store i64 97, ptr %1460, align 8 +// CHECK-NEXT: %1461 = insertvalue %"{{.*}}/runtime/internal/runtime.eface" { ptr @_llgo_int, ptr undef }, ptr %1460, 1 +// CHECK-NEXT: %1462 = extractvalue { ptr, ptr } %1459, 1 +// CHECK-NEXT: %1463 = extractvalue { ptr, ptr } %1459, 0 +// CHECK-NEXT: %__llgo_funcval_code194 = call ptr asm "", "=r,0"(ptr %1463) +// CHECK-NEXT: %1464 = call %reflect.Value %__llgo_funcval_code194(ptr {{(nest|swiftself)}} %1462, %"{{.*}}/runtime/internal/runtime.eface" %1461) +// CHECK-NEXT: %1465 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %1457, i32 0, i32 1 +// CHECK-NEXT: %1466 = load { ptr, ptr }, ptr @main.V, align 8 +// CHECK-NEXT: %1467 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 4) +// CHECK-NEXT: store i32 97, ptr %1467, align 4 +// CHECK-NEXT: %1468 = insertvalue %"{{.*}}/runtime/internal/runtime.eface" { ptr @_llgo_int32, ptr undef }, ptr %1467, 1 +// CHECK-NEXT: %1469 = extractvalue { ptr, ptr } %1466, 1 +// CHECK-NEXT: %1470 = extractvalue { ptr, ptr } %1466, 0 +// CHECK-NEXT: %__llgo_funcval_code195 = call ptr asm "", "=r,0"(ptr %1470) +// CHECK-NEXT: %1471 = call %reflect.Value %__llgo_funcval_code195(ptr {{(nest|swiftself)}} %1469, %"{{.*}}/runtime/internal/runtime.eface" %1468) +// CHECK-NEXT: store %reflect.Value %1464, ptr %1458, align 8 +// CHECK-NEXT: store %reflect.Value %1471, ptr %1465, align 8 +// CHECK-NEXT: %1472 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %1, i64 98 +// CHECK-NEXT: %1473 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %1472, i32 0, i32 0 +// CHECK-NEXT: %1474 = load { ptr, ptr }, ptr @main.V, align 8 +// CHECK-NEXT: %1475 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 4) +// CHECK-NEXT: store i32 98, ptr %1475, align 4 +// CHECK-NEXT: %1476 = insertvalue %"{{.*}}/runtime/internal/runtime.eface" { ptr @_llgo_int32, ptr undef }, ptr %1475, 1 +// CHECK-NEXT: %1477 = extractvalue { ptr, ptr } %1474, 1 +// CHECK-NEXT: %1478 = extractvalue { ptr, ptr } %1474, 0 +// CHECK-NEXT: %__llgo_funcval_code196 = call ptr asm "", "=r,0"(ptr %1478) +// CHECK-NEXT: %1479 = call %reflect.Value %__llgo_funcval_code196(ptr {{(nest|swiftself)}} %1477, %"{{.*}}/runtime/internal/runtime.eface" %1476) +// CHECK-NEXT: %1480 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %1472, i32 0, i32 1 +// CHECK-NEXT: %1481 = load { ptr, ptr }, ptr @main.V, align 8 +// CHECK-NEXT: %1482 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 8) +// CHECK-NEXT: store i64 98, ptr %1482, align 8 +// CHECK-NEXT: %1483 = insertvalue %"{{.*}}/runtime/internal/runtime.eface" { ptr @_llgo_uint, ptr undef }, ptr %1482, 1 +// CHECK-NEXT: %1484 = extractvalue { ptr, ptr } %1481, 1 +// CHECK-NEXT: %1485 = extractvalue { ptr, ptr } %1481, 0 +// CHECK-NEXT: %__llgo_funcval_code197 = call ptr asm "", "=r,0"(ptr %1485) +// CHECK-NEXT: %1486 = call %reflect.Value %__llgo_funcval_code197(ptr {{(nest|swiftself)}} %1484, %"{{.*}}/runtime/internal/runtime.eface" %1483) +// CHECK-NEXT: store %reflect.Value %1479, ptr %1473, align 8 +// CHECK-NEXT: store %reflect.Value %1486, ptr %1480, align 8 +// CHECK-NEXT: %1487 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %1, i64 99 +// CHECK-NEXT: %1488 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %1487, i32 0, i32 0 +// CHECK-NEXT: %1489 = load { ptr, ptr }, ptr @main.V, align 8 +// CHECK-NEXT: %1490 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 8) +// CHECK-NEXT: store i64 99, ptr %1490, align 8 +// CHECK-NEXT: %1491 = insertvalue %"{{.*}}/runtime/internal/runtime.eface" { ptr @_llgo_uint, ptr undef }, ptr %1490, 1 +// CHECK-NEXT: %1492 = extractvalue { ptr, ptr } %1489, 1 +// CHECK-NEXT: %1493 = extractvalue { ptr, ptr } %1489, 0 +// CHECK-NEXT: %__llgo_funcval_code198 = call ptr asm "", "=r,0"(ptr %1493) +// CHECK-NEXT: %1494 = call %reflect.Value %__llgo_funcval_code198(ptr {{(nest|swiftself)}} %1492, %"{{.*}}/runtime/internal/runtime.eface" %1491) +// CHECK-NEXT: %1495 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %1487, i32 0, i32 1 +// CHECK-NEXT: %1496 = load { ptr, ptr }, ptr @main.V, align 8 +// CHECK-NEXT: %1497 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 4) +// CHECK-NEXT: store i32 99, ptr %1497, align 4 +// CHECK-NEXT: %1498 = insertvalue %"{{.*}}/runtime/internal/runtime.eface" { ptr @_llgo_int32, ptr undef }, ptr %1497, 1 +// CHECK-NEXT: %1499 = extractvalue { ptr, ptr } %1496, 1 +// CHECK-NEXT: %1500 = extractvalue { ptr, ptr } %1496, 0 +// CHECK-NEXT: %__llgo_funcval_code199 = call ptr asm "", "=r,0"(ptr %1500) +// CHECK-NEXT: %1501 = call %reflect.Value %__llgo_funcval_code199(ptr {{(nest|swiftself)}} %1499, %"{{.*}}/runtime/internal/runtime.eface" %1498) +// CHECK-NEXT: store %reflect.Value %1494, ptr %1488, align 8 +// CHECK-NEXT: store %reflect.Value %1501, ptr %1495, align 8 +// CHECK-NEXT: %1502 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %1, i64 100 +// CHECK-NEXT: %1503 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %1502, i32 0, i32 0 +// CHECK-NEXT: %1504 = load { ptr, ptr }, ptr @main.V, align 8 +// CHECK-NEXT: %1505 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 4) +// CHECK-NEXT: store i32 100, ptr %1505, align 4 +// CHECK-NEXT: %1506 = insertvalue %"{{.*}}/runtime/internal/runtime.eface" { ptr @_llgo_int32, ptr undef }, ptr %1505, 1 +// CHECK-NEXT: %1507 = extractvalue { ptr, ptr } %1504, 1 +// CHECK-NEXT: %1508 = extractvalue { ptr, ptr } %1504, 0 +// CHECK-NEXT: %__llgo_funcval_code200 = call ptr asm "", "=r,0"(ptr %1508) +// CHECK-NEXT: %1509 = call %reflect.Value %__llgo_funcval_code200(ptr {{(nest|swiftself)}} %1507, %"{{.*}}/runtime/internal/runtime.eface" %1506) +// CHECK-NEXT: %1510 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %1502, i32 0, i32 1 +// CHECK-NEXT: %1511 = load { ptr, ptr }, ptr @main.V, align 8 +// CHECK-NEXT: %1512 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 8) +// CHECK-NEXT: store i64 100, ptr %1512, align 8 +// CHECK-NEXT: %1513 = insertvalue %"{{.*}}/runtime/internal/runtime.eface" { ptr @_llgo_uintptr, ptr undef }, ptr %1512, 1 +// CHECK-NEXT: %1514 = extractvalue { ptr, ptr } %1511, 1 +// CHECK-NEXT: %1515 = extractvalue { ptr, ptr } %1511, 0 +// CHECK-NEXT: %__llgo_funcval_code201 = call ptr asm "", "=r,0"(ptr %1515) +// CHECK-NEXT: %1516 = call %reflect.Value %__llgo_funcval_code201(ptr {{(nest|swiftself)}} %1514, %"{{.*}}/runtime/internal/runtime.eface" %1513) +// CHECK-NEXT: store %reflect.Value %1509, ptr %1503, align 8 +// CHECK-NEXT: store %reflect.Value %1516, ptr %1510, align 8 +// CHECK-NEXT: %1517 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %1, i64 101 +// CHECK-NEXT: %1518 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %1517, i32 0, i32 0 +// CHECK-NEXT: %1519 = load { ptr, ptr }, ptr @main.V, align 8 +// CHECK-NEXT: %1520 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 8) +// CHECK-NEXT: store i64 101, ptr %1520, align 8 +// CHECK-NEXT: %1521 = insertvalue %"{{.*}}/runtime/internal/runtime.eface" { ptr @_llgo_uintptr, ptr undef }, ptr %1520, 1 +// CHECK-NEXT: %1522 = extractvalue { ptr, ptr } %1519, 1 +// CHECK-NEXT: %1523 = extractvalue { ptr, ptr } %1519, 0 +// CHECK-NEXT: %__llgo_funcval_code202 = call ptr asm "", "=r,0"(ptr %1523) +// CHECK-NEXT: %1524 = call %reflect.Value %__llgo_funcval_code202(ptr {{(nest|swiftself)}} %1522, %"{{.*}}/runtime/internal/runtime.eface" %1521) +// CHECK-NEXT: %1525 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %1517, i32 0, i32 1 +// CHECK-NEXT: %1526 = load { ptr, ptr }, ptr @main.V, align 8 +// CHECK-NEXT: %1527 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 4) +// CHECK-NEXT: store i32 101, ptr %1527, align 4 +// CHECK-NEXT: %1528 = insertvalue %"{{.*}}/runtime/internal/runtime.eface" { ptr @_llgo_int32, ptr undef }, ptr %1527, 1 +// CHECK-NEXT: %1529 = extractvalue { ptr, ptr } %1526, 1 +// CHECK-NEXT: %1530 = extractvalue { ptr, ptr } %1526, 0 +// CHECK-NEXT: %__llgo_funcval_code203 = call ptr asm "", "=r,0"(ptr %1530) +// CHECK-NEXT: %1531 = call %reflect.Value %__llgo_funcval_code203(ptr {{(nest|swiftself)}} %1529, %"{{.*}}/runtime/internal/runtime.eface" %1528) +// CHECK-NEXT: store %reflect.Value %1524, ptr %1518, align 8 +// CHECK-NEXT: store %reflect.Value %1531, ptr %1525, align 8 +// CHECK-NEXT: %1532 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %1, i64 102 +// CHECK-NEXT: %1533 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %1532, i32 0, i32 0 +// CHECK-NEXT: %1534 = load { ptr, ptr }, ptr @main.V, align 8 +// CHECK-NEXT: %1535 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 4) +// CHECK-NEXT: store i32 102, ptr %1535, align 4 +// CHECK-NEXT: %1536 = insertvalue %"{{.*}}/runtime/internal/runtime.eface" { ptr @_llgo_int32, ptr undef }, ptr %1535, 1 +// CHECK-NEXT: %1537 = extractvalue { ptr, ptr } %1534, 1 +// CHECK-NEXT: %1538 = extractvalue { ptr, ptr } %1534, 0 +// CHECK-NEXT: %__llgo_funcval_code204 = call ptr asm "", "=r,0"(ptr %1538) +// CHECK-NEXT: %1539 = call %reflect.Value %__llgo_funcval_code204(ptr {{(nest|swiftself)}} %1537, %"{{.*}}/runtime/internal/runtime.eface" %1536) +// CHECK-NEXT: %1540 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %1532, i32 0, i32 1 +// CHECK-NEXT: %1541 = load { ptr, ptr }, ptr @main.V, align 8 +// CHECK-NEXT: %1542 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 4) +// CHECK-NEXT: store float 1.020000e+02, ptr %1542, align 4 +// CHECK-NEXT: %1543 = insertvalue %"{{.*}}/runtime/internal/runtime.eface" { ptr @_llgo_float32, ptr undef }, ptr %1542, 1 +// CHECK-NEXT: %1544 = extractvalue { ptr, ptr } %1541, 1 +// CHECK-NEXT: %1545 = extractvalue { ptr, ptr } %1541, 0 +// CHECK-NEXT: %__llgo_funcval_code205 = call ptr asm "", "=r,0"(ptr %1545) +// CHECK-NEXT: %1546 = call %reflect.Value %__llgo_funcval_code205(ptr {{(nest|swiftself)}} %1544, %"{{.*}}/runtime/internal/runtime.eface" %1543) +// CHECK-NEXT: store %reflect.Value %1539, ptr %1533, align 8 +// CHECK-NEXT: store %reflect.Value %1546, ptr %1540, align 8 +// CHECK-NEXT: %1547 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %1, i64 103 +// CHECK-NEXT: %1548 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %1547, i32 0, i32 0 +// CHECK-NEXT: %1549 = load { ptr, ptr }, ptr @main.V, align 8 +// CHECK-NEXT: %1550 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 4) +// CHECK-NEXT: store float 1.030000e+02, ptr %1550, align 4 +// CHECK-NEXT: %1551 = insertvalue %"{{.*}}/runtime/internal/runtime.eface" { ptr @_llgo_float32, ptr undef }, ptr %1550, 1 +// CHECK-NEXT: %1552 = extractvalue { ptr, ptr } %1549, 1 +// CHECK-NEXT: %1553 = extractvalue { ptr, ptr } %1549, 0 +// CHECK-NEXT: %__llgo_funcval_code206 = call ptr asm "", "=r,0"(ptr %1553) +// CHECK-NEXT: %1554 = call %reflect.Value %__llgo_funcval_code206(ptr {{(nest|swiftself)}} %1552, %"{{.*}}/runtime/internal/runtime.eface" %1551) +// CHECK-NEXT: %1555 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %1547, i32 0, i32 1 +// CHECK-NEXT: %1556 = load { ptr, ptr }, ptr @main.V, align 8 +// CHECK-NEXT: %1557 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 4) +// CHECK-NEXT: store i32 103, ptr %1557, align 4 +// CHECK-NEXT: %1558 = insertvalue %"{{.*}}/runtime/internal/runtime.eface" { ptr @_llgo_int32, ptr undef }, ptr %1557, 1 +// CHECK-NEXT: %1559 = extractvalue { ptr, ptr } %1556, 1 +// CHECK-NEXT: %1560 = extractvalue { ptr, ptr } %1556, 0 +// CHECK-NEXT: %__llgo_funcval_code207 = call ptr asm "", "=r,0"(ptr %1560) +// CHECK-NEXT: %1561 = call %reflect.Value %__llgo_funcval_code207(ptr {{(nest|swiftself)}} %1559, %"{{.*}}/runtime/internal/runtime.eface" %1558) +// CHECK-NEXT: store %reflect.Value %1554, ptr %1548, align 8 +// CHECK-NEXT: store %reflect.Value %1561, ptr %1555, align 8 +// CHECK-NEXT: %1562 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %1, i64 104 +// CHECK-NEXT: %1563 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %1562, i32 0, i32 0 +// CHECK-NEXT: %1564 = load { ptr, ptr }, ptr @main.V, align 8 +// CHECK-NEXT: %1565 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 4) +// CHECK-NEXT: store i32 104, ptr %1565, align 4 +// CHECK-NEXT: %1566 = insertvalue %"{{.*}}/runtime/internal/runtime.eface" { ptr @_llgo_int32, ptr undef }, ptr %1565, 1 +// CHECK-NEXT: %1567 = extractvalue { ptr, ptr } %1564, 1 +// CHECK-NEXT: %1568 = extractvalue { ptr, ptr } %1564, 0 +// CHECK-NEXT: %__llgo_funcval_code208 = call ptr asm "", "=r,0"(ptr %1568) +// CHECK-NEXT: %1569 = call %reflect.Value %__llgo_funcval_code208(ptr {{(nest|swiftself)}} %1567, %"{{.*}}/runtime/internal/runtime.eface" %1566) +// CHECK-NEXT: %1570 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %1562, i32 0, i32 1 +// CHECK-NEXT: %1571 = load { ptr, ptr }, ptr @main.V, align 8 +// CHECK-NEXT: %1572 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 8) +// CHECK-NEXT: store double 1.040000e+02, ptr %1572, align 8 +// CHECK-NEXT: %1573 = insertvalue %"{{.*}}/runtime/internal/runtime.eface" { ptr @_llgo_float64, ptr undef }, ptr %1572, 1 +// CHECK-NEXT: %1574 = extractvalue { ptr, ptr } %1571, 1 +// CHECK-NEXT: %1575 = extractvalue { ptr, ptr } %1571, 0 +// CHECK-NEXT: %__llgo_funcval_code209 = call ptr asm "", "=r,0"(ptr %1575) +// CHECK-NEXT: %1576 = call %reflect.Value %__llgo_funcval_code209(ptr {{(nest|swiftself)}} %1574, %"{{.*}}/runtime/internal/runtime.eface" %1573) +// CHECK-NEXT: store %reflect.Value %1569, ptr %1563, align 8 +// CHECK-NEXT: store %reflect.Value %1576, ptr %1570, align 8 +// CHECK-NEXT: %1577 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %1, i64 105 +// CHECK-NEXT: %1578 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %1577, i32 0, i32 0 +// CHECK-NEXT: %1579 = load { ptr, ptr }, ptr @main.V, align 8 +// CHECK-NEXT: %1580 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 8) +// CHECK-NEXT: store double 1.050000e+02, ptr %1580, align 8 +// CHECK-NEXT: %1581 = insertvalue %"{{.*}}/runtime/internal/runtime.eface" { ptr @_llgo_float64, ptr undef }, ptr %1580, 1 +// CHECK-NEXT: %1582 = extractvalue { ptr, ptr } %1579, 1 +// CHECK-NEXT: %1583 = extractvalue { ptr, ptr } %1579, 0 +// CHECK-NEXT: %__llgo_funcval_code210 = call ptr asm "", "=r,0"(ptr %1583) +// CHECK-NEXT: %1584 = call %reflect.Value %__llgo_funcval_code210(ptr {{(nest|swiftself)}} %1582, %"{{.*}}/runtime/internal/runtime.eface" %1581) +// CHECK-NEXT: %1585 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %1577, i32 0, i32 1 +// CHECK-NEXT: %1586 = load { ptr, ptr }, ptr @main.V, align 8 +// CHECK-NEXT: %1587 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 4) +// CHECK-NEXT: store i32 105, ptr %1587, align 4 +// CHECK-NEXT: %1588 = insertvalue %"{{.*}}/runtime/internal/runtime.eface" { ptr @_llgo_int32, ptr undef }, ptr %1587, 1 +// CHECK-NEXT: %1589 = extractvalue { ptr, ptr } %1586, 1 +// CHECK-NEXT: %1590 = extractvalue { ptr, ptr } %1586, 0 +// CHECK-NEXT: %__llgo_funcval_code211 = call ptr asm "", "=r,0"(ptr %1590) +// CHECK-NEXT: %1591 = call %reflect.Value %__llgo_funcval_code211(ptr {{(nest|swiftself)}} %1589, %"{{.*}}/runtime/internal/runtime.eface" %1588) +// CHECK-NEXT: store %reflect.Value %1584, ptr %1578, align 8 +// CHECK-NEXT: store %reflect.Value %1591, ptr %1585, align 8 +// CHECK-NEXT: %1592 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %1, i64 106 +// CHECK-NEXT: %1593 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %1592, i32 0, i32 0 +// CHECK-NEXT: %1594 = load { ptr, ptr }, ptr @main.V, align 8 +// CHECK-NEXT: %1595 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 4) +// CHECK-NEXT: store i32 106, ptr %1595, align 4 +// CHECK-NEXT: %1596 = insertvalue %"{{.*}}/runtime/internal/runtime.eface" { ptr @_llgo_uint32, ptr undef }, ptr %1595, 1 +// CHECK-NEXT: %1597 = extractvalue { ptr, ptr } %1594, 1 +// CHECK-NEXT: %1598 = extractvalue { ptr, ptr } %1594, 0 +// CHECK-NEXT: %__llgo_funcval_code212 = call ptr asm "", "=r,0"(ptr %1598) +// CHECK-NEXT: %1599 = call %reflect.Value %__llgo_funcval_code212(ptr {{(nest|swiftself)}} %1597, %"{{.*}}/runtime/internal/runtime.eface" %1596) +// CHECK-NEXT: %1600 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %1592, i32 0, i32 1 +// CHECK-NEXT: %1601 = load { ptr, ptr }, ptr @main.V, align 8 +// CHECK-NEXT: %1602 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 4) +// CHECK-NEXT: store i32 106, ptr %1602, align 4 +// CHECK-NEXT: %1603 = insertvalue %"{{.*}}/runtime/internal/runtime.eface" { ptr @_llgo_uint32, ptr undef }, ptr %1602, 1 +// CHECK-NEXT: %1604 = extractvalue { ptr, ptr } %1601, 1 +// CHECK-NEXT: %1605 = extractvalue { ptr, ptr } %1601, 0 +// CHECK-NEXT: %__llgo_funcval_code213 = call ptr asm "", "=r,0"(ptr %1605) +// CHECK-NEXT: %1606 = call %reflect.Value %__llgo_funcval_code213(ptr {{(nest|swiftself)}} %1604, %"{{.*}}/runtime/internal/runtime.eface" %1603) +// CHECK-NEXT: store %reflect.Value %1599, ptr %1593, align 8 +// CHECK-NEXT: store %reflect.Value %1606, ptr %1600, align 8 +// CHECK-NEXT: %1607 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %1, i64 107 +// CHECK-NEXT: %1608 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %1607, i32 0, i32 0 +// CHECK-NEXT: %1609 = load { ptr, ptr }, ptr @main.V, align 8 +// CHECK-NEXT: %1610 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 4) +// CHECK-NEXT: store i32 107, ptr %1610, align 4 +// CHECK-NEXT: %1611 = insertvalue %"{{.*}}/runtime/internal/runtime.eface" { ptr @_llgo_uint32, ptr undef }, ptr %1610, 1 +// CHECK-NEXT: %1612 = extractvalue { ptr, ptr } %1609, 1 +// CHECK-NEXT: %1613 = extractvalue { ptr, ptr } %1609, 0 +// CHECK-NEXT: %__llgo_funcval_code214 = call ptr asm "", "=r,0"(ptr %1613) +// CHECK-NEXT: %1614 = call %reflect.Value %__llgo_funcval_code214(ptr {{(nest|swiftself)}} %1612, %"{{.*}}/runtime/internal/runtime.eface" %1611) +// CHECK-NEXT: %1615 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %1607, i32 0, i32 1 +// CHECK-NEXT: %1616 = load { ptr, ptr }, ptr @main.V, align 8 +// CHECK-NEXT: %1617 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 8) +// CHECK-NEXT: store i64 107, ptr %1617, align 8 +// CHECK-NEXT: %1618 = insertvalue %"{{.*}}/runtime/internal/runtime.eface" { ptr @_llgo_int64, ptr undef }, ptr %1617, 1 +// CHECK-NEXT: %1619 = extractvalue { ptr, ptr } %1616, 1 +// CHECK-NEXT: %1620 = extractvalue { ptr, ptr } %1616, 0 +// CHECK-NEXT: %__llgo_funcval_code215 = call ptr asm "", "=r,0"(ptr %1620) +// CHECK-NEXT: %1621 = call %reflect.Value %__llgo_funcval_code215(ptr {{(nest|swiftself)}} %1619, %"{{.*}}/runtime/internal/runtime.eface" %1618) +// CHECK-NEXT: store %reflect.Value %1614, ptr %1608, align 8 +// CHECK-NEXT: store %reflect.Value %1621, ptr %1615, align 8 +// CHECK-NEXT: %1622 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %1, i64 108 +// CHECK-NEXT: %1623 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %1622, i32 0, i32 0 +// CHECK-NEXT: %1624 = load { ptr, ptr }, ptr @main.V, align 8 +// CHECK-NEXT: %1625 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 8) +// CHECK-NEXT: store i64 108, ptr %1625, align 8 +// CHECK-NEXT: %1626 = insertvalue %"{{.*}}/runtime/internal/runtime.eface" { ptr @_llgo_int64, ptr undef }, ptr %1625, 1 +// CHECK-NEXT: %1627 = extractvalue { ptr, ptr } %1624, 1 +// CHECK-NEXT: %1628 = extractvalue { ptr, ptr } %1624, 0 +// CHECK-NEXT: %__llgo_funcval_code216 = call ptr asm "", "=r,0"(ptr %1628) +// CHECK-NEXT: %1629 = call %reflect.Value %__llgo_funcval_code216(ptr {{(nest|swiftself)}} %1627, %"{{.*}}/runtime/internal/runtime.eface" %1626) +// CHECK-NEXT: %1630 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %1622, i32 0, i32 1 +// CHECK-NEXT: %1631 = load { ptr, ptr }, ptr @main.V, align 8 +// CHECK-NEXT: %1632 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 4) +// CHECK-NEXT: store i32 108, ptr %1632, align 4 +// CHECK-NEXT: %1633 = insertvalue %"{{.*}}/runtime/internal/runtime.eface" { ptr @_llgo_uint32, ptr undef }, ptr %1632, 1 +// CHECK-NEXT: %1634 = extractvalue { ptr, ptr } %1631, 1 +// CHECK-NEXT: %1635 = extractvalue { ptr, ptr } %1631, 0 +// CHECK-NEXT: %__llgo_funcval_code217 = call ptr asm "", "=r,0"(ptr %1635) +// CHECK-NEXT: %1636 = call %reflect.Value %__llgo_funcval_code217(ptr {{(nest|swiftself)}} %1634, %"{{.*}}/runtime/internal/runtime.eface" %1633) +// CHECK-NEXT: store %reflect.Value %1629, ptr %1623, align 8 +// CHECK-NEXT: store %reflect.Value %1636, ptr %1630, align 8 +// CHECK-NEXT: %1637 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %1, i64 109 +// CHECK-NEXT: %1638 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %1637, i32 0, i32 0 +// CHECK-NEXT: %1639 = load { ptr, ptr }, ptr @main.V, align 8 +// CHECK-NEXT: %1640 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 4) +// CHECK-NEXT: store i32 109, ptr %1640, align 4 +// CHECK-NEXT: %1641 = insertvalue %"{{.*}}/runtime/internal/runtime.eface" { ptr @_llgo_uint32, ptr undef }, ptr %1640, 1 +// CHECK-NEXT: %1642 = extractvalue { ptr, ptr } %1639, 1 +// CHECK-NEXT: %1643 = extractvalue { ptr, ptr } %1639, 0 +// CHECK-NEXT: %__llgo_funcval_code218 = call ptr asm "", "=r,0"(ptr %1643) +// CHECK-NEXT: %1644 = call %reflect.Value %__llgo_funcval_code218(ptr {{(nest|swiftself)}} %1642, %"{{.*}}/runtime/internal/runtime.eface" %1641) +// CHECK-NEXT: %1645 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %1637, i32 0, i32 1 +// CHECK-NEXT: %1646 = load { ptr, ptr }, ptr @main.V, align 8 +// CHECK-NEXT: %1647 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 8) +// CHECK-NEXT: store i64 109, ptr %1647, align 8 +// CHECK-NEXT: %1648 = insertvalue %"{{.*}}/runtime/internal/runtime.eface" { ptr @_llgo_uint64, ptr undef }, ptr %1647, 1 +// CHECK-NEXT: %1649 = extractvalue { ptr, ptr } %1646, 1 +// CHECK-NEXT: %1650 = extractvalue { ptr, ptr } %1646, 0 +// CHECK-NEXT: %__llgo_funcval_code219 = call ptr asm "", "=r,0"(ptr %1650) +// CHECK-NEXT: %1651 = call %reflect.Value %__llgo_funcval_code219(ptr {{(nest|swiftself)}} %1649, %"{{.*}}/runtime/internal/runtime.eface" %1648) +// CHECK-NEXT: store %reflect.Value %1644, ptr %1638, align 8 +// CHECK-NEXT: store %reflect.Value %1651, ptr %1645, align 8 +// CHECK-NEXT: %1652 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %1, i64 110 +// CHECK-NEXT: %1653 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %1652, i32 0, i32 0 +// CHECK-NEXT: %1654 = load { ptr, ptr }, ptr @main.V, align 8 +// CHECK-NEXT: %1655 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 8) +// CHECK-NEXT: store i64 110, ptr %1655, align 8 +// CHECK-NEXT: %1656 = insertvalue %"{{.*}}/runtime/internal/runtime.eface" { ptr @_llgo_uint64, ptr undef }, ptr %1655, 1 +// CHECK-NEXT: %1657 = extractvalue { ptr, ptr } %1654, 1 +// CHECK-NEXT: %1658 = extractvalue { ptr, ptr } %1654, 0 +// CHECK-NEXT: %__llgo_funcval_code220 = call ptr asm "", "=r,0"(ptr %1658) +// CHECK-NEXT: %1659 = call %reflect.Value %__llgo_funcval_code220(ptr {{(nest|swiftself)}} %1657, %"{{.*}}/runtime/internal/runtime.eface" %1656) +// CHECK-NEXT: %1660 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %1652, i32 0, i32 1 +// CHECK-NEXT: %1661 = load { ptr, ptr }, ptr @main.V, align 8 +// CHECK-NEXT: %1662 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 4) +// CHECK-NEXT: store i32 110, ptr %1662, align 4 +// CHECK-NEXT: %1663 = insertvalue %"{{.*}}/runtime/internal/runtime.eface" { ptr @_llgo_uint32, ptr undef }, ptr %1662, 1 +// CHECK-NEXT: %1664 = extractvalue { ptr, ptr } %1661, 1 +// CHECK-NEXT: %1665 = extractvalue { ptr, ptr } %1661, 0 +// CHECK-NEXT: %__llgo_funcval_code221 = call ptr asm "", "=r,0"(ptr %1665) +// CHECK-NEXT: %1666 = call %reflect.Value %__llgo_funcval_code221(ptr {{(nest|swiftself)}} %1664, %"{{.*}}/runtime/internal/runtime.eface" %1663) +// CHECK-NEXT: store %reflect.Value %1659, ptr %1653, align 8 +// CHECK-NEXT: store %reflect.Value %1666, ptr %1660, align 8 +// CHECK-NEXT: %1667 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %1, i64 111 +// CHECK-NEXT: %1668 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %1667, i32 0, i32 0 +// CHECK-NEXT: %1669 = load { ptr, ptr }, ptr @main.V, align 8 +// CHECK-NEXT: %1670 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 4) +// CHECK-NEXT: store i32 111, ptr %1670, align 4 +// CHECK-NEXT: %1671 = insertvalue %"{{.*}}/runtime/internal/runtime.eface" { ptr @_llgo_uint32, ptr undef }, ptr %1670, 1 +// CHECK-NEXT: %1672 = extractvalue { ptr, ptr } %1669, 1 +// CHECK-NEXT: %1673 = extractvalue { ptr, ptr } %1669, 0 +// CHECK-NEXT: %__llgo_funcval_code222 = call ptr asm "", "=r,0"(ptr %1673) +// CHECK-NEXT: %1674 = call %reflect.Value %__llgo_funcval_code222(ptr {{(nest|swiftself)}} %1672, %"{{.*}}/runtime/internal/runtime.eface" %1671) +// CHECK-NEXT: %1675 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %1667, i32 0, i32 1 +// CHECK-NEXT: %1676 = load { ptr, ptr }, ptr @main.V, align 8 +// CHECK-NEXT: %1677 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 8) +// CHECK-NEXT: store i64 111, ptr %1677, align 8 +// CHECK-NEXT: %1678 = insertvalue %"{{.*}}/runtime/internal/runtime.eface" { ptr @_llgo_int, ptr undef }, ptr %1677, 1 +// CHECK-NEXT: %1679 = extractvalue { ptr, ptr } %1676, 1 +// CHECK-NEXT: %1680 = extractvalue { ptr, ptr } %1676, 0 +// CHECK-NEXT: %__llgo_funcval_code223 = call ptr asm "", "=r,0"(ptr %1680) +// CHECK-NEXT: %1681 = call %reflect.Value %__llgo_funcval_code223(ptr {{(nest|swiftself)}} %1679, %"{{.*}}/runtime/internal/runtime.eface" %1678) +// CHECK-NEXT: store %reflect.Value %1674, ptr %1668, align 8 +// CHECK-NEXT: store %reflect.Value %1681, ptr %1675, align 8 +// CHECK-NEXT: %1682 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %1, i64 112 +// CHECK-NEXT: %1683 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %1682, i32 0, i32 0 +// CHECK-NEXT: %1684 = load { ptr, ptr }, ptr @main.V, align 8 +// CHECK-NEXT: %1685 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 8) +// CHECK-NEXT: store i64 112, ptr %1685, align 8 +// CHECK-NEXT: %1686 = insertvalue %"{{.*}}/runtime/internal/runtime.eface" { ptr @_llgo_int, ptr undef }, ptr %1685, 1 +// CHECK-NEXT: %1687 = extractvalue { ptr, ptr } %1684, 1 +// CHECK-NEXT: %1688 = extractvalue { ptr, ptr } %1684, 0 +// CHECK-NEXT: %__llgo_funcval_code224 = call ptr asm "", "=r,0"(ptr %1688) +// CHECK-NEXT: %1689 = call %reflect.Value %__llgo_funcval_code224(ptr {{(nest|swiftself)}} %1687, %"{{.*}}/runtime/internal/runtime.eface" %1686) +// CHECK-NEXT: %1690 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %1682, i32 0, i32 1 +// CHECK-NEXT: %1691 = load { ptr, ptr }, ptr @main.V, align 8 +// CHECK-NEXT: %1692 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 4) +// CHECK-NEXT: store i32 112, ptr %1692, align 4 +// CHECK-NEXT: %1693 = insertvalue %"{{.*}}/runtime/internal/runtime.eface" { ptr @_llgo_uint32, ptr undef }, ptr %1692, 1 +// CHECK-NEXT: %1694 = extractvalue { ptr, ptr } %1691, 1 +// CHECK-NEXT: %1695 = extractvalue { ptr, ptr } %1691, 0 +// CHECK-NEXT: %__llgo_funcval_code225 = call ptr asm "", "=r,0"(ptr %1695) +// CHECK-NEXT: %1696 = call %reflect.Value %__llgo_funcval_code225(ptr {{(nest|swiftself)}} %1694, %"{{.*}}/runtime/internal/runtime.eface" %1693) +// CHECK-NEXT: store %reflect.Value %1689, ptr %1683, align 8 +// CHECK-NEXT: store %reflect.Value %1696, ptr %1690, align 8 +// CHECK-NEXT: %1697 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %1, i64 113 +// CHECK-NEXT: %1698 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %1697, i32 0, i32 0 +// CHECK-NEXT: %1699 = load { ptr, ptr }, ptr @main.V, align 8 +// CHECK-NEXT: %1700 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 4) +// CHECK-NEXT: store i32 113, ptr %1700, align 4 +// CHECK-NEXT: %1701 = insertvalue %"{{.*}}/runtime/internal/runtime.eface" { ptr @_llgo_uint32, ptr undef }, ptr %1700, 1 +// CHECK-NEXT: %1702 = extractvalue { ptr, ptr } %1699, 1 +// CHECK-NEXT: %1703 = extractvalue { ptr, ptr } %1699, 0 +// CHECK-NEXT: %__llgo_funcval_code226 = call ptr asm "", "=r,0"(ptr %1703) +// CHECK-NEXT: %1704 = call %reflect.Value %__llgo_funcval_code226(ptr {{(nest|swiftself)}} %1702, %"{{.*}}/runtime/internal/runtime.eface" %1701) +// CHECK-NEXT: %1705 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %1697, i32 0, i32 1 +// CHECK-NEXT: %1706 = load { ptr, ptr }, ptr @main.V, align 8 +// CHECK-NEXT: %1707 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 8) +// CHECK-NEXT: store i64 113, ptr %1707, align 8 +// CHECK-NEXT: %1708 = insertvalue %"{{.*}}/runtime/internal/runtime.eface" { ptr @_llgo_uint, ptr undef }, ptr %1707, 1 +// CHECK-NEXT: %1709 = extractvalue { ptr, ptr } %1706, 1 +// CHECK-NEXT: %1710 = extractvalue { ptr, ptr } %1706, 0 +// CHECK-NEXT: %__llgo_funcval_code227 = call ptr asm "", "=r,0"(ptr %1710) +// CHECK-NEXT: %1711 = call %reflect.Value %__llgo_funcval_code227(ptr {{(nest|swiftself)}} %1709, %"{{.*}}/runtime/internal/runtime.eface" %1708) +// CHECK-NEXT: store %reflect.Value %1704, ptr %1698, align 8 +// CHECK-NEXT: store %reflect.Value %1711, ptr %1705, align 8 +// CHECK-NEXT: %1712 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %1, i64 114 +// CHECK-NEXT: %1713 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %1712, i32 0, i32 0 +// CHECK-NEXT: %1714 = load { ptr, ptr }, ptr @main.V, align 8 +// CHECK-NEXT: %1715 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 8) +// CHECK-NEXT: store i64 114, ptr %1715, align 8 +// CHECK-NEXT: %1716 = insertvalue %"{{.*}}/runtime/internal/runtime.eface" { ptr @_llgo_uint, ptr undef }, ptr %1715, 1 +// CHECK-NEXT: %1717 = extractvalue { ptr, ptr } %1714, 1 +// CHECK-NEXT: %1718 = extractvalue { ptr, ptr } %1714, 0 +// CHECK-NEXT: %__llgo_funcval_code228 = call ptr asm "", "=r,0"(ptr %1718) +// CHECK-NEXT: %1719 = call %reflect.Value %__llgo_funcval_code228(ptr {{(nest|swiftself)}} %1717, %"{{.*}}/runtime/internal/runtime.eface" %1716) +// CHECK-NEXT: %1720 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %1712, i32 0, i32 1 +// CHECK-NEXT: %1721 = load { ptr, ptr }, ptr @main.V, align 8 +// CHECK-NEXT: %1722 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 4) +// CHECK-NEXT: store i32 114, ptr %1722, align 4 +// CHECK-NEXT: %1723 = insertvalue %"{{.*}}/runtime/internal/runtime.eface" { ptr @_llgo_uint32, ptr undef }, ptr %1722, 1 +// CHECK-NEXT: %1724 = extractvalue { ptr, ptr } %1721, 1 +// CHECK-NEXT: %1725 = extractvalue { ptr, ptr } %1721, 0 +// CHECK-NEXT: %__llgo_funcval_code229 = call ptr asm "", "=r,0"(ptr %1725) +// CHECK-NEXT: %1726 = call %reflect.Value %__llgo_funcval_code229(ptr {{(nest|swiftself)}} %1724, %"{{.*}}/runtime/internal/runtime.eface" %1723) +// CHECK-NEXT: store %reflect.Value %1719, ptr %1713, align 8 +// CHECK-NEXT: store %reflect.Value %1726, ptr %1720, align 8 +// CHECK-NEXT: %1727 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %1, i64 115 +// CHECK-NEXT: %1728 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %1727, i32 0, i32 0 +// CHECK-NEXT: %1729 = load { ptr, ptr }, ptr @main.V, align 8 +// CHECK-NEXT: %1730 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 4) +// CHECK-NEXT: store i32 115, ptr %1730, align 4 +// CHECK-NEXT: %1731 = insertvalue %"{{.*}}/runtime/internal/runtime.eface" { ptr @_llgo_uint32, ptr undef }, ptr %1730, 1 +// CHECK-NEXT: %1732 = extractvalue { ptr, ptr } %1729, 1 +// CHECK-NEXT: %1733 = extractvalue { ptr, ptr } %1729, 0 +// CHECK-NEXT: %__llgo_funcval_code230 = call ptr asm "", "=r,0"(ptr %1733) +// CHECK-NEXT: %1734 = call %reflect.Value %__llgo_funcval_code230(ptr {{(nest|swiftself)}} %1732, %"{{.*}}/runtime/internal/runtime.eface" %1731) +// CHECK-NEXT: %1735 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %1727, i32 0, i32 1 +// CHECK-NEXT: %1736 = load { ptr, ptr }, ptr @main.V, align 8 +// CHECK-NEXT: %1737 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 8) +// CHECK-NEXT: store i64 115, ptr %1737, align 8 +// CHECK-NEXT: %1738 = insertvalue %"{{.*}}/runtime/internal/runtime.eface" { ptr @_llgo_uintptr, ptr undef }, ptr %1737, 1 +// CHECK-NEXT: %1739 = extractvalue { ptr, ptr } %1736, 1 +// CHECK-NEXT: %1740 = extractvalue { ptr, ptr } %1736, 0 +// CHECK-NEXT: %__llgo_funcval_code231 = call ptr asm "", "=r,0"(ptr %1740) +// CHECK-NEXT: %1741 = call %reflect.Value %__llgo_funcval_code231(ptr {{(nest|swiftself)}} %1739, %"{{.*}}/runtime/internal/runtime.eface" %1738) +// CHECK-NEXT: store %reflect.Value %1734, ptr %1728, align 8 +// CHECK-NEXT: store %reflect.Value %1741, ptr %1735, align 8 +// CHECK-NEXT: %1742 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %1, i64 116 +// CHECK-NEXT: %1743 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %1742, i32 0, i32 0 +// CHECK-NEXT: %1744 = load { ptr, ptr }, ptr @main.V, align 8 +// CHECK-NEXT: %1745 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 8) +// CHECK-NEXT: store i64 116, ptr %1745, align 8 +// CHECK-NEXT: %1746 = insertvalue %"{{.*}}/runtime/internal/runtime.eface" { ptr @_llgo_uintptr, ptr undef }, ptr %1745, 1 +// CHECK-NEXT: %1747 = extractvalue { ptr, ptr } %1744, 1 +// CHECK-NEXT: %1748 = extractvalue { ptr, ptr } %1744, 0 +// CHECK-NEXT: %__llgo_funcval_code232 = call ptr asm "", "=r,0"(ptr %1748) +// CHECK-NEXT: %1749 = call %reflect.Value %__llgo_funcval_code232(ptr {{(nest|swiftself)}} %1747, %"{{.*}}/runtime/internal/runtime.eface" %1746) +// CHECK-NEXT: %1750 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %1742, i32 0, i32 1 +// CHECK-NEXT: %1751 = load { ptr, ptr }, ptr @main.V, align 8 +// CHECK-NEXT: %1752 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 4) +// CHECK-NEXT: store i32 116, ptr %1752, align 4 +// CHECK-NEXT: %1753 = insertvalue %"{{.*}}/runtime/internal/runtime.eface" { ptr @_llgo_uint32, ptr undef }, ptr %1752, 1 +// CHECK-NEXT: %1754 = extractvalue { ptr, ptr } %1751, 1 +// CHECK-NEXT: %1755 = extractvalue { ptr, ptr } %1751, 0 +// CHECK-NEXT: %__llgo_funcval_code233 = call ptr asm "", "=r,0"(ptr %1755) +// CHECK-NEXT: %1756 = call %reflect.Value %__llgo_funcval_code233(ptr {{(nest|swiftself)}} %1754, %"{{.*}}/runtime/internal/runtime.eface" %1753) +// CHECK-NEXT: store %reflect.Value %1749, ptr %1743, align 8 +// CHECK-NEXT: store %reflect.Value %1756, ptr %1750, align 8 +// CHECK-NEXT: %1757 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %1, i64 117 +// CHECK-NEXT: %1758 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %1757, i32 0, i32 0 +// CHECK-NEXT: %1759 = load { ptr, ptr }, ptr @main.V, align 8 +// CHECK-NEXT: %1760 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 4) +// CHECK-NEXT: store i32 117, ptr %1760, align 4 +// CHECK-NEXT: %1761 = insertvalue %"{{.*}}/runtime/internal/runtime.eface" { ptr @_llgo_uint32, ptr undef }, ptr %1760, 1 +// CHECK-NEXT: %1762 = extractvalue { ptr, ptr } %1759, 1 +// CHECK-NEXT: %1763 = extractvalue { ptr, ptr } %1759, 0 +// CHECK-NEXT: %__llgo_funcval_code234 = call ptr asm "", "=r,0"(ptr %1763) +// CHECK-NEXT: %1764 = call %reflect.Value %__llgo_funcval_code234(ptr {{(nest|swiftself)}} %1762, %"{{.*}}/runtime/internal/runtime.eface" %1761) +// CHECK-NEXT: %1765 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %1757, i32 0, i32 1 +// CHECK-NEXT: %1766 = load { ptr, ptr }, ptr @main.V, align 8 +// CHECK-NEXT: %1767 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 4) +// CHECK-NEXT: store float 1.170000e+02, ptr %1767, align 4 +// CHECK-NEXT: %1768 = insertvalue %"{{.*}}/runtime/internal/runtime.eface" { ptr @_llgo_float32, ptr undef }, ptr %1767, 1 +// CHECK-NEXT: %1769 = extractvalue { ptr, ptr } %1766, 1 +// CHECK-NEXT: %1770 = extractvalue { ptr, ptr } %1766, 0 +// CHECK-NEXT: %__llgo_funcval_code235 = call ptr asm "", "=r,0"(ptr %1770) +// CHECK-NEXT: %1771 = call %reflect.Value %__llgo_funcval_code235(ptr {{(nest|swiftself)}} %1769, %"{{.*}}/runtime/internal/runtime.eface" %1768) +// CHECK-NEXT: store %reflect.Value %1764, ptr %1758, align 8 +// CHECK-NEXT: store %reflect.Value %1771, ptr %1765, align 8 +// CHECK-NEXT: %1772 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %1, i64 118 +// CHECK-NEXT: %1773 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %1772, i32 0, i32 0 +// CHECK-NEXT: %1774 = load { ptr, ptr }, ptr @main.V, align 8 +// CHECK-NEXT: %1775 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 4) +// CHECK-NEXT: store float 1.180000e+02, ptr %1775, align 4 +// CHECK-NEXT: %1776 = insertvalue %"{{.*}}/runtime/internal/runtime.eface" { ptr @_llgo_float32, ptr undef }, ptr %1775, 1 +// CHECK-NEXT: %1777 = extractvalue { ptr, ptr } %1774, 1 +// CHECK-NEXT: %1778 = extractvalue { ptr, ptr } %1774, 0 +// CHECK-NEXT: %__llgo_funcval_code236 = call ptr asm "", "=r,0"(ptr %1778) +// CHECK-NEXT: %1779 = call %reflect.Value %__llgo_funcval_code236(ptr {{(nest|swiftself)}} %1777, %"{{.*}}/runtime/internal/runtime.eface" %1776) +// CHECK-NEXT: %1780 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %1772, i32 0, i32 1 +// CHECK-NEXT: %1781 = load { ptr, ptr }, ptr @main.V, align 8 +// CHECK-NEXT: %1782 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 4) +// CHECK-NEXT: store i32 118, ptr %1782, align 4 +// CHECK-NEXT: %1783 = insertvalue %"{{.*}}/runtime/internal/runtime.eface" { ptr @_llgo_uint32, ptr undef }, ptr %1782, 1 +// CHECK-NEXT: %1784 = extractvalue { ptr, ptr } %1781, 1 +// CHECK-NEXT: %1785 = extractvalue { ptr, ptr } %1781, 0 +// CHECK-NEXT: %__llgo_funcval_code237 = call ptr asm "", "=r,0"(ptr %1785) +// CHECK-NEXT: %1786 = call %reflect.Value %__llgo_funcval_code237(ptr {{(nest|swiftself)}} %1784, %"{{.*}}/runtime/internal/runtime.eface" %1783) +// CHECK-NEXT: store %reflect.Value %1779, ptr %1773, align 8 +// CHECK-NEXT: store %reflect.Value %1786, ptr %1780, align 8 +// CHECK-NEXT: %1787 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %1, i64 119 +// CHECK-NEXT: %1788 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %1787, i32 0, i32 0 +// CHECK-NEXT: %1789 = load { ptr, ptr }, ptr @main.V, align 8 +// CHECK-NEXT: %1790 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 4) +// CHECK-NEXT: store i32 119, ptr %1790, align 4 +// CHECK-NEXT: %1791 = insertvalue %"{{.*}}/runtime/internal/runtime.eface" { ptr @_llgo_uint32, ptr undef }, ptr %1790, 1 +// CHECK-NEXT: %1792 = extractvalue { ptr, ptr } %1789, 1 +// CHECK-NEXT: %1793 = extractvalue { ptr, ptr } %1789, 0 +// CHECK-NEXT: %__llgo_funcval_code238 = call ptr asm "", "=r,0"(ptr %1793) +// CHECK-NEXT: %1794 = call %reflect.Value %__llgo_funcval_code238(ptr {{(nest|swiftself)}} %1792, %"{{.*}}/runtime/internal/runtime.eface" %1791) +// CHECK-NEXT: %1795 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %1787, i32 0, i32 1 +// CHECK-NEXT: %1796 = load { ptr, ptr }, ptr @main.V, align 8 +// CHECK-NEXT: %1797 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 8) +// CHECK-NEXT: store double 1.190000e+02, ptr %1797, align 8 +// CHECK-NEXT: %1798 = insertvalue %"{{.*}}/runtime/internal/runtime.eface" { ptr @_llgo_float64, ptr undef }, ptr %1797, 1 +// CHECK-NEXT: %1799 = extractvalue { ptr, ptr } %1796, 1 +// CHECK-NEXT: %1800 = extractvalue { ptr, ptr } %1796, 0 +// CHECK-NEXT: %__llgo_funcval_code239 = call ptr asm "", "=r,0"(ptr %1800) +// CHECK-NEXT: %1801 = call %reflect.Value %__llgo_funcval_code239(ptr {{(nest|swiftself)}} %1799, %"{{.*}}/runtime/internal/runtime.eface" %1798) +// CHECK-NEXT: store %reflect.Value %1794, ptr %1788, align 8 +// CHECK-NEXT: store %reflect.Value %1801, ptr %1795, align 8 +// CHECK-NEXT: %1802 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %1, i64 120 +// CHECK-NEXT: %1803 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %1802, i32 0, i32 0 +// CHECK-NEXT: %1804 = load { ptr, ptr }, ptr @main.V, align 8 +// CHECK-NEXT: %1805 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 8) +// CHECK-NEXT: store double 1.200000e+02, ptr %1805, align 8 +// CHECK-NEXT: %1806 = insertvalue %"{{.*}}/runtime/internal/runtime.eface" { ptr @_llgo_float64, ptr undef }, ptr %1805, 1 +// CHECK-NEXT: %1807 = extractvalue { ptr, ptr } %1804, 1 +// CHECK-NEXT: %1808 = extractvalue { ptr, ptr } %1804, 0 +// CHECK-NEXT: %__llgo_funcval_code240 = call ptr asm "", "=r,0"(ptr %1808) +// CHECK-NEXT: %1809 = call %reflect.Value %__llgo_funcval_code240(ptr {{(nest|swiftself)}} %1807, %"{{.*}}/runtime/internal/runtime.eface" %1806) +// CHECK-NEXT: %1810 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %1802, i32 0, i32 1 +// CHECK-NEXT: %1811 = load { ptr, ptr }, ptr @main.V, align 8 +// CHECK-NEXT: %1812 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 4) +// CHECK-NEXT: store i32 120, ptr %1812, align 4 +// CHECK-NEXT: %1813 = insertvalue %"{{.*}}/runtime/internal/runtime.eface" { ptr @_llgo_uint32, ptr undef }, ptr %1812, 1 +// CHECK-NEXT: %1814 = extractvalue { ptr, ptr } %1811, 1 +// CHECK-NEXT: %1815 = extractvalue { ptr, ptr } %1811, 0 +// CHECK-NEXT: %__llgo_funcval_code241 = call ptr asm "", "=r,0"(ptr %1815) +// CHECK-NEXT: %1816 = call %reflect.Value %__llgo_funcval_code241(ptr {{(nest|swiftself)}} %1814, %"{{.*}}/runtime/internal/runtime.eface" %1813) +// CHECK-NEXT: store %reflect.Value %1809, ptr %1803, align 8 +// CHECK-NEXT: store %reflect.Value %1816, ptr %1810, align 8 +// CHECK-NEXT: %1817 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %1, i64 121 +// CHECK-NEXT: %1818 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %1817, i32 0, i32 0 +// CHECK-NEXT: %1819 = load { ptr, ptr }, ptr @main.V, align 8 +// CHECK-NEXT: %1820 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 8) +// CHECK-NEXT: store i64 121, ptr %1820, align 8 +// CHECK-NEXT: %1821 = insertvalue %"{{.*}}/runtime/internal/runtime.eface" { ptr @_llgo_int64, ptr undef }, ptr %1820, 1 +// CHECK-NEXT: %1822 = extractvalue { ptr, ptr } %1819, 1 +// CHECK-NEXT: %1823 = extractvalue { ptr, ptr } %1819, 0 +// CHECK-NEXT: %__llgo_funcval_code242 = call ptr asm "", "=r,0"(ptr %1823) +// CHECK-NEXT: %1824 = call %reflect.Value %__llgo_funcval_code242(ptr {{(nest|swiftself)}} %1822, %"{{.*}}/runtime/internal/runtime.eface" %1821) +// CHECK-NEXT: %1825 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %1817, i32 0, i32 1 +// CHECK-NEXT: %1826 = load { ptr, ptr }, ptr @main.V, align 8 +// CHECK-NEXT: %1827 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 8) +// CHECK-NEXT: store i64 121, ptr %1827, align 8 +// CHECK-NEXT: %1828 = insertvalue %"{{.*}}/runtime/internal/runtime.eface" { ptr @_llgo_int64, ptr undef }, ptr %1827, 1 +// CHECK-NEXT: %1829 = extractvalue { ptr, ptr } %1826, 1 +// CHECK-NEXT: %1830 = extractvalue { ptr, ptr } %1826, 0 +// CHECK-NEXT: %__llgo_funcval_code243 = call ptr asm "", "=r,0"(ptr %1830) +// CHECK-NEXT: %1831 = call %reflect.Value %__llgo_funcval_code243(ptr {{(nest|swiftself)}} %1829, %"{{.*}}/runtime/internal/runtime.eface" %1828) +// CHECK-NEXT: store %reflect.Value %1824, ptr %1818, align 8 +// CHECK-NEXT: store %reflect.Value %1831, ptr %1825, align 8 +// CHECK-NEXT: %1832 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %1, i64 122 +// CHECK-NEXT: %1833 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %1832, i32 0, i32 0 +// CHECK-NEXT: %1834 = load { ptr, ptr }, ptr @main.V, align 8 +// CHECK-NEXT: %1835 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 8) +// CHECK-NEXT: store i64 122, ptr %1835, align 8 +// CHECK-NEXT: %1836 = insertvalue %"{{.*}}/runtime/internal/runtime.eface" { ptr @_llgo_int64, ptr undef }, ptr %1835, 1 +// CHECK-NEXT: %1837 = extractvalue { ptr, ptr } %1834, 1 +// CHECK-NEXT: %1838 = extractvalue { ptr, ptr } %1834, 0 +// CHECK-NEXT: %__llgo_funcval_code244 = call ptr asm "", "=r,0"(ptr %1838) +// CHECK-NEXT: %1839 = call %reflect.Value %__llgo_funcval_code244(ptr {{(nest|swiftself)}} %1837, %"{{.*}}/runtime/internal/runtime.eface" %1836) +// CHECK-NEXT: %1840 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %1832, i32 0, i32 1 +// CHECK-NEXT: %1841 = load { ptr, ptr }, ptr @main.V, align 8 +// CHECK-NEXT: %1842 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 8) +// CHECK-NEXT: store i64 122, ptr %1842, align 8 +// CHECK-NEXT: %1843 = insertvalue %"{{.*}}/runtime/internal/runtime.eface" { ptr @_llgo_uint64, ptr undef }, ptr %1842, 1 +// CHECK-NEXT: %1844 = extractvalue { ptr, ptr } %1841, 1 +// CHECK-NEXT: %1845 = extractvalue { ptr, ptr } %1841, 0 +// CHECK-NEXT: %__llgo_funcval_code245 = call ptr asm "", "=r,0"(ptr %1845) +// CHECK-NEXT: %1846 = call %reflect.Value %__llgo_funcval_code245(ptr {{(nest|swiftself)}} %1844, %"{{.*}}/runtime/internal/runtime.eface" %1843) +// CHECK-NEXT: store %reflect.Value %1839, ptr %1833, align 8 +// CHECK-NEXT: store %reflect.Value %1846, ptr %1840, align 8 +// CHECK-NEXT: %1847 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %1, i64 123 +// CHECK-NEXT: %1848 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %1847, i32 0, i32 0 +// CHECK-NEXT: %1849 = load { ptr, ptr }, ptr @main.V, align 8 +// CHECK-NEXT: %1850 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 8) +// CHECK-NEXT: store i64 123, ptr %1850, align 8 +// CHECK-NEXT: %1851 = insertvalue %"{{.*}}/runtime/internal/runtime.eface" { ptr @_llgo_uint64, ptr undef }, ptr %1850, 1 +// CHECK-NEXT: %1852 = extractvalue { ptr, ptr } %1849, 1 +// CHECK-NEXT: %1853 = extractvalue { ptr, ptr } %1849, 0 +// CHECK-NEXT: %__llgo_funcval_code246 = call ptr asm "", "=r,0"(ptr %1853) +// CHECK-NEXT: %1854 = call %reflect.Value %__llgo_funcval_code246(ptr {{(nest|swiftself)}} %1852, %"{{.*}}/runtime/internal/runtime.eface" %1851) +// CHECK-NEXT: %1855 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %1847, i32 0, i32 1 +// CHECK-NEXT: %1856 = load { ptr, ptr }, ptr @main.V, align 8 +// CHECK-NEXT: %1857 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 8) +// CHECK-NEXT: store i64 123, ptr %1857, align 8 +// CHECK-NEXT: %1858 = insertvalue %"{{.*}}/runtime/internal/runtime.eface" { ptr @_llgo_int64, ptr undef }, ptr %1857, 1 +// CHECK-NEXT: %1859 = extractvalue { ptr, ptr } %1856, 1 +// CHECK-NEXT: %1860 = extractvalue { ptr, ptr } %1856, 0 +// CHECK-NEXT: %__llgo_funcval_code247 = call ptr asm "", "=r,0"(ptr %1860) +// CHECK-NEXT: %1861 = call %reflect.Value %__llgo_funcval_code247(ptr {{(nest|swiftself)}} %1859, %"{{.*}}/runtime/internal/runtime.eface" %1858) +// CHECK-NEXT: store %reflect.Value %1854, ptr %1848, align 8 +// CHECK-NEXT: store %reflect.Value %1861, ptr %1855, align 8 +// CHECK-NEXT: %1862 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %1, i64 124 +// CHECK-NEXT: %1863 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %1862, i32 0, i32 0 +// CHECK-NEXT: %1864 = load { ptr, ptr }, ptr @main.V, align 8 +// CHECK-NEXT: %1865 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 8) +// CHECK-NEXT: store i64 124, ptr %1865, align 8 +// CHECK-NEXT: %1866 = insertvalue %"{{.*}}/runtime/internal/runtime.eface" { ptr @_llgo_int64, ptr undef }, ptr %1865, 1 +// CHECK-NEXT: %1867 = extractvalue { ptr, ptr } %1864, 1 +// CHECK-NEXT: %1868 = extractvalue { ptr, ptr } %1864, 0 +// CHECK-NEXT: %__llgo_funcval_code248 = call ptr asm "", "=r,0"(ptr %1868) +// CHECK-NEXT: %1869 = call %reflect.Value %__llgo_funcval_code248(ptr {{(nest|swiftself)}} %1867, %"{{.*}}/runtime/internal/runtime.eface" %1866) +// CHECK-NEXT: %1870 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %1862, i32 0, i32 1 +// CHECK-NEXT: %1871 = load { ptr, ptr }, ptr @main.V, align 8 +// CHECK-NEXT: %1872 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 8) +// CHECK-NEXT: store i64 124, ptr %1872, align 8 +// CHECK-NEXT: %1873 = insertvalue %"{{.*}}/runtime/internal/runtime.eface" { ptr @_llgo_int, ptr undef }, ptr %1872, 1 +// CHECK-NEXT: %1874 = extractvalue { ptr, ptr } %1871, 1 +// CHECK-NEXT: %1875 = extractvalue { ptr, ptr } %1871, 0 +// CHECK-NEXT: %__llgo_funcval_code249 = call ptr asm "", "=r,0"(ptr %1875) +// CHECK-NEXT: %1876 = call %reflect.Value %__llgo_funcval_code249(ptr {{(nest|swiftself)}} %1874, %"{{.*}}/runtime/internal/runtime.eface" %1873) +// CHECK-NEXT: store %reflect.Value %1869, ptr %1863, align 8 +// CHECK-NEXT: store %reflect.Value %1876, ptr %1870, align 8 +// CHECK-NEXT: %1877 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %1, i64 125 +// CHECK-NEXT: %1878 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %1877, i32 0, i32 0 +// CHECK-NEXT: %1879 = load { ptr, ptr }, ptr @main.V, align 8 +// CHECK-NEXT: %1880 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 8) +// CHECK-NEXT: store i64 125, ptr %1880, align 8 +// CHECK-NEXT: %1881 = insertvalue %"{{.*}}/runtime/internal/runtime.eface" { ptr @_llgo_int, ptr undef }, ptr %1880, 1 +// CHECK-NEXT: %1882 = extractvalue { ptr, ptr } %1879, 1 +// CHECK-NEXT: %1883 = extractvalue { ptr, ptr } %1879, 0 +// CHECK-NEXT: %__llgo_funcval_code250 = call ptr asm "", "=r,0"(ptr %1883) +// CHECK-NEXT: %1884 = call %reflect.Value %__llgo_funcval_code250(ptr {{(nest|swiftself)}} %1882, %"{{.*}}/runtime/internal/runtime.eface" %1881) +// CHECK-NEXT: %1885 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %1877, i32 0, i32 1 +// CHECK-NEXT: %1886 = load { ptr, ptr }, ptr @main.V, align 8 +// CHECK-NEXT: %1887 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 8) +// CHECK-NEXT: store i64 125, ptr %1887, align 8 +// CHECK-NEXT: %1888 = insertvalue %"{{.*}}/runtime/internal/runtime.eface" { ptr @_llgo_int64, ptr undef }, ptr %1887, 1 +// CHECK-NEXT: %1889 = extractvalue { ptr, ptr } %1886, 1 +// CHECK-NEXT: %1890 = extractvalue { ptr, ptr } %1886, 0 +// CHECK-NEXT: %__llgo_funcval_code251 = call ptr asm "", "=r,0"(ptr %1890) +// CHECK-NEXT: %1891 = call %reflect.Value %__llgo_funcval_code251(ptr {{(nest|swiftself)}} %1889, %"{{.*}}/runtime/internal/runtime.eface" %1888) +// CHECK-NEXT: store %reflect.Value %1884, ptr %1878, align 8 +// CHECK-NEXT: store %reflect.Value %1891, ptr %1885, align 8 +// CHECK-NEXT: %1892 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %1, i64 126 +// CHECK-NEXT: %1893 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %1892, i32 0, i32 0 +// CHECK-NEXT: %1894 = load { ptr, ptr }, ptr @main.V, align 8 +// CHECK-NEXT: %1895 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 8) +// CHECK-NEXT: store i64 126, ptr %1895, align 8 +// CHECK-NEXT: %1896 = insertvalue %"{{.*}}/runtime/internal/runtime.eface" { ptr @_llgo_int64, ptr undef }, ptr %1895, 1 +// CHECK-NEXT: %1897 = extractvalue { ptr, ptr } %1894, 1 +// CHECK-NEXT: %1898 = extractvalue { ptr, ptr } %1894, 0 +// CHECK-NEXT: %__llgo_funcval_code252 = call ptr asm "", "=r,0"(ptr %1898) +// CHECK-NEXT: %1899 = call %reflect.Value %__llgo_funcval_code252(ptr {{(nest|swiftself)}} %1897, %"{{.*}}/runtime/internal/runtime.eface" %1896) +// CHECK-NEXT: %1900 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %1892, i32 0, i32 1 +// CHECK-NEXT: %1901 = load { ptr, ptr }, ptr @main.V, align 8 +// CHECK-NEXT: %1902 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 8) +// CHECK-NEXT: store i64 126, ptr %1902, align 8 +// CHECK-NEXT: %1903 = insertvalue %"{{.*}}/runtime/internal/runtime.eface" { ptr @_llgo_uint, ptr undef }, ptr %1902, 1 +// CHECK-NEXT: %1904 = extractvalue { ptr, ptr } %1901, 1 +// CHECK-NEXT: %1905 = extractvalue { ptr, ptr } %1901, 0 +// CHECK-NEXT: %__llgo_funcval_code253 = call ptr asm "", "=r,0"(ptr %1905) +// CHECK-NEXT: %1906 = call %reflect.Value %__llgo_funcval_code253(ptr {{(nest|swiftself)}} %1904, %"{{.*}}/runtime/internal/runtime.eface" %1903) +// CHECK-NEXT: store %reflect.Value %1899, ptr %1893, align 8 +// CHECK-NEXT: store %reflect.Value %1906, ptr %1900, align 8 +// CHECK-NEXT: %1907 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %1, i64 127 +// CHECK-NEXT: %1908 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %1907, i32 0, i32 0 +// CHECK-NEXT: %1909 = load { ptr, ptr }, ptr @main.V, align 8 +// CHECK-NEXT: %1910 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 8) +// CHECK-NEXT: store i64 127, ptr %1910, align 8 +// CHECK-NEXT: %1911 = insertvalue %"{{.*}}/runtime/internal/runtime.eface" { ptr @_llgo_uint, ptr undef }, ptr %1910, 1 +// CHECK-NEXT: %1912 = extractvalue { ptr, ptr } %1909, 1 +// CHECK-NEXT: %1913 = extractvalue { ptr, ptr } %1909, 0 +// CHECK-NEXT: %__llgo_funcval_code254 = call ptr asm "", "=r,0"(ptr %1913) +// CHECK-NEXT: %1914 = call %reflect.Value %__llgo_funcval_code254(ptr {{(nest|swiftself)}} %1912, %"{{.*}}/runtime/internal/runtime.eface" %1911) +// CHECK-NEXT: %1915 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %1907, i32 0, i32 1 +// CHECK-NEXT: %1916 = load { ptr, ptr }, ptr @main.V, align 8 +// CHECK-NEXT: %1917 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 8) +// CHECK-NEXT: store i64 127, ptr %1917, align 8 +// CHECK-NEXT: %1918 = insertvalue %"{{.*}}/runtime/internal/runtime.eface" { ptr @_llgo_int64, ptr undef }, ptr %1917, 1 +// CHECK-NEXT: %1919 = extractvalue { ptr, ptr } %1916, 1 +// CHECK-NEXT: %1920 = extractvalue { ptr, ptr } %1916, 0 +// CHECK-NEXT: %__llgo_funcval_code255 = call ptr asm "", "=r,0"(ptr %1920) +// CHECK-NEXT: %1921 = call %reflect.Value %__llgo_funcval_code255(ptr {{(nest|swiftself)}} %1919, %"{{.*}}/runtime/internal/runtime.eface" %1918) +// CHECK-NEXT: store %reflect.Value %1914, ptr %1908, align 8 +// CHECK-NEXT: store %reflect.Value %1921, ptr %1915, align 8 +// CHECK-NEXT: %1922 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %1, i64 128 +// CHECK-NEXT: %1923 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %1922, i32 0, i32 0 +// CHECK-NEXT: %1924 = load { ptr, ptr }, ptr @main.V, align 8 +// CHECK-NEXT: %1925 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 8) +// CHECK-NEXT: store i64 128, ptr %1925, align 8 +// CHECK-NEXT: %1926 = insertvalue %"{{.*}}/runtime/internal/runtime.eface" { ptr @_llgo_int64, ptr undef }, ptr %1925, 1 +// CHECK-NEXT: %1927 = extractvalue { ptr, ptr } %1924, 1 +// CHECK-NEXT: %1928 = extractvalue { ptr, ptr } %1924, 0 +// CHECK-NEXT: %__llgo_funcval_code256 = call ptr asm "", "=r,0"(ptr %1928) +// CHECK-NEXT: %1929 = call %reflect.Value %__llgo_funcval_code256(ptr {{(nest|swiftself)}} %1927, %"{{.*}}/runtime/internal/runtime.eface" %1926) +// CHECK-NEXT: %1930 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %1922, i32 0, i32 1 +// CHECK-NEXT: %1931 = load { ptr, ptr }, ptr @main.V, align 8 +// CHECK-NEXT: %1932 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 8) +// CHECK-NEXT: store i64 128, ptr %1932, align 8 +// CHECK-NEXT: %1933 = insertvalue %"{{.*}}/runtime/internal/runtime.eface" { ptr @_llgo_uintptr, ptr undef }, ptr %1932, 1 +// CHECK-NEXT: %1934 = extractvalue { ptr, ptr } %1931, 1 +// CHECK-NEXT: %1935 = extractvalue { ptr, ptr } %1931, 0 +// CHECK-NEXT: %__llgo_funcval_code257 = call ptr asm "", "=r,0"(ptr %1935) +// CHECK-NEXT: %1936 = call %reflect.Value %__llgo_funcval_code257(ptr {{(nest|swiftself)}} %1934, %"{{.*}}/runtime/internal/runtime.eface" %1933) +// CHECK-NEXT: store %reflect.Value %1929, ptr %1923, align 8 +// CHECK-NEXT: store %reflect.Value %1936, ptr %1930, align 8 +// CHECK-NEXT: %1937 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %1, i64 129 +// CHECK-NEXT: %1938 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %1937, i32 0, i32 0 +// CHECK-NEXT: %1939 = load { ptr, ptr }, ptr @main.V, align 8 +// CHECK-NEXT: %1940 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 8) +// CHECK-NEXT: store i64 129, ptr %1940, align 8 +// CHECK-NEXT: %1941 = insertvalue %"{{.*}}/runtime/internal/runtime.eface" { ptr @_llgo_uintptr, ptr undef }, ptr %1940, 1 +// CHECK-NEXT: %1942 = extractvalue { ptr, ptr } %1939, 1 +// CHECK-NEXT: %1943 = extractvalue { ptr, ptr } %1939, 0 +// CHECK-NEXT: %__llgo_funcval_code258 = call ptr asm "", "=r,0"(ptr %1943) +// CHECK-NEXT: %1944 = call %reflect.Value %__llgo_funcval_code258(ptr {{(nest|swiftself)}} %1942, %"{{.*}}/runtime/internal/runtime.eface" %1941) +// CHECK-NEXT: %1945 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %1937, i32 0, i32 1 +// CHECK-NEXT: %1946 = load { ptr, ptr }, ptr @main.V, align 8 +// CHECK-NEXT: %1947 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 8) +// CHECK-NEXT: store i64 129, ptr %1947, align 8 +// CHECK-NEXT: %1948 = insertvalue %"{{.*}}/runtime/internal/runtime.eface" { ptr @_llgo_int64, ptr undef }, ptr %1947, 1 +// CHECK-NEXT: %1949 = extractvalue { ptr, ptr } %1946, 1 +// CHECK-NEXT: %1950 = extractvalue { ptr, ptr } %1946, 0 +// CHECK-NEXT: %__llgo_funcval_code259 = call ptr asm "", "=r,0"(ptr %1950) +// CHECK-NEXT: %1951 = call %reflect.Value %__llgo_funcval_code259(ptr {{(nest|swiftself)}} %1949, %"{{.*}}/runtime/internal/runtime.eface" %1948) +// CHECK-NEXT: store %reflect.Value %1944, ptr %1938, align 8 +// CHECK-NEXT: store %reflect.Value %1951, ptr %1945, align 8 +// CHECK-NEXT: %1952 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %1, i64 130 +// CHECK-NEXT: %1953 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %1952, i32 0, i32 0 +// CHECK-NEXT: %1954 = load { ptr, ptr }, ptr @main.V, align 8 +// CHECK-NEXT: %1955 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 8) +// CHECK-NEXT: store i64 130, ptr %1955, align 8 +// CHECK-NEXT: %1956 = insertvalue %"{{.*}}/runtime/internal/runtime.eface" { ptr @_llgo_int64, ptr undef }, ptr %1955, 1 +// CHECK-NEXT: %1957 = extractvalue { ptr, ptr } %1954, 1 +// CHECK-NEXT: %1958 = extractvalue { ptr, ptr } %1954, 0 +// CHECK-NEXT: %__llgo_funcval_code260 = call ptr asm "", "=r,0"(ptr %1958) +// CHECK-NEXT: %1959 = call %reflect.Value %__llgo_funcval_code260(ptr {{(nest|swiftself)}} %1957, %"{{.*}}/runtime/internal/runtime.eface" %1956) +// CHECK-NEXT: %1960 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %1952, i32 0, i32 1 +// CHECK-NEXT: %1961 = load { ptr, ptr }, ptr @main.V, align 8 +// CHECK-NEXT: %1962 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 4) +// CHECK-NEXT: store float 1.300000e+02, ptr %1962, align 4 +// CHECK-NEXT: %1963 = insertvalue %"{{.*}}/runtime/internal/runtime.eface" { ptr @_llgo_float32, ptr undef }, ptr %1962, 1 +// CHECK-NEXT: %1964 = extractvalue { ptr, ptr } %1961, 1 +// CHECK-NEXT: %1965 = extractvalue { ptr, ptr } %1961, 0 +// CHECK-NEXT: %__llgo_funcval_code261 = call ptr asm "", "=r,0"(ptr %1965) +// CHECK-NEXT: %1966 = call %reflect.Value %__llgo_funcval_code261(ptr {{(nest|swiftself)}} %1964, %"{{.*}}/runtime/internal/runtime.eface" %1963) +// CHECK-NEXT: store %reflect.Value %1959, ptr %1953, align 8 +// CHECK-NEXT: store %reflect.Value %1966, ptr %1960, align 8 +// CHECK-NEXT: %1967 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %1, i64 131 +// CHECK-NEXT: %1968 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %1967, i32 0, i32 0 +// CHECK-NEXT: %1969 = load { ptr, ptr }, ptr @main.V, align 8 +// CHECK-NEXT: %1970 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 4) +// CHECK-NEXT: store float 1.310000e+02, ptr %1970, align 4 +// CHECK-NEXT: %1971 = insertvalue %"{{.*}}/runtime/internal/runtime.eface" { ptr @_llgo_float32, ptr undef }, ptr %1970, 1 +// CHECK-NEXT: %1972 = extractvalue { ptr, ptr } %1969, 1 +// CHECK-NEXT: %1973 = extractvalue { ptr, ptr } %1969, 0 +// CHECK-NEXT: %__llgo_funcval_code262 = call ptr asm "", "=r,0"(ptr %1973) +// CHECK-NEXT: %1974 = call %reflect.Value %__llgo_funcval_code262(ptr {{(nest|swiftself)}} %1972, %"{{.*}}/runtime/internal/runtime.eface" %1971) +// CHECK-NEXT: %1975 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %1967, i32 0, i32 1 +// CHECK-NEXT: %1976 = load { ptr, ptr }, ptr @main.V, align 8 +// CHECK-NEXT: %1977 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 8) +// CHECK-NEXT: store i64 131, ptr %1977, align 8 +// CHECK-NEXT: %1978 = insertvalue %"{{.*}}/runtime/internal/runtime.eface" { ptr @_llgo_int64, ptr undef }, ptr %1977, 1 +// CHECK-NEXT: %1979 = extractvalue { ptr, ptr } %1976, 1 +// CHECK-NEXT: %1980 = extractvalue { ptr, ptr } %1976, 0 +// CHECK-NEXT: %__llgo_funcval_code263 = call ptr asm "", "=r,0"(ptr %1980) +// CHECK-NEXT: %1981 = call %reflect.Value %__llgo_funcval_code263(ptr {{(nest|swiftself)}} %1979, %"{{.*}}/runtime/internal/runtime.eface" %1978) +// CHECK-NEXT: store %reflect.Value %1974, ptr %1968, align 8 +// CHECK-NEXT: store %reflect.Value %1981, ptr %1975, align 8 +// CHECK-NEXT: %1982 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %1, i64 132 +// CHECK-NEXT: %1983 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %1982, i32 0, i32 0 +// CHECK-NEXT: %1984 = load { ptr, ptr }, ptr @main.V, align 8 +// CHECK-NEXT: %1985 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 8) +// CHECK-NEXT: store i64 132, ptr %1985, align 8 +// CHECK-NEXT: %1986 = insertvalue %"{{.*}}/runtime/internal/runtime.eface" { ptr @_llgo_int64, ptr undef }, ptr %1985, 1 +// CHECK-NEXT: %1987 = extractvalue { ptr, ptr } %1984, 1 +// CHECK-NEXT: %1988 = extractvalue { ptr, ptr } %1984, 0 +// CHECK-NEXT: %__llgo_funcval_code264 = call ptr asm "", "=r,0"(ptr %1988) +// CHECK-NEXT: %1989 = call %reflect.Value %__llgo_funcval_code264(ptr {{(nest|swiftself)}} %1987, %"{{.*}}/runtime/internal/runtime.eface" %1986) +// CHECK-NEXT: %1990 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %1982, i32 0, i32 1 +// CHECK-NEXT: %1991 = load { ptr, ptr }, ptr @main.V, align 8 +// CHECK-NEXT: %1992 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 8) +// CHECK-NEXT: store double 1.320000e+02, ptr %1992, align 8 +// CHECK-NEXT: %1993 = insertvalue %"{{.*}}/runtime/internal/runtime.eface" { ptr @_llgo_float64, ptr undef }, ptr %1992, 1 +// CHECK-NEXT: %1994 = extractvalue { ptr, ptr } %1991, 1 +// CHECK-NEXT: %1995 = extractvalue { ptr, ptr } %1991, 0 +// CHECK-NEXT: %__llgo_funcval_code265 = call ptr asm "", "=r,0"(ptr %1995) +// CHECK-NEXT: %1996 = call %reflect.Value %__llgo_funcval_code265(ptr {{(nest|swiftself)}} %1994, %"{{.*}}/runtime/internal/runtime.eface" %1993) +// CHECK-NEXT: store %reflect.Value %1989, ptr %1983, align 8 +// CHECK-NEXT: store %reflect.Value %1996, ptr %1990, align 8 +// CHECK-NEXT: %1997 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %1, i64 133 +// CHECK-NEXT: %1998 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %1997, i32 0, i32 0 +// CHECK-NEXT: %1999 = load { ptr, ptr }, ptr @main.V, align 8 +// CHECK-NEXT: %2000 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 8) +// CHECK-NEXT: store double 1.330000e+02, ptr %2000, align 8 +// CHECK-NEXT: %2001 = insertvalue %"{{.*}}/runtime/internal/runtime.eface" { ptr @_llgo_float64, ptr undef }, ptr %2000, 1 +// CHECK-NEXT: %2002 = extractvalue { ptr, ptr } %1999, 1 +// CHECK-NEXT: %2003 = extractvalue { ptr, ptr } %1999, 0 +// CHECK-NEXT: %__llgo_funcval_code266 = call ptr asm "", "=r,0"(ptr %2003) +// CHECK-NEXT: %2004 = call %reflect.Value %__llgo_funcval_code266(ptr {{(nest|swiftself)}} %2002, %"{{.*}}/runtime/internal/runtime.eface" %2001) +// CHECK-NEXT: %2005 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %1997, i32 0, i32 1 +// CHECK-NEXT: %2006 = load { ptr, ptr }, ptr @main.V, align 8 +// CHECK-NEXT: %2007 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 8) +// CHECK-NEXT: store i64 133, ptr %2007, align 8 +// CHECK-NEXT: %2008 = insertvalue %"{{.*}}/runtime/internal/runtime.eface" { ptr @_llgo_int64, ptr undef }, ptr %2007, 1 +// CHECK-NEXT: %2009 = extractvalue { ptr, ptr } %2006, 1 +// CHECK-NEXT: %2010 = extractvalue { ptr, ptr } %2006, 0 +// CHECK-NEXT: %__llgo_funcval_code267 = call ptr asm "", "=r,0"(ptr %2010) +// CHECK-NEXT: %2011 = call %reflect.Value %__llgo_funcval_code267(ptr {{(nest|swiftself)}} %2009, %"{{.*}}/runtime/internal/runtime.eface" %2008) +// CHECK-NEXT: store %reflect.Value %2004, ptr %1998, align 8 +// CHECK-NEXT: store %reflect.Value %2011, ptr %2005, align 8 +// CHECK-NEXT: %2012 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %1, i64 134 +// CHECK-NEXT: %2013 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %2012, i32 0, i32 0 +// CHECK-NEXT: %2014 = load { ptr, ptr }, ptr @main.V, align 8 +// CHECK-NEXT: %2015 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 8) +// CHECK-NEXT: store i64 134, ptr %2015, align 8 +// CHECK-NEXT: %2016 = insertvalue %"{{.*}}/runtime/internal/runtime.eface" { ptr @_llgo_uint64, ptr undef }, ptr %2015, 1 +// CHECK-NEXT: %2017 = extractvalue { ptr, ptr } %2014, 1 +// CHECK-NEXT: %2018 = extractvalue { ptr, ptr } %2014, 0 +// CHECK-NEXT: %__llgo_funcval_code268 = call ptr asm "", "=r,0"(ptr %2018) +// CHECK-NEXT: %2019 = call %reflect.Value %__llgo_funcval_code268(ptr {{(nest|swiftself)}} %2017, %"{{.*}}/runtime/internal/runtime.eface" %2016) +// CHECK-NEXT: %2020 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %2012, i32 0, i32 1 +// CHECK-NEXT: %2021 = load { ptr, ptr }, ptr @main.V, align 8 +// CHECK-NEXT: %2022 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 8) +// CHECK-NEXT: store i64 134, ptr %2022, align 8 +// CHECK-NEXT: %2023 = insertvalue %"{{.*}}/runtime/internal/runtime.eface" { ptr @_llgo_uint64, ptr undef }, ptr %2022, 1 +// CHECK-NEXT: %2024 = extractvalue { ptr, ptr } %2021, 1 +// CHECK-NEXT: %2025 = extractvalue { ptr, ptr } %2021, 0 +// CHECK-NEXT: %__llgo_funcval_code269 = call ptr asm "", "=r,0"(ptr %2025) +// CHECK-NEXT: %2026 = call %reflect.Value %__llgo_funcval_code269(ptr {{(nest|swiftself)}} %2024, %"{{.*}}/runtime/internal/runtime.eface" %2023) +// CHECK-NEXT: store %reflect.Value %2019, ptr %2013, align 8 +// CHECK-NEXT: store %reflect.Value %2026, ptr %2020, align 8 +// CHECK-NEXT: %2027 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %1, i64 135 +// CHECK-NEXT: %2028 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %2027, i32 0, i32 0 +// CHECK-NEXT: %2029 = load { ptr, ptr }, ptr @main.V, align 8 +// CHECK-NEXT: %2030 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 8) +// CHECK-NEXT: store i64 135, ptr %2030, align 8 +// CHECK-NEXT: %2031 = insertvalue %"{{.*}}/runtime/internal/runtime.eface" { ptr @_llgo_uint64, ptr undef }, ptr %2030, 1 +// CHECK-NEXT: %2032 = extractvalue { ptr, ptr } %2029, 1 +// CHECK-NEXT: %2033 = extractvalue { ptr, ptr } %2029, 0 +// CHECK-NEXT: %__llgo_funcval_code270 = call ptr asm "", "=r,0"(ptr %2033) +// CHECK-NEXT: %2034 = call %reflect.Value %__llgo_funcval_code270(ptr {{(nest|swiftself)}} %2032, %"{{.*}}/runtime/internal/runtime.eface" %2031) +// CHECK-NEXT: %2035 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %2027, i32 0, i32 1 +// CHECK-NEXT: %2036 = load { ptr, ptr }, ptr @main.V, align 8 +// CHECK-NEXT: %2037 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 8) +// CHECK-NEXT: store i64 135, ptr %2037, align 8 +// CHECK-NEXT: %2038 = insertvalue %"{{.*}}/runtime/internal/runtime.eface" { ptr @_llgo_int, ptr undef }, ptr %2037, 1 +// CHECK-NEXT: %2039 = extractvalue { ptr, ptr } %2036, 1 +// CHECK-NEXT: %2040 = extractvalue { ptr, ptr } %2036, 0 +// CHECK-NEXT: %__llgo_funcval_code271 = call ptr asm "", "=r,0"(ptr %2040) +// CHECK-NEXT: %2041 = call %reflect.Value %__llgo_funcval_code271(ptr {{(nest|swiftself)}} %2039, %"{{.*}}/runtime/internal/runtime.eface" %2038) +// CHECK-NEXT: store %reflect.Value %2034, ptr %2028, align 8 +// CHECK-NEXT: store %reflect.Value %2041, ptr %2035, align 8 +// CHECK-NEXT: %2042 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %1, i64 136 +// CHECK-NEXT: %2043 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %2042, i32 0, i32 0 +// CHECK-NEXT: %2044 = load { ptr, ptr }, ptr @main.V, align 8 +// CHECK-NEXT: %2045 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 8) +// CHECK-NEXT: store i64 136, ptr %2045, align 8 +// CHECK-NEXT: %2046 = insertvalue %"{{.*}}/runtime/internal/runtime.eface" { ptr @_llgo_int, ptr undef }, ptr %2045, 1 +// CHECK-NEXT: %2047 = extractvalue { ptr, ptr } %2044, 1 +// CHECK-NEXT: %2048 = extractvalue { ptr, ptr } %2044, 0 +// CHECK-NEXT: %__llgo_funcval_code272 = call ptr asm "", "=r,0"(ptr %2048) +// CHECK-NEXT: %2049 = call %reflect.Value %__llgo_funcval_code272(ptr {{(nest|swiftself)}} %2047, %"{{.*}}/runtime/internal/runtime.eface" %2046) +// CHECK-NEXT: %2050 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %2042, i32 0, i32 1 +// CHECK-NEXT: %2051 = load { ptr, ptr }, ptr @main.V, align 8 +// CHECK-NEXT: %2052 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 8) +// CHECK-NEXT: store i64 136, ptr %2052, align 8 +// CHECK-NEXT: %2053 = insertvalue %"{{.*}}/runtime/internal/runtime.eface" { ptr @_llgo_uint64, ptr undef }, ptr %2052, 1 +// CHECK-NEXT: %2054 = extractvalue { ptr, ptr } %2051, 1 +// CHECK-NEXT: %2055 = extractvalue { ptr, ptr } %2051, 0 +// CHECK-NEXT: %__llgo_funcval_code273 = call ptr asm "", "=r,0"(ptr %2055) +// CHECK-NEXT: %2056 = call %reflect.Value %__llgo_funcval_code273(ptr {{(nest|swiftself)}} %2054, %"{{.*}}/runtime/internal/runtime.eface" %2053) +// CHECK-NEXT: store %reflect.Value %2049, ptr %2043, align 8 +// CHECK-NEXT: store %reflect.Value %2056, ptr %2050, align 8 +// CHECK-NEXT: %2057 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %1, i64 137 +// CHECK-NEXT: %2058 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %2057, i32 0, i32 0 +// CHECK-NEXT: %2059 = load { ptr, ptr }, ptr @main.V, align 8 +// CHECK-NEXT: %2060 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 8) +// CHECK-NEXT: store i64 137, ptr %2060, align 8 +// CHECK-NEXT: %2061 = insertvalue %"{{.*}}/runtime/internal/runtime.eface" { ptr @_llgo_uint64, ptr undef }, ptr %2060, 1 +// CHECK-NEXT: %2062 = extractvalue { ptr, ptr } %2059, 1 +// CHECK-NEXT: %2063 = extractvalue { ptr, ptr } %2059, 0 +// CHECK-NEXT: %__llgo_funcval_code274 = call ptr asm "", "=r,0"(ptr %2063) +// CHECK-NEXT: %2064 = call %reflect.Value %__llgo_funcval_code274(ptr {{(nest|swiftself)}} %2062, %"{{.*}}/runtime/internal/runtime.eface" %2061) +// CHECK-NEXT: %2065 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %2057, i32 0, i32 1 +// CHECK-NEXT: %2066 = load { ptr, ptr }, ptr @main.V, align 8 +// CHECK-NEXT: %2067 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 8) +// CHECK-NEXT: store i64 137, ptr %2067, align 8 +// CHECK-NEXT: %2068 = insertvalue %"{{.*}}/runtime/internal/runtime.eface" { ptr @_llgo_uint, ptr undef }, ptr %2067, 1 +// CHECK-NEXT: %2069 = extractvalue { ptr, ptr } %2066, 1 +// CHECK-NEXT: %2070 = extractvalue { ptr, ptr } %2066, 0 +// CHECK-NEXT: %__llgo_funcval_code275 = call ptr asm "", "=r,0"(ptr %2070) +// CHECK-NEXT: %2071 = call %reflect.Value %__llgo_funcval_code275(ptr {{(nest|swiftself)}} %2069, %"{{.*}}/runtime/internal/runtime.eface" %2068) +// CHECK-NEXT: store %reflect.Value %2064, ptr %2058, align 8 +// CHECK-NEXT: store %reflect.Value %2071, ptr %2065, align 8 +// CHECK-NEXT: %2072 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %1, i64 138 +// CHECK-NEXT: %2073 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %2072, i32 0, i32 0 +// CHECK-NEXT: %2074 = load { ptr, ptr }, ptr @main.V, align 8 +// CHECK-NEXT: %2075 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 8) +// CHECK-NEXT: store i64 138, ptr %2075, align 8 +// CHECK-NEXT: %2076 = insertvalue %"{{.*}}/runtime/internal/runtime.eface" { ptr @_llgo_uint, ptr undef }, ptr %2075, 1 +// CHECK-NEXT: %2077 = extractvalue { ptr, ptr } %2074, 1 +// CHECK-NEXT: %2078 = extractvalue { ptr, ptr } %2074, 0 +// CHECK-NEXT: %__llgo_funcval_code276 = call ptr asm "", "=r,0"(ptr %2078) +// CHECK-NEXT: %2079 = call %reflect.Value %__llgo_funcval_code276(ptr {{(nest|swiftself)}} %2077, %"{{.*}}/runtime/internal/runtime.eface" %2076) +// CHECK-NEXT: %2080 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %2072, i32 0, i32 1 +// CHECK-NEXT: %2081 = load { ptr, ptr }, ptr @main.V, align 8 +// CHECK-NEXT: %2082 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 8) +// CHECK-NEXT: store i64 138, ptr %2082, align 8 +// CHECK-NEXT: %2083 = insertvalue %"{{.*}}/runtime/internal/runtime.eface" { ptr @_llgo_uint64, ptr undef }, ptr %2082, 1 +// CHECK-NEXT: %2084 = extractvalue { ptr, ptr } %2081, 1 +// CHECK-NEXT: %2085 = extractvalue { ptr, ptr } %2081, 0 +// CHECK-NEXT: %__llgo_funcval_code277 = call ptr asm "", "=r,0"(ptr %2085) +// CHECK-NEXT: %2086 = call %reflect.Value %__llgo_funcval_code277(ptr {{(nest|swiftself)}} %2084, %"{{.*}}/runtime/internal/runtime.eface" %2083) +// CHECK-NEXT: store %reflect.Value %2079, ptr %2073, align 8 +// CHECK-NEXT: store %reflect.Value %2086, ptr %2080, align 8 +// CHECK-NEXT: %2087 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %1, i64 139 +// CHECK-NEXT: %2088 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %2087, i32 0, i32 0 +// CHECK-NEXT: %2089 = load { ptr, ptr }, ptr @main.V, align 8 +// CHECK-NEXT: %2090 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 8) +// CHECK-NEXT: store i64 139, ptr %2090, align 8 +// CHECK-NEXT: %2091 = insertvalue %"{{.*}}/runtime/internal/runtime.eface" { ptr @_llgo_uint64, ptr undef }, ptr %2090, 1 +// CHECK-NEXT: %2092 = extractvalue { ptr, ptr } %2089, 1 +// CHECK-NEXT: %2093 = extractvalue { ptr, ptr } %2089, 0 +// CHECK-NEXT: %__llgo_funcval_code278 = call ptr asm "", "=r,0"(ptr %2093) +// CHECK-NEXT: %2094 = call %reflect.Value %__llgo_funcval_code278(ptr {{(nest|swiftself)}} %2092, %"{{.*}}/runtime/internal/runtime.eface" %2091) +// CHECK-NEXT: %2095 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %2087, i32 0, i32 1 +// CHECK-NEXT: %2096 = load { ptr, ptr }, ptr @main.V, align 8 +// CHECK-NEXT: %2097 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 8) +// CHECK-NEXT: store i64 139, ptr %2097, align 8 +// CHECK-NEXT: %2098 = insertvalue %"{{.*}}/runtime/internal/runtime.eface" { ptr @_llgo_uintptr, ptr undef }, ptr %2097, 1 +// CHECK-NEXT: %2099 = extractvalue { ptr, ptr } %2096, 1 +// CHECK-NEXT: %2100 = extractvalue { ptr, ptr } %2096, 0 +// CHECK-NEXT: %__llgo_funcval_code279 = call ptr asm "", "=r,0"(ptr %2100) +// CHECK-NEXT: %2101 = call %reflect.Value %__llgo_funcval_code279(ptr {{(nest|swiftself)}} %2099, %"{{.*}}/runtime/internal/runtime.eface" %2098) +// CHECK-NEXT: store %reflect.Value %2094, ptr %2088, align 8 +// CHECK-NEXT: store %reflect.Value %2101, ptr %2095, align 8 +// CHECK-NEXT: %2102 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %1, i64 140 +// CHECK-NEXT: %2103 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %2102, i32 0, i32 0 +// CHECK-NEXT: %2104 = load { ptr, ptr }, ptr @main.V, align 8 +// CHECK-NEXT: %2105 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 8) +// CHECK-NEXT: store i64 140, ptr %2105, align 8 +// CHECK-NEXT: %2106 = insertvalue %"{{.*}}/runtime/internal/runtime.eface" { ptr @_llgo_uintptr, ptr undef }, ptr %2105, 1 +// CHECK-NEXT: %2107 = extractvalue { ptr, ptr } %2104, 1 +// CHECK-NEXT: %2108 = extractvalue { ptr, ptr } %2104, 0 +// CHECK-NEXT: %__llgo_funcval_code280 = call ptr asm "", "=r,0"(ptr %2108) +// CHECK-NEXT: %2109 = call %reflect.Value %__llgo_funcval_code280(ptr {{(nest|swiftself)}} %2107, %"{{.*}}/runtime/internal/runtime.eface" %2106) +// CHECK-NEXT: %2110 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %2102, i32 0, i32 1 +// CHECK-NEXT: %2111 = load { ptr, ptr }, ptr @main.V, align 8 +// CHECK-NEXT: %2112 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 8) +// CHECK-NEXT: store i64 140, ptr %2112, align 8 +// CHECK-NEXT: %2113 = insertvalue %"{{.*}}/runtime/internal/runtime.eface" { ptr @_llgo_uint64, ptr undef }, ptr %2112, 1 +// CHECK-NEXT: %2114 = extractvalue { ptr, ptr } %2111, 1 +// CHECK-NEXT: %2115 = extractvalue { ptr, ptr } %2111, 0 +// CHECK-NEXT: %__llgo_funcval_code281 = call ptr asm "", "=r,0"(ptr %2115) +// CHECK-NEXT: %2116 = call %reflect.Value %__llgo_funcval_code281(ptr {{(nest|swiftself)}} %2114, %"{{.*}}/runtime/internal/runtime.eface" %2113) +// CHECK-NEXT: store %reflect.Value %2109, ptr %2103, align 8 +// CHECK-NEXT: store %reflect.Value %2116, ptr %2110, align 8 +// CHECK-NEXT: %2117 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %1, i64 141 +// CHECK-NEXT: %2118 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %2117, i32 0, i32 0 +// CHECK-NEXT: %2119 = load { ptr, ptr }, ptr @main.V, align 8 +// CHECK-NEXT: %2120 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 8) +// CHECK-NEXT: store i64 141, ptr %2120, align 8 +// CHECK-NEXT: %2121 = insertvalue %"{{.*}}/runtime/internal/runtime.eface" { ptr @_llgo_uint64, ptr undef }, ptr %2120, 1 +// CHECK-NEXT: %2122 = extractvalue { ptr, ptr } %2119, 1 +// CHECK-NEXT: %2123 = extractvalue { ptr, ptr } %2119, 0 +// CHECK-NEXT: %__llgo_funcval_code282 = call ptr asm "", "=r,0"(ptr %2123) +// CHECK-NEXT: %2124 = call %reflect.Value %__llgo_funcval_code282(ptr {{(nest|swiftself)}} %2122, %"{{.*}}/runtime/internal/runtime.eface" %2121) +// CHECK-NEXT: %2125 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %2117, i32 0, i32 1 +// CHECK-NEXT: %2126 = load { ptr, ptr }, ptr @main.V, align 8 +// CHECK-NEXT: %2127 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 4) +// CHECK-NEXT: store float 1.410000e+02, ptr %2127, align 4 +// CHECK-NEXT: %2128 = insertvalue %"{{.*}}/runtime/internal/runtime.eface" { ptr @_llgo_float32, ptr undef }, ptr %2127, 1 +// CHECK-NEXT: %2129 = extractvalue { ptr, ptr } %2126, 1 +// CHECK-NEXT: %2130 = extractvalue { ptr, ptr } %2126, 0 +// CHECK-NEXT: %__llgo_funcval_code283 = call ptr asm "", "=r,0"(ptr %2130) +// CHECK-NEXT: %2131 = call %reflect.Value %__llgo_funcval_code283(ptr {{(nest|swiftself)}} %2129, %"{{.*}}/runtime/internal/runtime.eface" %2128) +// CHECK-NEXT: store %reflect.Value %2124, ptr %2118, align 8 +// CHECK-NEXT: store %reflect.Value %2131, ptr %2125, align 8 +// CHECK-NEXT: %2132 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %1, i64 142 +// CHECK-NEXT: %2133 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %2132, i32 0, i32 0 +// CHECK-NEXT: %2134 = load { ptr, ptr }, ptr @main.V, align 8 +// CHECK-NEXT: %2135 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 4) +// CHECK-NEXT: store float 1.420000e+02, ptr %2135, align 4 +// CHECK-NEXT: %2136 = insertvalue %"{{.*}}/runtime/internal/runtime.eface" { ptr @_llgo_float32, ptr undef }, ptr %2135, 1 +// CHECK-NEXT: %2137 = extractvalue { ptr, ptr } %2134, 1 +// CHECK-NEXT: %2138 = extractvalue { ptr, ptr } %2134, 0 +// CHECK-NEXT: %__llgo_funcval_code284 = call ptr asm "", "=r,0"(ptr %2138) +// CHECK-NEXT: %2139 = call %reflect.Value %__llgo_funcval_code284(ptr {{(nest|swiftself)}} %2137, %"{{.*}}/runtime/internal/runtime.eface" %2136) +// CHECK-NEXT: %2140 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %2132, i32 0, i32 1 +// CHECK-NEXT: %2141 = load { ptr, ptr }, ptr @main.V, align 8 +// CHECK-NEXT: %2142 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 8) +// CHECK-NEXT: store i64 142, ptr %2142, align 8 +// CHECK-NEXT: %2143 = insertvalue %"{{.*}}/runtime/internal/runtime.eface" { ptr @_llgo_uint64, ptr undef }, ptr %2142, 1 +// CHECK-NEXT: %2144 = extractvalue { ptr, ptr } %2141, 1 +// CHECK-NEXT: %2145 = extractvalue { ptr, ptr } %2141, 0 +// CHECK-NEXT: %__llgo_funcval_code285 = call ptr asm "", "=r,0"(ptr %2145) +// CHECK-NEXT: %2146 = call %reflect.Value %__llgo_funcval_code285(ptr {{(nest|swiftself)}} %2144, %"{{.*}}/runtime/internal/runtime.eface" %2143) +// CHECK-NEXT: store %reflect.Value %2139, ptr %2133, align 8 +// CHECK-NEXT: store %reflect.Value %2146, ptr %2140, align 8 +// CHECK-NEXT: %2147 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %1, i64 143 +// CHECK-NEXT: %2148 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %2147, i32 0, i32 0 +// CHECK-NEXT: %2149 = load { ptr, ptr }, ptr @main.V, align 8 +// CHECK-NEXT: %2150 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 8) +// CHECK-NEXT: store i64 143, ptr %2150, align 8 +// CHECK-NEXT: %2151 = insertvalue %"{{.*}}/runtime/internal/runtime.eface" { ptr @_llgo_uint64, ptr undef }, ptr %2150, 1 +// CHECK-NEXT: %2152 = extractvalue { ptr, ptr } %2149, 1 +// CHECK-NEXT: %2153 = extractvalue { ptr, ptr } %2149, 0 +// CHECK-NEXT: %__llgo_funcval_code286 = call ptr asm "", "=r,0"(ptr %2153) +// CHECK-NEXT: %2154 = call %reflect.Value %__llgo_funcval_code286(ptr {{(nest|swiftself)}} %2152, %"{{.*}}/runtime/internal/runtime.eface" %2151) +// CHECK-NEXT: %2155 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %2147, i32 0, i32 1 +// CHECK-NEXT: %2156 = load { ptr, ptr }, ptr @main.V, align 8 +// CHECK-NEXT: %2157 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 8) +// CHECK-NEXT: store double 1.430000e+02, ptr %2157, align 8 +// CHECK-NEXT: %2158 = insertvalue %"{{.*}}/runtime/internal/runtime.eface" { ptr @_llgo_float64, ptr undef }, ptr %2157, 1 +// CHECK-NEXT: %2159 = extractvalue { ptr, ptr } %2156, 1 +// CHECK-NEXT: %2160 = extractvalue { ptr, ptr } %2156, 0 +// CHECK-NEXT: %__llgo_funcval_code287 = call ptr asm "", "=r,0"(ptr %2160) +// CHECK-NEXT: %2161 = call %reflect.Value %__llgo_funcval_code287(ptr {{(nest|swiftself)}} %2159, %"{{.*}}/runtime/internal/runtime.eface" %2158) +// CHECK-NEXT: store %reflect.Value %2154, ptr %2148, align 8 +// CHECK-NEXT: store %reflect.Value %2161, ptr %2155, align 8 +// CHECK-NEXT: %2162 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %1, i64 144 +// CHECK-NEXT: %2163 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %2162, i32 0, i32 0 +// CHECK-NEXT: %2164 = load { ptr, ptr }, ptr @main.V, align 8 +// CHECK-NEXT: %2165 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 8) +// CHECK-NEXT: store double 1.440000e+02, ptr %2165, align 8 +// CHECK-NEXT: %2166 = insertvalue %"{{.*}}/runtime/internal/runtime.eface" { ptr @_llgo_float64, ptr undef }, ptr %2165, 1 +// CHECK-NEXT: %2167 = extractvalue { ptr, ptr } %2164, 1 +// CHECK-NEXT: %2168 = extractvalue { ptr, ptr } %2164, 0 +// CHECK-NEXT: %__llgo_funcval_code288 = call ptr asm "", "=r,0"(ptr %2168) +// CHECK-NEXT: %2169 = call %reflect.Value %__llgo_funcval_code288(ptr {{(nest|swiftself)}} %2167, %"{{.*}}/runtime/internal/runtime.eface" %2166) +// CHECK-NEXT: %2170 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %2162, i32 0, i32 1 +// CHECK-NEXT: %2171 = load { ptr, ptr }, ptr @main.V, align 8 +// CHECK-NEXT: %2172 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 8) +// CHECK-NEXT: store i64 144, ptr %2172, align 8 +// CHECK-NEXT: %2173 = insertvalue %"{{.*}}/runtime/internal/runtime.eface" { ptr @_llgo_uint64, ptr undef }, ptr %2172, 1 +// CHECK-NEXT: %2174 = extractvalue { ptr, ptr } %2171, 1 +// CHECK-NEXT: %2175 = extractvalue { ptr, ptr } %2171, 0 +// CHECK-NEXT: %__llgo_funcval_code289 = call ptr asm "", "=r,0"(ptr %2175) +// CHECK-NEXT: %2176 = call %reflect.Value %__llgo_funcval_code289(ptr {{(nest|swiftself)}} %2174, %"{{.*}}/runtime/internal/runtime.eface" %2173) +// CHECK-NEXT: store %reflect.Value %2169, ptr %2163, align 8 +// CHECK-NEXT: store %reflect.Value %2176, ptr %2170, align 8 +// CHECK-NEXT: %2177 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %1, i64 145 +// CHECK-NEXT: %2178 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %2177, i32 0, i32 0 +// CHECK-NEXT: %2179 = load { ptr, ptr }, ptr @main.V, align 8 +// CHECK-NEXT: %2180 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 8) +// CHECK-NEXT: store i64 145, ptr %2180, align 8 +// CHECK-NEXT: %2181 = insertvalue %"{{.*}}/runtime/internal/runtime.eface" { ptr @_llgo_int, ptr undef }, ptr %2180, 1 +// CHECK-NEXT: %2182 = extractvalue { ptr, ptr } %2179, 1 +// CHECK-NEXT: %2183 = extractvalue { ptr, ptr } %2179, 0 +// CHECK-NEXT: %__llgo_funcval_code290 = call ptr asm "", "=r,0"(ptr %2183) +// CHECK-NEXT: %2184 = call %reflect.Value %__llgo_funcval_code290(ptr {{(nest|swiftself)}} %2182, %"{{.*}}/runtime/internal/runtime.eface" %2181) +// CHECK-NEXT: %2185 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %2177, i32 0, i32 1 +// CHECK-NEXT: %2186 = load { ptr, ptr }, ptr @main.V, align 8 +// CHECK-NEXT: %2187 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 8) +// CHECK-NEXT: store i64 145, ptr %2187, align 8 +// CHECK-NEXT: %2188 = insertvalue %"{{.*}}/runtime/internal/runtime.eface" { ptr @_llgo_int, ptr undef }, ptr %2187, 1 +// CHECK-NEXT: %2189 = extractvalue { ptr, ptr } %2186, 1 +// CHECK-NEXT: %2190 = extractvalue { ptr, ptr } %2186, 0 +// CHECK-NEXT: %__llgo_funcval_code291 = call ptr asm "", "=r,0"(ptr %2190) +// CHECK-NEXT: %2191 = call %reflect.Value %__llgo_funcval_code291(ptr {{(nest|swiftself)}} %2189, %"{{.*}}/runtime/internal/runtime.eface" %2188) +// CHECK-NEXT: store %reflect.Value %2184, ptr %2178, align 8 +// CHECK-NEXT: store %reflect.Value %2191, ptr %2185, align 8 +// CHECK-NEXT: %2192 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %1, i64 146 +// CHECK-NEXT: %2193 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %2192, i32 0, i32 0 +// CHECK-NEXT: %2194 = load { ptr, ptr }, ptr @main.V, align 8 +// CHECK-NEXT: %2195 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 8) +// CHECK-NEXT: store i64 146, ptr %2195, align 8 +// CHECK-NEXT: %2196 = insertvalue %"{{.*}}/runtime/internal/runtime.eface" { ptr @_llgo_int, ptr undef }, ptr %2195, 1 +// CHECK-NEXT: %2197 = extractvalue { ptr, ptr } %2194, 1 +// CHECK-NEXT: %2198 = extractvalue { ptr, ptr } %2194, 0 +// CHECK-NEXT: %__llgo_funcval_code292 = call ptr asm "", "=r,0"(ptr %2198) +// CHECK-NEXT: %2199 = call %reflect.Value %__llgo_funcval_code292(ptr {{(nest|swiftself)}} %2197, %"{{.*}}/runtime/internal/runtime.eface" %2196) +// CHECK-NEXT: %2200 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %2192, i32 0, i32 1 +// CHECK-NEXT: %2201 = load { ptr, ptr }, ptr @main.V, align 8 +// CHECK-NEXT: %2202 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 8) +// CHECK-NEXT: store i64 146, ptr %2202, align 8 +// CHECK-NEXT: %2203 = insertvalue %"{{.*}}/runtime/internal/runtime.eface" { ptr @_llgo_uint, ptr undef }, ptr %2202, 1 +// CHECK-NEXT: %2204 = extractvalue { ptr, ptr } %2201, 1 +// CHECK-NEXT: %2205 = extractvalue { ptr, ptr } %2201, 0 +// CHECK-NEXT: %__llgo_funcval_code293 = call ptr asm "", "=r,0"(ptr %2205) +// CHECK-NEXT: %2206 = call %reflect.Value %__llgo_funcval_code293(ptr {{(nest|swiftself)}} %2204, %"{{.*}}/runtime/internal/runtime.eface" %2203) +// CHECK-NEXT: store %reflect.Value %2199, ptr %2193, align 8 +// CHECK-NEXT: store %reflect.Value %2206, ptr %2200, align 8 +// CHECK-NEXT: %2207 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %1, i64 147 +// CHECK-NEXT: %2208 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %2207, i32 0, i32 0 +// CHECK-NEXT: %2209 = load { ptr, ptr }, ptr @main.V, align 8 +// CHECK-NEXT: %2210 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 8) +// CHECK-NEXT: store i64 147, ptr %2210, align 8 +// CHECK-NEXT: %2211 = insertvalue %"{{.*}}/runtime/internal/runtime.eface" { ptr @_llgo_uint, ptr undef }, ptr %2210, 1 +// CHECK-NEXT: %2212 = extractvalue { ptr, ptr } %2209, 1 +// CHECK-NEXT: %2213 = extractvalue { ptr, ptr } %2209, 0 +// CHECK-NEXT: %__llgo_funcval_code294 = call ptr asm "", "=r,0"(ptr %2213) +// CHECK-NEXT: %2214 = call %reflect.Value %__llgo_funcval_code294(ptr {{(nest|swiftself)}} %2212, %"{{.*}}/runtime/internal/runtime.eface" %2211) +// CHECK-NEXT: %2215 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %2207, i32 0, i32 1 +// CHECK-NEXT: %2216 = load { ptr, ptr }, ptr @main.V, align 8 +// CHECK-NEXT: %2217 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 8) +// CHECK-NEXT: store i64 147, ptr %2217, align 8 +// CHECK-NEXT: %2218 = insertvalue %"{{.*}}/runtime/internal/runtime.eface" { ptr @_llgo_int, ptr undef }, ptr %2217, 1 +// CHECK-NEXT: %2219 = extractvalue { ptr, ptr } %2216, 1 +// CHECK-NEXT: %2220 = extractvalue { ptr, ptr } %2216, 0 +// CHECK-NEXT: %__llgo_funcval_code295 = call ptr asm "", "=r,0"(ptr %2220) +// CHECK-NEXT: %2221 = call %reflect.Value %__llgo_funcval_code295(ptr {{(nest|swiftself)}} %2219, %"{{.*}}/runtime/internal/runtime.eface" %2218) +// CHECK-NEXT: store %reflect.Value %2214, ptr %2208, align 8 +// CHECK-NEXT: store %reflect.Value %2221, ptr %2215, align 8 +// CHECK-NEXT: %2222 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %1, i64 148 +// CHECK-NEXT: %2223 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %2222, i32 0, i32 0 +// CHECK-NEXT: %2224 = load { ptr, ptr }, ptr @main.V, align 8 +// CHECK-NEXT: %2225 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 8) +// CHECK-NEXT: store i64 148, ptr %2225, align 8 +// CHECK-NEXT: %2226 = insertvalue %"{{.*}}/runtime/internal/runtime.eface" { ptr @_llgo_int, ptr undef }, ptr %2225, 1 +// CHECK-NEXT: %2227 = extractvalue { ptr, ptr } %2224, 1 +// CHECK-NEXT: %2228 = extractvalue { ptr, ptr } %2224, 0 +// CHECK-NEXT: %__llgo_funcval_code296 = call ptr asm "", "=r,0"(ptr %2228) +// CHECK-NEXT: %2229 = call %reflect.Value %__llgo_funcval_code296(ptr {{(nest|swiftself)}} %2227, %"{{.*}}/runtime/internal/runtime.eface" %2226) +// CHECK-NEXT: %2230 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %2222, i32 0, i32 1 +// CHECK-NEXT: %2231 = load { ptr, ptr }, ptr @main.V, align 8 +// CHECK-NEXT: %2232 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 8) +// CHECK-NEXT: store i64 148, ptr %2232, align 8 +// CHECK-NEXT: %2233 = insertvalue %"{{.*}}/runtime/internal/runtime.eface" { ptr @_llgo_uintptr, ptr undef }, ptr %2232, 1 +// CHECK-NEXT: %2234 = extractvalue { ptr, ptr } %2231, 1 +// CHECK-NEXT: %2235 = extractvalue { ptr, ptr } %2231, 0 +// CHECK-NEXT: %__llgo_funcval_code297 = call ptr asm "", "=r,0"(ptr %2235) +// CHECK-NEXT: %2236 = call %reflect.Value %__llgo_funcval_code297(ptr {{(nest|swiftself)}} %2234, %"{{.*}}/runtime/internal/runtime.eface" %2233) +// CHECK-NEXT: store %reflect.Value %2229, ptr %2223, align 8 +// CHECK-NEXT: store %reflect.Value %2236, ptr %2230, align 8 +// CHECK-NEXT: %2237 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %1, i64 149 +// CHECK-NEXT: %2238 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %2237, i32 0, i32 0 +// CHECK-NEXT: %2239 = load { ptr, ptr }, ptr @main.V, align 8 +// CHECK-NEXT: %2240 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 8) +// CHECK-NEXT: store i64 149, ptr %2240, align 8 +// CHECK-NEXT: %2241 = insertvalue %"{{.*}}/runtime/internal/runtime.eface" { ptr @_llgo_uintptr, ptr undef }, ptr %2240, 1 +// CHECK-NEXT: %2242 = extractvalue { ptr, ptr } %2239, 1 +// CHECK-NEXT: %2243 = extractvalue { ptr, ptr } %2239, 0 +// CHECK-NEXT: %__llgo_funcval_code298 = call ptr asm "", "=r,0"(ptr %2243) +// CHECK-NEXT: %2244 = call %reflect.Value %__llgo_funcval_code298(ptr {{(nest|swiftself)}} %2242, %"{{.*}}/runtime/internal/runtime.eface" %2241) +// CHECK-NEXT: %2245 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %2237, i32 0, i32 1 +// CHECK-NEXT: %2246 = load { ptr, ptr }, ptr @main.V, align 8 +// CHECK-NEXT: %2247 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 8) +// CHECK-NEXT: store i64 149, ptr %2247, align 8 +// CHECK-NEXT: %2248 = insertvalue %"{{.*}}/runtime/internal/runtime.eface" { ptr @_llgo_int, ptr undef }, ptr %2247, 1 +// CHECK-NEXT: %2249 = extractvalue { ptr, ptr } %2246, 1 +// CHECK-NEXT: %2250 = extractvalue { ptr, ptr } %2246, 0 +// CHECK-NEXT: %__llgo_funcval_code299 = call ptr asm "", "=r,0"(ptr %2250) +// CHECK-NEXT: %2251 = call %reflect.Value %__llgo_funcval_code299(ptr {{(nest|swiftself)}} %2249, %"{{.*}}/runtime/internal/runtime.eface" %2248) +// CHECK-NEXT: store %reflect.Value %2244, ptr %2238, align 8 +// CHECK-NEXT: store %reflect.Value %2251, ptr %2245, align 8 +// CHECK-NEXT: %2252 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %1, i64 150 +// CHECK-NEXT: %2253 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %2252, i32 0, i32 0 +// CHECK-NEXT: %2254 = load { ptr, ptr }, ptr @main.V, align 8 +// CHECK-NEXT: %2255 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 8) +// CHECK-NEXT: store i64 150, ptr %2255, align 8 +// CHECK-NEXT: %2256 = insertvalue %"{{.*}}/runtime/internal/runtime.eface" { ptr @_llgo_int, ptr undef }, ptr %2255, 1 +// CHECK-NEXT: %2257 = extractvalue { ptr, ptr } %2254, 1 +// CHECK-NEXT: %2258 = extractvalue { ptr, ptr } %2254, 0 +// CHECK-NEXT: %__llgo_funcval_code300 = call ptr asm "", "=r,0"(ptr %2258) +// CHECK-NEXT: %2259 = call %reflect.Value %__llgo_funcval_code300(ptr {{(nest|swiftself)}} %2257, %"{{.*}}/runtime/internal/runtime.eface" %2256) +// CHECK-NEXT: %2260 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %2252, i32 0, i32 1 +// CHECK-NEXT: %2261 = load { ptr, ptr }, ptr @main.V, align 8 +// CHECK-NEXT: %2262 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 4) +// CHECK-NEXT: store float 1.500000e+02, ptr %2262, align 4 +// CHECK-NEXT: %2263 = insertvalue %"{{.*}}/runtime/internal/runtime.eface" { ptr @_llgo_float32, ptr undef }, ptr %2262, 1 +// CHECK-NEXT: %2264 = extractvalue { ptr, ptr } %2261, 1 +// CHECK-NEXT: %2265 = extractvalue { ptr, ptr } %2261, 0 +// CHECK-NEXT: %__llgo_funcval_code301 = call ptr asm "", "=r,0"(ptr %2265) +// CHECK-NEXT: %2266 = call %reflect.Value %__llgo_funcval_code301(ptr {{(nest|swiftself)}} %2264, %"{{.*}}/runtime/internal/runtime.eface" %2263) +// CHECK-NEXT: store %reflect.Value %2259, ptr %2253, align 8 +// CHECK-NEXT: store %reflect.Value %2266, ptr %2260, align 8 +// CHECK-NEXT: %2267 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %1, i64 151 +// CHECK-NEXT: %2268 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %2267, i32 0, i32 0 +// CHECK-NEXT: %2269 = load { ptr, ptr }, ptr @main.V, align 8 +// CHECK-NEXT: %2270 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 4) +// CHECK-NEXT: store float 1.510000e+02, ptr %2270, align 4 +// CHECK-NEXT: %2271 = insertvalue %"{{.*}}/runtime/internal/runtime.eface" { ptr @_llgo_float32, ptr undef }, ptr %2270, 1 +// CHECK-NEXT: %2272 = extractvalue { ptr, ptr } %2269, 1 +// CHECK-NEXT: %2273 = extractvalue { ptr, ptr } %2269, 0 +// CHECK-NEXT: %__llgo_funcval_code302 = call ptr asm "", "=r,0"(ptr %2273) +// CHECK-NEXT: %2274 = call %reflect.Value %__llgo_funcval_code302(ptr {{(nest|swiftself)}} %2272, %"{{.*}}/runtime/internal/runtime.eface" %2271) +// CHECK-NEXT: %2275 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %2267, i32 0, i32 1 +// CHECK-NEXT: %2276 = load { ptr, ptr }, ptr @main.V, align 8 +// CHECK-NEXT: %2277 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 8) +// CHECK-NEXT: store i64 151, ptr %2277, align 8 +// CHECK-NEXT: %2278 = insertvalue %"{{.*}}/runtime/internal/runtime.eface" { ptr @_llgo_int, ptr undef }, ptr %2277, 1 +// CHECK-NEXT: %2279 = extractvalue { ptr, ptr } %2276, 1 +// CHECK-NEXT: %2280 = extractvalue { ptr, ptr } %2276, 0 +// CHECK-NEXT: %__llgo_funcval_code303 = call ptr asm "", "=r,0"(ptr %2280) +// CHECK-NEXT: %2281 = call %reflect.Value %__llgo_funcval_code303(ptr {{(nest|swiftself)}} %2279, %"{{.*}}/runtime/internal/runtime.eface" %2278) +// CHECK-NEXT: store %reflect.Value %2274, ptr %2268, align 8 +// CHECK-NEXT: store %reflect.Value %2281, ptr %2275, align 8 +// CHECK-NEXT: %2282 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %1, i64 152 +// CHECK-NEXT: %2283 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %2282, i32 0, i32 0 +// CHECK-NEXT: %2284 = load { ptr, ptr }, ptr @main.V, align 8 +// CHECK-NEXT: %2285 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 8) +// CHECK-NEXT: store i64 152, ptr %2285, align 8 +// CHECK-NEXT: %2286 = insertvalue %"{{.*}}/runtime/internal/runtime.eface" { ptr @_llgo_int, ptr undef }, ptr %2285, 1 +// CHECK-NEXT: %2287 = extractvalue { ptr, ptr } %2284, 1 +// CHECK-NEXT: %2288 = extractvalue { ptr, ptr } %2284, 0 +// CHECK-NEXT: %__llgo_funcval_code304 = call ptr asm "", "=r,0"(ptr %2288) +// CHECK-NEXT: %2289 = call %reflect.Value %__llgo_funcval_code304(ptr {{(nest|swiftself)}} %2287, %"{{.*}}/runtime/internal/runtime.eface" %2286) +// CHECK-NEXT: %2290 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %2282, i32 0, i32 1 +// CHECK-NEXT: %2291 = load { ptr, ptr }, ptr @main.V, align 8 +// CHECK-NEXT: %2292 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 8) +// CHECK-NEXT: store double 1.520000e+02, ptr %2292, align 8 +// CHECK-NEXT: %2293 = insertvalue %"{{.*}}/runtime/internal/runtime.eface" { ptr @_llgo_float64, ptr undef }, ptr %2292, 1 +// CHECK-NEXT: %2294 = extractvalue { ptr, ptr } %2291, 1 +// CHECK-NEXT: %2295 = extractvalue { ptr, ptr } %2291, 0 +// CHECK-NEXT: %__llgo_funcval_code305 = call ptr asm "", "=r,0"(ptr %2295) +// CHECK-NEXT: %2296 = call %reflect.Value %__llgo_funcval_code305(ptr {{(nest|swiftself)}} %2294, %"{{.*}}/runtime/internal/runtime.eface" %2293) +// CHECK-NEXT: store %reflect.Value %2289, ptr %2283, align 8 +// CHECK-NEXT: store %reflect.Value %2296, ptr %2290, align 8 +// CHECK-NEXT: %2297 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %1, i64 153 +// CHECK-NEXT: %2298 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %2297, i32 0, i32 0 +// CHECK-NEXT: %2299 = load { ptr, ptr }, ptr @main.V, align 8 +// CHECK-NEXT: %2300 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 8) +// CHECK-NEXT: store double 1.530000e+02, ptr %2300, align 8 +// CHECK-NEXT: %2301 = insertvalue %"{{.*}}/runtime/internal/runtime.eface" { ptr @_llgo_float64, ptr undef }, ptr %2300, 1 +// CHECK-NEXT: %2302 = extractvalue { ptr, ptr } %2299, 1 +// CHECK-NEXT: %2303 = extractvalue { ptr, ptr } %2299, 0 +// CHECK-NEXT: %__llgo_funcval_code306 = call ptr asm "", "=r,0"(ptr %2303) +// CHECK-NEXT: %2304 = call %reflect.Value %__llgo_funcval_code306(ptr {{(nest|swiftself)}} %2302, %"{{.*}}/runtime/internal/runtime.eface" %2301) +// CHECK-NEXT: %2305 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %2297, i32 0, i32 1 +// CHECK-NEXT: %2306 = load { ptr, ptr }, ptr @main.V, align 8 +// CHECK-NEXT: %2307 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 8) +// CHECK-NEXT: store i64 153, ptr %2307, align 8 +// CHECK-NEXT: %2308 = insertvalue %"{{.*}}/runtime/internal/runtime.eface" { ptr @_llgo_int, ptr undef }, ptr %2307, 1 +// CHECK-NEXT: %2309 = extractvalue { ptr, ptr } %2306, 1 +// CHECK-NEXT: %2310 = extractvalue { ptr, ptr } %2306, 0 +// CHECK-NEXT: %__llgo_funcval_code307 = call ptr asm "", "=r,0"(ptr %2310) +// CHECK-NEXT: %2311 = call %reflect.Value %__llgo_funcval_code307(ptr {{(nest|swiftself)}} %2309, %"{{.*}}/runtime/internal/runtime.eface" %2308) +// CHECK-NEXT: store %reflect.Value %2304, ptr %2298, align 8 +// CHECK-NEXT: store %reflect.Value %2311, ptr %2305, align 8 +// CHECK-NEXT: %2312 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %1, i64 154 +// CHECK-NEXT: %2313 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %2312, i32 0, i32 0 +// CHECK-NEXT: %2314 = load { ptr, ptr }, ptr @main.V, align 8 +// CHECK-NEXT: %2315 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 8) +// CHECK-NEXT: store i64 154, ptr %2315, align 8 +// CHECK-NEXT: %2316 = insertvalue %"{{.*}}/runtime/internal/runtime.eface" { ptr @_llgo_uint, ptr undef }, ptr %2315, 1 +// CHECK-NEXT: %2317 = extractvalue { ptr, ptr } %2314, 1 +// CHECK-NEXT: %2318 = extractvalue { ptr, ptr } %2314, 0 +// CHECK-NEXT: %__llgo_funcval_code308 = call ptr asm "", "=r,0"(ptr %2318) +// CHECK-NEXT: %2319 = call %reflect.Value %__llgo_funcval_code308(ptr {{(nest|swiftself)}} %2317, %"{{.*}}/runtime/internal/runtime.eface" %2316) +// CHECK-NEXT: %2320 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %2312, i32 0, i32 1 +// CHECK-NEXT: %2321 = load { ptr, ptr }, ptr @main.V, align 8 +// CHECK-NEXT: %2322 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 8) +// CHECK-NEXT: store i64 154, ptr %2322, align 8 +// CHECK-NEXT: %2323 = insertvalue %"{{.*}}/runtime/internal/runtime.eface" { ptr @_llgo_uint, ptr undef }, ptr %2322, 1 +// CHECK-NEXT: %2324 = extractvalue { ptr, ptr } %2321, 1 +// CHECK-NEXT: %2325 = extractvalue { ptr, ptr } %2321, 0 +// CHECK-NEXT: %__llgo_funcval_code309 = call ptr asm "", "=r,0"(ptr %2325) +// CHECK-NEXT: %2326 = call %reflect.Value %__llgo_funcval_code309(ptr {{(nest|swiftself)}} %2324, %"{{.*}}/runtime/internal/runtime.eface" %2323) +// CHECK-NEXT: store %reflect.Value %2319, ptr %2313, align 8 +// CHECK-NEXT: store %reflect.Value %2326, ptr %2320, align 8 +// CHECK-NEXT: %2327 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %1, i64 155 +// CHECK-NEXT: %2328 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %2327, i32 0, i32 0 +// CHECK-NEXT: %2329 = load { ptr, ptr }, ptr @main.V, align 8 +// CHECK-NEXT: %2330 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 8) +// CHECK-NEXT: store i64 155, ptr %2330, align 8 +// CHECK-NEXT: %2331 = insertvalue %"{{.*}}/runtime/internal/runtime.eface" { ptr @_llgo_uint, ptr undef }, ptr %2330, 1 +// CHECK-NEXT: %2332 = extractvalue { ptr, ptr } %2329, 1 +// CHECK-NEXT: %2333 = extractvalue { ptr, ptr } %2329, 0 +// CHECK-NEXT: %__llgo_funcval_code310 = call ptr asm "", "=r,0"(ptr %2333) +// CHECK-NEXT: %2334 = call %reflect.Value %__llgo_funcval_code310(ptr {{(nest|swiftself)}} %2332, %"{{.*}}/runtime/internal/runtime.eface" %2331) +// CHECK-NEXT: %2335 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %2327, i32 0, i32 1 +// CHECK-NEXT: %2336 = load { ptr, ptr }, ptr @main.V, align 8 +// CHECK-NEXT: %2337 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 8) +// CHECK-NEXT: store i64 155, ptr %2337, align 8 +// CHECK-NEXT: %2338 = insertvalue %"{{.*}}/runtime/internal/runtime.eface" { ptr @_llgo_uintptr, ptr undef }, ptr %2337, 1 +// CHECK-NEXT: %2339 = extractvalue { ptr, ptr } %2336, 1 +// CHECK-NEXT: %2340 = extractvalue { ptr, ptr } %2336, 0 +// CHECK-NEXT: %__llgo_funcval_code311 = call ptr asm "", "=r,0"(ptr %2340) +// CHECK-NEXT: %2341 = call %reflect.Value %__llgo_funcval_code311(ptr {{(nest|swiftself)}} %2339, %"{{.*}}/runtime/internal/runtime.eface" %2338) +// CHECK-NEXT: store %reflect.Value %2334, ptr %2328, align 8 +// CHECK-NEXT: store %reflect.Value %2341, ptr %2335, align 8 +// CHECK-NEXT: %2342 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %1, i64 156 +// CHECK-NEXT: %2343 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %2342, i32 0, i32 0 +// CHECK-NEXT: %2344 = load { ptr, ptr }, ptr @main.V, align 8 +// CHECK-NEXT: %2345 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 8) +// CHECK-NEXT: store i64 156, ptr %2345, align 8 +// CHECK-NEXT: %2346 = insertvalue %"{{.*}}/runtime/internal/runtime.eface" { ptr @_llgo_uintptr, ptr undef }, ptr %2345, 1 +// CHECK-NEXT: %2347 = extractvalue { ptr, ptr } %2344, 1 +// CHECK-NEXT: %2348 = extractvalue { ptr, ptr } %2344, 0 +// CHECK-NEXT: %__llgo_funcval_code312 = call ptr asm "", "=r,0"(ptr %2348) +// CHECK-NEXT: %2349 = call %reflect.Value %__llgo_funcval_code312(ptr {{(nest|swiftself)}} %2347, %"{{.*}}/runtime/internal/runtime.eface" %2346) +// CHECK-NEXT: %2350 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %2342, i32 0, i32 1 +// CHECK-NEXT: %2351 = load { ptr, ptr }, ptr @main.V, align 8 +// CHECK-NEXT: %2352 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 8) +// CHECK-NEXT: store i64 156, ptr %2352, align 8 +// CHECK-NEXT: %2353 = insertvalue %"{{.*}}/runtime/internal/runtime.eface" { ptr @_llgo_uint, ptr undef }, ptr %2352, 1 +// CHECK-NEXT: %2354 = extractvalue { ptr, ptr } %2351, 1 +// CHECK-NEXT: %2355 = extractvalue { ptr, ptr } %2351, 0 +// CHECK-NEXT: %__llgo_funcval_code313 = call ptr asm "", "=r,0"(ptr %2355) +// CHECK-NEXT: %2356 = call %reflect.Value %__llgo_funcval_code313(ptr {{(nest|swiftself)}} %2354, %"{{.*}}/runtime/internal/runtime.eface" %2353) +// CHECK-NEXT: store %reflect.Value %2349, ptr %2343, align 8 +// CHECK-NEXT: store %reflect.Value %2356, ptr %2350, align 8 +// CHECK-NEXT: %2357 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %1, i64 157 +// CHECK-NEXT: %2358 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %2357, i32 0, i32 0 +// CHECK-NEXT: %2359 = load { ptr, ptr }, ptr @main.V, align 8 +// CHECK-NEXT: %2360 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 8) +// CHECK-NEXT: store i64 157, ptr %2360, align 8 +// CHECK-NEXT: %2361 = insertvalue %"{{.*}}/runtime/internal/runtime.eface" { ptr @_llgo_uint, ptr undef }, ptr %2360, 1 +// CHECK-NEXT: %2362 = extractvalue { ptr, ptr } %2359, 1 +// CHECK-NEXT: %2363 = extractvalue { ptr, ptr } %2359, 0 +// CHECK-NEXT: %__llgo_funcval_code314 = call ptr asm "", "=r,0"(ptr %2363) +// CHECK-NEXT: %2364 = call %reflect.Value %__llgo_funcval_code314(ptr {{(nest|swiftself)}} %2362, %"{{.*}}/runtime/internal/runtime.eface" %2361) +// CHECK-NEXT: %2365 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %2357, i32 0, i32 1 +// CHECK-NEXT: %2366 = load { ptr, ptr }, ptr @main.V, align 8 +// CHECK-NEXT: %2367 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 4) +// CHECK-NEXT: store float 1.570000e+02, ptr %2367, align 4 +// CHECK-NEXT: %2368 = insertvalue %"{{.*}}/runtime/internal/runtime.eface" { ptr @_llgo_float32, ptr undef }, ptr %2367, 1 +// CHECK-NEXT: %2369 = extractvalue { ptr, ptr } %2366, 1 +// CHECK-NEXT: %2370 = extractvalue { ptr, ptr } %2366, 0 +// CHECK-NEXT: %__llgo_funcval_code315 = call ptr asm "", "=r,0"(ptr %2370) +// CHECK-NEXT: %2371 = call %reflect.Value %__llgo_funcval_code315(ptr {{(nest|swiftself)}} %2369, %"{{.*}}/runtime/internal/runtime.eface" %2368) +// CHECK-NEXT: store %reflect.Value %2364, ptr %2358, align 8 +// CHECK-NEXT: store %reflect.Value %2371, ptr %2365, align 8 +// CHECK-NEXT: %2372 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %1, i64 158 +// CHECK-NEXT: %2373 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %2372, i32 0, i32 0 +// CHECK-NEXT: %2374 = load { ptr, ptr }, ptr @main.V, align 8 +// CHECK-NEXT: %2375 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 4) +// CHECK-NEXT: store float 1.580000e+02, ptr %2375, align 4 +// CHECK-NEXT: %2376 = insertvalue %"{{.*}}/runtime/internal/runtime.eface" { ptr @_llgo_float32, ptr undef }, ptr %2375, 1 +// CHECK-NEXT: %2377 = extractvalue { ptr, ptr } %2374, 1 +// CHECK-NEXT: %2378 = extractvalue { ptr, ptr } %2374, 0 +// CHECK-NEXT: %__llgo_funcval_code316 = call ptr asm "", "=r,0"(ptr %2378) +// CHECK-NEXT: %2379 = call %reflect.Value %__llgo_funcval_code316(ptr {{(nest|swiftself)}} %2377, %"{{.*}}/runtime/internal/runtime.eface" %2376) +// CHECK-NEXT: %2380 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %2372, i32 0, i32 1 +// CHECK-NEXT: %2381 = load { ptr, ptr }, ptr @main.V, align 8 +// CHECK-NEXT: %2382 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 8) +// CHECK-NEXT: store i64 158, ptr %2382, align 8 +// CHECK-NEXT: %2383 = insertvalue %"{{.*}}/runtime/internal/runtime.eface" { ptr @_llgo_uint, ptr undef }, ptr %2382, 1 +// CHECK-NEXT: %2384 = extractvalue { ptr, ptr } %2381, 1 +// CHECK-NEXT: %2385 = extractvalue { ptr, ptr } %2381, 0 +// CHECK-NEXT: %__llgo_funcval_code317 = call ptr asm "", "=r,0"(ptr %2385) +// CHECK-NEXT: %2386 = call %reflect.Value %__llgo_funcval_code317(ptr {{(nest|swiftself)}} %2384, %"{{.*}}/runtime/internal/runtime.eface" %2383) +// CHECK-NEXT: store %reflect.Value %2379, ptr %2373, align 8 +// CHECK-NEXT: store %reflect.Value %2386, ptr %2380, align 8 +// CHECK-NEXT: %2387 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %1, i64 159 +// CHECK-NEXT: %2388 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %2387, i32 0, i32 0 +// CHECK-NEXT: %2389 = load { ptr, ptr }, ptr @main.V, align 8 +// CHECK-NEXT: %2390 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 8) +// CHECK-NEXT: store i64 159, ptr %2390, align 8 +// CHECK-NEXT: %2391 = insertvalue %"{{.*}}/runtime/internal/runtime.eface" { ptr @_llgo_uint, ptr undef }, ptr %2390, 1 +// CHECK-NEXT: %2392 = extractvalue { ptr, ptr } %2389, 1 +// CHECK-NEXT: %2393 = extractvalue { ptr, ptr } %2389, 0 +// CHECK-NEXT: %__llgo_funcval_code318 = call ptr asm "", "=r,0"(ptr %2393) +// CHECK-NEXT: %2394 = call %reflect.Value %__llgo_funcval_code318(ptr {{(nest|swiftself)}} %2392, %"{{.*}}/runtime/internal/runtime.eface" %2391) +// CHECK-NEXT: %2395 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %2387, i32 0, i32 1 +// CHECK-NEXT: %2396 = load { ptr, ptr }, ptr @main.V, align 8 +// CHECK-NEXT: %2397 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 8) +// CHECK-NEXT: store double 1.590000e+02, ptr %2397, align 8 +// CHECK-NEXT: %2398 = insertvalue %"{{.*}}/runtime/internal/runtime.eface" { ptr @_llgo_float64, ptr undef }, ptr %2397, 1 +// CHECK-NEXT: %2399 = extractvalue { ptr, ptr } %2396, 1 +// CHECK-NEXT: %2400 = extractvalue { ptr, ptr } %2396, 0 +// CHECK-NEXT: %__llgo_funcval_code319 = call ptr asm "", "=r,0"(ptr %2400) +// CHECK-NEXT: %2401 = call %reflect.Value %__llgo_funcval_code319(ptr {{(nest|swiftself)}} %2399, %"{{.*}}/runtime/internal/runtime.eface" %2398) +// CHECK-NEXT: store %reflect.Value %2394, ptr %2388, align 8 +// CHECK-NEXT: store %reflect.Value %2401, ptr %2395, align 8 +// CHECK-NEXT: %2402 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %1, i64 160 +// CHECK-NEXT: %2403 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %2402, i32 0, i32 0 +// CHECK-NEXT: %2404 = load { ptr, ptr }, ptr @main.V, align 8 +// CHECK-NEXT: %2405 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 8) +// CHECK-NEXT: store double 1.600000e+02, ptr %2405, align 8 +// CHECK-NEXT: %2406 = insertvalue %"{{.*}}/runtime/internal/runtime.eface" { ptr @_llgo_float64, ptr undef }, ptr %2405, 1 +// CHECK-NEXT: %2407 = extractvalue { ptr, ptr } %2404, 1 +// CHECK-NEXT: %2408 = extractvalue { ptr, ptr } %2404, 0 +// CHECK-NEXT: %__llgo_funcval_code320 = call ptr asm "", "=r,0"(ptr %2408) +// CHECK-NEXT: %2409 = call %reflect.Value %__llgo_funcval_code320(ptr {{(nest|swiftself)}} %2407, %"{{.*}}/runtime/internal/runtime.eface" %2406) +// CHECK-NEXT: %2410 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %2402, i32 0, i32 1 +// CHECK-NEXT: %2411 = load { ptr, ptr }, ptr @main.V, align 8 +// CHECK-NEXT: %2412 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 8) +// CHECK-NEXT: store i64 160, ptr %2412, align 8 +// CHECK-NEXT: %2413 = insertvalue %"{{.*}}/runtime/internal/runtime.eface" { ptr @_llgo_uint, ptr undef }, ptr %2412, 1 +// CHECK-NEXT: %2414 = extractvalue { ptr, ptr } %2411, 1 +// CHECK-NEXT: %2415 = extractvalue { ptr, ptr } %2411, 0 +// CHECK-NEXT: %__llgo_funcval_code321 = call ptr asm "", "=r,0"(ptr %2415) +// CHECK-NEXT: %2416 = call %reflect.Value %__llgo_funcval_code321(ptr {{(nest|swiftself)}} %2414, %"{{.*}}/runtime/internal/runtime.eface" %2413) +// CHECK-NEXT: store %reflect.Value %2409, ptr %2403, align 8 +// CHECK-NEXT: store %reflect.Value %2416, ptr %2410, align 8 +// CHECK-NEXT: %2417 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %1, i64 161 +// CHECK-NEXT: %2418 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %2417, i32 0, i32 0 +// CHECK-NEXT: %2419 = load { ptr, ptr }, ptr @main.V, align 8 +// CHECK-NEXT: %2420 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 8) +// CHECK-NEXT: store i64 161, ptr %2420, align 8 +// CHECK-NEXT: %2421 = insertvalue %"{{.*}}/runtime/internal/runtime.eface" { ptr @_llgo_uintptr, ptr undef }, ptr %2420, 1 +// CHECK-NEXT: %2422 = extractvalue { ptr, ptr } %2419, 1 +// CHECK-NEXT: %2423 = extractvalue { ptr, ptr } %2419, 0 +// CHECK-NEXT: %__llgo_funcval_code322 = call ptr asm "", "=r,0"(ptr %2423) +// CHECK-NEXT: %2424 = call %reflect.Value %__llgo_funcval_code322(ptr {{(nest|swiftself)}} %2422, %"{{.*}}/runtime/internal/runtime.eface" %2421) +// CHECK-NEXT: %2425 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %2417, i32 0, i32 1 +// CHECK-NEXT: %2426 = load { ptr, ptr }, ptr @main.V, align 8 +// CHECK-NEXT: %2427 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 8) +// CHECK-NEXT: store i64 161, ptr %2427, align 8 +// CHECK-NEXT: %2428 = insertvalue %"{{.*}}/runtime/internal/runtime.eface" { ptr @_llgo_uintptr, ptr undef }, ptr %2427, 1 +// CHECK-NEXT: %2429 = extractvalue { ptr, ptr } %2426, 1 +// CHECK-NEXT: %2430 = extractvalue { ptr, ptr } %2426, 0 +// CHECK-NEXT: %__llgo_funcval_code323 = call ptr asm "", "=r,0"(ptr %2430) +// CHECK-NEXT: %2431 = call %reflect.Value %__llgo_funcval_code323(ptr {{(nest|swiftself)}} %2429, %"{{.*}}/runtime/internal/runtime.eface" %2428) +// CHECK-NEXT: store %reflect.Value %2424, ptr %2418, align 8 +// CHECK-NEXT: store %reflect.Value %2431, ptr %2425, align 8 +// CHECK-NEXT: %2432 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %1, i64 162 +// CHECK-NEXT: %2433 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %2432, i32 0, i32 0 +// CHECK-NEXT: %2434 = load { ptr, ptr }, ptr @main.V, align 8 +// CHECK-NEXT: %2435 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 8) +// CHECK-NEXT: store i64 162, ptr %2435, align 8 +// CHECK-NEXT: %2436 = insertvalue %"{{.*}}/runtime/internal/runtime.eface" { ptr @_llgo_uintptr, ptr undef }, ptr %2435, 1 +// CHECK-NEXT: %2437 = extractvalue { ptr, ptr } %2434, 1 +// CHECK-NEXT: %2438 = extractvalue { ptr, ptr } %2434, 0 +// CHECK-NEXT: %__llgo_funcval_code324 = call ptr asm "", "=r,0"(ptr %2438) +// CHECK-NEXT: %2439 = call %reflect.Value %__llgo_funcval_code324(ptr {{(nest|swiftself)}} %2437, %"{{.*}}/runtime/internal/runtime.eface" %2436) +// CHECK-NEXT: %2440 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %2432, i32 0, i32 1 +// CHECK-NEXT: %2441 = load { ptr, ptr }, ptr @main.V, align 8 +// CHECK-NEXT: %2442 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 4) +// CHECK-NEXT: store float 1.620000e+02, ptr %2442, align 4 +// CHECK-NEXT: %2443 = insertvalue %"{{.*}}/runtime/internal/runtime.eface" { ptr @_llgo_float32, ptr undef }, ptr %2442, 1 +// CHECK-NEXT: %2444 = extractvalue { ptr, ptr } %2441, 1 +// CHECK-NEXT: %2445 = extractvalue { ptr, ptr } %2441, 0 +// CHECK-NEXT: %__llgo_funcval_code325 = call ptr asm "", "=r,0"(ptr %2445) +// CHECK-NEXT: %2446 = call %reflect.Value %__llgo_funcval_code325(ptr {{(nest|swiftself)}} %2444, %"{{.*}}/runtime/internal/runtime.eface" %2443) +// CHECK-NEXT: store %reflect.Value %2439, ptr %2433, align 8 +// CHECK-NEXT: store %reflect.Value %2446, ptr %2440, align 8 +// CHECK-NEXT: %2447 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %1, i64 163 +// CHECK-NEXT: %2448 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %2447, i32 0, i32 0 +// CHECK-NEXT: %2449 = load { ptr, ptr }, ptr @main.V, align 8 +// CHECK-NEXT: %2450 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 4) +// CHECK-NEXT: store float 1.630000e+02, ptr %2450, align 4 +// CHECK-NEXT: %2451 = insertvalue %"{{.*}}/runtime/internal/runtime.eface" { ptr @_llgo_float32, ptr undef }, ptr %2450, 1 +// CHECK-NEXT: %2452 = extractvalue { ptr, ptr } %2449, 1 +// CHECK-NEXT: %2453 = extractvalue { ptr, ptr } %2449, 0 +// CHECK-NEXT: %__llgo_funcval_code326 = call ptr asm "", "=r,0"(ptr %2453) +// CHECK-NEXT: %2454 = call %reflect.Value %__llgo_funcval_code326(ptr {{(nest|swiftself)}} %2452, %"{{.*}}/runtime/internal/runtime.eface" %2451) +// CHECK-NEXT: %2455 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %2447, i32 0, i32 1 +// CHECK-NEXT: %2456 = load { ptr, ptr }, ptr @main.V, align 8 +// CHECK-NEXT: %2457 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 8) +// CHECK-NEXT: store i64 163, ptr %2457, align 8 +// CHECK-NEXT: %2458 = insertvalue %"{{.*}}/runtime/internal/runtime.eface" { ptr @_llgo_uintptr, ptr undef }, ptr %2457, 1 +// CHECK-NEXT: %2459 = extractvalue { ptr, ptr } %2456, 1 +// CHECK-NEXT: %2460 = extractvalue { ptr, ptr } %2456, 0 +// CHECK-NEXT: %__llgo_funcval_code327 = call ptr asm "", "=r,0"(ptr %2460) +// CHECK-NEXT: %2461 = call %reflect.Value %__llgo_funcval_code327(ptr {{(nest|swiftself)}} %2459, %"{{.*}}/runtime/internal/runtime.eface" %2458) +// CHECK-NEXT: store %reflect.Value %2454, ptr %2448, align 8 +// CHECK-NEXT: store %reflect.Value %2461, ptr %2455, align 8 +// CHECK-NEXT: %2462 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %1, i64 164 +// CHECK-NEXT: %2463 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %2462, i32 0, i32 0 +// CHECK-NEXT: %2464 = load { ptr, ptr }, ptr @main.V, align 8 +// CHECK-NEXT: %2465 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 8) +// CHECK-NEXT: store i64 164, ptr %2465, align 8 +// CHECK-NEXT: %2466 = insertvalue %"{{.*}}/runtime/internal/runtime.eface" { ptr @_llgo_uintptr, ptr undef }, ptr %2465, 1 +// CHECK-NEXT: %2467 = extractvalue { ptr, ptr } %2464, 1 +// CHECK-NEXT: %2468 = extractvalue { ptr, ptr } %2464, 0 +// CHECK-NEXT: %__llgo_funcval_code328 = call ptr asm "", "=r,0"(ptr %2468) +// CHECK-NEXT: %2469 = call %reflect.Value %__llgo_funcval_code328(ptr {{(nest|swiftself)}} %2467, %"{{.*}}/runtime/internal/runtime.eface" %2466) +// CHECK-NEXT: %2470 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %2462, i32 0, i32 1 +// CHECK-NEXT: %2471 = load { ptr, ptr }, ptr @main.V, align 8 +// CHECK-NEXT: %2472 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 8) +// CHECK-NEXT: store double 1.640000e+02, ptr %2472, align 8 +// CHECK-NEXT: %2473 = insertvalue %"{{.*}}/runtime/internal/runtime.eface" { ptr @_llgo_float64, ptr undef }, ptr %2472, 1 +// CHECK-NEXT: %2474 = extractvalue { ptr, ptr } %2471, 1 +// CHECK-NEXT: %2475 = extractvalue { ptr, ptr } %2471, 0 +// CHECK-NEXT: %__llgo_funcval_code329 = call ptr asm "", "=r,0"(ptr %2475) +// CHECK-NEXT: %2476 = call %reflect.Value %__llgo_funcval_code329(ptr {{(nest|swiftself)}} %2474, %"{{.*}}/runtime/internal/runtime.eface" %2473) +// CHECK-NEXT: store %reflect.Value %2469, ptr %2463, align 8 +// CHECK-NEXT: store %reflect.Value %2476, ptr %2470, align 8 +// CHECK-NEXT: %2477 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %1, i64 165 +// CHECK-NEXT: %2478 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %2477, i32 0, i32 0 +// CHECK-NEXT: %2479 = load { ptr, ptr }, ptr @main.V, align 8 +// CHECK-NEXT: %2480 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 8) +// CHECK-NEXT: store double 1.650000e+02, ptr %2480, align 8 +// CHECK-NEXT: %2481 = insertvalue %"{{.*}}/runtime/internal/runtime.eface" { ptr @_llgo_float64, ptr undef }, ptr %2480, 1 +// CHECK-NEXT: %2482 = extractvalue { ptr, ptr } %2479, 1 +// CHECK-NEXT: %2483 = extractvalue { ptr, ptr } %2479, 0 +// CHECK-NEXT: %__llgo_funcval_code330 = call ptr asm "", "=r,0"(ptr %2483) +// CHECK-NEXT: %2484 = call %reflect.Value %__llgo_funcval_code330(ptr {{(nest|swiftself)}} %2482, %"{{.*}}/runtime/internal/runtime.eface" %2481) +// CHECK-NEXT: %2485 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %2477, i32 0, i32 1 +// CHECK-NEXT: %2486 = load { ptr, ptr }, ptr @main.V, align 8 +// CHECK-NEXT: %2487 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 8) +// CHECK-NEXT: store i64 165, ptr %2487, align 8 +// CHECK-NEXT: %2488 = insertvalue %"{{.*}}/runtime/internal/runtime.eface" { ptr @_llgo_uintptr, ptr undef }, ptr %2487, 1 +// CHECK-NEXT: %2489 = extractvalue { ptr, ptr } %2486, 1 +// CHECK-NEXT: %2490 = extractvalue { ptr, ptr } %2486, 0 +// CHECK-NEXT: %__llgo_funcval_code331 = call ptr asm "", "=r,0"(ptr %2490) +// CHECK-NEXT: %2491 = call %reflect.Value %__llgo_funcval_code331(ptr {{(nest|swiftself)}} %2489, %"{{.*}}/runtime/internal/runtime.eface" %2488) +// CHECK-NEXT: store %reflect.Value %2484, ptr %2478, align 8 +// CHECK-NEXT: store %reflect.Value %2491, ptr %2485, align 8 +// CHECK-NEXT: %2492 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %1, i64 166 +// CHECK-NEXT: %2493 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %2492, i32 0, i32 0 +// CHECK-NEXT: %2494 = load { ptr, ptr }, ptr @main.V, align 8 +// CHECK-NEXT: %2495 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 4) +// CHECK-NEXT: store float 1.660000e+02, ptr %2495, align 4 +// CHECK-NEXT: %2496 = insertvalue %"{{.*}}/runtime/internal/runtime.eface" { ptr @_llgo_float32, ptr undef }, ptr %2495, 1 +// CHECK-NEXT: %2497 = extractvalue { ptr, ptr } %2494, 1 +// CHECK-NEXT: %2498 = extractvalue { ptr, ptr } %2494, 0 +// CHECK-NEXT: %__llgo_funcval_code332 = call ptr asm "", "=r,0"(ptr %2498) +// CHECK-NEXT: %2499 = call %reflect.Value %__llgo_funcval_code332(ptr {{(nest|swiftself)}} %2497, %"{{.*}}/runtime/internal/runtime.eface" %2496) +// CHECK-NEXT: %2500 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %2492, i32 0, i32 1 +// CHECK-NEXT: %2501 = load { ptr, ptr }, ptr @main.V, align 8 +// CHECK-NEXT: %2502 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 4) +// CHECK-NEXT: store float 1.660000e+02, ptr %2502, align 4 +// CHECK-NEXT: %2503 = insertvalue %"{{.*}}/runtime/internal/runtime.eface" { ptr @_llgo_float32, ptr undef }, ptr %2502, 1 +// CHECK-NEXT: %2504 = extractvalue { ptr, ptr } %2501, 1 +// CHECK-NEXT: %2505 = extractvalue { ptr, ptr } %2501, 0 +// CHECK-NEXT: %__llgo_funcval_code333 = call ptr asm "", "=r,0"(ptr %2505) +// CHECK-NEXT: %2506 = call %reflect.Value %__llgo_funcval_code333(ptr {{(nest|swiftself)}} %2504, %"{{.*}}/runtime/internal/runtime.eface" %2503) +// CHECK-NEXT: store %reflect.Value %2499, ptr %2493, align 8 +// CHECK-NEXT: store %reflect.Value %2506, ptr %2500, align 8 +// CHECK-NEXT: %2507 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %1, i64 167 +// CHECK-NEXT: %2508 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %2507, i32 0, i32 0 +// CHECK-NEXT: %2509 = load { ptr, ptr }, ptr @main.V, align 8 +// CHECK-NEXT: %2510 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 4) +// CHECK-NEXT: store float 1.670000e+02, ptr %2510, align 4 +// CHECK-NEXT: %2511 = insertvalue %"{{.*}}/runtime/internal/runtime.eface" { ptr @_llgo_float32, ptr undef }, ptr %2510, 1 +// CHECK-NEXT: %2512 = extractvalue { ptr, ptr } %2509, 1 +// CHECK-NEXT: %2513 = extractvalue { ptr, ptr } %2509, 0 +// CHECK-NEXT: %__llgo_funcval_code334 = call ptr asm "", "=r,0"(ptr %2513) +// CHECK-NEXT: %2514 = call %reflect.Value %__llgo_funcval_code334(ptr {{(nest|swiftself)}} %2512, %"{{.*}}/runtime/internal/runtime.eface" %2511) +// CHECK-NEXT: %2515 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %2507, i32 0, i32 1 +// CHECK-NEXT: %2516 = load { ptr, ptr }, ptr @main.V, align 8 +// CHECK-NEXT: %2517 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 8) +// CHECK-NEXT: store double 1.670000e+02, ptr %2517, align 8 +// CHECK-NEXT: %2518 = insertvalue %"{{.*}}/runtime/internal/runtime.eface" { ptr @_llgo_float64, ptr undef }, ptr %2517, 1 +// CHECK-NEXT: %2519 = extractvalue { ptr, ptr } %2516, 1 +// CHECK-NEXT: %2520 = extractvalue { ptr, ptr } %2516, 0 +// CHECK-NEXT: %__llgo_funcval_code335 = call ptr asm "", "=r,0"(ptr %2520) +// CHECK-NEXT: %2521 = call %reflect.Value %__llgo_funcval_code335(ptr {{(nest|swiftself)}} %2519, %"{{.*}}/runtime/internal/runtime.eface" %2518) +// CHECK-NEXT: store %reflect.Value %2514, ptr %2508, align 8 +// CHECK-NEXT: store %reflect.Value %2521, ptr %2515, align 8 +// CHECK-NEXT: %2522 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %1, i64 168 +// CHECK-NEXT: %2523 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %2522, i32 0, i32 0 +// CHECK-NEXT: %2524 = load { ptr, ptr }, ptr @main.V, align 8 +// CHECK-NEXT: %2525 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 8) +// CHECK-NEXT: store double 1.680000e+02, ptr %2525, align 8 +// CHECK-NEXT: %2526 = insertvalue %"{{.*}}/runtime/internal/runtime.eface" { ptr @_llgo_float64, ptr undef }, ptr %2525, 1 +// CHECK-NEXT: %2527 = extractvalue { ptr, ptr } %2524, 1 +// CHECK-NEXT: %2528 = extractvalue { ptr, ptr } %2524, 0 +// CHECK-NEXT: %__llgo_funcval_code336 = call ptr asm "", "=r,0"(ptr %2528) +// CHECK-NEXT: %2529 = call %reflect.Value %__llgo_funcval_code336(ptr {{(nest|swiftself)}} %2527, %"{{.*}}/runtime/internal/runtime.eface" %2526) +// CHECK-NEXT: %2530 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %2522, i32 0, i32 1 +// CHECK-NEXT: %2531 = load { ptr, ptr }, ptr @main.V, align 8 +// CHECK-NEXT: %2532 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 4) +// CHECK-NEXT: store float 1.680000e+02, ptr %2532, align 4 +// CHECK-NEXT: %2533 = insertvalue %"{{.*}}/runtime/internal/runtime.eface" { ptr @_llgo_float32, ptr undef }, ptr %2532, 1 +// CHECK-NEXT: %2534 = extractvalue { ptr, ptr } %2531, 1 +// CHECK-NEXT: %2535 = extractvalue { ptr, ptr } %2531, 0 +// CHECK-NEXT: %__llgo_funcval_code337 = call ptr asm "", "=r,0"(ptr %2535) +// CHECK-NEXT: %2536 = call %reflect.Value %__llgo_funcval_code337(ptr {{(nest|swiftself)}} %2534, %"{{.*}}/runtime/internal/runtime.eface" %2533) +// CHECK-NEXT: store %reflect.Value %2529, ptr %2523, align 8 +// CHECK-NEXT: store %reflect.Value %2536, ptr %2530, align 8 +// CHECK-NEXT: %2537 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %1, i64 169 +// CHECK-NEXT: %2538 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %2537, i32 0, i32 0 +// CHECK-NEXT: %2539 = load { ptr, ptr }, ptr @main.V, align 8 +// CHECK-NEXT: %2540 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 8) +// CHECK-NEXT: store double 1.690000e+02, ptr %2540, align 8 +// CHECK-NEXT: %2541 = insertvalue %"{{.*}}/runtime/internal/runtime.eface" { ptr @_llgo_float64, ptr undef }, ptr %2540, 1 +// CHECK-NEXT: %2542 = extractvalue { ptr, ptr } %2539, 1 +// CHECK-NEXT: %2543 = extractvalue { ptr, ptr } %2539, 0 +// CHECK-NEXT: %__llgo_funcval_code338 = call ptr asm "", "=r,0"(ptr %2543) +// CHECK-NEXT: %2544 = call %reflect.Value %__llgo_funcval_code338(ptr {{(nest|swiftself)}} %2542, %"{{.*}}/runtime/internal/runtime.eface" %2541) +// CHECK-NEXT: %2545 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %2537, i32 0, i32 1 +// CHECK-NEXT: %2546 = load { ptr, ptr }, ptr @main.V, align 8 +// CHECK-NEXT: %2547 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 8) +// CHECK-NEXT: store double 1.690000e+02, ptr %2547, align 8 +// CHECK-NEXT: %2548 = insertvalue %"{{.*}}/runtime/internal/runtime.eface" { ptr @_llgo_float64, ptr undef }, ptr %2547, 1 +// CHECK-NEXT: %2549 = extractvalue { ptr, ptr } %2546, 1 +// CHECK-NEXT: %2550 = extractvalue { ptr, ptr } %2546, 0 +// CHECK-NEXT: %__llgo_funcval_code339 = call ptr asm "", "=r,0"(ptr %2550) +// CHECK-NEXT: %2551 = call %reflect.Value %__llgo_funcval_code339(ptr {{(nest|swiftself)}} %2549, %"{{.*}}/runtime/internal/runtime.eface" %2548) +// CHECK-NEXT: store %reflect.Value %2544, ptr %2538, align 8 +// CHECK-NEXT: store %reflect.Value %2551, ptr %2545, align 8 +// CHECK-NEXT: %2552 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %1, i64 170 +// CHECK-NEXT: %2553 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %2552, i32 0, i32 0 +// CHECK-NEXT: %2554 = load { ptr, ptr }, ptr @main.V, align 8 +// CHECK-NEXT: %2555 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 8) +// CHECK-NEXT: store double 1.500000e+00, ptr %2555, align 8 +// CHECK-NEXT: %2556 = insertvalue %"{{.*}}/runtime/internal/runtime.eface" { ptr @_llgo_float64, ptr undef }, ptr %2555, 1 +// CHECK-NEXT: %2557 = extractvalue { ptr, ptr } %2554, 1 +// CHECK-NEXT: %2558 = extractvalue { ptr, ptr } %2554, 0 +// CHECK-NEXT: %__llgo_funcval_code340 = call ptr asm "", "=r,0"(ptr %2558) +// CHECK-NEXT: %2559 = call %reflect.Value %__llgo_funcval_code340(ptr {{(nest|swiftself)}} %2557, %"{{.*}}/runtime/internal/runtime.eface" %2556) +// CHECK-NEXT: %2560 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %2552, i32 0, i32 1 +// CHECK-NEXT: %2561 = load { ptr, ptr }, ptr @main.V, align 8 +// CHECK-NEXT: %2562 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 8) +// CHECK-NEXT: store i64 1, ptr %2562, align 8 +// CHECK-NEXT: %2563 = insertvalue %"{{.*}}/runtime/internal/runtime.eface" { ptr @_llgo_int, ptr undef }, ptr %2562, 1 +// CHECK-NEXT: %2564 = extractvalue { ptr, ptr } %2561, 1 +// CHECK-NEXT: %2565 = extractvalue { ptr, ptr } %2561, 0 +// CHECK-NEXT: %__llgo_funcval_code341 = call ptr asm "", "=r,0"(ptr %2565) +// CHECK-NEXT: %2566 = call %reflect.Value %__llgo_funcval_code341(ptr {{(nest|swiftself)}} %2564, %"{{.*}}/runtime/internal/runtime.eface" %2563) +// CHECK-NEXT: store %reflect.Value %2559, ptr %2553, align 8 +// CHECK-NEXT: store %reflect.Value %2566, ptr %2560, align 8 +// CHECK-NEXT: %2567 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %1, i64 171 +// CHECK-NEXT: %2568 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %2567, i32 0, i32 0 +// CHECK-NEXT: %2569 = load { ptr, ptr }, ptr @main.V, align 8 +// CHECK-NEXT: %2570 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 8) +// CHECK-NEXT: store { float, float } { float 0.000000e+00, float 1.000000e+00 }, ptr %2570, align 4 +// CHECK-NEXT: %2571 = insertvalue %"{{.*}}/runtime/internal/runtime.eface" { ptr @_llgo_complex64, ptr undef }, ptr %2570, 1 +// CHECK-NEXT: %2572 = extractvalue { ptr, ptr } %2569, 1 +// CHECK-NEXT: %2573 = extractvalue { ptr, ptr } %2569, 0 +// CHECK-NEXT: %__llgo_funcval_code342 = call ptr asm "", "=r,0"(ptr %2573) +// CHECK-NEXT: %2574 = call %reflect.Value %__llgo_funcval_code342(ptr {{(nest|swiftself)}} %2572, %"{{.*}}/runtime/internal/runtime.eface" %2571) +// CHECK-NEXT: %2575 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %2567, i32 0, i32 1 +// CHECK-NEXT: %2576 = load { ptr, ptr }, ptr @main.V, align 8 +// CHECK-NEXT: %2577 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 8) +// CHECK-NEXT: store { float, float } { float 0.000000e+00, float 1.000000e+00 }, ptr %2577, align 4 +// CHECK-NEXT: %2578 = insertvalue %"{{.*}}/runtime/internal/runtime.eface" { ptr @_llgo_complex64, ptr undef }, ptr %2577, 1 +// CHECK-NEXT: %2579 = extractvalue { ptr, ptr } %2576, 1 +// CHECK-NEXT: %2580 = extractvalue { ptr, ptr } %2576, 0 +// CHECK-NEXT: %__llgo_funcval_code343 = call ptr asm "", "=r,0"(ptr %2580) +// CHECK-NEXT: %2581 = call %reflect.Value %__llgo_funcval_code343(ptr {{(nest|swiftself)}} %2579, %"{{.*}}/runtime/internal/runtime.eface" %2578) +// CHECK-NEXT: store %reflect.Value %2574, ptr %2568, align 8 +// CHECK-NEXT: store %reflect.Value %2581, ptr %2575, align 8 +// CHECK-NEXT: %2582 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %1, i64 172 +// CHECK-NEXT: %2583 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %2582, i32 0, i32 0 +// CHECK-NEXT: %2584 = load { ptr, ptr }, ptr @main.V, align 8 +// CHECK-NEXT: %2585 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 8) +// CHECK-NEXT: store { float, float } { float 0.000000e+00, float 2.000000e+00 }, ptr %2585, align 4 +// CHECK-NEXT: %2586 = insertvalue %"{{.*}}/runtime/internal/runtime.eface" { ptr @_llgo_complex64, ptr undef }, ptr %2585, 1 +// CHECK-NEXT: %2587 = extractvalue { ptr, ptr } %2584, 1 +// CHECK-NEXT: %2588 = extractvalue { ptr, ptr } %2584, 0 +// CHECK-NEXT: %__llgo_funcval_code344 = call ptr asm "", "=r,0"(ptr %2588) +// CHECK-NEXT: %2589 = call %reflect.Value %__llgo_funcval_code344(ptr {{(nest|swiftself)}} %2587, %"{{.*}}/runtime/internal/runtime.eface" %2586) +// CHECK-NEXT: %2590 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %2582, i32 0, i32 1 +// CHECK-NEXT: %2591 = load { ptr, ptr }, ptr @main.V, align 8 +// CHECK-NEXT: %2592 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 16) +// CHECK-NEXT: store { double, double } { double 0.000000e+00, double 2.000000e+00 }, ptr %2592, align 8 +// CHECK-NEXT: %2593 = insertvalue %"{{.*}}/runtime/internal/runtime.eface" { ptr @_llgo_complex128, ptr undef }, ptr %2592, 1 +// CHECK-NEXT: %2594 = extractvalue { ptr, ptr } %2591, 1 +// CHECK-NEXT: %2595 = extractvalue { ptr, ptr } %2591, 0 +// CHECK-NEXT: %__llgo_funcval_code345 = call ptr asm "", "=r,0"(ptr %2595) +// CHECK-NEXT: %2596 = call %reflect.Value %__llgo_funcval_code345(ptr {{(nest|swiftself)}} %2594, %"{{.*}}/runtime/internal/runtime.eface" %2593) +// CHECK-NEXT: store %reflect.Value %2589, ptr %2583, align 8 +// CHECK-NEXT: store %reflect.Value %2596, ptr %2590, align 8 +// CHECK-NEXT: %2597 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %1, i64 173 +// CHECK-NEXT: %2598 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %2597, i32 0, i32 0 +// CHECK-NEXT: %2599 = load { ptr, ptr }, ptr @main.V, align 8 +// CHECK-NEXT: %2600 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 16) +// CHECK-NEXT: store { double, double } { double 0.000000e+00, double 3.000000e+00 }, ptr %2600, align 8 +// CHECK-NEXT: %2601 = insertvalue %"{{.*}}/runtime/internal/runtime.eface" { ptr @_llgo_complex128, ptr undef }, ptr %2600, 1 +// CHECK-NEXT: %2602 = extractvalue { ptr, ptr } %2599, 1 +// CHECK-NEXT: %2603 = extractvalue { ptr, ptr } %2599, 0 +// CHECK-NEXT: %__llgo_funcval_code346 = call ptr asm "", "=r,0"(ptr %2603) +// CHECK-NEXT: %2604 = call %reflect.Value %__llgo_funcval_code346(ptr {{(nest|swiftself)}} %2602, %"{{.*}}/runtime/internal/runtime.eface" %2601) +// CHECK-NEXT: %2605 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %2597, i32 0, i32 1 +// CHECK-NEXT: %2606 = load { ptr, ptr }, ptr @main.V, align 8 +// CHECK-NEXT: %2607 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 8) +// CHECK-NEXT: store { float, float } { float 0.000000e+00, float 3.000000e+00 }, ptr %2607, align 4 +// CHECK-NEXT: %2608 = insertvalue %"{{.*}}/runtime/internal/runtime.eface" { ptr @_llgo_complex64, ptr undef }, ptr %2607, 1 +// CHECK-NEXT: %2609 = extractvalue { ptr, ptr } %2606, 1 +// CHECK-NEXT: %2610 = extractvalue { ptr, ptr } %2606, 0 +// CHECK-NEXT: %__llgo_funcval_code347 = call ptr asm "", "=r,0"(ptr %2610) +// CHECK-NEXT: %2611 = call %reflect.Value %__llgo_funcval_code347(ptr {{(nest|swiftself)}} %2609, %"{{.*}}/runtime/internal/runtime.eface" %2608) +// CHECK-NEXT: store %reflect.Value %2604, ptr %2598, align 8 +// CHECK-NEXT: store %reflect.Value %2611, ptr %2605, align 8 +// CHECK-NEXT: %2612 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %1, i64 174 +// CHECK-NEXT: %2613 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %2612, i32 0, i32 0 +// CHECK-NEXT: %2614 = load { ptr, ptr }, ptr @main.V, align 8 +// CHECK-NEXT: %2615 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 16) +// CHECK-NEXT: store { double, double } { double 0.000000e+00, double 4.000000e+00 }, ptr %2615, align 8 +// CHECK-NEXT: %2616 = insertvalue %"{{.*}}/runtime/internal/runtime.eface" { ptr @_llgo_complex128, ptr undef }, ptr %2615, 1 +// CHECK-NEXT: %2617 = extractvalue { ptr, ptr } %2614, 1 +// CHECK-NEXT: %2618 = extractvalue { ptr, ptr } %2614, 0 +// CHECK-NEXT: %__llgo_funcval_code348 = call ptr asm "", "=r,0"(ptr %2618) +// CHECK-NEXT: %2619 = call %reflect.Value %__llgo_funcval_code348(ptr {{(nest|swiftself)}} %2617, %"{{.*}}/runtime/internal/runtime.eface" %2616) +// CHECK-NEXT: %2620 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %2612, i32 0, i32 1 +// CHECK-NEXT: %2621 = load { ptr, ptr }, ptr @main.V, align 8 +// CHECK-NEXT: %2622 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 16) +// CHECK-NEXT: store { double, double } { double 0.000000e+00, double 4.000000e+00 }, ptr %2622, align 8 +// CHECK-NEXT: %2623 = insertvalue %"{{.*}}/runtime/internal/runtime.eface" { ptr @_llgo_complex128, ptr undef }, ptr %2622, 1 +// CHECK-NEXT: %2624 = extractvalue { ptr, ptr } %2621, 1 +// CHECK-NEXT: %2625 = extractvalue { ptr, ptr } %2621, 0 +// CHECK-NEXT: %__llgo_funcval_code349 = call ptr asm "", "=r,0"(ptr %2625) +// CHECK-NEXT: %2626 = call %reflect.Value %__llgo_funcval_code349(ptr {{(nest|swiftself)}} %2624, %"{{.*}}/runtime/internal/runtime.eface" %2623) +// CHECK-NEXT: store %reflect.Value %2619, ptr %2613, align 8 +// CHECK-NEXT: store %reflect.Value %2626, ptr %2620, align 8 +// CHECK-NEXT: %2627 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %1, i64 175 +// CHECK-NEXT: %2628 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %2627, i32 0, i32 0 +// CHECK-NEXT: %2629 = load { ptr, ptr }, ptr @main.V, align 8 +// CHECK-NEXT: %2630 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 16) +// CHECK-NEXT: store %"{{.*}}/runtime/internal/runtime.String" { ptr @{{[0-9]+}}, i64 5 }, ptr %2630, align 8 +// CHECK-NEXT: %2631 = insertvalue %"{{.*}}/runtime/internal/runtime.eface" { ptr @_llgo_string, ptr undef }, ptr %2630, 1 +// CHECK-NEXT: %2632 = extractvalue { ptr, ptr } %2629, 1 +// CHECK-NEXT: %2633 = extractvalue { ptr, ptr } %2629, 0 +// CHECK-NEXT: %__llgo_funcval_code350 = call ptr asm "", "=r,0"(ptr %2633) +// CHECK-NEXT: %2634 = call %reflect.Value %__llgo_funcval_code350(ptr {{(nest|swiftself)}} %2632, %"{{.*}}/runtime/internal/runtime.eface" %2631) +// CHECK-NEXT: %2635 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %2627, i32 0, i32 1 +// CHECK-NEXT: %2636 = load { ptr, ptr }, ptr @main.V, align 8 +// CHECK-NEXT: %2637 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 16) +// CHECK-NEXT: store %"{{.*}}/runtime/internal/runtime.String" { ptr @{{[0-9]+}}, i64 5 }, ptr %2637, align 8 +// CHECK-NEXT: %2638 = insertvalue %"{{.*}}/runtime/internal/runtime.eface" { ptr @_llgo_string, ptr undef }, ptr %2637, 1 +// CHECK-NEXT: %2639 = extractvalue { ptr, ptr } %2636, 1 +// CHECK-NEXT: %2640 = extractvalue { ptr, ptr } %2636, 0 +// CHECK-NEXT: %__llgo_funcval_code351 = call ptr asm "", "=r,0"(ptr %2640) +// CHECK-NEXT: %2641 = call %reflect.Value %__llgo_funcval_code351(ptr {{(nest|swiftself)}} %2639, %"{{.*}}/runtime/internal/runtime.eface" %2638) +// CHECK-NEXT: store %reflect.Value %2634, ptr %2628, align 8 +// CHECK-NEXT: store %reflect.Value %2641, ptr %2635, align 8 +// CHECK-NEXT: %2642 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %1, i64 176 +// CHECK-NEXT: %2643 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %2642, i32 0, i32 0 +// CHECK-NEXT: %2644 = load { ptr, ptr }, ptr @main.V, align 8 +// CHECK-NEXT: %2645 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 16) +// CHECK-NEXT: store %"{{.*}}/runtime/internal/runtime.String" { ptr @{{[0-9]+}}, i64 6 }, ptr %2645, align 8 +// CHECK-NEXT: %2646 = insertvalue %"{{.*}}/runtime/internal/runtime.eface" { ptr @_llgo_string, ptr undef }, ptr %2645, 1 +// CHECK-NEXT: %2647 = extractvalue { ptr, ptr } %2644, 1 +// CHECK-NEXT: %2648 = extractvalue { ptr, ptr } %2644, 0 +// CHECK-NEXT: %__llgo_funcval_code352 = call ptr asm "", "=r,0"(ptr %2648) +// CHECK-NEXT: %2649 = call %reflect.Value %__llgo_funcval_code352(ptr {{(nest|swiftself)}} %2647, %"{{.*}}/runtime/internal/runtime.eface" %2646) +// CHECK-NEXT: %2650 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %2642, i32 0, i32 1 +// CHECK-NEXT: %2651 = load { ptr, ptr }, ptr @main.V, align 8 +// CHECK-NEXT: %2652 = call %"{{.*}}/runtime/internal/runtime.Slice" @"{{.*}}/runtime/internal/runtime.StringToBytes"(%"{{.*}}/runtime/internal/runtime.String" { ptr @{{[0-9]+}}, i64 6 }) +// CHECK-NEXT: %2653 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 24) +// CHECK-NEXT: store %"{{.*}}/runtime/internal/runtime.Slice" %2652, ptr %2653, align 8 +// CHECK-NEXT: %2654 = insertvalue %"{{.*}}/runtime/internal/runtime.eface" { ptr @"[]_llgo_uint8", ptr undef }, ptr %2653, 1 +// CHECK-NEXT: %2655 = extractvalue { ptr, ptr } %2651, 1 +// CHECK-NEXT: %2656 = extractvalue { ptr, ptr } %2651, 0 +// CHECK-NEXT: %__llgo_funcval_code353 = call ptr asm "", "=r,0"(ptr %2656) +// CHECK-NEXT: %2657 = call %reflect.Value %__llgo_funcval_code353(ptr {{(nest|swiftself)}} %2655, %"{{.*}}/runtime/internal/runtime.eface" %2654) +// CHECK-NEXT: store %reflect.Value %2649, ptr %2643, align 8 +// CHECK-NEXT: store %reflect.Value %2657, ptr %2650, align 8 +// CHECK-NEXT: %2658 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %1, i64 177 +// CHECK-NEXT: %2659 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %2658, i32 0, i32 0 +// CHECK-NEXT: %2660 = load { ptr, ptr }, ptr @main.V, align 8 +// CHECK-NEXT: %2661 = call %"{{.*}}/runtime/internal/runtime.Slice" @"{{.*}}/runtime/internal/runtime.StringToBytes"(%"{{.*}}/runtime/internal/runtime.String" { ptr @{{[0-9]+}}, i64 6 }) +// CHECK-NEXT: %2662 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 24) +// CHECK-NEXT: store %"{{.*}}/runtime/internal/runtime.Slice" %2661, ptr %2662, align 8 +// CHECK-NEXT: %2663 = insertvalue %"{{.*}}/runtime/internal/runtime.eface" { ptr @"[]_llgo_uint8", ptr undef }, ptr %2662, 1 +// CHECK-NEXT: %2664 = extractvalue { ptr, ptr } %2660, 1 +// CHECK-NEXT: %2665 = extractvalue { ptr, ptr } %2660, 0 +// CHECK-NEXT: %__llgo_funcval_code354 = call ptr asm "", "=r,0"(ptr %2665) +// CHECK-NEXT: %2666 = call %reflect.Value %__llgo_funcval_code354(ptr {{(nest|swiftself)}} %2664, %"{{.*}}/runtime/internal/runtime.eface" %2663) +// CHECK-NEXT: %2667 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %2658, i32 0, i32 1 +// CHECK-NEXT: %2668 = load { ptr, ptr }, ptr @main.V, align 8 +// CHECK-NEXT: %2669 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 16) +// CHECK-NEXT: store %"{{.*}}/runtime/internal/runtime.String" { ptr @{{[0-9]+}}, i64 6 }, ptr %2669, align 8 +// CHECK-NEXT: %2670 = insertvalue %"{{.*}}/runtime/internal/runtime.eface" { ptr @_llgo_string, ptr undef }, ptr %2669, 1 +// CHECK-NEXT: %2671 = extractvalue { ptr, ptr } %2668, 1 +// CHECK-NEXT: %2672 = extractvalue { ptr, ptr } %2668, 0 +// CHECK-NEXT: %__llgo_funcval_code355 = call ptr asm "", "=r,0"(ptr %2672) +// CHECK-NEXT: %2673 = call %reflect.Value %__llgo_funcval_code355(ptr {{(nest|swiftself)}} %2671, %"{{.*}}/runtime/internal/runtime.eface" %2670) +// CHECK-NEXT: store %reflect.Value %2666, ptr %2659, align 8 +// CHECK-NEXT: store %reflect.Value %2673, ptr %2667, align 8 +// CHECK-NEXT: %2674 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %1, i64 178 +// CHECK-NEXT: %2675 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %2674, i32 0, i32 0 +// CHECK-NEXT: %2676 = load { ptr, ptr }, ptr @main.V, align 8 +// CHECK-NEXT: %2677 = call %"{{.*}}/runtime/internal/runtime.Slice" @"{{.*}}/runtime/internal/runtime.StringToBytes"(%"{{.*}}/runtime/internal/runtime.String" { ptr @{{[0-9]+}}, i64 6 }) +// CHECK-NEXT: %2678 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 24) +// CHECK-NEXT: store %"{{.*}}/runtime/internal/runtime.Slice" %2677, ptr %2678, align 8 +// CHECK-NEXT: %2679 = insertvalue %"{{.*}}/runtime/internal/runtime.eface" { ptr @"[]_llgo_uint8", ptr undef }, ptr %2678, 1 +// CHECK-NEXT: %2680 = extractvalue { ptr, ptr } %2676, 1 +// CHECK-NEXT: %2681 = extractvalue { ptr, ptr } %2676, 0 +// CHECK-NEXT: %__llgo_funcval_code356 = call ptr asm "", "=r,0"(ptr %2681) +// CHECK-NEXT: %2682 = call %reflect.Value %__llgo_funcval_code356(ptr {{(nest|swiftself)}} %2680, %"{{.*}}/runtime/internal/runtime.eface" %2679) +// CHECK-NEXT: %2683 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %2674, i32 0, i32 1 +// CHECK-NEXT: %2684 = load { ptr, ptr }, ptr @main.V, align 8 +// CHECK-NEXT: %2685 = call %"{{.*}}/runtime/internal/runtime.Slice" @"{{.*}}/runtime/internal/runtime.StringToBytes"(%"{{.*}}/runtime/internal/runtime.String" { ptr @{{[0-9]+}}, i64 6 }) +// CHECK-NEXT: %2686 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 24) +// CHECK-NEXT: store %"{{.*}}/runtime/internal/runtime.Slice" %2685, ptr %2686, align 8 +// CHECK-NEXT: %2687 = insertvalue %"{{.*}}/runtime/internal/runtime.eface" { ptr @"[]_llgo_uint8", ptr undef }, ptr %2686, 1 +// CHECK-NEXT: %2688 = extractvalue { ptr, ptr } %2684, 1 +// CHECK-NEXT: %2689 = extractvalue { ptr, ptr } %2684, 0 +// CHECK-NEXT: %__llgo_funcval_code357 = call ptr asm "", "=r,0"(ptr %2689) +// CHECK-NEXT: %2690 = call %reflect.Value %__llgo_funcval_code357(ptr {{(nest|swiftself)}} %2688, %"{{.*}}/runtime/internal/runtime.eface" %2687) +// CHECK-NEXT: store %reflect.Value %2682, ptr %2675, align 8 +// CHECK-NEXT: store %reflect.Value %2690, ptr %2683, align 8 +// CHECK-NEXT: %2691 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %1, i64 179 +// CHECK-NEXT: %2692 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %2691, i32 0, i32 0 +// CHECK-NEXT: %2693 = load { ptr, ptr }, ptr @main.V, align 8 +// CHECK-NEXT: %2694 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 16) +// CHECK-NEXT: store %"{{.*}}/runtime/internal/runtime.String" { ptr @{{[0-9]+}}, i64 8 }, ptr %2694, align 8 +// CHECK-NEXT: %2695 = insertvalue %"{{.*}}/runtime/internal/runtime.eface" { ptr @_llgo_string, ptr undef }, ptr %2694, 1 +// CHECK-NEXT: %2696 = extractvalue { ptr, ptr } %2693, 1 +// CHECK-NEXT: %2697 = extractvalue { ptr, ptr } %2693, 0 +// CHECK-NEXT: %__llgo_funcval_code358 = call ptr asm "", "=r,0"(ptr %2697) +// CHECK-NEXT: %2698 = call %reflect.Value %__llgo_funcval_code358(ptr {{(nest|swiftself)}} %2696, %"{{.*}}/runtime/internal/runtime.eface" %2695) +// CHECK-NEXT: %2699 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %2691, i32 0, i32 1 +// CHECK-NEXT: %2700 = load { ptr, ptr }, ptr @main.V, align 8 +// CHECK-NEXT: %2701 = call %"{{.*}}/runtime/internal/runtime.Slice" @"{{.*}}/runtime/internal/runtime.StringToRunes"(%"{{.*}}/runtime/internal/runtime.String" { ptr @{{[0-9]+}}, i64 8 }) +// CHECK-NEXT: %2702 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 24) +// CHECK-NEXT: store %"{{.*}}/runtime/internal/runtime.Slice" %2701, ptr %2702, align 8 +// CHECK-NEXT: %2703 = insertvalue %"{{.*}}/runtime/internal/runtime.eface" { ptr @"[]_llgo_int32", ptr undef }, ptr %2702, 1 +// CHECK-NEXT: %2704 = extractvalue { ptr, ptr } %2700, 1 +// CHECK-NEXT: %2705 = extractvalue { ptr, ptr } %2700, 0 +// CHECK-NEXT: %__llgo_funcval_code359 = call ptr asm "", "=r,0"(ptr %2705) +// CHECK-NEXT: %2706 = call %reflect.Value %__llgo_funcval_code359(ptr {{(nest|swiftself)}} %2704, %"{{.*}}/runtime/internal/runtime.eface" %2703) +// CHECK-NEXT: store %reflect.Value %2698, ptr %2692, align 8 +// CHECK-NEXT: store %reflect.Value %2706, ptr %2699, align 8 +// CHECK-NEXT: %2707 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %1, i64 180 +// CHECK-NEXT: %2708 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %2707, i32 0, i32 0 +// CHECK-NEXT: %2709 = load { ptr, ptr }, ptr @main.V, align 8 +// CHECK-NEXT: %2710 = call %"{{.*}}/runtime/internal/runtime.Slice" @"{{.*}}/runtime/internal/runtime.StringToRunes"(%"{{.*}}/runtime/internal/runtime.String" { ptr @{{[0-9]+}}, i64 8 }) +// CHECK-NEXT: %2711 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 24) +// CHECK-NEXT: store %"{{.*}}/runtime/internal/runtime.Slice" %2710, ptr %2711, align 8 +// CHECK-NEXT: %2712 = insertvalue %"{{.*}}/runtime/internal/runtime.eface" { ptr @"[]_llgo_int32", ptr undef }, ptr %2711, 1 +// CHECK-NEXT: %2713 = extractvalue { ptr, ptr } %2709, 1 +// CHECK-NEXT: %2714 = extractvalue { ptr, ptr } %2709, 0 +// CHECK-NEXT: %__llgo_funcval_code360 = call ptr asm "", "=r,0"(ptr %2714) +// CHECK-NEXT: %2715 = call %reflect.Value %__llgo_funcval_code360(ptr {{(nest|swiftself)}} %2713, %"{{.*}}/runtime/internal/runtime.eface" %2712) +// CHECK-NEXT: %2716 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %2707, i32 0, i32 1 +// CHECK-NEXT: %2717 = load { ptr, ptr }, ptr @main.V, align 8 +// CHECK-NEXT: %2718 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 16) +// CHECK-NEXT: store %"{{.*}}/runtime/internal/runtime.String" { ptr @{{[0-9]+}}, i64 8 }, ptr %2718, align 8 +// CHECK-NEXT: %2719 = insertvalue %"{{.*}}/runtime/internal/runtime.eface" { ptr @_llgo_string, ptr undef }, ptr %2718, 1 +// CHECK-NEXT: %2720 = extractvalue { ptr, ptr } %2717, 1 +// CHECK-NEXT: %2721 = extractvalue { ptr, ptr } %2717, 0 +// CHECK-NEXT: %__llgo_funcval_code361 = call ptr asm "", "=r,0"(ptr %2721) +// CHECK-NEXT: %2722 = call %reflect.Value %__llgo_funcval_code361(ptr {{(nest|swiftself)}} %2720, %"{{.*}}/runtime/internal/runtime.eface" %2719) +// CHECK-NEXT: store %reflect.Value %2715, ptr %2708, align 8 +// CHECK-NEXT: store %reflect.Value %2722, ptr %2716, align 8 +// CHECK-NEXT: %2723 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %1, i64 181 +// CHECK-NEXT: %2724 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %2723, i32 0, i32 0 +// CHECK-NEXT: %2725 = load { ptr, ptr }, ptr @main.V, align 8 +// CHECK-NEXT: %2726 = call %"{{.*}}/runtime/internal/runtime.Slice" @"{{.*}}/runtime/internal/runtime.StringToRunes"(%"{{.*}}/runtime/internal/runtime.String" { ptr @{{[0-9]+}}, i64 17 }) +// CHECK-NEXT: %2727 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 24) +// CHECK-NEXT: store %"{{.*}}/runtime/internal/runtime.Slice" %2726, ptr %2727, align 8 +// CHECK-NEXT: %2728 = insertvalue %"{{.*}}/runtime/internal/runtime.eface" { ptr @"[]_llgo_int32", ptr undef }, ptr %2727, 1 +// CHECK-NEXT: %2729 = extractvalue { ptr, ptr } %2725, 1 +// CHECK-NEXT: %2730 = extractvalue { ptr, ptr } %2725, 0 +// CHECK-NEXT: %__llgo_funcval_code362 = call ptr asm "", "=r,0"(ptr %2730) +// CHECK-NEXT: %2731 = call %reflect.Value %__llgo_funcval_code362(ptr {{(nest|swiftself)}} %2729, %"{{.*}}/runtime/internal/runtime.eface" %2728) +// CHECK-NEXT: %2732 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %2723, i32 0, i32 1 +// CHECK-NEXT: %2733 = load { ptr, ptr }, ptr @main.V, align 8 +// CHECK-NEXT: %2734 = call %"{{.*}}/runtime/internal/runtime.Slice" @"{{.*}}/runtime/internal/runtime.StringToRunes"(%"{{.*}}/runtime/internal/runtime.String" { ptr @{{[0-9]+}}, i64 17 }) +// CHECK-NEXT: %2735 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 24) +// CHECK-NEXT: store %"{{.*}}/runtime/internal/runtime.Slice" %2734, ptr %2735, align 8 +// CHECK-NEXT: %2736 = insertvalue %"{{.*}}/runtime/internal/runtime.eface" { ptr @"[]_llgo_int32", ptr undef }, ptr %2735, 1 +// CHECK-NEXT: %2737 = extractvalue { ptr, ptr } %2733, 1 +// CHECK-NEXT: %2738 = extractvalue { ptr, ptr } %2733, 0 +// CHECK-NEXT: %__llgo_funcval_code363 = call ptr asm "", "=r,0"(ptr %2738) +// CHECK-NEXT: %2739 = call %reflect.Value %__llgo_funcval_code363(ptr {{(nest|swiftself)}} %2737, %"{{.*}}/runtime/internal/runtime.eface" %2736) +// CHECK-NEXT: store %reflect.Value %2731, ptr %2724, align 8 +// CHECK-NEXT: store %reflect.Value %2739, ptr %2732, align 8 +// CHECK-NEXT: %2740 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %1, i64 182 +// CHECK-NEXT: %2741 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %2740, i32 0, i32 0 +// CHECK-NEXT: %2742 = load { ptr, ptr }, ptr @main.V, align 8 +// CHECK-NEXT: %2743 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 8) +// CHECK-NEXT: store i64 97, ptr %2743, align 8 +// CHECK-NEXT: %2744 = insertvalue %"{{.*}}/runtime/internal/runtime.eface" { ptr @_llgo_int, ptr undef }, ptr %2743, 1 +// CHECK-NEXT: %2745 = extractvalue { ptr, ptr } %2742, 1 +// CHECK-NEXT: %2746 = extractvalue { ptr, ptr } %2742, 0 +// CHECK-NEXT: %__llgo_funcval_code364 = call ptr asm "", "=r,0"(ptr %2746) +// CHECK-NEXT: %2747 = call %reflect.Value %__llgo_funcval_code364(ptr {{(nest|swiftself)}} %2745, %"{{.*}}/runtime/internal/runtime.eface" %2744) +// CHECK-NEXT: %2748 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %2740, i32 0, i32 1 +// CHECK-NEXT: %2749 = load { ptr, ptr }, ptr @main.V, align 8 +// CHECK-NEXT: %2750 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 16) +// CHECK-NEXT: store %"{{.*}}/runtime/internal/runtime.String" { ptr @{{[0-9]+}}, i64 1 }, ptr %2750, align 8 +// CHECK-NEXT: %2751 = insertvalue %"{{.*}}/runtime/internal/runtime.eface" { ptr @_llgo_string, ptr undef }, ptr %2750, 1 +// CHECK-NEXT: %2752 = extractvalue { ptr, ptr } %2749, 1 +// CHECK-NEXT: %2753 = extractvalue { ptr, ptr } %2749, 0 +// CHECK-NEXT: %__llgo_funcval_code365 = call ptr asm "", "=r,0"(ptr %2753) +// CHECK-NEXT: %2754 = call %reflect.Value %__llgo_funcval_code365(ptr {{(nest|swiftself)}} %2752, %"{{.*}}/runtime/internal/runtime.eface" %2751) +// CHECK-NEXT: store %reflect.Value %2747, ptr %2741, align 8 +// CHECK-NEXT: store %reflect.Value %2754, ptr %2748, align 8 +// CHECK-NEXT: %2755 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %1, i64 183 +// CHECK-NEXT: %2756 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %2755, i32 0, i32 0 +// CHECK-NEXT: %2757 = load { ptr, ptr }, ptr @main.V, align 8 +// CHECK-NEXT: %2758 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 1) +// CHECK-NEXT: store i8 97, ptr %2758, align 1 +// CHECK-NEXT: %2759 = insertvalue %"{{.*}}/runtime/internal/runtime.eface" { ptr @_llgo_int8, ptr undef }, ptr %2758, 1 +// CHECK-NEXT: %2760 = extractvalue { ptr, ptr } %2757, 1 +// CHECK-NEXT: %2761 = extractvalue { ptr, ptr } %2757, 0 +// CHECK-NEXT: %__llgo_funcval_code366 = call ptr asm "", "=r,0"(ptr %2761) +// CHECK-NEXT: %2762 = call %reflect.Value %__llgo_funcval_code366(ptr {{(nest|swiftself)}} %2760, %"{{.*}}/runtime/internal/runtime.eface" %2759) +// CHECK-NEXT: %2763 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %2755, i32 0, i32 1 +// CHECK-NEXT: %2764 = load { ptr, ptr }, ptr @main.V, align 8 +// CHECK-NEXT: %2765 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 16) +// CHECK-NEXT: store %"{{.*}}/runtime/internal/runtime.String" { ptr @{{[0-9]+}}, i64 1 }, ptr %2765, align 8 +// CHECK-NEXT: %2766 = insertvalue %"{{.*}}/runtime/internal/runtime.eface" { ptr @_llgo_string, ptr undef }, ptr %2765, 1 +// CHECK-NEXT: %2767 = extractvalue { ptr, ptr } %2764, 1 +// CHECK-NEXT: %2768 = extractvalue { ptr, ptr } %2764, 0 +// CHECK-NEXT: %__llgo_funcval_code367 = call ptr asm "", "=r,0"(ptr %2768) +// CHECK-NEXT: %2769 = call %reflect.Value %__llgo_funcval_code367(ptr {{(nest|swiftself)}} %2767, %"{{.*}}/runtime/internal/runtime.eface" %2766) +// CHECK-NEXT: store %reflect.Value %2762, ptr %2756, align 8 +// CHECK-NEXT: store %reflect.Value %2769, ptr %2763, align 8 +// CHECK-NEXT: %2770 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %1, i64 184 +// CHECK-NEXT: %2771 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %2770, i32 0, i32 0 +// CHECK-NEXT: %2772 = load { ptr, ptr }, ptr @main.V, align 8 +// CHECK-NEXT: %2773 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 2) +// CHECK-NEXT: store i16 97, ptr %2773, align 2 +// CHECK-NEXT: %2774 = insertvalue %"{{.*}}/runtime/internal/runtime.eface" { ptr @_llgo_int16, ptr undef }, ptr %2773, 1 +// CHECK-NEXT: %2775 = extractvalue { ptr, ptr } %2772, 1 +// CHECK-NEXT: %2776 = extractvalue { ptr, ptr } %2772, 0 +// CHECK-NEXT: %__llgo_funcval_code368 = call ptr asm "", "=r,0"(ptr %2776) +// CHECK-NEXT: %2777 = call %reflect.Value %__llgo_funcval_code368(ptr {{(nest|swiftself)}} %2775, %"{{.*}}/runtime/internal/runtime.eface" %2774) +// CHECK-NEXT: %2778 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %2770, i32 0, i32 1 +// CHECK-NEXT: %2779 = load { ptr, ptr }, ptr @main.V, align 8 +// CHECK-NEXT: %2780 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 16) +// CHECK-NEXT: store %"{{.*}}/runtime/internal/runtime.String" { ptr @{{[0-9]+}}, i64 1 }, ptr %2780, align 8 +// CHECK-NEXT: %2781 = insertvalue %"{{.*}}/runtime/internal/runtime.eface" { ptr @_llgo_string, ptr undef }, ptr %2780, 1 +// CHECK-NEXT: %2782 = extractvalue { ptr, ptr } %2779, 1 +// CHECK-NEXT: %2783 = extractvalue { ptr, ptr } %2779, 0 +// CHECK-NEXT: %__llgo_funcval_code369 = call ptr asm "", "=r,0"(ptr %2783) +// CHECK-NEXT: %2784 = call %reflect.Value %__llgo_funcval_code369(ptr {{(nest|swiftself)}} %2782, %"{{.*}}/runtime/internal/runtime.eface" %2781) +// CHECK-NEXT: store %reflect.Value %2777, ptr %2771, align 8 +// CHECK-NEXT: store %reflect.Value %2784, ptr %2778, align 8 +// CHECK-NEXT: %2785 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %1, i64 185 +// CHECK-NEXT: %2786 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %2785, i32 0, i32 0 +// CHECK-NEXT: %2787 = load { ptr, ptr }, ptr @main.V, align 8 +// CHECK-NEXT: %2788 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 4) +// CHECK-NEXT: store i32 97, ptr %2788, align 4 +// CHECK-NEXT: %2789 = insertvalue %"{{.*}}/runtime/internal/runtime.eface" { ptr @_llgo_int32, ptr undef }, ptr %2788, 1 +// CHECK-NEXT: %2790 = extractvalue { ptr, ptr } %2787, 1 +// CHECK-NEXT: %2791 = extractvalue { ptr, ptr } %2787, 0 +// CHECK-NEXT: %__llgo_funcval_code370 = call ptr asm "", "=r,0"(ptr %2791) +// CHECK-NEXT: %2792 = call %reflect.Value %__llgo_funcval_code370(ptr {{(nest|swiftself)}} %2790, %"{{.*}}/runtime/internal/runtime.eface" %2789) +// CHECK-NEXT: %2793 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %2785, i32 0, i32 1 +// CHECK-NEXT: %2794 = load { ptr, ptr }, ptr @main.V, align 8 +// CHECK-NEXT: %2795 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 16) +// CHECK-NEXT: store %"{{.*}}/runtime/internal/runtime.String" { ptr @{{[0-9]+}}, i64 1 }, ptr %2795, align 8 +// CHECK-NEXT: %2796 = insertvalue %"{{.*}}/runtime/internal/runtime.eface" { ptr @_llgo_string, ptr undef }, ptr %2795, 1 +// CHECK-NEXT: %2797 = extractvalue { ptr, ptr } %2794, 1 +// CHECK-NEXT: %2798 = extractvalue { ptr, ptr } %2794, 0 +// CHECK-NEXT: %__llgo_funcval_code371 = call ptr asm "", "=r,0"(ptr %2798) +// CHECK-NEXT: %2799 = call %reflect.Value %__llgo_funcval_code371(ptr {{(nest|swiftself)}} %2797, %"{{.*}}/runtime/internal/runtime.eface" %2796) +// CHECK-NEXT: store %reflect.Value %2792, ptr %2786, align 8 +// CHECK-NEXT: store %reflect.Value %2799, ptr %2793, align 8 +// CHECK-NEXT: %2800 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %1, i64 186 +// CHECK-NEXT: %2801 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %2800, i32 0, i32 0 +// CHECK-NEXT: %2802 = load { ptr, ptr }, ptr @main.V, align 8 +// CHECK-NEXT: %2803 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 8) +// CHECK-NEXT: store i64 97, ptr %2803, align 8 +// CHECK-NEXT: %2804 = insertvalue %"{{.*}}/runtime/internal/runtime.eface" { ptr @_llgo_int64, ptr undef }, ptr %2803, 1 +// CHECK-NEXT: %2805 = extractvalue { ptr, ptr } %2802, 1 +// CHECK-NEXT: %2806 = extractvalue { ptr, ptr } %2802, 0 +// CHECK-NEXT: %__llgo_funcval_code372 = call ptr asm "", "=r,0"(ptr %2806) +// CHECK-NEXT: %2807 = call %reflect.Value %__llgo_funcval_code372(ptr {{(nest|swiftself)}} %2805, %"{{.*}}/runtime/internal/runtime.eface" %2804) +// CHECK-NEXT: %2808 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %2800, i32 0, i32 1 +// CHECK-NEXT: %2809 = load { ptr, ptr }, ptr @main.V, align 8 +// CHECK-NEXT: %2810 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 16) +// CHECK-NEXT: store %"{{.*}}/runtime/internal/runtime.String" { ptr @{{[0-9]+}}, i64 1 }, ptr %2810, align 8 +// CHECK-NEXT: %2811 = insertvalue %"{{.*}}/runtime/internal/runtime.eface" { ptr @_llgo_string, ptr undef }, ptr %2810, 1 +// CHECK-NEXT: %2812 = extractvalue { ptr, ptr } %2809, 1 +// CHECK-NEXT: %2813 = extractvalue { ptr, ptr } %2809, 0 +// CHECK-NEXT: %__llgo_funcval_code373 = call ptr asm "", "=r,0"(ptr %2813) +// CHECK-NEXT: %2814 = call %reflect.Value %__llgo_funcval_code373(ptr {{(nest|swiftself)}} %2812, %"{{.*}}/runtime/internal/runtime.eface" %2811) +// CHECK-NEXT: store %reflect.Value %2807, ptr %2801, align 8 +// CHECK-NEXT: store %reflect.Value %2814, ptr %2808, align 8 +// CHECK-NEXT: %2815 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %1, i64 187 +// CHECK-NEXT: %2816 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %2815, i32 0, i32 0 +// CHECK-NEXT: %2817 = load { ptr, ptr }, ptr @main.V, align 8 +// CHECK-NEXT: %2818 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 8) +// CHECK-NEXT: store i64 97, ptr %2818, align 8 +// CHECK-NEXT: %2819 = insertvalue %"{{.*}}/runtime/internal/runtime.eface" { ptr @_llgo_uint, ptr undef }, ptr %2818, 1 +// CHECK-NEXT: %2820 = extractvalue { ptr, ptr } %2817, 1 +// CHECK-NEXT: %2821 = extractvalue { ptr, ptr } %2817, 0 +// CHECK-NEXT: %__llgo_funcval_code374 = call ptr asm "", "=r,0"(ptr %2821) +// CHECK-NEXT: %2822 = call %reflect.Value %__llgo_funcval_code374(ptr {{(nest|swiftself)}} %2820, %"{{.*}}/runtime/internal/runtime.eface" %2819) +// CHECK-NEXT: %2823 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %2815, i32 0, i32 1 +// CHECK-NEXT: %2824 = load { ptr, ptr }, ptr @main.V, align 8 +// CHECK-NEXT: %2825 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 16) +// CHECK-NEXT: store %"{{.*}}/runtime/internal/runtime.String" { ptr @{{[0-9]+}}, i64 1 }, ptr %2825, align 8 +// CHECK-NEXT: %2826 = insertvalue %"{{.*}}/runtime/internal/runtime.eface" { ptr @_llgo_string, ptr undef }, ptr %2825, 1 +// CHECK-NEXT: %2827 = extractvalue { ptr, ptr } %2824, 1 +// CHECK-NEXT: %2828 = extractvalue { ptr, ptr } %2824, 0 +// CHECK-NEXT: %__llgo_funcval_code375 = call ptr asm "", "=r,0"(ptr %2828) +// CHECK-NEXT: %2829 = call %reflect.Value %__llgo_funcval_code375(ptr {{(nest|swiftself)}} %2827, %"{{.*}}/runtime/internal/runtime.eface" %2826) +// CHECK-NEXT: store %reflect.Value %2822, ptr %2816, align 8 +// CHECK-NEXT: store %reflect.Value %2829, ptr %2823, align 8 +// CHECK-NEXT: %2830 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %1, i64 188 +// CHECK-NEXT: %2831 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %2830, i32 0, i32 0 +// CHECK-NEXT: %2832 = load { ptr, ptr }, ptr @main.V, align 8 +// CHECK-NEXT: %2833 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 1) +// CHECK-NEXT: store i8 97, ptr %2833, align 1 +// CHECK-NEXT: %2834 = insertvalue %"{{.*}}/runtime/internal/runtime.eface" { ptr @_llgo_uint8, ptr undef }, ptr %2833, 1 +// CHECK-NEXT: %2835 = extractvalue { ptr, ptr } %2832, 1 +// CHECK-NEXT: %2836 = extractvalue { ptr, ptr } %2832, 0 +// CHECK-NEXT: %__llgo_funcval_code376 = call ptr asm "", "=r,0"(ptr %2836) +// CHECK-NEXT: %2837 = call %reflect.Value %__llgo_funcval_code376(ptr {{(nest|swiftself)}} %2835, %"{{.*}}/runtime/internal/runtime.eface" %2834) +// CHECK-NEXT: %2838 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %2830, i32 0, i32 1 +// CHECK-NEXT: %2839 = load { ptr, ptr }, ptr @main.V, align 8 +// CHECK-NEXT: %2840 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 16) +// CHECK-NEXT: store %"{{.*}}/runtime/internal/runtime.String" { ptr @{{[0-9]+}}, i64 1 }, ptr %2840, align 8 +// CHECK-NEXT: %2841 = insertvalue %"{{.*}}/runtime/internal/runtime.eface" { ptr @_llgo_string, ptr undef }, ptr %2840, 1 +// CHECK-NEXT: %2842 = extractvalue { ptr, ptr } %2839, 1 +// CHECK-NEXT: %2843 = extractvalue { ptr, ptr } %2839, 0 +// CHECK-NEXT: %__llgo_funcval_code377 = call ptr asm "", "=r,0"(ptr %2843) +// CHECK-NEXT: %2844 = call %reflect.Value %__llgo_funcval_code377(ptr {{(nest|swiftself)}} %2842, %"{{.*}}/runtime/internal/runtime.eface" %2841) +// CHECK-NEXT: store %reflect.Value %2837, ptr %2831, align 8 +// CHECK-NEXT: store %reflect.Value %2844, ptr %2838, align 8 +// CHECK-NEXT: %2845 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %1, i64 189 +// CHECK-NEXT: %2846 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %2845, i32 0, i32 0 +// CHECK-NEXT: %2847 = load { ptr, ptr }, ptr @main.V, align 8 +// CHECK-NEXT: %2848 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 2) +// CHECK-NEXT: store i16 97, ptr %2848, align 2 +// CHECK-NEXT: %2849 = insertvalue %"{{.*}}/runtime/internal/runtime.eface" { ptr @_llgo_uint16, ptr undef }, ptr %2848, 1 +// CHECK-NEXT: %2850 = extractvalue { ptr, ptr } %2847, 1 +// CHECK-NEXT: %2851 = extractvalue { ptr, ptr } %2847, 0 +// CHECK-NEXT: %__llgo_funcval_code378 = call ptr asm "", "=r,0"(ptr %2851) +// CHECK-NEXT: %2852 = call %reflect.Value %__llgo_funcval_code378(ptr {{(nest|swiftself)}} %2850, %"{{.*}}/runtime/internal/runtime.eface" %2849) +// CHECK-NEXT: %2853 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %2845, i32 0, i32 1 +// CHECK-NEXT: %2854 = load { ptr, ptr }, ptr @main.V, align 8 +// CHECK-NEXT: %2855 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 16) +// CHECK-NEXT: store %"{{.*}}/runtime/internal/runtime.String" { ptr @{{[0-9]+}}, i64 1 }, ptr %2855, align 8 +// CHECK-NEXT: %2856 = insertvalue %"{{.*}}/runtime/internal/runtime.eface" { ptr @_llgo_string, ptr undef }, ptr %2855, 1 +// CHECK-NEXT: %2857 = extractvalue { ptr, ptr } %2854, 1 +// CHECK-NEXT: %2858 = extractvalue { ptr, ptr } %2854, 0 +// CHECK-NEXT: %__llgo_funcval_code379 = call ptr asm "", "=r,0"(ptr %2858) +// CHECK-NEXT: %2859 = call %reflect.Value %__llgo_funcval_code379(ptr {{(nest|swiftself)}} %2857, %"{{.*}}/runtime/internal/runtime.eface" %2856) +// CHECK-NEXT: store %reflect.Value %2852, ptr %2846, align 8 +// CHECK-NEXT: store %reflect.Value %2859, ptr %2853, align 8 +// CHECK-NEXT: %2860 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %1, i64 190 +// CHECK-NEXT: %2861 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %2860, i32 0, i32 0 +// CHECK-NEXT: %2862 = load { ptr, ptr }, ptr @main.V, align 8 +// CHECK-NEXT: %2863 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 4) +// CHECK-NEXT: store i32 97, ptr %2863, align 4 +// CHECK-NEXT: %2864 = insertvalue %"{{.*}}/runtime/internal/runtime.eface" { ptr @_llgo_uint32, ptr undef }, ptr %2863, 1 +// CHECK-NEXT: %2865 = extractvalue { ptr, ptr } %2862, 1 +// CHECK-NEXT: %2866 = extractvalue { ptr, ptr } %2862, 0 +// CHECK-NEXT: %__llgo_funcval_code380 = call ptr asm "", "=r,0"(ptr %2866) +// CHECK-NEXT: %2867 = call %reflect.Value %__llgo_funcval_code380(ptr {{(nest|swiftself)}} %2865, %"{{.*}}/runtime/internal/runtime.eface" %2864) +// CHECK-NEXT: %2868 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %2860, i32 0, i32 1 +// CHECK-NEXT: %2869 = load { ptr, ptr }, ptr @main.V, align 8 +// CHECK-NEXT: %2870 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 16) +// CHECK-NEXT: store %"{{.*}}/runtime/internal/runtime.String" { ptr @{{[0-9]+}}, i64 1 }, ptr %2870, align 8 +// CHECK-NEXT: %2871 = insertvalue %"{{.*}}/runtime/internal/runtime.eface" { ptr @_llgo_string, ptr undef }, ptr %2870, 1 +// CHECK-NEXT: %2872 = extractvalue { ptr, ptr } %2869, 1 +// CHECK-NEXT: %2873 = extractvalue { ptr, ptr } %2869, 0 +// CHECK-NEXT: %__llgo_funcval_code381 = call ptr asm "", "=r,0"(ptr %2873) +// CHECK-NEXT: %2874 = call %reflect.Value %__llgo_funcval_code381(ptr {{(nest|swiftself)}} %2872, %"{{.*}}/runtime/internal/runtime.eface" %2871) +// CHECK-NEXT: store %reflect.Value %2867, ptr %2861, align 8 +// CHECK-NEXT: store %reflect.Value %2874, ptr %2868, align 8 +// CHECK-NEXT: %2875 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %1, i64 191 +// CHECK-NEXT: %2876 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %2875, i32 0, i32 0 +// CHECK-NEXT: %2877 = load { ptr, ptr }, ptr @main.V, align 8 +// CHECK-NEXT: %2878 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 8) +// CHECK-NEXT: store i64 97, ptr %2878, align 8 +// CHECK-NEXT: %2879 = insertvalue %"{{.*}}/runtime/internal/runtime.eface" { ptr @_llgo_uint64, ptr undef }, ptr %2878, 1 +// CHECK-NEXT: %2880 = extractvalue { ptr, ptr } %2877, 1 +// CHECK-NEXT: %2881 = extractvalue { ptr, ptr } %2877, 0 +// CHECK-NEXT: %__llgo_funcval_code382 = call ptr asm "", "=r,0"(ptr %2881) +// CHECK-NEXT: %2882 = call %reflect.Value %__llgo_funcval_code382(ptr {{(nest|swiftself)}} %2880, %"{{.*}}/runtime/internal/runtime.eface" %2879) +// CHECK-NEXT: %2883 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %2875, i32 0, i32 1 +// CHECK-NEXT: %2884 = load { ptr, ptr }, ptr @main.V, align 8 +// CHECK-NEXT: %2885 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 16) +// CHECK-NEXT: store %"{{.*}}/runtime/internal/runtime.String" { ptr @{{[0-9]+}}, i64 1 }, ptr %2885, align 8 +// CHECK-NEXT: %2886 = insertvalue %"{{.*}}/runtime/internal/runtime.eface" { ptr @_llgo_string, ptr undef }, ptr %2885, 1 +// CHECK-NEXT: %2887 = extractvalue { ptr, ptr } %2884, 1 +// CHECK-NEXT: %2888 = extractvalue { ptr, ptr } %2884, 0 +// CHECK-NEXT: %__llgo_funcval_code383 = call ptr asm "", "=r,0"(ptr %2888) +// CHECK-NEXT: %2889 = call %reflect.Value %__llgo_funcval_code383(ptr {{(nest|swiftself)}} %2887, %"{{.*}}/runtime/internal/runtime.eface" %2886) +// CHECK-NEXT: store %reflect.Value %2882, ptr %2876, align 8 +// CHECK-NEXT: store %reflect.Value %2889, ptr %2883, align 8 +// CHECK-NEXT: %2890 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %1, i64 192 +// CHECK-NEXT: %2891 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %2890, i32 0, i32 0 +// CHECK-NEXT: %2892 = load { ptr, ptr }, ptr @main.V, align 8 +// CHECK-NEXT: %2893 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 8) +// CHECK-NEXT: store i64 97, ptr %2893, align 8 +// CHECK-NEXT: %2894 = insertvalue %"{{.*}}/runtime/internal/runtime.eface" { ptr @_llgo_uintptr, ptr undef }, ptr %2893, 1 +// CHECK-NEXT: %2895 = extractvalue { ptr, ptr } %2892, 1 +// CHECK-NEXT: %2896 = extractvalue { ptr, ptr } %2892, 0 +// CHECK-NEXT: %__llgo_funcval_code384 = call ptr asm "", "=r,0"(ptr %2896) +// CHECK-NEXT: %2897 = call %reflect.Value %__llgo_funcval_code384(ptr {{(nest|swiftself)}} %2895, %"{{.*}}/runtime/internal/runtime.eface" %2894) +// CHECK-NEXT: %2898 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %2890, i32 0, i32 1 +// CHECK-NEXT: %2899 = load { ptr, ptr }, ptr @main.V, align 8 +// CHECK-NEXT: %2900 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 16) +// CHECK-NEXT: store %"{{.*}}/runtime/internal/runtime.String" { ptr @{{[0-9]+}}, i64 1 }, ptr %2900, align 8 +// CHECK-NEXT: %2901 = insertvalue %"{{.*}}/runtime/internal/runtime.eface" { ptr @_llgo_string, ptr undef }, ptr %2900, 1 +// CHECK-NEXT: %2902 = extractvalue { ptr, ptr } %2899, 1 +// CHECK-NEXT: %2903 = extractvalue { ptr, ptr } %2899, 0 +// CHECK-NEXT: %__llgo_funcval_code385 = call ptr asm "", "=r,0"(ptr %2903) +// CHECK-NEXT: %2904 = call %reflect.Value %__llgo_funcval_code385(ptr {{(nest|swiftself)}} %2902, %"{{.*}}/runtime/internal/runtime.eface" %2901) +// CHECK-NEXT: store %reflect.Value %2897, ptr %2891, align 8 +// CHECK-NEXT: store %reflect.Value %2904, ptr %2898, align 8 +// CHECK-NEXT: %2905 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %1, i64 193 +// CHECK-NEXT: %2906 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %2905, i32 0, i32 0 +// CHECK-NEXT: %2907 = load { ptr, ptr }, ptr @main.V, align 8 +// CHECK-NEXT: %2908 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 8) +// CHECK-NEXT: store i64 -1, ptr %2908, align 8 +// CHECK-NEXT: %2909 = insertvalue %"{{.*}}/runtime/internal/runtime.eface" { ptr @_llgo_int, ptr undef }, ptr %2908, 1 +// CHECK-NEXT: %2910 = extractvalue { ptr, ptr } %2907, 1 +// CHECK-NEXT: %2911 = extractvalue { ptr, ptr } %2907, 0 +// CHECK-NEXT: %__llgo_funcval_code386 = call ptr asm "", "=r,0"(ptr %2911) +// CHECK-NEXT: %2912 = call %reflect.Value %__llgo_funcval_code386(ptr {{(nest|swiftself)}} %2910, %"{{.*}}/runtime/internal/runtime.eface" %2909) +// CHECK-NEXT: %2913 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %2905, i32 0, i32 1 +// CHECK-NEXT: %2914 = load { ptr, ptr }, ptr @main.V, align 8 +// CHECK-NEXT: %2915 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 16) +// CHECK-NEXT: store %"{{.*}}/runtime/internal/runtime.String" { ptr @{{[0-9]+}}, i64 3 }, ptr %2915, align 8 +// CHECK-NEXT: %2916 = insertvalue %"{{.*}}/runtime/internal/runtime.eface" { ptr @_llgo_string, ptr undef }, ptr %2915, 1 +// CHECK-NEXT: %2917 = extractvalue { ptr, ptr } %2914, 1 +// CHECK-NEXT: %2918 = extractvalue { ptr, ptr } %2914, 0 +// CHECK-NEXT: %__llgo_funcval_code387 = call ptr asm "", "=r,0"(ptr %2918) +// CHECK-NEXT: %2919 = call %reflect.Value %__llgo_funcval_code387(ptr {{(nest|swiftself)}} %2917, %"{{.*}}/runtime/internal/runtime.eface" %2916) +// CHECK-NEXT: store %reflect.Value %2912, ptr %2906, align 8 +// CHECK-NEXT: store %reflect.Value %2919, ptr %2913, align 8 +// CHECK-NEXT: %2920 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %1, i64 194 +// CHECK-NEXT: %2921 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %2920, i32 0, i32 0 +// CHECK-NEXT: %2922 = load { ptr, ptr }, ptr @main.V, align 8 +// CHECK-NEXT: %2923 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 1) +// CHECK-NEXT: store i8 -2, ptr %2923, align 1 +// CHECK-NEXT: %2924 = insertvalue %"{{.*}}/runtime/internal/runtime.eface" { ptr @_llgo_int8, ptr undef }, ptr %2923, 1 +// CHECK-NEXT: %2925 = extractvalue { ptr, ptr } %2922, 1 +// CHECK-NEXT: %2926 = extractvalue { ptr, ptr } %2922, 0 +// CHECK-NEXT: %__llgo_funcval_code388 = call ptr asm "", "=r,0"(ptr %2926) +// CHECK-NEXT: %2927 = call %reflect.Value %__llgo_funcval_code388(ptr {{(nest|swiftself)}} %2925, %"{{.*}}/runtime/internal/runtime.eface" %2924) +// CHECK-NEXT: %2928 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %2920, i32 0, i32 1 +// CHECK-NEXT: %2929 = load { ptr, ptr }, ptr @main.V, align 8 +// CHECK-NEXT: %2930 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 16) +// CHECK-NEXT: store %"{{.*}}/runtime/internal/runtime.String" { ptr @{{[0-9]+}}, i64 3 }, ptr %2930, align 8 +// CHECK-NEXT: %2931 = insertvalue %"{{.*}}/runtime/internal/runtime.eface" { ptr @_llgo_string, ptr undef }, ptr %2930, 1 +// CHECK-NEXT: %2932 = extractvalue { ptr, ptr } %2929, 1 +// CHECK-NEXT: %2933 = extractvalue { ptr, ptr } %2929, 0 +// CHECK-NEXT: %__llgo_funcval_code389 = call ptr asm "", "=r,0"(ptr %2933) +// CHECK-NEXT: %2934 = call %reflect.Value %__llgo_funcval_code389(ptr {{(nest|swiftself)}} %2932, %"{{.*}}/runtime/internal/runtime.eface" %2931) +// CHECK-NEXT: store %reflect.Value %2927, ptr %2921, align 8 +// CHECK-NEXT: store %reflect.Value %2934, ptr %2928, align 8 +// CHECK-NEXT: %2935 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %1, i64 195 +// CHECK-NEXT: %2936 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %2935, i32 0, i32 0 +// CHECK-NEXT: %2937 = load { ptr, ptr }, ptr @main.V, align 8 +// CHECK-NEXT: %2938 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 2) +// CHECK-NEXT: store i16 -3, ptr %2938, align 2 +// CHECK-NEXT: %2939 = insertvalue %"{{.*}}/runtime/internal/runtime.eface" { ptr @_llgo_int16, ptr undef }, ptr %2938, 1 +// CHECK-NEXT: %2940 = extractvalue { ptr, ptr } %2937, 1 +// CHECK-NEXT: %2941 = extractvalue { ptr, ptr } %2937, 0 +// CHECK-NEXT: %__llgo_funcval_code390 = call ptr asm "", "=r,0"(ptr %2941) +// CHECK-NEXT: %2942 = call %reflect.Value %__llgo_funcval_code390(ptr {{(nest|swiftself)}} %2940, %"{{.*}}/runtime/internal/runtime.eface" %2939) +// CHECK-NEXT: %2943 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %2935, i32 0, i32 1 +// CHECK-NEXT: %2944 = load { ptr, ptr }, ptr @main.V, align 8 +// CHECK-NEXT: %2945 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 16) +// CHECK-NEXT: store %"{{.*}}/runtime/internal/runtime.String" { ptr @{{[0-9]+}}, i64 3 }, ptr %2945, align 8 +// CHECK-NEXT: %2946 = insertvalue %"{{.*}}/runtime/internal/runtime.eface" { ptr @_llgo_string, ptr undef }, ptr %2945, 1 +// CHECK-NEXT: %2947 = extractvalue { ptr, ptr } %2944, 1 +// CHECK-NEXT: %2948 = extractvalue { ptr, ptr } %2944, 0 +// CHECK-NEXT: %__llgo_funcval_code391 = call ptr asm "", "=r,0"(ptr %2948) +// CHECK-NEXT: %2949 = call %reflect.Value %__llgo_funcval_code391(ptr {{(nest|swiftself)}} %2947, %"{{.*}}/runtime/internal/runtime.eface" %2946) +// CHECK-NEXT: store %reflect.Value %2942, ptr %2936, align 8 +// CHECK-NEXT: store %reflect.Value %2949, ptr %2943, align 8 +// CHECK-NEXT: %2950 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %1, i64 196 +// CHECK-NEXT: %2951 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %2950, i32 0, i32 0 +// CHECK-NEXT: %2952 = load { ptr, ptr }, ptr @main.V, align 8 +// CHECK-NEXT: %2953 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 4) +// CHECK-NEXT: store i32 -4, ptr %2953, align 4 +// CHECK-NEXT: %2954 = insertvalue %"{{.*}}/runtime/internal/runtime.eface" { ptr @_llgo_int32, ptr undef }, ptr %2953, 1 +// CHECK-NEXT: %2955 = extractvalue { ptr, ptr } %2952, 1 +// CHECK-NEXT: %2956 = extractvalue { ptr, ptr } %2952, 0 +// CHECK-NEXT: %__llgo_funcval_code392 = call ptr asm "", "=r,0"(ptr %2956) +// CHECK-NEXT: %2957 = call %reflect.Value %__llgo_funcval_code392(ptr {{(nest|swiftself)}} %2955, %"{{.*}}/runtime/internal/runtime.eface" %2954) +// CHECK-NEXT: %2958 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %2950, i32 0, i32 1 +// CHECK-NEXT: %2959 = load { ptr, ptr }, ptr @main.V, align 8 +// CHECK-NEXT: %2960 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 16) +// CHECK-NEXT: store %"{{.*}}/runtime/internal/runtime.String" { ptr @{{[0-9]+}}, i64 3 }, ptr %2960, align 8 +// CHECK-NEXT: %2961 = insertvalue %"{{.*}}/runtime/internal/runtime.eface" { ptr @_llgo_string, ptr undef }, ptr %2960, 1 +// CHECK-NEXT: %2962 = extractvalue { ptr, ptr } %2959, 1 +// CHECK-NEXT: %2963 = extractvalue { ptr, ptr } %2959, 0 +// CHECK-NEXT: %__llgo_funcval_code393 = call ptr asm "", "=r,0"(ptr %2963) +// CHECK-NEXT: %2964 = call %reflect.Value %__llgo_funcval_code393(ptr {{(nest|swiftself)}} %2962, %"{{.*}}/runtime/internal/runtime.eface" %2961) +// CHECK-NEXT: store %reflect.Value %2957, ptr %2951, align 8 +// CHECK-NEXT: store %reflect.Value %2964, ptr %2958, align 8 +// CHECK-NEXT: %2965 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %1, i64 197 +// CHECK-NEXT: %2966 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %2965, i32 0, i32 0 +// CHECK-NEXT: %2967 = load { ptr, ptr }, ptr @main.V, align 8 +// CHECK-NEXT: %2968 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 8) +// CHECK-NEXT: store i64 -5, ptr %2968, align 8 +// CHECK-NEXT: %2969 = insertvalue %"{{.*}}/runtime/internal/runtime.eface" { ptr @_llgo_int64, ptr undef }, ptr %2968, 1 +// CHECK-NEXT: %2970 = extractvalue { ptr, ptr } %2967, 1 +// CHECK-NEXT: %2971 = extractvalue { ptr, ptr } %2967, 0 +// CHECK-NEXT: %__llgo_funcval_code394 = call ptr asm "", "=r,0"(ptr %2971) +// CHECK-NEXT: %2972 = call %reflect.Value %__llgo_funcval_code394(ptr {{(nest|swiftself)}} %2970, %"{{.*}}/runtime/internal/runtime.eface" %2969) +// CHECK-NEXT: %2973 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %2965, i32 0, i32 1 +// CHECK-NEXT: %2974 = load { ptr, ptr }, ptr @main.V, align 8 +// CHECK-NEXT: %2975 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 16) +// CHECK-NEXT: store %"{{.*}}/runtime/internal/runtime.String" { ptr @{{[0-9]+}}, i64 3 }, ptr %2975, align 8 +// CHECK-NEXT: %2976 = insertvalue %"{{.*}}/runtime/internal/runtime.eface" { ptr @_llgo_string, ptr undef }, ptr %2975, 1 +// CHECK-NEXT: %2977 = extractvalue { ptr, ptr } %2974, 1 +// CHECK-NEXT: %2978 = extractvalue { ptr, ptr } %2974, 0 +// CHECK-NEXT: %__llgo_funcval_code395 = call ptr asm "", "=r,0"(ptr %2978) +// CHECK-NEXT: %2979 = call %reflect.Value %__llgo_funcval_code395(ptr {{(nest|swiftself)}} %2977, %"{{.*}}/runtime/internal/runtime.eface" %2976) +// CHECK-NEXT: store %reflect.Value %2972, ptr %2966, align 8 +// CHECK-NEXT: store %reflect.Value %2979, ptr %2973, align 8 +// CHECK-NEXT: %2980 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %1, i64 198 +// CHECK-NEXT: %2981 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %2980, i32 0, i32 0 +// CHECK-NEXT: %2982 = load { ptr, ptr }, ptr @main.V, align 8 +// CHECK-NEXT: %2983 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 8) +// CHECK-NEXT: store i64 -4294967296, ptr %2983, align 8 +// CHECK-NEXT: %2984 = insertvalue %"{{.*}}/runtime/internal/runtime.eface" { ptr @_llgo_int64, ptr undef }, ptr %2983, 1 +// CHECK-NEXT: %2985 = extractvalue { ptr, ptr } %2982, 1 +// CHECK-NEXT: %2986 = extractvalue { ptr, ptr } %2982, 0 +// CHECK-NEXT: %__llgo_funcval_code396 = call ptr asm "", "=r,0"(ptr %2986) +// CHECK-NEXT: %2987 = call %reflect.Value %__llgo_funcval_code396(ptr {{(nest|swiftself)}} %2985, %"{{.*}}/runtime/internal/runtime.eface" %2984) +// CHECK-NEXT: %2988 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %2980, i32 0, i32 1 +// CHECK-NEXT: %2989 = load { ptr, ptr }, ptr @main.V, align 8 +// CHECK-NEXT: %2990 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 16) +// CHECK-NEXT: store %"{{.*}}/runtime/internal/runtime.String" { ptr @{{[0-9]+}}, i64 3 }, ptr %2990, align 8 +// CHECK-NEXT: %2991 = insertvalue %"{{.*}}/runtime/internal/runtime.eface" { ptr @_llgo_string, ptr undef }, ptr %2990, 1 +// CHECK-NEXT: %2992 = extractvalue { ptr, ptr } %2989, 1 +// CHECK-NEXT: %2993 = extractvalue { ptr, ptr } %2989, 0 +// CHECK-NEXT: %__llgo_funcval_code397 = call ptr asm "", "=r,0"(ptr %2993) +// CHECK-NEXT: %2994 = call %reflect.Value %__llgo_funcval_code397(ptr {{(nest|swiftself)}} %2992, %"{{.*}}/runtime/internal/runtime.eface" %2991) +// CHECK-NEXT: store %reflect.Value %2987, ptr %2981, align 8 +// CHECK-NEXT: store %reflect.Value %2994, ptr %2988, align 8 +// CHECK-NEXT: %2995 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %1, i64 199 +// CHECK-NEXT: %2996 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %2995, i32 0, i32 0 +// CHECK-NEXT: %2997 = load { ptr, ptr }, ptr @main.V, align 8 +// CHECK-NEXT: %2998 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 8) +// CHECK-NEXT: store i64 4294967296, ptr %2998, align 8 +// CHECK-NEXT: %2999 = insertvalue %"{{.*}}/runtime/internal/runtime.eface" { ptr @_llgo_int64, ptr undef }, ptr %2998, 1 +// CHECK-NEXT: %3000 = extractvalue { ptr, ptr } %2997, 1 +// CHECK-NEXT: %3001 = extractvalue { ptr, ptr } %2997, 0 +// CHECK-NEXT: %__llgo_funcval_code398 = call ptr asm "", "=r,0"(ptr %3001) +// CHECK-NEXT: %3002 = call %reflect.Value %__llgo_funcval_code398(ptr {{(nest|swiftself)}} %3000, %"{{.*}}/runtime/internal/runtime.eface" %2999) +// CHECK-NEXT: %3003 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %2995, i32 0, i32 1 +// CHECK-NEXT: %3004 = load { ptr, ptr }, ptr @main.V, align 8 +// CHECK-NEXT: %3005 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 16) +// CHECK-NEXT: store %"{{.*}}/runtime/internal/runtime.String" { ptr @{{[0-9]+}}, i64 3 }, ptr %3005, align 8 +// CHECK-NEXT: %3006 = insertvalue %"{{.*}}/runtime/internal/runtime.eface" { ptr @_llgo_string, ptr undef }, ptr %3005, 1 +// CHECK-NEXT: %3007 = extractvalue { ptr, ptr } %3004, 1 +// CHECK-NEXT: %3008 = extractvalue { ptr, ptr } %3004, 0 +// CHECK-NEXT: %__llgo_funcval_code399 = call ptr asm "", "=r,0"(ptr %3008) +// CHECK-NEXT: %3009 = call %reflect.Value %__llgo_funcval_code399(ptr {{(nest|swiftself)}} %3007, %"{{.*}}/runtime/internal/runtime.eface" %3006) +// CHECK-NEXT: store %reflect.Value %3002, ptr %2996, align 8 +// CHECK-NEXT: store %reflect.Value %3009, ptr %3003, align 8 +// CHECK-NEXT: %3010 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %1, i64 200 +// CHECK-NEXT: %3011 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %3010, i32 0, i32 0 +// CHECK-NEXT: %3012 = load { ptr, ptr }, ptr @main.V, align 8 +// CHECK-NEXT: %3013 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 8) +// CHECK-NEXT: store i64 1114113, ptr %3013, align 8 +// CHECK-NEXT: %3014 = insertvalue %"{{.*}}/runtime/internal/runtime.eface" { ptr @_llgo_uint, ptr undef }, ptr %3013, 1 +// CHECK-NEXT: %3015 = extractvalue { ptr, ptr } %3012, 1 +// CHECK-NEXT: %3016 = extractvalue { ptr, ptr } %3012, 0 +// CHECK-NEXT: %__llgo_funcval_code400 = call ptr asm "", "=r,0"(ptr %3016) +// CHECK-NEXT: %3017 = call %reflect.Value %__llgo_funcval_code400(ptr {{(nest|swiftself)}} %3015, %"{{.*}}/runtime/internal/runtime.eface" %3014) +// CHECK-NEXT: %3018 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %3010, i32 0, i32 1 +// CHECK-NEXT: %3019 = load { ptr, ptr }, ptr @main.V, align 8 +// CHECK-NEXT: %3020 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 16) +// CHECK-NEXT: store %"{{.*}}/runtime/internal/runtime.String" { ptr @{{[0-9]+}}, i64 3 }, ptr %3020, align 8 +// CHECK-NEXT: %3021 = insertvalue %"{{.*}}/runtime/internal/runtime.eface" { ptr @_llgo_string, ptr undef }, ptr %3020, 1 +// CHECK-NEXT: %3022 = extractvalue { ptr, ptr } %3019, 1 +// CHECK-NEXT: %3023 = extractvalue { ptr, ptr } %3019, 0 +// CHECK-NEXT: %__llgo_funcval_code401 = call ptr asm "", "=r,0"(ptr %3023) +// CHECK-NEXT: %3024 = call %reflect.Value %__llgo_funcval_code401(ptr {{(nest|swiftself)}} %3022, %"{{.*}}/runtime/internal/runtime.eface" %3021) +// CHECK-NEXT: store %reflect.Value %3017, ptr %3011, align 8 +// CHECK-NEXT: store %reflect.Value %3024, ptr %3018, align 8 +// CHECK-NEXT: %3025 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %1, i64 201 +// CHECK-NEXT: %3026 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %3025, i32 0, i32 0 +// CHECK-NEXT: %3027 = load { ptr, ptr }, ptr @main.V, align 8 +// CHECK-NEXT: %3028 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 4) +// CHECK-NEXT: store i32 1114114, ptr %3028, align 4 +// CHECK-NEXT: %3029 = insertvalue %"{{.*}}/runtime/internal/runtime.eface" { ptr @_llgo_uint32, ptr undef }, ptr %3028, 1 +// CHECK-NEXT: %3030 = extractvalue { ptr, ptr } %3027, 1 +// CHECK-NEXT: %3031 = extractvalue { ptr, ptr } %3027, 0 +// CHECK-NEXT: %__llgo_funcval_code402 = call ptr asm "", "=r,0"(ptr %3031) +// CHECK-NEXT: %3032 = call %reflect.Value %__llgo_funcval_code402(ptr {{(nest|swiftself)}} %3030, %"{{.*}}/runtime/internal/runtime.eface" %3029) +// CHECK-NEXT: %3033 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %3025, i32 0, i32 1 +// CHECK-NEXT: %3034 = load { ptr, ptr }, ptr @main.V, align 8 +// CHECK-NEXT: %3035 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 16) +// CHECK-NEXT: store %"{{.*}}/runtime/internal/runtime.String" { ptr @{{[0-9]+}}, i64 3 }, ptr %3035, align 8 +// CHECK-NEXT: %3036 = insertvalue %"{{.*}}/runtime/internal/runtime.eface" { ptr @_llgo_string, ptr undef }, ptr %3035, 1 +// CHECK-NEXT: %3037 = extractvalue { ptr, ptr } %3034, 1 +// CHECK-NEXT: %3038 = extractvalue { ptr, ptr } %3034, 0 +// CHECK-NEXT: %__llgo_funcval_code403 = call ptr asm "", "=r,0"(ptr %3038) +// CHECK-NEXT: %3039 = call %reflect.Value %__llgo_funcval_code403(ptr {{(nest|swiftself)}} %3037, %"{{.*}}/runtime/internal/runtime.eface" %3036) +// CHECK-NEXT: store %reflect.Value %3032, ptr %3026, align 8 +// CHECK-NEXT: store %reflect.Value %3039, ptr %3033, align 8 +// CHECK-NEXT: %3040 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %1, i64 202 +// CHECK-NEXT: %3041 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %3040, i32 0, i32 0 +// CHECK-NEXT: %3042 = load { ptr, ptr }, ptr @main.V, align 8 +// CHECK-NEXT: %3043 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 8) +// CHECK-NEXT: store i64 1114115, ptr %3043, align 8 +// CHECK-NEXT: %3044 = insertvalue %"{{.*}}/runtime/internal/runtime.eface" { ptr @_llgo_uint64, ptr undef }, ptr %3043, 1 +// CHECK-NEXT: %3045 = extractvalue { ptr, ptr } %3042, 1 +// CHECK-NEXT: %3046 = extractvalue { ptr, ptr } %3042, 0 +// CHECK-NEXT: %__llgo_funcval_code404 = call ptr asm "", "=r,0"(ptr %3046) +// CHECK-NEXT: %3047 = call %reflect.Value %__llgo_funcval_code404(ptr {{(nest|swiftself)}} %3045, %"{{.*}}/runtime/internal/runtime.eface" %3044) +// CHECK-NEXT: %3048 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %3040, i32 0, i32 1 +// CHECK-NEXT: %3049 = load { ptr, ptr }, ptr @main.V, align 8 +// CHECK-NEXT: %3050 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 16) +// CHECK-NEXT: store %"{{.*}}/runtime/internal/runtime.String" { ptr @{{[0-9]+}}, i64 3 }, ptr %3050, align 8 +// CHECK-NEXT: %3051 = insertvalue %"{{.*}}/runtime/internal/runtime.eface" { ptr @_llgo_string, ptr undef }, ptr %3050, 1 +// CHECK-NEXT: %3052 = extractvalue { ptr, ptr } %3049, 1 +// CHECK-NEXT: %3053 = extractvalue { ptr, ptr } %3049, 0 +// CHECK-NEXT: %__llgo_funcval_code405 = call ptr asm "", "=r,0"(ptr %3053) +// CHECK-NEXT: %3054 = call %reflect.Value %__llgo_funcval_code405(ptr {{(nest|swiftself)}} %3052, %"{{.*}}/runtime/internal/runtime.eface" %3051) +// CHECK-NEXT: store %reflect.Value %3047, ptr %3041, align 8 +// CHECK-NEXT: store %reflect.Value %3054, ptr %3048, align 8 +// CHECK-NEXT: %3055 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %1, i64 203 +// CHECK-NEXT: %3056 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %3055, i32 0, i32 0 +// CHECK-NEXT: %3057 = load { ptr, ptr }, ptr @main.V, align 8 +// CHECK-NEXT: %3058 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 8) +// CHECK-NEXT: store i64 4294967296, ptr %3058, align 8 +// CHECK-NEXT: %3059 = insertvalue %"{{.*}}/runtime/internal/runtime.eface" { ptr @_llgo_uint64, ptr undef }, ptr %3058, 1 +// CHECK-NEXT: %3060 = extractvalue { ptr, ptr } %3057, 1 +// CHECK-NEXT: %3061 = extractvalue { ptr, ptr } %3057, 0 +// CHECK-NEXT: %__llgo_funcval_code406 = call ptr asm "", "=r,0"(ptr %3061) +// CHECK-NEXT: %3062 = call %reflect.Value %__llgo_funcval_code406(ptr {{(nest|swiftself)}} %3060, %"{{.*}}/runtime/internal/runtime.eface" %3059) +// CHECK-NEXT: %3063 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %3055, i32 0, i32 1 +// CHECK-NEXT: %3064 = load { ptr, ptr }, ptr @main.V, align 8 +// CHECK-NEXT: %3065 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 16) +// CHECK-NEXT: store %"{{.*}}/runtime/internal/runtime.String" { ptr @{{[0-9]+}}, i64 3 }, ptr %3065, align 8 +// CHECK-NEXT: %3066 = insertvalue %"{{.*}}/runtime/internal/runtime.eface" { ptr @_llgo_string, ptr undef }, ptr %3065, 1 +// CHECK-NEXT: %3067 = extractvalue { ptr, ptr } %3064, 1 +// CHECK-NEXT: %3068 = extractvalue { ptr, ptr } %3064, 0 +// CHECK-NEXT: %__llgo_funcval_code407 = call ptr asm "", "=r,0"(ptr %3068) +// CHECK-NEXT: %3069 = call %reflect.Value %__llgo_funcval_code407(ptr {{(nest|swiftself)}} %3067, %"{{.*}}/runtime/internal/runtime.eface" %3066) +// CHECK-NEXT: store %reflect.Value %3062, ptr %3056, align 8 +// CHECK-NEXT: store %reflect.Value %3069, ptr %3063, align 8 +// CHECK-NEXT: %3070 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %1, i64 204 +// CHECK-NEXT: %3071 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %3070, i32 0, i32 0 +// CHECK-NEXT: %3072 = load { ptr, ptr }, ptr @main.V, align 8 +// CHECK-NEXT: %3073 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 8) +// CHECK-NEXT: store i64 1114116, ptr %3073, align 8 +// CHECK-NEXT: %3074 = insertvalue %"{{.*}}/runtime/internal/runtime.eface" { ptr @_llgo_uintptr, ptr undef }, ptr %3073, 1 +// CHECK-NEXT: %3075 = extractvalue { ptr, ptr } %3072, 1 +// CHECK-NEXT: %3076 = extractvalue { ptr, ptr } %3072, 0 +// CHECK-NEXT: %__llgo_funcval_code408 = call ptr asm "", "=r,0"(ptr %3076) +// CHECK-NEXT: %3077 = call %reflect.Value %__llgo_funcval_code408(ptr {{(nest|swiftself)}} %3075, %"{{.*}}/runtime/internal/runtime.eface" %3074) +// CHECK-NEXT: %3078 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %3070, i32 0, i32 1 +// CHECK-NEXT: %3079 = load { ptr, ptr }, ptr @main.V, align 8 +// CHECK-NEXT: %3080 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 16) +// CHECK-NEXT: store %"{{.*}}/runtime/internal/runtime.String" { ptr @{{[0-9]+}}, i64 3 }, ptr %3080, align 8 +// CHECK-NEXT: %3081 = insertvalue %"{{.*}}/runtime/internal/runtime.eface" { ptr @_llgo_string, ptr undef }, ptr %3080, 1 +// CHECK-NEXT: %3082 = extractvalue { ptr, ptr } %3079, 1 +// CHECK-NEXT: %3083 = extractvalue { ptr, ptr } %3079, 0 +// CHECK-NEXT: %__llgo_funcval_code409 = call ptr asm "", "=r,0"(ptr %3083) +// CHECK-NEXT: %3084 = call %reflect.Value %__llgo_funcval_code409(ptr {{(nest|swiftself)}} %3082, %"{{.*}}/runtime/internal/runtime.eface" %3081) +// CHECK-NEXT: store %reflect.Value %3077, ptr %3071, align 8 +// CHECK-NEXT: store %reflect.Value %3084, ptr %3078, align 8 +// CHECK-NEXT: %3085 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %1, i64 205 +// CHECK-NEXT: %3086 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %3085, i32 0, i32 0 +// CHECK-NEXT: %3087 = load { ptr, ptr }, ptr @main.V, align 8 +// CHECK-NEXT: %3088 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 16) +// CHECK-NEXT: store %"{{.*}}/runtime/internal/runtime.String" { ptr @{{[0-9]+}}, i64 5 }, ptr %3088, align 8 +// CHECK-NEXT: %3089 = insertvalue %"{{.*}}/runtime/internal/runtime.eface" { ptr @_llgo_main.MyString, ptr undef }, ptr %3088, 1 +// CHECK-NEXT: %3090 = extractvalue { ptr, ptr } %3087, 1 +// CHECK-NEXT: %3091 = extractvalue { ptr, ptr } %3087, 0 +// CHECK-NEXT: %__llgo_funcval_code410 = call ptr asm "", "=r,0"(ptr %3091) +// CHECK-NEXT: %3092 = call %reflect.Value %__llgo_funcval_code410(ptr {{(nest|swiftself)}} %3090, %"{{.*}}/runtime/internal/runtime.eface" %3089) +// CHECK-NEXT: %3093 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %3085, i32 0, i32 1 +// CHECK-NEXT: %3094 = load { ptr, ptr }, ptr @main.V, align 8 +// CHECK-NEXT: %3095 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 16) +// CHECK-NEXT: store %"{{.*}}/runtime/internal/runtime.String" { ptr @{{[0-9]+}}, i64 5 }, ptr %3095, align 8 +// CHECK-NEXT: %3096 = insertvalue %"{{.*}}/runtime/internal/runtime.eface" { ptr @_llgo_string, ptr undef }, ptr %3095, 1 +// CHECK-NEXT: %3097 = extractvalue { ptr, ptr } %3094, 1 +// CHECK-NEXT: %3098 = extractvalue { ptr, ptr } %3094, 0 +// CHECK-NEXT: %__llgo_funcval_code411 = call ptr asm "", "=r,0"(ptr %3098) +// CHECK-NEXT: %3099 = call %reflect.Value %__llgo_funcval_code411(ptr {{(nest|swiftself)}} %3097, %"{{.*}}/runtime/internal/runtime.eface" %3096) +// CHECK-NEXT: store %reflect.Value %3092, ptr %3086, align 8 +// CHECK-NEXT: store %reflect.Value %3099, ptr %3093, align 8 +// CHECK-NEXT: %3100 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %1, i64 206 +// CHECK-NEXT: %3101 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %3100, i32 0, i32 0 +// CHECK-NEXT: %3102 = load { ptr, ptr }, ptr @main.V, align 8 +// CHECK-NEXT: %3103 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 16) +// CHECK-NEXT: store %"{{.*}}/runtime/internal/runtime.String" { ptr @{{[0-9]+}}, i64 5 }, ptr %3103, align 8 +// CHECK-NEXT: %3104 = insertvalue %"{{.*}}/runtime/internal/runtime.eface" { ptr @_llgo_string, ptr undef }, ptr %3103, 1 +// CHECK-NEXT: %3105 = extractvalue { ptr, ptr } %3102, 1 +// CHECK-NEXT: %3106 = extractvalue { ptr, ptr } %3102, 0 +// CHECK-NEXT: %__llgo_funcval_code412 = call ptr asm "", "=r,0"(ptr %3106) +// CHECK-NEXT: %3107 = call %reflect.Value %__llgo_funcval_code412(ptr {{(nest|swiftself)}} %3105, %"{{.*}}/runtime/internal/runtime.eface" %3104) +// CHECK-NEXT: %3108 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %3100, i32 0, i32 1 +// CHECK-NEXT: %3109 = load { ptr, ptr }, ptr @main.V, align 8 +// CHECK-NEXT: %3110 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 16) +// CHECK-NEXT: store %"{{.*}}/runtime/internal/runtime.String" { ptr @{{[0-9]+}}, i64 5 }, ptr %3110, align 8 +// CHECK-NEXT: %3111 = insertvalue %"{{.*}}/runtime/internal/runtime.eface" { ptr @_llgo_main.MyString, ptr undef }, ptr %3110, 1 +// CHECK-NEXT: %3112 = extractvalue { ptr, ptr } %3109, 1 +// CHECK-NEXT: %3113 = extractvalue { ptr, ptr } %3109, 0 +// CHECK-NEXT: %__llgo_funcval_code413 = call ptr asm "", "=r,0"(ptr %3113) +// CHECK-NEXT: %3114 = call %reflect.Value %__llgo_funcval_code413(ptr {{(nest|swiftself)}} %3112, %"{{.*}}/runtime/internal/runtime.eface" %3111) +// CHECK-NEXT: store %reflect.Value %3107, ptr %3101, align 8 +// CHECK-NEXT: store %reflect.Value %3114, ptr %3108, align 8 +// CHECK-NEXT: %3115 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %1, i64 207 +// CHECK-NEXT: %3116 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %3115, i32 0, i32 0 +// CHECK-NEXT: %3117 = load { ptr, ptr }, ptr @main.V, align 8 +// CHECK-NEXT: %3118 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 16) +// CHECK-NEXT: store %"{{.*}}/runtime/internal/runtime.String" { ptr @{{[0-9]+}}, i64 5 }, ptr %3118, align 8 +// CHECK-NEXT: %3119 = insertvalue %"{{.*}}/runtime/internal/runtime.eface" { ptr @_llgo_string, ptr undef }, ptr %3118, 1 +// CHECK-NEXT: %3120 = extractvalue { ptr, ptr } %3117, 1 +// CHECK-NEXT: %3121 = extractvalue { ptr, ptr } %3117, 0 +// CHECK-NEXT: %__llgo_funcval_code414 = call ptr asm "", "=r,0"(ptr %3121) +// CHECK-NEXT: %3122 = call %reflect.Value %__llgo_funcval_code414(ptr {{(nest|swiftself)}} %3120, %"{{.*}}/runtime/internal/runtime.eface" %3119) +// CHECK-NEXT: %3123 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %3115, i32 0, i32 1 +// CHECK-NEXT: %3124 = load { ptr, ptr }, ptr @main.V, align 8 +// CHECK-NEXT: %3125 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 16) +// CHECK-NEXT: store %"{{.*}}/runtime/internal/runtime.String" { ptr @{{[0-9]+}}, i64 5 }, ptr %3125, align 8 +// CHECK-NEXT: %3126 = insertvalue %"{{.*}}/runtime/internal/runtime.eface" { ptr @_llgo_string, ptr undef }, ptr %3125, 1 +// CHECK-NEXT: %3127 = extractvalue { ptr, ptr } %3124, 1 +// CHECK-NEXT: %3128 = extractvalue { ptr, ptr } %3124, 0 +// CHECK-NEXT: %__llgo_funcval_code415 = call ptr asm "", "=r,0"(ptr %3128) +// CHECK-NEXT: %3129 = call %reflect.Value %__llgo_funcval_code415(ptr {{(nest|swiftself)}} %3127, %"{{.*}}/runtime/internal/runtime.eface" %3126) +// CHECK-NEXT: store %reflect.Value %3122, ptr %3116, align 8 +// CHECK-NEXT: store %reflect.Value %3129, ptr %3123, align 8 +// CHECK-NEXT: %3130 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %1, i64 208 +// CHECK-NEXT: %3131 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %3130, i32 0, i32 0 +// CHECK-NEXT: %3132 = load { ptr, ptr }, ptr @main.V, align 8 +// CHECK-NEXT: %3133 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 16) +// CHECK-NEXT: store %"{{.*}}/runtime/internal/runtime.String" { ptr @{{[0-9]+}}, i64 5 }, ptr %3133, align 8 +// CHECK-NEXT: %3134 = insertvalue %"{{.*}}/runtime/internal/runtime.eface" { ptr @_llgo_main.MyString, ptr undef }, ptr %3133, 1 +// CHECK-NEXT: %3135 = extractvalue { ptr, ptr } %3132, 1 +// CHECK-NEXT: %3136 = extractvalue { ptr, ptr } %3132, 0 +// CHECK-NEXT: %__llgo_funcval_code416 = call ptr asm "", "=r,0"(ptr %3136) +// CHECK-NEXT: %3137 = call %reflect.Value %__llgo_funcval_code416(ptr {{(nest|swiftself)}} %3135, %"{{.*}}/runtime/internal/runtime.eface" %3134) +// CHECK-NEXT: %3138 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %3130, i32 0, i32 1 +// CHECK-NEXT: %3139 = load { ptr, ptr }, ptr @main.V, align 8 +// CHECK-NEXT: %3140 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 16) +// CHECK-NEXT: store %"{{.*}}/runtime/internal/runtime.String" { ptr @{{[0-9]+}}, i64 5 }, ptr %3140, align 8 +// CHECK-NEXT: %3141 = insertvalue %"{{.*}}/runtime/internal/runtime.eface" { ptr @_llgo_main.MyString, ptr undef }, ptr %3140, 1 +// CHECK-NEXT: %3142 = extractvalue { ptr, ptr } %3139, 1 +// CHECK-NEXT: %3143 = extractvalue { ptr, ptr } %3139, 0 +// CHECK-NEXT: %__llgo_funcval_code417 = call ptr asm "", "=r,0"(ptr %3143) +// CHECK-NEXT: %3144 = call %reflect.Value %__llgo_funcval_code417(ptr {{(nest|swiftself)}} %3142, %"{{.*}}/runtime/internal/runtime.eface" %3141) +// CHECK-NEXT: store %reflect.Value %3137, ptr %3131, align 8 +// CHECK-NEXT: store %reflect.Value %3144, ptr %3138, align 8 +// CHECK-NEXT: %3145 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %1, i64 209 +// CHECK-NEXT: %3146 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %3145, i32 0, i32 0 +// CHECK-NEXT: %3147 = load { ptr, ptr }, ptr @main.V, align 8 +// CHECK-NEXT: %3148 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 16) +// CHECK-NEXT: store %"{{.*}}/runtime/internal/runtime.String" { ptr @{{[0-9]+}}, i64 6 }, ptr %3148, align 8 +// CHECK-NEXT: %3149 = insertvalue %"{{.*}}/runtime/internal/runtime.eface" { ptr @_llgo_main.MyString, ptr undef }, ptr %3148, 1 +// CHECK-NEXT: %3150 = extractvalue { ptr, ptr } %3147, 1 +// CHECK-NEXT: %3151 = extractvalue { ptr, ptr } %3147, 0 +// CHECK-NEXT: %__llgo_funcval_code418 = call ptr asm "", "=r,0"(ptr %3151) +// CHECK-NEXT: %3152 = call %reflect.Value %__llgo_funcval_code418(ptr {{(nest|swiftself)}} %3150, %"{{.*}}/runtime/internal/runtime.eface" %3149) +// CHECK-NEXT: %3153 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %3145, i32 0, i32 1 +// CHECK-NEXT: %3154 = load { ptr, ptr }, ptr @main.V, align 8 +// CHECK-NEXT: %3155 = call %"{{.*}}/runtime/internal/runtime.Slice" @"{{.*}}/runtime/internal/runtime.StringToBytes"(%"{{.*}}/runtime/internal/runtime.String" { ptr @{{[0-9]+}}, i64 6 }) +// CHECK-NEXT: %3156 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 24) +// CHECK-NEXT: store %"{{.*}}/runtime/internal/runtime.Slice" %3155, ptr %3156, align 8 +// CHECK-NEXT: %3157 = insertvalue %"{{.*}}/runtime/internal/runtime.eface" { ptr @"[]_llgo_uint8", ptr undef }, ptr %3156, 1 +// CHECK-NEXT: %3158 = extractvalue { ptr, ptr } %3154, 1 +// CHECK-NEXT: %3159 = extractvalue { ptr, ptr } %3154, 0 +// CHECK-NEXT: %__llgo_funcval_code419 = call ptr asm "", "=r,0"(ptr %3159) +// CHECK-NEXT: %3160 = call %reflect.Value %__llgo_funcval_code419(ptr {{(nest|swiftself)}} %3158, %"{{.*}}/runtime/internal/runtime.eface" %3157) +// CHECK-NEXT: store %reflect.Value %3152, ptr %3146, align 8 +// CHECK-NEXT: store %reflect.Value %3160, ptr %3153, align 8 +// CHECK-NEXT: %3161 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %1, i64 210 +// CHECK-NEXT: %3162 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %3161, i32 0, i32 0 +// CHECK-NEXT: %3163 = load { ptr, ptr }, ptr @main.V, align 8 +// CHECK-NEXT: %3164 = call %"{{.*}}/runtime/internal/runtime.Slice" @"{{.*}}/runtime/internal/runtime.StringToBytes"(%"{{.*}}/runtime/internal/runtime.String" { ptr @{{[0-9]+}}, i64 6 }) +// CHECK-NEXT: %3165 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 24) +// CHECK-NEXT: store %"{{.*}}/runtime/internal/runtime.Slice" %3164, ptr %3165, align 8 +// CHECK-NEXT: %3166 = insertvalue %"{{.*}}/runtime/internal/runtime.eface" { ptr @"[]_llgo_uint8", ptr undef }, ptr %3165, 1 +// CHECK-NEXT: %3167 = extractvalue { ptr, ptr } %3163, 1 +// CHECK-NEXT: %3168 = extractvalue { ptr, ptr } %3163, 0 +// CHECK-NEXT: %__llgo_funcval_code420 = call ptr asm "", "=r,0"(ptr %3168) +// CHECK-NEXT: %3169 = call %reflect.Value %__llgo_funcval_code420(ptr {{(nest|swiftself)}} %3167, %"{{.*}}/runtime/internal/runtime.eface" %3166) +// CHECK-NEXT: %3170 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %3161, i32 0, i32 1 +// CHECK-NEXT: %3171 = load { ptr, ptr }, ptr @main.V, align 8 +// CHECK-NEXT: %3172 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 16) +// CHECK-NEXT: store %"{{.*}}/runtime/internal/runtime.String" { ptr @{{[0-9]+}}, i64 6 }, ptr %3172, align 8 +// CHECK-NEXT: %3173 = insertvalue %"{{.*}}/runtime/internal/runtime.eface" { ptr @_llgo_main.MyString, ptr undef }, ptr %3172, 1 +// CHECK-NEXT: %3174 = extractvalue { ptr, ptr } %3171, 1 +// CHECK-NEXT: %3175 = extractvalue { ptr, ptr } %3171, 0 +// CHECK-NEXT: %__llgo_funcval_code421 = call ptr asm "", "=r,0"(ptr %3175) +// CHECK-NEXT: %3176 = call %reflect.Value %__llgo_funcval_code421(ptr {{(nest|swiftself)}} %3174, %"{{.*}}/runtime/internal/runtime.eface" %3173) +// CHECK-NEXT: store %reflect.Value %3169, ptr %3162, align 8 +// CHECK-NEXT: store %reflect.Value %3176, ptr %3170, align 8 +// CHECK-NEXT: %3177 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %1, i64 211 +// CHECK-NEXT: %3178 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %3177, i32 0, i32 0 +// CHECK-NEXT: %3179 = load { ptr, ptr }, ptr @main.V, align 8 +// CHECK-NEXT: %3180 = call %"{{.*}}/runtime/internal/runtime.Slice" @"{{.*}}/runtime/internal/runtime.StringToBytes"(%"{{.*}}/runtime/internal/runtime.String" { ptr @{{[0-9]+}}, i64 6 }) +// CHECK-NEXT: %3181 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 24) +// CHECK-NEXT: store %"{{.*}}/runtime/internal/runtime.Slice" %3180, ptr %3181, align 8 +// CHECK-NEXT: %3182 = insertvalue %"{{.*}}/runtime/internal/runtime.eface" { ptr @"[]_llgo_uint8", ptr undef }, ptr %3181, 1 +// CHECK-NEXT: %3183 = extractvalue { ptr, ptr } %3179, 1 +// CHECK-NEXT: %3184 = extractvalue { ptr, ptr } %3179, 0 +// CHECK-NEXT: %__llgo_funcval_code422 = call ptr asm "", "=r,0"(ptr %3184) +// CHECK-NEXT: %3185 = call %reflect.Value %__llgo_funcval_code422(ptr {{(nest|swiftself)}} %3183, %"{{.*}}/runtime/internal/runtime.eface" %3182) +// CHECK-NEXT: %3186 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %3177, i32 0, i32 1 +// CHECK-NEXT: %3187 = load { ptr, ptr }, ptr @main.V, align 8 +// CHECK-NEXT: %3188 = call %"{{.*}}/runtime/internal/runtime.Slice" @"{{.*}}/runtime/internal/runtime.StringToBytes"(%"{{.*}}/runtime/internal/runtime.String" { ptr @{{[0-9]+}}, i64 6 }) +// CHECK-NEXT: %3189 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 24) +// CHECK-NEXT: store %"{{.*}}/runtime/internal/runtime.Slice" %3188, ptr %3189, align 8 +// CHECK-NEXT: %3190 = insertvalue %"{{.*}}/runtime/internal/runtime.eface" { ptr @"[]_llgo_uint8", ptr undef }, ptr %3189, 1 +// CHECK-NEXT: %3191 = extractvalue { ptr, ptr } %3187, 1 +// CHECK-NEXT: %3192 = extractvalue { ptr, ptr } %3187, 0 +// CHECK-NEXT: %__llgo_funcval_code423 = call ptr asm "", "=r,0"(ptr %3192) +// CHECK-NEXT: %3193 = call %reflect.Value %__llgo_funcval_code423(ptr {{(nest|swiftself)}} %3191, %"{{.*}}/runtime/internal/runtime.eface" %3190) +// CHECK-NEXT: store %reflect.Value %3185, ptr %3178, align 8 +// CHECK-NEXT: store %reflect.Value %3193, ptr %3186, align 8 +// CHECK-NEXT: %3194 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %1, i64 212 +// CHECK-NEXT: %3195 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %3194, i32 0, i32 0 +// CHECK-NEXT: %3196 = load { ptr, ptr }, ptr @main.V, align 8 +// CHECK-NEXT: %3197 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 16) +// CHECK-NEXT: store %"{{.*}}/runtime/internal/runtime.String" { ptr @{{[0-9]+}}, i64 8 }, ptr %3197, align 8 +// CHECK-NEXT: %3198 = insertvalue %"{{.*}}/runtime/internal/runtime.eface" { ptr @_llgo_main.MyString, ptr undef }, ptr %3197, 1 +// CHECK-NEXT: %3199 = extractvalue { ptr, ptr } %3196, 1 +// CHECK-NEXT: %3200 = extractvalue { ptr, ptr } %3196, 0 +// CHECK-NEXT: %__llgo_funcval_code424 = call ptr asm "", "=r,0"(ptr %3200) +// CHECK-NEXT: %3201 = call %reflect.Value %__llgo_funcval_code424(ptr {{(nest|swiftself)}} %3199, %"{{.*}}/runtime/internal/runtime.eface" %3198) +// CHECK-NEXT: %3202 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %3194, i32 0, i32 1 +// CHECK-NEXT: %3203 = load { ptr, ptr }, ptr @main.V, align 8 +// CHECK-NEXT: %3204 = call %"{{.*}}/runtime/internal/runtime.Slice" @"{{.*}}/runtime/internal/runtime.StringToRunes"(%"{{.*}}/runtime/internal/runtime.String" { ptr @{{[0-9]+}}, i64 8 }) +// CHECK-NEXT: %3205 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 24) +// CHECK-NEXT: store %"{{.*}}/runtime/internal/runtime.Slice" %3204, ptr %3205, align 8 +// CHECK-NEXT: %3206 = insertvalue %"{{.*}}/runtime/internal/runtime.eface" { ptr @"[]_llgo_int32", ptr undef }, ptr %3205, 1 +// CHECK-NEXT: %3207 = extractvalue { ptr, ptr } %3203, 1 +// CHECK-NEXT: %3208 = extractvalue { ptr, ptr } %3203, 0 +// CHECK-NEXT: %__llgo_funcval_code425 = call ptr asm "", "=r,0"(ptr %3208) +// CHECK-NEXT: %3209 = call %reflect.Value %__llgo_funcval_code425(ptr {{(nest|swiftself)}} %3207, %"{{.*}}/runtime/internal/runtime.eface" %3206) +// CHECK-NEXT: store %reflect.Value %3201, ptr %3195, align 8 +// CHECK-NEXT: store %reflect.Value %3209, ptr %3202, align 8 +// CHECK-NEXT: %3210 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %1, i64 213 +// CHECK-NEXT: %3211 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %3210, i32 0, i32 0 +// CHECK-NEXT: %3212 = load { ptr, ptr }, ptr @main.V, align 8 +// CHECK-NEXT: %3213 = call %"{{.*}}/runtime/internal/runtime.Slice" @"{{.*}}/runtime/internal/runtime.StringToRunes"(%"{{.*}}/runtime/internal/runtime.String" { ptr @{{[0-9]+}}, i64 8 }) +// CHECK-NEXT: %3214 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 24) +// CHECK-NEXT: store %"{{.*}}/runtime/internal/runtime.Slice" %3213, ptr %3214, align 8 +// CHECK-NEXT: %3215 = insertvalue %"{{.*}}/runtime/internal/runtime.eface" { ptr @"[]_llgo_int32", ptr undef }, ptr %3214, 1 +// CHECK-NEXT: %3216 = extractvalue { ptr, ptr } %3212, 1 +// CHECK-NEXT: %3217 = extractvalue { ptr, ptr } %3212, 0 +// CHECK-NEXT: %__llgo_funcval_code426 = call ptr asm "", "=r,0"(ptr %3217) +// CHECK-NEXT: %3218 = call %reflect.Value %__llgo_funcval_code426(ptr {{(nest|swiftself)}} %3216, %"{{.*}}/runtime/internal/runtime.eface" %3215) +// CHECK-NEXT: %3219 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %3210, i32 0, i32 1 +// CHECK-NEXT: %3220 = load { ptr, ptr }, ptr @main.V, align 8 +// CHECK-NEXT: %3221 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 16) +// CHECK-NEXT: store %"{{.*}}/runtime/internal/runtime.String" { ptr @{{[0-9]+}}, i64 8 }, ptr %3221, align 8 +// CHECK-NEXT: %3222 = insertvalue %"{{.*}}/runtime/internal/runtime.eface" { ptr @_llgo_main.MyString, ptr undef }, ptr %3221, 1 +// CHECK-NEXT: %3223 = extractvalue { ptr, ptr } %3220, 1 +// CHECK-NEXT: %3224 = extractvalue { ptr, ptr } %3220, 0 +// CHECK-NEXT: %__llgo_funcval_code427 = call ptr asm "", "=r,0"(ptr %3224) +// CHECK-NEXT: %3225 = call %reflect.Value %__llgo_funcval_code427(ptr {{(nest|swiftself)}} %3223, %"{{.*}}/runtime/internal/runtime.eface" %3222) +// CHECK-NEXT: store %reflect.Value %3218, ptr %3211, align 8 +// CHECK-NEXT: store %reflect.Value %3225, ptr %3219, align 8 +// CHECK-NEXT: %3226 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %1, i64 214 +// CHECK-NEXT: %3227 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %3226, i32 0, i32 0 +// CHECK-NEXT: %3228 = load { ptr, ptr }, ptr @main.V, align 8 +// CHECK-NEXT: %3229 = call %"{{.*}}/runtime/internal/runtime.Slice" @"{{.*}}/runtime/internal/runtime.StringToRunes"(%"{{.*}}/runtime/internal/runtime.String" { ptr @{{[0-9]+}}, i64 17 }) +// CHECK-NEXT: %3230 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 24) +// CHECK-NEXT: store %"{{.*}}/runtime/internal/runtime.Slice" %3229, ptr %3230, align 8 +// CHECK-NEXT: %3231 = insertvalue %"{{.*}}/runtime/internal/runtime.eface" { ptr @"[]_llgo_int32", ptr undef }, ptr %3230, 1 +// CHECK-NEXT: %3232 = extractvalue { ptr, ptr } %3228, 1 +// CHECK-NEXT: %3233 = extractvalue { ptr, ptr } %3228, 0 +// CHECK-NEXT: %__llgo_funcval_code428 = call ptr asm "", "=r,0"(ptr %3233) +// CHECK-NEXT: %3234 = call %reflect.Value %__llgo_funcval_code428(ptr {{(nest|swiftself)}} %3232, %"{{.*}}/runtime/internal/runtime.eface" %3231) +// CHECK-NEXT: %3235 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %3226, i32 0, i32 1 +// CHECK-NEXT: %3236 = load { ptr, ptr }, ptr @main.V, align 8 +// CHECK-NEXT: %3237 = call %"{{.*}}/runtime/internal/runtime.Slice" @"{{.*}}/runtime/internal/runtime.StringToRunes"(%"{{.*}}/runtime/internal/runtime.String" { ptr @{{[0-9]+}}, i64 17 }) +// CHECK-NEXT: %3238 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 24) +// CHECK-NEXT: store %"{{.*}}/runtime/internal/runtime.Slice" %3237, ptr %3238, align 8 +// CHECK-NEXT: %3239 = insertvalue %"{{.*}}/runtime/internal/runtime.eface" { ptr @"[]_llgo_int32", ptr undef }, ptr %3238, 1 +// CHECK-NEXT: %3240 = extractvalue { ptr, ptr } %3236, 1 +// CHECK-NEXT: %3241 = extractvalue { ptr, ptr } %3236, 0 +// CHECK-NEXT: %__llgo_funcval_code429 = call ptr asm "", "=r,0"(ptr %3241) +// CHECK-NEXT: %3242 = call %reflect.Value %__llgo_funcval_code429(ptr {{(nest|swiftself)}} %3240, %"{{.*}}/runtime/internal/runtime.eface" %3239) +// CHECK-NEXT: store %reflect.Value %3234, ptr %3227, align 8 +// CHECK-NEXT: store %reflect.Value %3242, ptr %3235, align 8 +// CHECK-NEXT: %3243 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %1, i64 215 +// CHECK-NEXT: %3244 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %3243, i32 0, i32 0 +// CHECK-NEXT: %3245 = load { ptr, ptr }, ptr @main.V, align 8 +// CHECK-NEXT: %3246 = call %"{{.*}}/runtime/internal/runtime.Slice" @"{{.*}}/runtime/internal/runtime.StringToRunes"(%"{{.*}}/runtime/internal/runtime.String" { ptr @{{[0-9]+}}, i64 17 }) +// CHECK-NEXT: %3247 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 24) +// CHECK-NEXT: store %"{{.*}}/runtime/internal/runtime.Slice" %3246, ptr %3247, align 8 +// CHECK-NEXT: %3248 = insertvalue %"{{.*}}/runtime/internal/runtime.eface" { ptr @"[]_llgo_int32", ptr undef }, ptr %3247, 1 +// CHECK-NEXT: %3249 = extractvalue { ptr, ptr } %3245, 1 +// CHECK-NEXT: %3250 = extractvalue { ptr, ptr } %3245, 0 +// CHECK-NEXT: %__llgo_funcval_code430 = call ptr asm "", "=r,0"(ptr %3250) +// CHECK-NEXT: %3251 = call %reflect.Value %__llgo_funcval_code430(ptr {{(nest|swiftself)}} %3249, %"{{.*}}/runtime/internal/runtime.eface" %3248) +// CHECK-NEXT: %3252 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %3243, i32 0, i32 1 +// CHECK-NEXT: %3253 = load { ptr, ptr }, ptr @main.V, align 8 +// CHECK-NEXT: %3254 = call %"{{.*}}/runtime/internal/runtime.Slice" @"{{.*}}/runtime/internal/runtime.StringToRunes"(%"{{.*}}/runtime/internal/runtime.String" { ptr @{{[0-9]+}}, i64 17 }) +// CHECK-NEXT: %3255 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 24) +// CHECK-NEXT: store %"{{.*}}/runtime/internal/runtime.Slice" %3254, ptr %3255, align 8 +// CHECK-NEXT: %3256 = insertvalue %"{{.*}}/runtime/internal/runtime.eface" { ptr @_llgo_main.MyRunes, ptr undef }, ptr %3255, 1 +// CHECK-NEXT: %3257 = extractvalue { ptr, ptr } %3253, 1 +// CHECK-NEXT: %3258 = extractvalue { ptr, ptr } %3253, 0 +// CHECK-NEXT: %__llgo_funcval_code431 = call ptr asm "", "=r,0"(ptr %3258) +// CHECK-NEXT: %3259 = call %reflect.Value %__llgo_funcval_code431(ptr {{(nest|swiftself)}} %3257, %"{{.*}}/runtime/internal/runtime.eface" %3256) +// CHECK-NEXT: store %reflect.Value %3251, ptr %3244, align 8 +// CHECK-NEXT: store %reflect.Value %3259, ptr %3252, align 8 +// CHECK-NEXT: %3260 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %1, i64 216 +// CHECK-NEXT: %3261 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %3260, i32 0, i32 0 +// CHECK-NEXT: %3262 = load { ptr, ptr }, ptr @main.V, align 8 +// CHECK-NEXT: %3263 = call %"{{.*}}/runtime/internal/runtime.Slice" @"{{.*}}/runtime/internal/runtime.StringToRunes"(%"{{.*}}/runtime/internal/runtime.String" { ptr @{{[0-9]+}}, i64 17 }) +// CHECK-NEXT: %3264 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 24) +// CHECK-NEXT: store %"{{.*}}/runtime/internal/runtime.Slice" %3263, ptr %3264, align 8 +// CHECK-NEXT: %3265 = insertvalue %"{{.*}}/runtime/internal/runtime.eface" { ptr @_llgo_main.MyRunes, ptr undef }, ptr %3264, 1 +// CHECK-NEXT: %3266 = extractvalue { ptr, ptr } %3262, 1 +// CHECK-NEXT: %3267 = extractvalue { ptr, ptr } %3262, 0 +// CHECK-NEXT: %__llgo_funcval_code432 = call ptr asm "", "=r,0"(ptr %3267) +// CHECK-NEXT: %3268 = call %reflect.Value %__llgo_funcval_code432(ptr {{(nest|swiftself)}} %3266, %"{{.*}}/runtime/internal/runtime.eface" %3265) +// CHECK-NEXT: %3269 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %3260, i32 0, i32 1 +// CHECK-NEXT: %3270 = load { ptr, ptr }, ptr @main.V, align 8 +// CHECK-NEXT: %3271 = call %"{{.*}}/runtime/internal/runtime.Slice" @"{{.*}}/runtime/internal/runtime.StringToRunes"(%"{{.*}}/runtime/internal/runtime.String" { ptr @{{[0-9]+}}, i64 17 }) +// CHECK-NEXT: %3272 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 24) +// CHECK-NEXT: store %"{{.*}}/runtime/internal/runtime.Slice" %3271, ptr %3272, align 8 +// CHECK-NEXT: %3273 = insertvalue %"{{.*}}/runtime/internal/runtime.eface" { ptr @"[]_llgo_int32", ptr undef }, ptr %3272, 1 +// CHECK-NEXT: %3274 = extractvalue { ptr, ptr } %3270, 1 +// CHECK-NEXT: %3275 = extractvalue { ptr, ptr } %3270, 0 +// CHECK-NEXT: %__llgo_funcval_code433 = call ptr asm "", "=r,0"(ptr %3275) +// CHECK-NEXT: %3276 = call %reflect.Value %__llgo_funcval_code433(ptr {{(nest|swiftself)}} %3274, %"{{.*}}/runtime/internal/runtime.eface" %3273) +// CHECK-NEXT: store %reflect.Value %3268, ptr %3261, align 8 +// CHECK-NEXT: store %reflect.Value %3276, ptr %3269, align 8 +// CHECK-NEXT: %3277 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %1, i64 217 +// CHECK-NEXT: %3278 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %3277, i32 0, i32 0 +// CHECK-NEXT: %3279 = load { ptr, ptr }, ptr @main.V, align 8 +// CHECK-NEXT: %3280 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 8) +// CHECK-NEXT: store i64 97, ptr %3280, align 8 +// CHECK-NEXT: %3281 = insertvalue %"{{.*}}/runtime/internal/runtime.eface" { ptr @_llgo_int, ptr undef }, ptr %3280, 1 +// CHECK-NEXT: %3282 = extractvalue { ptr, ptr } %3279, 1 +// CHECK-NEXT: %3283 = extractvalue { ptr, ptr } %3279, 0 +// CHECK-NEXT: %__llgo_funcval_code434 = call ptr asm "", "=r,0"(ptr %3283) +// CHECK-NEXT: %3284 = call %reflect.Value %__llgo_funcval_code434(ptr {{(nest|swiftself)}} %3282, %"{{.*}}/runtime/internal/runtime.eface" %3281) +// CHECK-NEXT: %3285 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %3277, i32 0, i32 1 +// CHECK-NEXT: %3286 = load { ptr, ptr }, ptr @main.V, align 8 +// CHECK-NEXT: %3287 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 16) +// CHECK-NEXT: store %"{{.*}}/runtime/internal/runtime.String" { ptr @{{[0-9]+}}, i64 1 }, ptr %3287, align 8 +// CHECK-NEXT: %3288 = insertvalue %"{{.*}}/runtime/internal/runtime.eface" { ptr @_llgo_main.MyString, ptr undef }, ptr %3287, 1 +// CHECK-NEXT: %3289 = extractvalue { ptr, ptr } %3286, 1 +// CHECK-NEXT: %3290 = extractvalue { ptr, ptr } %3286, 0 +// CHECK-NEXT: %__llgo_funcval_code435 = call ptr asm "", "=r,0"(ptr %3290) +// CHECK-NEXT: %3291 = call %reflect.Value %__llgo_funcval_code435(ptr {{(nest|swiftself)}} %3289, %"{{.*}}/runtime/internal/runtime.eface" %3288) +// CHECK-NEXT: store %reflect.Value %3284, ptr %3278, align 8 +// CHECK-NEXT: store %reflect.Value %3291, ptr %3285, align 8 +// CHECK-NEXT: %3292 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %1, i64 218 +// CHECK-NEXT: %3293 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %3292, i32 0, i32 0 +// CHECK-NEXT: %3294 = load { ptr, ptr }, ptr @main.V, align 8 +// CHECK-NEXT: %3295 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 1) +// CHECK-NEXT: store i8 97, ptr %3295, align 1 +// CHECK-NEXT: %3296 = insertvalue %"{{.*}}/runtime/internal/runtime.eface" { ptr @_llgo_int8, ptr undef }, ptr %3295, 1 +// CHECK-NEXT: %3297 = extractvalue { ptr, ptr } %3294, 1 +// CHECK-NEXT: %3298 = extractvalue { ptr, ptr } %3294, 0 +// CHECK-NEXT: %__llgo_funcval_code436 = call ptr asm "", "=r,0"(ptr %3298) +// CHECK-NEXT: %3299 = call %reflect.Value %__llgo_funcval_code436(ptr {{(nest|swiftself)}} %3297, %"{{.*}}/runtime/internal/runtime.eface" %3296) +// CHECK-NEXT: %3300 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %3292, i32 0, i32 1 +// CHECK-NEXT: %3301 = load { ptr, ptr }, ptr @main.V, align 8 +// CHECK-NEXT: %3302 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 16) +// CHECK-NEXT: store %"{{.*}}/runtime/internal/runtime.String" { ptr @{{[0-9]+}}, i64 1 }, ptr %3302, align 8 +// CHECK-NEXT: %3303 = insertvalue %"{{.*}}/runtime/internal/runtime.eface" { ptr @_llgo_main.MyString, ptr undef }, ptr %3302, 1 +// CHECK-NEXT: %3304 = extractvalue { ptr, ptr } %3301, 1 +// CHECK-NEXT: %3305 = extractvalue { ptr, ptr } %3301, 0 +// CHECK-NEXT: %__llgo_funcval_code437 = call ptr asm "", "=r,0"(ptr %3305) +// CHECK-NEXT: %3306 = call %reflect.Value %__llgo_funcval_code437(ptr {{(nest|swiftself)}} %3304, %"{{.*}}/runtime/internal/runtime.eface" %3303) +// CHECK-NEXT: store %reflect.Value %3299, ptr %3293, align 8 +// CHECK-NEXT: store %reflect.Value %3306, ptr %3300, align 8 +// CHECK-NEXT: %3307 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %1, i64 219 +// CHECK-NEXT: %3308 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %3307, i32 0, i32 0 +// CHECK-NEXT: %3309 = load { ptr, ptr }, ptr @main.V, align 8 +// CHECK-NEXT: %3310 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 2) +// CHECK-NEXT: store i16 97, ptr %3310, align 2 +// CHECK-NEXT: %3311 = insertvalue %"{{.*}}/runtime/internal/runtime.eface" { ptr @_llgo_int16, ptr undef }, ptr %3310, 1 +// CHECK-NEXT: %3312 = extractvalue { ptr, ptr } %3309, 1 +// CHECK-NEXT: %3313 = extractvalue { ptr, ptr } %3309, 0 +// CHECK-NEXT: %__llgo_funcval_code438 = call ptr asm "", "=r,0"(ptr %3313) +// CHECK-NEXT: %3314 = call %reflect.Value %__llgo_funcval_code438(ptr {{(nest|swiftself)}} %3312, %"{{.*}}/runtime/internal/runtime.eface" %3311) +// CHECK-NEXT: %3315 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %3307, i32 0, i32 1 +// CHECK-NEXT: %3316 = load { ptr, ptr }, ptr @main.V, align 8 +// CHECK-NEXT: %3317 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 16) +// CHECK-NEXT: store %"{{.*}}/runtime/internal/runtime.String" { ptr @{{[0-9]+}}, i64 1 }, ptr %3317, align 8 +// CHECK-NEXT: %3318 = insertvalue %"{{.*}}/runtime/internal/runtime.eface" { ptr @_llgo_main.MyString, ptr undef }, ptr %3317, 1 +// CHECK-NEXT: %3319 = extractvalue { ptr, ptr } %3316, 1 +// CHECK-NEXT: %3320 = extractvalue { ptr, ptr } %3316, 0 +// CHECK-NEXT: %__llgo_funcval_code439 = call ptr asm "", "=r,0"(ptr %3320) +// CHECK-NEXT: %3321 = call %reflect.Value %__llgo_funcval_code439(ptr {{(nest|swiftself)}} %3319, %"{{.*}}/runtime/internal/runtime.eface" %3318) +// CHECK-NEXT: store %reflect.Value %3314, ptr %3308, align 8 +// CHECK-NEXT: store %reflect.Value %3321, ptr %3315, align 8 +// CHECK-NEXT: %3322 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %1, i64 220 +// CHECK-NEXT: %3323 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %3322, i32 0, i32 0 +// CHECK-NEXT: %3324 = load { ptr, ptr }, ptr @main.V, align 8 +// CHECK-NEXT: %3325 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 4) +// CHECK-NEXT: store i32 97, ptr %3325, align 4 +// CHECK-NEXT: %3326 = insertvalue %"{{.*}}/runtime/internal/runtime.eface" { ptr @_llgo_int32, ptr undef }, ptr %3325, 1 +// CHECK-NEXT: %3327 = extractvalue { ptr, ptr } %3324, 1 +// CHECK-NEXT: %3328 = extractvalue { ptr, ptr } %3324, 0 +// CHECK-NEXT: %__llgo_funcval_code440 = call ptr asm "", "=r,0"(ptr %3328) +// CHECK-NEXT: %3329 = call %reflect.Value %__llgo_funcval_code440(ptr {{(nest|swiftself)}} %3327, %"{{.*}}/runtime/internal/runtime.eface" %3326) +// CHECK-NEXT: %3330 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %3322, i32 0, i32 1 +// CHECK-NEXT: %3331 = load { ptr, ptr }, ptr @main.V, align 8 +// CHECK-NEXT: %3332 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 16) +// CHECK-NEXT: store %"{{.*}}/runtime/internal/runtime.String" { ptr @{{[0-9]+}}, i64 1 }, ptr %3332, align 8 +// CHECK-NEXT: %3333 = insertvalue %"{{.*}}/runtime/internal/runtime.eface" { ptr @_llgo_main.MyString, ptr undef }, ptr %3332, 1 +// CHECK-NEXT: %3334 = extractvalue { ptr, ptr } %3331, 1 +// CHECK-NEXT: %3335 = extractvalue { ptr, ptr } %3331, 0 +// CHECK-NEXT: %__llgo_funcval_code441 = call ptr asm "", "=r,0"(ptr %3335) +// CHECK-NEXT: %3336 = call %reflect.Value %__llgo_funcval_code441(ptr {{(nest|swiftself)}} %3334, %"{{.*}}/runtime/internal/runtime.eface" %3333) +// CHECK-NEXT: store %reflect.Value %3329, ptr %3323, align 8 +// CHECK-NEXT: store %reflect.Value %3336, ptr %3330, align 8 +// CHECK-NEXT: %3337 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %1, i64 221 +// CHECK-NEXT: %3338 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %3337, i32 0, i32 0 +// CHECK-NEXT: %3339 = load { ptr, ptr }, ptr @main.V, align 8 +// CHECK-NEXT: %3340 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 8) +// CHECK-NEXT: store i64 97, ptr %3340, align 8 +// CHECK-NEXT: %3341 = insertvalue %"{{.*}}/runtime/internal/runtime.eface" { ptr @_llgo_int64, ptr undef }, ptr %3340, 1 +// CHECK-NEXT: %3342 = extractvalue { ptr, ptr } %3339, 1 +// CHECK-NEXT: %3343 = extractvalue { ptr, ptr } %3339, 0 +// CHECK-NEXT: %__llgo_funcval_code442 = call ptr asm "", "=r,0"(ptr %3343) +// CHECK-NEXT: %3344 = call %reflect.Value %__llgo_funcval_code442(ptr {{(nest|swiftself)}} %3342, %"{{.*}}/runtime/internal/runtime.eface" %3341) +// CHECK-NEXT: %3345 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %3337, i32 0, i32 1 +// CHECK-NEXT: %3346 = load { ptr, ptr }, ptr @main.V, align 8 +// CHECK-NEXT: %3347 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 16) +// CHECK-NEXT: store %"{{.*}}/runtime/internal/runtime.String" { ptr @{{[0-9]+}}, i64 1 }, ptr %3347, align 8 +// CHECK-NEXT: %3348 = insertvalue %"{{.*}}/runtime/internal/runtime.eface" { ptr @_llgo_main.MyString, ptr undef }, ptr %3347, 1 +// CHECK-NEXT: %3349 = extractvalue { ptr, ptr } %3346, 1 +// CHECK-NEXT: %3350 = extractvalue { ptr, ptr } %3346, 0 +// CHECK-NEXT: %__llgo_funcval_code443 = call ptr asm "", "=r,0"(ptr %3350) +// CHECK-NEXT: %3351 = call %reflect.Value %__llgo_funcval_code443(ptr {{(nest|swiftself)}} %3349, %"{{.*}}/runtime/internal/runtime.eface" %3348) +// CHECK-NEXT: store %reflect.Value %3344, ptr %3338, align 8 +// CHECK-NEXT: store %reflect.Value %3351, ptr %3345, align 8 +// CHECK-NEXT: %3352 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %1, i64 222 +// CHECK-NEXT: %3353 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %3352, i32 0, i32 0 +// CHECK-NEXT: %3354 = load { ptr, ptr }, ptr @main.V, align 8 +// CHECK-NEXT: %3355 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 8) +// CHECK-NEXT: store i64 97, ptr %3355, align 8 +// CHECK-NEXT: %3356 = insertvalue %"{{.*}}/runtime/internal/runtime.eface" { ptr @_llgo_uint, ptr undef }, ptr %3355, 1 +// CHECK-NEXT: %3357 = extractvalue { ptr, ptr } %3354, 1 +// CHECK-NEXT: %3358 = extractvalue { ptr, ptr } %3354, 0 +// CHECK-NEXT: %__llgo_funcval_code444 = call ptr asm "", "=r,0"(ptr %3358) +// CHECK-NEXT: %3359 = call %reflect.Value %__llgo_funcval_code444(ptr {{(nest|swiftself)}} %3357, %"{{.*}}/runtime/internal/runtime.eface" %3356) +// CHECK-NEXT: %3360 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %3352, i32 0, i32 1 +// CHECK-NEXT: %3361 = load { ptr, ptr }, ptr @main.V, align 8 +// CHECK-NEXT: %3362 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 16) +// CHECK-NEXT: store %"{{.*}}/runtime/internal/runtime.String" { ptr @{{[0-9]+}}, i64 1 }, ptr %3362, align 8 +// CHECK-NEXT: %3363 = insertvalue %"{{.*}}/runtime/internal/runtime.eface" { ptr @_llgo_main.MyString, ptr undef }, ptr %3362, 1 +// CHECK-NEXT: %3364 = extractvalue { ptr, ptr } %3361, 1 +// CHECK-NEXT: %3365 = extractvalue { ptr, ptr } %3361, 0 +// CHECK-NEXT: %__llgo_funcval_code445 = call ptr asm "", "=r,0"(ptr %3365) +// CHECK-NEXT: %3366 = call %reflect.Value %__llgo_funcval_code445(ptr {{(nest|swiftself)}} %3364, %"{{.*}}/runtime/internal/runtime.eface" %3363) +// CHECK-NEXT: store %reflect.Value %3359, ptr %3353, align 8 +// CHECK-NEXT: store %reflect.Value %3366, ptr %3360, align 8 +// CHECK-NEXT: %3367 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %1, i64 223 +// CHECK-NEXT: %3368 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %3367, i32 0, i32 0 +// CHECK-NEXT: %3369 = load { ptr, ptr }, ptr @main.V, align 8 +// CHECK-NEXT: %3370 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 1) +// CHECK-NEXT: store i8 97, ptr %3370, align 1 +// CHECK-NEXT: %3371 = insertvalue %"{{.*}}/runtime/internal/runtime.eface" { ptr @_llgo_uint8, ptr undef }, ptr %3370, 1 +// CHECK-NEXT: %3372 = extractvalue { ptr, ptr } %3369, 1 +// CHECK-NEXT: %3373 = extractvalue { ptr, ptr } %3369, 0 +// CHECK-NEXT: %__llgo_funcval_code446 = call ptr asm "", "=r,0"(ptr %3373) +// CHECK-NEXT: %3374 = call %reflect.Value %__llgo_funcval_code446(ptr {{(nest|swiftself)}} %3372, %"{{.*}}/runtime/internal/runtime.eface" %3371) +// CHECK-NEXT: %3375 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %3367, i32 0, i32 1 +// CHECK-NEXT: %3376 = load { ptr, ptr }, ptr @main.V, align 8 +// CHECK-NEXT: %3377 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 16) +// CHECK-NEXT: store %"{{.*}}/runtime/internal/runtime.String" { ptr @{{[0-9]+}}, i64 1 }, ptr %3377, align 8 +// CHECK-NEXT: %3378 = insertvalue %"{{.*}}/runtime/internal/runtime.eface" { ptr @_llgo_main.MyString, ptr undef }, ptr %3377, 1 +// CHECK-NEXT: %3379 = extractvalue { ptr, ptr } %3376, 1 +// CHECK-NEXT: %3380 = extractvalue { ptr, ptr } %3376, 0 +// CHECK-NEXT: %__llgo_funcval_code447 = call ptr asm "", "=r,0"(ptr %3380) +// CHECK-NEXT: %3381 = call %reflect.Value %__llgo_funcval_code447(ptr {{(nest|swiftself)}} %3379, %"{{.*}}/runtime/internal/runtime.eface" %3378) +// CHECK-NEXT: store %reflect.Value %3374, ptr %3368, align 8 +// CHECK-NEXT: store %reflect.Value %3381, ptr %3375, align 8 +// CHECK-NEXT: %3382 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %1, i64 224 +// CHECK-NEXT: %3383 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %3382, i32 0, i32 0 +// CHECK-NEXT: %3384 = load { ptr, ptr }, ptr @main.V, align 8 +// CHECK-NEXT: %3385 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 2) +// CHECK-NEXT: store i16 97, ptr %3385, align 2 +// CHECK-NEXT: %3386 = insertvalue %"{{.*}}/runtime/internal/runtime.eface" { ptr @_llgo_uint16, ptr undef }, ptr %3385, 1 +// CHECK-NEXT: %3387 = extractvalue { ptr, ptr } %3384, 1 +// CHECK-NEXT: %3388 = extractvalue { ptr, ptr } %3384, 0 +// CHECK-NEXT: %__llgo_funcval_code448 = call ptr asm "", "=r,0"(ptr %3388) +// CHECK-NEXT: %3389 = call %reflect.Value %__llgo_funcval_code448(ptr {{(nest|swiftself)}} %3387, %"{{.*}}/runtime/internal/runtime.eface" %3386) +// CHECK-NEXT: %3390 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %3382, i32 0, i32 1 +// CHECK-NEXT: %3391 = load { ptr, ptr }, ptr @main.V, align 8 +// CHECK-NEXT: %3392 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 16) +// CHECK-NEXT: store %"{{.*}}/runtime/internal/runtime.String" { ptr @{{[0-9]+}}, i64 1 }, ptr %3392, align 8 +// CHECK-NEXT: %3393 = insertvalue %"{{.*}}/runtime/internal/runtime.eface" { ptr @_llgo_main.MyString, ptr undef }, ptr %3392, 1 +// CHECK-NEXT: %3394 = extractvalue { ptr, ptr } %3391, 1 +// CHECK-NEXT: %3395 = extractvalue { ptr, ptr } %3391, 0 +// CHECK-NEXT: %__llgo_funcval_code449 = call ptr asm "", "=r,0"(ptr %3395) +// CHECK-NEXT: %3396 = call %reflect.Value %__llgo_funcval_code449(ptr {{(nest|swiftself)}} %3394, %"{{.*}}/runtime/internal/runtime.eface" %3393) +// CHECK-NEXT: store %reflect.Value %3389, ptr %3383, align 8 +// CHECK-NEXT: store %reflect.Value %3396, ptr %3390, align 8 +// CHECK-NEXT: %3397 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %1, i64 225 +// CHECK-NEXT: %3398 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %3397, i32 0, i32 0 +// CHECK-NEXT: %3399 = load { ptr, ptr }, ptr @main.V, align 8 +// CHECK-NEXT: %3400 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 4) +// CHECK-NEXT: store i32 97, ptr %3400, align 4 +// CHECK-NEXT: %3401 = insertvalue %"{{.*}}/runtime/internal/runtime.eface" { ptr @_llgo_uint32, ptr undef }, ptr %3400, 1 +// CHECK-NEXT: %3402 = extractvalue { ptr, ptr } %3399, 1 +// CHECK-NEXT: %3403 = extractvalue { ptr, ptr } %3399, 0 +// CHECK-NEXT: %__llgo_funcval_code450 = call ptr asm "", "=r,0"(ptr %3403) +// CHECK-NEXT: %3404 = call %reflect.Value %__llgo_funcval_code450(ptr {{(nest|swiftself)}} %3402, %"{{.*}}/runtime/internal/runtime.eface" %3401) +// CHECK-NEXT: %3405 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %3397, i32 0, i32 1 +// CHECK-NEXT: %3406 = load { ptr, ptr }, ptr @main.V, align 8 +// CHECK-NEXT: %3407 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 16) +// CHECK-NEXT: store %"{{.*}}/runtime/internal/runtime.String" { ptr @{{[0-9]+}}, i64 1 }, ptr %3407, align 8 +// CHECK-NEXT: %3408 = insertvalue %"{{.*}}/runtime/internal/runtime.eface" { ptr @_llgo_main.MyString, ptr undef }, ptr %3407, 1 +// CHECK-NEXT: %3409 = extractvalue { ptr, ptr } %3406, 1 +// CHECK-NEXT: %3410 = extractvalue { ptr, ptr } %3406, 0 +// CHECK-NEXT: %__llgo_funcval_code451 = call ptr asm "", "=r,0"(ptr %3410) +// CHECK-NEXT: %3411 = call %reflect.Value %__llgo_funcval_code451(ptr {{(nest|swiftself)}} %3409, %"{{.*}}/runtime/internal/runtime.eface" %3408) +// CHECK-NEXT: store %reflect.Value %3404, ptr %3398, align 8 +// CHECK-NEXT: store %reflect.Value %3411, ptr %3405, align 8 +// CHECK-NEXT: %3412 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %1, i64 226 +// CHECK-NEXT: %3413 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %3412, i32 0, i32 0 +// CHECK-NEXT: %3414 = load { ptr, ptr }, ptr @main.V, align 8 +// CHECK-NEXT: %3415 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 8) +// CHECK-NEXT: store i64 97, ptr %3415, align 8 +// CHECK-NEXT: %3416 = insertvalue %"{{.*}}/runtime/internal/runtime.eface" { ptr @_llgo_uint64, ptr undef }, ptr %3415, 1 +// CHECK-NEXT: %3417 = extractvalue { ptr, ptr } %3414, 1 +// CHECK-NEXT: %3418 = extractvalue { ptr, ptr } %3414, 0 +// CHECK-NEXT: %__llgo_funcval_code452 = call ptr asm "", "=r,0"(ptr %3418) +// CHECK-NEXT: %3419 = call %reflect.Value %__llgo_funcval_code452(ptr {{(nest|swiftself)}} %3417, %"{{.*}}/runtime/internal/runtime.eface" %3416) +// CHECK-NEXT: %3420 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %3412, i32 0, i32 1 +// CHECK-NEXT: %3421 = load { ptr, ptr }, ptr @main.V, align 8 +// CHECK-NEXT: %3422 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 16) +// CHECK-NEXT: store %"{{.*}}/runtime/internal/runtime.String" { ptr @{{[0-9]+}}, i64 1 }, ptr %3422, align 8 +// CHECK-NEXT: %3423 = insertvalue %"{{.*}}/runtime/internal/runtime.eface" { ptr @_llgo_main.MyString, ptr undef }, ptr %3422, 1 +// CHECK-NEXT: %3424 = extractvalue { ptr, ptr } %3421, 1 +// CHECK-NEXT: %3425 = extractvalue { ptr, ptr } %3421, 0 +// CHECK-NEXT: %__llgo_funcval_code453 = call ptr asm "", "=r,0"(ptr %3425) +// CHECK-NEXT: %3426 = call %reflect.Value %__llgo_funcval_code453(ptr {{(nest|swiftself)}} %3424, %"{{.*}}/runtime/internal/runtime.eface" %3423) +// CHECK-NEXT: store %reflect.Value %3419, ptr %3413, align 8 +// CHECK-NEXT: store %reflect.Value %3426, ptr %3420, align 8 +// CHECK-NEXT: %3427 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %1, i64 227 +// CHECK-NEXT: %3428 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %3427, i32 0, i32 0 +// CHECK-NEXT: %3429 = load { ptr, ptr }, ptr @main.V, align 8 +// CHECK-NEXT: %3430 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 8) +// CHECK-NEXT: store i64 97, ptr %3430, align 8 +// CHECK-NEXT: %3431 = insertvalue %"{{.*}}/runtime/internal/runtime.eface" { ptr @_llgo_uintptr, ptr undef }, ptr %3430, 1 +// CHECK-NEXT: %3432 = extractvalue { ptr, ptr } %3429, 1 +// CHECK-NEXT: %3433 = extractvalue { ptr, ptr } %3429, 0 +// CHECK-NEXT: %__llgo_funcval_code454 = call ptr asm "", "=r,0"(ptr %3433) +// CHECK-NEXT: %3434 = call %reflect.Value %__llgo_funcval_code454(ptr {{(nest|swiftself)}} %3432, %"{{.*}}/runtime/internal/runtime.eface" %3431) +// CHECK-NEXT: %3435 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %3427, i32 0, i32 1 +// CHECK-NEXT: %3436 = load { ptr, ptr }, ptr @main.V, align 8 +// CHECK-NEXT: %3437 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 16) +// CHECK-NEXT: store %"{{.*}}/runtime/internal/runtime.String" { ptr @{{[0-9]+}}, i64 1 }, ptr %3437, align 8 +// CHECK-NEXT: %3438 = insertvalue %"{{.*}}/runtime/internal/runtime.eface" { ptr @_llgo_main.MyString, ptr undef }, ptr %3437, 1 +// CHECK-NEXT: %3439 = extractvalue { ptr, ptr } %3436, 1 +// CHECK-NEXT: %3440 = extractvalue { ptr, ptr } %3436, 0 +// CHECK-NEXT: %__llgo_funcval_code455 = call ptr asm "", "=r,0"(ptr %3440) +// CHECK-NEXT: %3441 = call %reflect.Value %__llgo_funcval_code455(ptr {{(nest|swiftself)}} %3439, %"{{.*}}/runtime/internal/runtime.eface" %3438) +// CHECK-NEXT: store %reflect.Value %3434, ptr %3428, align 8 +// CHECK-NEXT: store %reflect.Value %3441, ptr %3435, align 8 +// CHECK-NEXT: %3442 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %1, i64 228 +// CHECK-NEXT: %3443 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %3442, i32 0, i32 0 +// CHECK-NEXT: %3444 = load { ptr, ptr }, ptr @main.V, align 8 +// CHECK-NEXT: %3445 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 8) +// CHECK-NEXT: store i64 -1, ptr %3445, align 8 +// CHECK-NEXT: %3446 = insertvalue %"{{.*}}/runtime/internal/runtime.eface" { ptr @_llgo_int, ptr undef }, ptr %3445, 1 +// CHECK-NEXT: %3447 = extractvalue { ptr, ptr } %3444, 1 +// CHECK-NEXT: %3448 = extractvalue { ptr, ptr } %3444, 0 +// CHECK-NEXT: %__llgo_funcval_code456 = call ptr asm "", "=r,0"(ptr %3448) +// CHECK-NEXT: %3449 = call %reflect.Value %__llgo_funcval_code456(ptr {{(nest|swiftself)}} %3447, %"{{.*}}/runtime/internal/runtime.eface" %3446) +// CHECK-NEXT: %3450 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %3442, i32 0, i32 1 +// CHECK-NEXT: %3451 = load { ptr, ptr }, ptr @main.V, align 8 +// CHECK-NEXT: %3452 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 16) +// CHECK-NEXT: store %"{{.*}}/runtime/internal/runtime.String" { ptr @{{[0-9]+}}, i64 3 }, ptr %3452, align 8 +// CHECK-NEXT: %3453 = insertvalue %"{{.*}}/runtime/internal/runtime.eface" { ptr @_llgo_main.MyString, ptr undef }, ptr %3452, 1 +// CHECK-NEXT: %3454 = extractvalue { ptr, ptr } %3451, 1 +// CHECK-NEXT: %3455 = extractvalue { ptr, ptr } %3451, 0 +// CHECK-NEXT: %__llgo_funcval_code457 = call ptr asm "", "=r,0"(ptr %3455) +// CHECK-NEXT: %3456 = call %reflect.Value %__llgo_funcval_code457(ptr {{(nest|swiftself)}} %3454, %"{{.*}}/runtime/internal/runtime.eface" %3453) +// CHECK-NEXT: store %reflect.Value %3449, ptr %3443, align 8 +// CHECK-NEXT: store %reflect.Value %3456, ptr %3450, align 8 +// CHECK-NEXT: %3457 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %1, i64 229 +// CHECK-NEXT: %3458 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %3457, i32 0, i32 0 +// CHECK-NEXT: %3459 = load { ptr, ptr }, ptr @main.V, align 8 +// CHECK-NEXT: %3460 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 1) +// CHECK-NEXT: store i8 -2, ptr %3460, align 1 +// CHECK-NEXT: %3461 = insertvalue %"{{.*}}/runtime/internal/runtime.eface" { ptr @_llgo_int8, ptr undef }, ptr %3460, 1 +// CHECK-NEXT: %3462 = extractvalue { ptr, ptr } %3459, 1 +// CHECK-NEXT: %3463 = extractvalue { ptr, ptr } %3459, 0 +// CHECK-NEXT: %__llgo_funcval_code458 = call ptr asm "", "=r,0"(ptr %3463) +// CHECK-NEXT: %3464 = call %reflect.Value %__llgo_funcval_code458(ptr {{(nest|swiftself)}} %3462, %"{{.*}}/runtime/internal/runtime.eface" %3461) +// CHECK-NEXT: %3465 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %3457, i32 0, i32 1 +// CHECK-NEXT: %3466 = load { ptr, ptr }, ptr @main.V, align 8 +// CHECK-NEXT: %3467 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 16) +// CHECK-NEXT: store %"{{.*}}/runtime/internal/runtime.String" { ptr @{{[0-9]+}}, i64 3 }, ptr %3467, align 8 +// CHECK-NEXT: %3468 = insertvalue %"{{.*}}/runtime/internal/runtime.eface" { ptr @_llgo_main.MyString, ptr undef }, ptr %3467, 1 +// CHECK-NEXT: %3469 = extractvalue { ptr, ptr } %3466, 1 +// CHECK-NEXT: %3470 = extractvalue { ptr, ptr } %3466, 0 +// CHECK-NEXT: %__llgo_funcval_code459 = call ptr asm "", "=r,0"(ptr %3470) +// CHECK-NEXT: %3471 = call %reflect.Value %__llgo_funcval_code459(ptr {{(nest|swiftself)}} %3469, %"{{.*}}/runtime/internal/runtime.eface" %3468) +// CHECK-NEXT: store %reflect.Value %3464, ptr %3458, align 8 +// CHECK-NEXT: store %reflect.Value %3471, ptr %3465, align 8 +// CHECK-NEXT: %3472 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %1, i64 230 +// CHECK-NEXT: %3473 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %3472, i32 0, i32 0 +// CHECK-NEXT: %3474 = load { ptr, ptr }, ptr @main.V, align 8 +// CHECK-NEXT: %3475 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 2) +// CHECK-NEXT: store i16 -3, ptr %3475, align 2 +// CHECK-NEXT: %3476 = insertvalue %"{{.*}}/runtime/internal/runtime.eface" { ptr @_llgo_int16, ptr undef }, ptr %3475, 1 +// CHECK-NEXT: %3477 = extractvalue { ptr, ptr } %3474, 1 +// CHECK-NEXT: %3478 = extractvalue { ptr, ptr } %3474, 0 +// CHECK-NEXT: %__llgo_funcval_code460 = call ptr asm "", "=r,0"(ptr %3478) +// CHECK-NEXT: %3479 = call %reflect.Value %__llgo_funcval_code460(ptr {{(nest|swiftself)}} %3477, %"{{.*}}/runtime/internal/runtime.eface" %3476) +// CHECK-NEXT: %3480 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %3472, i32 0, i32 1 +// CHECK-NEXT: %3481 = load { ptr, ptr }, ptr @main.V, align 8 +// CHECK-NEXT: %3482 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 16) +// CHECK-NEXT: store %"{{.*}}/runtime/internal/runtime.String" { ptr @{{[0-9]+}}, i64 3 }, ptr %3482, align 8 +// CHECK-NEXT: %3483 = insertvalue %"{{.*}}/runtime/internal/runtime.eface" { ptr @_llgo_main.MyString, ptr undef }, ptr %3482, 1 +// CHECK-NEXT: %3484 = extractvalue { ptr, ptr } %3481, 1 +// CHECK-NEXT: %3485 = extractvalue { ptr, ptr } %3481, 0 +// CHECK-NEXT: %__llgo_funcval_code461 = call ptr asm "", "=r,0"(ptr %3485) +// CHECK-NEXT: %3486 = call %reflect.Value %__llgo_funcval_code461(ptr {{(nest|swiftself)}} %3484, %"{{.*}}/runtime/internal/runtime.eface" %3483) +// CHECK-NEXT: store %reflect.Value %3479, ptr %3473, align 8 +// CHECK-NEXT: store %reflect.Value %3486, ptr %3480, align 8 +// CHECK-NEXT: %3487 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %1, i64 231 +// CHECK-NEXT: %3488 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %3487, i32 0, i32 0 +// CHECK-NEXT: %3489 = load { ptr, ptr }, ptr @main.V, align 8 +// CHECK-NEXT: %3490 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 4) +// CHECK-NEXT: store i32 -4, ptr %3490, align 4 +// CHECK-NEXT: %3491 = insertvalue %"{{.*}}/runtime/internal/runtime.eface" { ptr @_llgo_int32, ptr undef }, ptr %3490, 1 +// CHECK-NEXT: %3492 = extractvalue { ptr, ptr } %3489, 1 +// CHECK-NEXT: %3493 = extractvalue { ptr, ptr } %3489, 0 +// CHECK-NEXT: %__llgo_funcval_code462 = call ptr asm "", "=r,0"(ptr %3493) +// CHECK-NEXT: %3494 = call %reflect.Value %__llgo_funcval_code462(ptr {{(nest|swiftself)}} %3492, %"{{.*}}/runtime/internal/runtime.eface" %3491) +// CHECK-NEXT: %3495 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %3487, i32 0, i32 1 +// CHECK-NEXT: %3496 = load { ptr, ptr }, ptr @main.V, align 8 +// CHECK-NEXT: %3497 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 16) +// CHECK-NEXT: store %"{{.*}}/runtime/internal/runtime.String" { ptr @{{[0-9]+}}, i64 3 }, ptr %3497, align 8 +// CHECK-NEXT: %3498 = insertvalue %"{{.*}}/runtime/internal/runtime.eface" { ptr @_llgo_main.MyString, ptr undef }, ptr %3497, 1 +// CHECK-NEXT: %3499 = extractvalue { ptr, ptr } %3496, 1 +// CHECK-NEXT: %3500 = extractvalue { ptr, ptr } %3496, 0 +// CHECK-NEXT: %__llgo_funcval_code463 = call ptr asm "", "=r,0"(ptr %3500) +// CHECK-NEXT: %3501 = call %reflect.Value %__llgo_funcval_code463(ptr {{(nest|swiftself)}} %3499, %"{{.*}}/runtime/internal/runtime.eface" %3498) +// CHECK-NEXT: store %reflect.Value %3494, ptr %3488, align 8 +// CHECK-NEXT: store %reflect.Value %3501, ptr %3495, align 8 +// CHECK-NEXT: %3502 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %1, i64 232 +// CHECK-NEXT: %3503 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %3502, i32 0, i32 0 +// CHECK-NEXT: %3504 = load { ptr, ptr }, ptr @main.V, align 8 +// CHECK-NEXT: %3505 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 8) +// CHECK-NEXT: store i64 -5, ptr %3505, align 8 +// CHECK-NEXT: %3506 = insertvalue %"{{.*}}/runtime/internal/runtime.eface" { ptr @_llgo_int64, ptr undef }, ptr %3505, 1 +// CHECK-NEXT: %3507 = extractvalue { ptr, ptr } %3504, 1 +// CHECK-NEXT: %3508 = extractvalue { ptr, ptr } %3504, 0 +// CHECK-NEXT: %__llgo_funcval_code464 = call ptr asm "", "=r,0"(ptr %3508) +// CHECK-NEXT: %3509 = call %reflect.Value %__llgo_funcval_code464(ptr {{(nest|swiftself)}} %3507, %"{{.*}}/runtime/internal/runtime.eface" %3506) +// CHECK-NEXT: %3510 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %3502, i32 0, i32 1 +// CHECK-NEXT: %3511 = load { ptr, ptr }, ptr @main.V, align 8 +// CHECK-NEXT: %3512 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 16) +// CHECK-NEXT: store %"{{.*}}/runtime/internal/runtime.String" { ptr @{{[0-9]+}}, i64 3 }, ptr %3512, align 8 +// CHECK-NEXT: %3513 = insertvalue %"{{.*}}/runtime/internal/runtime.eface" { ptr @_llgo_main.MyString, ptr undef }, ptr %3512, 1 +// CHECK-NEXT: %3514 = extractvalue { ptr, ptr } %3511, 1 +// CHECK-NEXT: %3515 = extractvalue { ptr, ptr } %3511, 0 +// CHECK-NEXT: %__llgo_funcval_code465 = call ptr asm "", "=r,0"(ptr %3515) +// CHECK-NEXT: %3516 = call %reflect.Value %__llgo_funcval_code465(ptr {{(nest|swiftself)}} %3514, %"{{.*}}/runtime/internal/runtime.eface" %3513) +// CHECK-NEXT: store %reflect.Value %3509, ptr %3503, align 8 +// CHECK-NEXT: store %reflect.Value %3516, ptr %3510, align 8 +// CHECK-NEXT: %3517 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %1, i64 233 +// CHECK-NEXT: %3518 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %3517, i32 0, i32 0 +// CHECK-NEXT: %3519 = load { ptr, ptr }, ptr @main.V, align 8 +// CHECK-NEXT: %3520 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 8) +// CHECK-NEXT: store i64 1114113, ptr %3520, align 8 +// CHECK-NEXT: %3521 = insertvalue %"{{.*}}/runtime/internal/runtime.eface" { ptr @_llgo_uint, ptr undef }, ptr %3520, 1 +// CHECK-NEXT: %3522 = extractvalue { ptr, ptr } %3519, 1 +// CHECK-NEXT: %3523 = extractvalue { ptr, ptr } %3519, 0 +// CHECK-NEXT: %__llgo_funcval_code466 = call ptr asm "", "=r,0"(ptr %3523) +// CHECK-NEXT: %3524 = call %reflect.Value %__llgo_funcval_code466(ptr {{(nest|swiftself)}} %3522, %"{{.*}}/runtime/internal/runtime.eface" %3521) +// CHECK-NEXT: %3525 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %3517, i32 0, i32 1 +// CHECK-NEXT: %3526 = load { ptr, ptr }, ptr @main.V, align 8 +// CHECK-NEXT: %3527 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 16) +// CHECK-NEXT: store %"{{.*}}/runtime/internal/runtime.String" { ptr @{{[0-9]+}}, i64 3 }, ptr %3527, align 8 +// CHECK-NEXT: %3528 = insertvalue %"{{.*}}/runtime/internal/runtime.eface" { ptr @_llgo_main.MyString, ptr undef }, ptr %3527, 1 +// CHECK-NEXT: %3529 = extractvalue { ptr, ptr } %3526, 1 +// CHECK-NEXT: %3530 = extractvalue { ptr, ptr } %3526, 0 +// CHECK-NEXT: %__llgo_funcval_code467 = call ptr asm "", "=r,0"(ptr %3530) +// CHECK-NEXT: %3531 = call %reflect.Value %__llgo_funcval_code467(ptr {{(nest|swiftself)}} %3529, %"{{.*}}/runtime/internal/runtime.eface" %3528) +// CHECK-NEXT: store %reflect.Value %3524, ptr %3518, align 8 +// CHECK-NEXT: store %reflect.Value %3531, ptr %3525, align 8 +// CHECK-NEXT: %3532 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %1, i64 234 +// CHECK-NEXT: %3533 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %3532, i32 0, i32 0 +// CHECK-NEXT: %3534 = load { ptr, ptr }, ptr @main.V, align 8 +// CHECK-NEXT: %3535 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 4) +// CHECK-NEXT: store i32 1114114, ptr %3535, align 4 +// CHECK-NEXT: %3536 = insertvalue %"{{.*}}/runtime/internal/runtime.eface" { ptr @_llgo_uint32, ptr undef }, ptr %3535, 1 +// CHECK-NEXT: %3537 = extractvalue { ptr, ptr } %3534, 1 +// CHECK-NEXT: %3538 = extractvalue { ptr, ptr } %3534, 0 +// CHECK-NEXT: %__llgo_funcval_code468 = call ptr asm "", "=r,0"(ptr %3538) +// CHECK-NEXT: %3539 = call %reflect.Value %__llgo_funcval_code468(ptr {{(nest|swiftself)}} %3537, %"{{.*}}/runtime/internal/runtime.eface" %3536) +// CHECK-NEXT: %3540 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %3532, i32 0, i32 1 +// CHECK-NEXT: %3541 = load { ptr, ptr }, ptr @main.V, align 8 +// CHECK-NEXT: %3542 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 16) +// CHECK-NEXT: store %"{{.*}}/runtime/internal/runtime.String" { ptr @{{[0-9]+}}, i64 3 }, ptr %3542, align 8 +// CHECK-NEXT: %3543 = insertvalue %"{{.*}}/runtime/internal/runtime.eface" { ptr @_llgo_main.MyString, ptr undef }, ptr %3542, 1 +// CHECK-NEXT: %3544 = extractvalue { ptr, ptr } %3541, 1 +// CHECK-NEXT: %3545 = extractvalue { ptr, ptr } %3541, 0 +// CHECK-NEXT: %__llgo_funcval_code469 = call ptr asm "", "=r,0"(ptr %3545) +// CHECK-NEXT: %3546 = call %reflect.Value %__llgo_funcval_code469(ptr {{(nest|swiftself)}} %3544, %"{{.*}}/runtime/internal/runtime.eface" %3543) +// CHECK-NEXT: store %reflect.Value %3539, ptr %3533, align 8 +// CHECK-NEXT: store %reflect.Value %3546, ptr %3540, align 8 +// CHECK-NEXT: %3547 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %1, i64 235 +// CHECK-NEXT: %3548 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %3547, i32 0, i32 0 +// CHECK-NEXT: %3549 = load { ptr, ptr }, ptr @main.V, align 8 +// CHECK-NEXT: %3550 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 8) +// CHECK-NEXT: store i64 1114115, ptr %3550, align 8 +// CHECK-NEXT: %3551 = insertvalue %"{{.*}}/runtime/internal/runtime.eface" { ptr @_llgo_uint64, ptr undef }, ptr %3550, 1 +// CHECK-NEXT: %3552 = extractvalue { ptr, ptr } %3549, 1 +// CHECK-NEXT: %3553 = extractvalue { ptr, ptr } %3549, 0 +// CHECK-NEXT: %__llgo_funcval_code470 = call ptr asm "", "=r,0"(ptr %3553) +// CHECK-NEXT: %3554 = call %reflect.Value %__llgo_funcval_code470(ptr {{(nest|swiftself)}} %3552, %"{{.*}}/runtime/internal/runtime.eface" %3551) +// CHECK-NEXT: %3555 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %3547, i32 0, i32 1 +// CHECK-NEXT: %3556 = load { ptr, ptr }, ptr @main.V, align 8 +// CHECK-NEXT: %3557 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 16) +// CHECK-NEXT: store %"{{.*}}/runtime/internal/runtime.String" { ptr @{{[0-9]+}}, i64 3 }, ptr %3557, align 8 +// CHECK-NEXT: %3558 = insertvalue %"{{.*}}/runtime/internal/runtime.eface" { ptr @_llgo_main.MyString, ptr undef }, ptr %3557, 1 +// CHECK-NEXT: %3559 = extractvalue { ptr, ptr } %3556, 1 +// CHECK-NEXT: %3560 = extractvalue { ptr, ptr } %3556, 0 +// CHECK-NEXT: %__llgo_funcval_code471 = call ptr asm "", "=r,0"(ptr %3560) +// CHECK-NEXT: %3561 = call %reflect.Value %__llgo_funcval_code471(ptr {{(nest|swiftself)}} %3559, %"{{.*}}/runtime/internal/runtime.eface" %3558) +// CHECK-NEXT: store %reflect.Value %3554, ptr %3548, align 8 +// CHECK-NEXT: store %reflect.Value %3561, ptr %3555, align 8 +// CHECK-NEXT: %3562 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %1, i64 236 +// CHECK-NEXT: %3563 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %3562, i32 0, i32 0 +// CHECK-NEXT: %3564 = load { ptr, ptr }, ptr @main.V, align 8 +// CHECK-NEXT: %3565 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 8) +// CHECK-NEXT: store i64 1114116, ptr %3565, align 8 +// CHECK-NEXT: %3566 = insertvalue %"{{.*}}/runtime/internal/runtime.eface" { ptr @_llgo_uintptr, ptr undef }, ptr %3565, 1 +// CHECK-NEXT: %3567 = extractvalue { ptr, ptr } %3564, 1 +// CHECK-NEXT: %3568 = extractvalue { ptr, ptr } %3564, 0 +// CHECK-NEXT: %__llgo_funcval_code472 = call ptr asm "", "=r,0"(ptr %3568) +// CHECK-NEXT: %3569 = call %reflect.Value %__llgo_funcval_code472(ptr {{(nest|swiftself)}} %3567, %"{{.*}}/runtime/internal/runtime.eface" %3566) +// CHECK-NEXT: %3570 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %3562, i32 0, i32 1 +// CHECK-NEXT: %3571 = load { ptr, ptr }, ptr @main.V, align 8 +// CHECK-NEXT: %3572 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 16) +// CHECK-NEXT: store %"{{.*}}/runtime/internal/runtime.String" { ptr @{{[0-9]+}}, i64 3 }, ptr %3572, align 8 +// CHECK-NEXT: %3573 = insertvalue %"{{.*}}/runtime/internal/runtime.eface" { ptr @_llgo_main.MyString, ptr undef }, ptr %3572, 1 +// CHECK-NEXT: %3574 = extractvalue { ptr, ptr } %3571, 1 +// CHECK-NEXT: %3575 = extractvalue { ptr, ptr } %3571, 0 +// CHECK-NEXT: %__llgo_funcval_code473 = call ptr asm "", "=r,0"(ptr %3575) +// CHECK-NEXT: %3576 = call %reflect.Value %__llgo_funcval_code473(ptr {{(nest|swiftself)}} %3574, %"{{.*}}/runtime/internal/runtime.eface" %3573) +// CHECK-NEXT: store %reflect.Value %3569, ptr %3563, align 8 +// CHECK-NEXT: store %reflect.Value %3576, ptr %3570, align 8 +// CHECK-NEXT: %3577 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %1, i64 237 +// CHECK-NEXT: %3578 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %3577, i32 0, i32 0 +// CHECK-NEXT: %3579 = load { ptr, ptr }, ptr @main.V, align 8 +// CHECK-NEXT: %3580 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 16) +// CHECK-NEXT: store %"{{.*}}/runtime/internal/runtime.String" { ptr @{{[0-9]+}}, i64 6 }, ptr %3580, align 8 +// CHECK-NEXT: %3581 = insertvalue %"{{.*}}/runtime/internal/runtime.eface" { ptr @_llgo_string, ptr undef }, ptr %3580, 1 +// CHECK-NEXT: %3582 = extractvalue { ptr, ptr } %3579, 1 +// CHECK-NEXT: %3583 = extractvalue { ptr, ptr } %3579, 0 +// CHECK-NEXT: %__llgo_funcval_code474 = call ptr asm "", "=r,0"(ptr %3583) +// CHECK-NEXT: %3584 = call %reflect.Value %__llgo_funcval_code474(ptr {{(nest|swiftself)}} %3582, %"{{.*}}/runtime/internal/runtime.eface" %3581) +// CHECK-NEXT: %3585 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %3577, i32 0, i32 1 +// CHECK-NEXT: %3586 = load { ptr, ptr }, ptr @main.V, align 8 +// CHECK-NEXT: %3587 = call %"{{.*}}/runtime/internal/runtime.Slice" @"{{.*}}/runtime/internal/runtime.StringToBytes"(%"{{.*}}/runtime/internal/runtime.String" { ptr @{{[0-9]+}}, i64 6 }) +// CHECK-NEXT: %3588 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 24) +// CHECK-NEXT: store %"{{.*}}/runtime/internal/runtime.Slice" %3587, ptr %3588, align 8 +// CHECK-NEXT: %3589 = insertvalue %"{{.*}}/runtime/internal/runtime.eface" { ptr @_llgo_main.MyBytes, ptr undef }, ptr %3588, 1 +// CHECK-NEXT: %3590 = extractvalue { ptr, ptr } %3586, 1 +// CHECK-NEXT: %3591 = extractvalue { ptr, ptr } %3586, 0 +// CHECK-NEXT: %__llgo_funcval_code475 = call ptr asm "", "=r,0"(ptr %3591) +// CHECK-NEXT: %3592 = call %reflect.Value %__llgo_funcval_code475(ptr {{(nest|swiftself)}} %3590, %"{{.*}}/runtime/internal/runtime.eface" %3589) +// CHECK-NEXT: store %reflect.Value %3584, ptr %3578, align 8 +// CHECK-NEXT: store %reflect.Value %3592, ptr %3585, align 8 +// CHECK-NEXT: %3593 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %1, i64 238 +// CHECK-NEXT: %3594 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %3593, i32 0, i32 0 +// CHECK-NEXT: %3595 = load { ptr, ptr }, ptr @main.V, align 8 +// CHECK-NEXT: %3596 = call %"{{.*}}/runtime/internal/runtime.Slice" @"{{.*}}/runtime/internal/runtime.StringToBytes"(%"{{.*}}/runtime/internal/runtime.String" { ptr @{{[0-9]+}}, i64 6 }) +// CHECK-NEXT: %3597 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 24) +// CHECK-NEXT: store %"{{.*}}/runtime/internal/runtime.Slice" %3596, ptr %3597, align 8 +// CHECK-NEXT: %3598 = insertvalue %"{{.*}}/runtime/internal/runtime.eface" { ptr @_llgo_main.MyBytes, ptr undef }, ptr %3597, 1 +// CHECK-NEXT: %3599 = extractvalue { ptr, ptr } %3595, 1 +// CHECK-NEXT: %3600 = extractvalue { ptr, ptr } %3595, 0 +// CHECK-NEXT: %__llgo_funcval_code476 = call ptr asm "", "=r,0"(ptr %3600) +// CHECK-NEXT: %3601 = call %reflect.Value %__llgo_funcval_code476(ptr {{(nest|swiftself)}} %3599, %"{{.*}}/runtime/internal/runtime.eface" %3598) +// CHECK-NEXT: %3602 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %3593, i32 0, i32 1 +// CHECK-NEXT: %3603 = load { ptr, ptr }, ptr @main.V, align 8 +// CHECK-NEXT: %3604 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 16) +// CHECK-NEXT: store %"{{.*}}/runtime/internal/runtime.String" { ptr @{{[0-9]+}}, i64 6 }, ptr %3604, align 8 +// CHECK-NEXT: %3605 = insertvalue %"{{.*}}/runtime/internal/runtime.eface" { ptr @_llgo_string, ptr undef }, ptr %3604, 1 +// CHECK-NEXT: %3606 = extractvalue { ptr, ptr } %3603, 1 +// CHECK-NEXT: %3607 = extractvalue { ptr, ptr } %3603, 0 +// CHECK-NEXT: %__llgo_funcval_code477 = call ptr asm "", "=r,0"(ptr %3607) +// CHECK-NEXT: %3608 = call %reflect.Value %__llgo_funcval_code477(ptr {{(nest|swiftself)}} %3606, %"{{.*}}/runtime/internal/runtime.eface" %3605) +// CHECK-NEXT: store %reflect.Value %3601, ptr %3594, align 8 +// CHECK-NEXT: store %reflect.Value %3608, ptr %3602, align 8 +// CHECK-NEXT: %3609 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %1, i64 239 +// CHECK-NEXT: %3610 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %3609, i32 0, i32 0 +// CHECK-NEXT: %3611 = load { ptr, ptr }, ptr @main.V, align 8 +// CHECK-NEXT: %3612 = call %"{{.*}}/runtime/internal/runtime.Slice" @"{{.*}}/runtime/internal/runtime.StringToBytes"(%"{{.*}}/runtime/internal/runtime.String" { ptr @{{[0-9]+}}, i64 6 }) +// CHECK-NEXT: %3613 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 24) +// CHECK-NEXT: store %"{{.*}}/runtime/internal/runtime.Slice" %3612, ptr %3613, align 8 +// CHECK-NEXT: %3614 = insertvalue %"{{.*}}/runtime/internal/runtime.eface" { ptr @_llgo_main.MyBytes, ptr undef }, ptr %3613, 1 +// CHECK-NEXT: %3615 = extractvalue { ptr, ptr } %3611, 1 +// CHECK-NEXT: %3616 = extractvalue { ptr, ptr } %3611, 0 +// CHECK-NEXT: %__llgo_funcval_code478 = call ptr asm "", "=r,0"(ptr %3616) +// CHECK-NEXT: %3617 = call %reflect.Value %__llgo_funcval_code478(ptr {{(nest|swiftself)}} %3615, %"{{.*}}/runtime/internal/runtime.eface" %3614) +// CHECK-NEXT: %3618 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %3609, i32 0, i32 1 +// CHECK-NEXT: %3619 = load { ptr, ptr }, ptr @main.V, align 8 +// CHECK-NEXT: %3620 = call %"{{.*}}/runtime/internal/runtime.Slice" @"{{.*}}/runtime/internal/runtime.StringToBytes"(%"{{.*}}/runtime/internal/runtime.String" { ptr @{{[0-9]+}}, i64 6 }) +// CHECK-NEXT: %3621 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 24) +// CHECK-NEXT: store %"{{.*}}/runtime/internal/runtime.Slice" %3620, ptr %3621, align 8 +// CHECK-NEXT: %3622 = insertvalue %"{{.*}}/runtime/internal/runtime.eface" { ptr @_llgo_main.MyBytes, ptr undef }, ptr %3621, 1 +// CHECK-NEXT: %3623 = extractvalue { ptr, ptr } %3619, 1 +// CHECK-NEXT: %3624 = extractvalue { ptr, ptr } %3619, 0 +// CHECK-NEXT: %__llgo_funcval_code479 = call ptr asm "", "=r,0"(ptr %3624) +// CHECK-NEXT: %3625 = call %reflect.Value %__llgo_funcval_code479(ptr {{(nest|swiftself)}} %3623, %"{{.*}}/runtime/internal/runtime.eface" %3622) +// CHECK-NEXT: store %reflect.Value %3617, ptr %3610, align 8 +// CHECK-NEXT: store %reflect.Value %3625, ptr %3618, align 8 +// CHECK-NEXT: %3626 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %1, i64 240 +// CHECK-NEXT: %3627 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %3626, i32 0, i32 0 +// CHECK-NEXT: %3628 = load { ptr, ptr }, ptr @main.V, align 8 +// CHECK-NEXT: %3629 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 16) +// CHECK-NEXT: store %"{{.*}}/runtime/internal/runtime.String" { ptr @{{[0-9]+}}, i64 6 }, ptr %3629, align 8 +// CHECK-NEXT: %3630 = insertvalue %"{{.*}}/runtime/internal/runtime.eface" { ptr @_llgo_main.MyString, ptr undef }, ptr %3629, 1 +// CHECK-NEXT: %3631 = extractvalue { ptr, ptr } %3628, 1 +// CHECK-NEXT: %3632 = extractvalue { ptr, ptr } %3628, 0 +// CHECK-NEXT: %__llgo_funcval_code480 = call ptr asm "", "=r,0"(ptr %3632) +// CHECK-NEXT: %3633 = call %reflect.Value %__llgo_funcval_code480(ptr {{(nest|swiftself)}} %3631, %"{{.*}}/runtime/internal/runtime.eface" %3630) +// CHECK-NEXT: %3634 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %3626, i32 0, i32 1 +// CHECK-NEXT: %3635 = load { ptr, ptr }, ptr @main.V, align 8 +// CHECK-NEXT: %3636 = call %"{{.*}}/runtime/internal/runtime.Slice" @"{{.*}}/runtime/internal/runtime.StringToBytes"(%"{{.*}}/runtime/internal/runtime.String" { ptr @{{[0-9]+}}, i64 6 }) +// CHECK-NEXT: %3637 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 24) +// CHECK-NEXT: store %"{{.*}}/runtime/internal/runtime.Slice" %3636, ptr %3637, align 8 +// CHECK-NEXT: %3638 = insertvalue %"{{.*}}/runtime/internal/runtime.eface" { ptr @_llgo_main.MyBytes, ptr undef }, ptr %3637, 1 +// CHECK-NEXT: %3639 = extractvalue { ptr, ptr } %3635, 1 +// CHECK-NEXT: %3640 = extractvalue { ptr, ptr } %3635, 0 +// CHECK-NEXT: %__llgo_funcval_code481 = call ptr asm "", "=r,0"(ptr %3640) +// CHECK-NEXT: %3641 = call %reflect.Value %__llgo_funcval_code481(ptr {{(nest|swiftself)}} %3639, %"{{.*}}/runtime/internal/runtime.eface" %3638) +// CHECK-NEXT: store %reflect.Value %3633, ptr %3627, align 8 +// CHECK-NEXT: store %reflect.Value %3641, ptr %3634, align 8 +// CHECK-NEXT: %3642 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %1, i64 241 +// CHECK-NEXT: %3643 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %3642, i32 0, i32 0 +// CHECK-NEXT: %3644 = load { ptr, ptr }, ptr @main.V, align 8 +// CHECK-NEXT: %3645 = call %"{{.*}}/runtime/internal/runtime.Slice" @"{{.*}}/runtime/internal/runtime.StringToBytes"(%"{{.*}}/runtime/internal/runtime.String" { ptr @{{[0-9]+}}, i64 6 }) +// CHECK-NEXT: %3646 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 24) +// CHECK-NEXT: store %"{{.*}}/runtime/internal/runtime.Slice" %3645, ptr %3646, align 8 +// CHECK-NEXT: %3647 = insertvalue %"{{.*}}/runtime/internal/runtime.eface" { ptr @_llgo_main.MyBytes, ptr undef }, ptr %3646, 1 +// CHECK-NEXT: %3648 = extractvalue { ptr, ptr } %3644, 1 +// CHECK-NEXT: %3649 = extractvalue { ptr, ptr } %3644, 0 +// CHECK-NEXT: %__llgo_funcval_code482 = call ptr asm "", "=r,0"(ptr %3649) +// CHECK-NEXT: %3650 = call %reflect.Value %__llgo_funcval_code482(ptr {{(nest|swiftself)}} %3648, %"{{.*}}/runtime/internal/runtime.eface" %3647) +// CHECK-NEXT: %3651 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %3642, i32 0, i32 1 +// CHECK-NEXT: %3652 = load { ptr, ptr }, ptr @main.V, align 8 +// CHECK-NEXT: %3653 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 16) +// CHECK-NEXT: store %"{{.*}}/runtime/internal/runtime.String" { ptr @{{[0-9]+}}, i64 6 }, ptr %3653, align 8 +// CHECK-NEXT: %3654 = insertvalue %"{{.*}}/runtime/internal/runtime.eface" { ptr @_llgo_main.MyString, ptr undef }, ptr %3653, 1 +// CHECK-NEXT: %3655 = extractvalue { ptr, ptr } %3652, 1 +// CHECK-NEXT: %3656 = extractvalue { ptr, ptr } %3652, 0 +// CHECK-NEXT: %__llgo_funcval_code483 = call ptr asm "", "=r,0"(ptr %3656) +// CHECK-NEXT: %3657 = call %reflect.Value %__llgo_funcval_code483(ptr {{(nest|swiftself)}} %3655, %"{{.*}}/runtime/internal/runtime.eface" %3654) +// CHECK-NEXT: store %reflect.Value %3650, ptr %3643, align 8 +// CHECK-NEXT: store %reflect.Value %3657, ptr %3651, align 8 +// CHECK-NEXT: %3658 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %1, i64 242 +// CHECK-NEXT: %3659 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %3658, i32 0, i32 0 +// CHECK-NEXT: %3660 = load { ptr, ptr }, ptr @main.V, align 8 +// CHECK-NEXT: %3661 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 16) +// CHECK-NEXT: store %"{{.*}}/runtime/internal/runtime.String" { ptr @{{[0-9]+}}, i64 8 }, ptr %3661, align 8 +// CHECK-NEXT: %3662 = insertvalue %"{{.*}}/runtime/internal/runtime.eface" { ptr @_llgo_string, ptr undef }, ptr %3661, 1 +// CHECK-NEXT: %3663 = extractvalue { ptr, ptr } %3660, 1 +// CHECK-NEXT: %3664 = extractvalue { ptr, ptr } %3660, 0 +// CHECK-NEXT: %__llgo_funcval_code484 = call ptr asm "", "=r,0"(ptr %3664) +// CHECK-NEXT: %3665 = call %reflect.Value %__llgo_funcval_code484(ptr {{(nest|swiftself)}} %3663, %"{{.*}}/runtime/internal/runtime.eface" %3662) +// CHECK-NEXT: %3666 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %3658, i32 0, i32 1 +// CHECK-NEXT: %3667 = load { ptr, ptr }, ptr @main.V, align 8 +// CHECK-NEXT: %3668 = call %"{{.*}}/runtime/internal/runtime.Slice" @"{{.*}}/runtime/internal/runtime.StringToRunes"(%"{{.*}}/runtime/internal/runtime.String" { ptr @{{[0-9]+}}, i64 8 }) +// CHECK-NEXT: %3669 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 24) +// CHECK-NEXT: store %"{{.*}}/runtime/internal/runtime.Slice" %3668, ptr %3669, align 8 +// CHECK-NEXT: %3670 = insertvalue %"{{.*}}/runtime/internal/runtime.eface" { ptr @_llgo_main.MyRunes, ptr undef }, ptr %3669, 1 +// CHECK-NEXT: %3671 = extractvalue { ptr, ptr } %3667, 1 +// CHECK-NEXT: %3672 = extractvalue { ptr, ptr } %3667, 0 +// CHECK-NEXT: %__llgo_funcval_code485 = call ptr asm "", "=r,0"(ptr %3672) +// CHECK-NEXT: %3673 = call %reflect.Value %__llgo_funcval_code485(ptr {{(nest|swiftself)}} %3671, %"{{.*}}/runtime/internal/runtime.eface" %3670) +// CHECK-NEXT: store %reflect.Value %3665, ptr %3659, align 8 +// CHECK-NEXT: store %reflect.Value %3673, ptr %3666, align 8 +// CHECK-NEXT: %3674 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %1, i64 243 +// CHECK-NEXT: %3675 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %3674, i32 0, i32 0 +// CHECK-NEXT: %3676 = load { ptr, ptr }, ptr @main.V, align 8 +// CHECK-NEXT: %3677 = call %"{{.*}}/runtime/internal/runtime.Slice" @"{{.*}}/runtime/internal/runtime.StringToRunes"(%"{{.*}}/runtime/internal/runtime.String" { ptr @{{[0-9]+}}, i64 8 }) +// CHECK-NEXT: %3678 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 24) +// CHECK-NEXT: store %"{{.*}}/runtime/internal/runtime.Slice" %3677, ptr %3678, align 8 +// CHECK-NEXT: %3679 = insertvalue %"{{.*}}/runtime/internal/runtime.eface" { ptr @_llgo_main.MyRunes, ptr undef }, ptr %3678, 1 +// CHECK-NEXT: %3680 = extractvalue { ptr, ptr } %3676, 1 +// CHECK-NEXT: %3681 = extractvalue { ptr, ptr } %3676, 0 +// CHECK-NEXT: %__llgo_funcval_code486 = call ptr asm "", "=r,0"(ptr %3681) +// CHECK-NEXT: %3682 = call %reflect.Value %__llgo_funcval_code486(ptr {{(nest|swiftself)}} %3680, %"{{.*}}/runtime/internal/runtime.eface" %3679) +// CHECK-NEXT: %3683 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %3674, i32 0, i32 1 +// CHECK-NEXT: %3684 = load { ptr, ptr }, ptr @main.V, align 8 +// CHECK-NEXT: %3685 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 16) +// CHECK-NEXT: store %"{{.*}}/runtime/internal/runtime.String" { ptr @{{[0-9]+}}, i64 8 }, ptr %3685, align 8 +// CHECK-NEXT: %3686 = insertvalue %"{{.*}}/runtime/internal/runtime.eface" { ptr @_llgo_string, ptr undef }, ptr %3685, 1 +// CHECK-NEXT: %3687 = extractvalue { ptr, ptr } %3684, 1 +// CHECK-NEXT: %3688 = extractvalue { ptr, ptr } %3684, 0 +// CHECK-NEXT: %__llgo_funcval_code487 = call ptr asm "", "=r,0"(ptr %3688) +// CHECK-NEXT: %3689 = call %reflect.Value %__llgo_funcval_code487(ptr {{(nest|swiftself)}} %3687, %"{{.*}}/runtime/internal/runtime.eface" %3686) +// CHECK-NEXT: store %reflect.Value %3682, ptr %3675, align 8 +// CHECK-NEXT: store %reflect.Value %3689, ptr %3683, align 8 +// CHECK-NEXT: %3690 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %1, i64 244 +// CHECK-NEXT: %3691 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %3690, i32 0, i32 0 +// CHECK-NEXT: %3692 = load { ptr, ptr }, ptr @main.V, align 8 +// CHECK-NEXT: %3693 = call %"{{.*}}/runtime/internal/runtime.Slice" @"{{.*}}/runtime/internal/runtime.StringToRunes"(%"{{.*}}/runtime/internal/runtime.String" { ptr @{{[0-9]+}}, i64 17 }) +// CHECK-NEXT: %3694 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 24) +// CHECK-NEXT: store %"{{.*}}/runtime/internal/runtime.Slice" %3693, ptr %3694, align 8 +// CHECK-NEXT: %3695 = insertvalue %"{{.*}}/runtime/internal/runtime.eface" { ptr @_llgo_main.MyRunes, ptr undef }, ptr %3694, 1 +// CHECK-NEXT: %3696 = extractvalue { ptr, ptr } %3692, 1 +// CHECK-NEXT: %3697 = extractvalue { ptr, ptr } %3692, 0 +// CHECK-NEXT: %__llgo_funcval_code488 = call ptr asm "", "=r,0"(ptr %3697) +// CHECK-NEXT: %3698 = call %reflect.Value %__llgo_funcval_code488(ptr {{(nest|swiftself)}} %3696, %"{{.*}}/runtime/internal/runtime.eface" %3695) +// CHECK-NEXT: %3699 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %3690, i32 0, i32 1 +// CHECK-NEXT: %3700 = load { ptr, ptr }, ptr @main.V, align 8 +// CHECK-NEXT: %3701 = call %"{{.*}}/runtime/internal/runtime.Slice" @"{{.*}}/runtime/internal/runtime.StringToRunes"(%"{{.*}}/runtime/internal/runtime.String" { ptr @{{[0-9]+}}, i64 17 }) +// CHECK-NEXT: %3702 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 24) +// CHECK-NEXT: store %"{{.*}}/runtime/internal/runtime.Slice" %3701, ptr %3702, align 8 +// CHECK-NEXT: %3703 = insertvalue %"{{.*}}/runtime/internal/runtime.eface" { ptr @_llgo_main.MyRunes, ptr undef }, ptr %3702, 1 +// CHECK-NEXT: %3704 = extractvalue { ptr, ptr } %3700, 1 +// CHECK-NEXT: %3705 = extractvalue { ptr, ptr } %3700, 0 +// CHECK-NEXT: %__llgo_funcval_code489 = call ptr asm "", "=r,0"(ptr %3705) +// CHECK-NEXT: %3706 = call %reflect.Value %__llgo_funcval_code489(ptr {{(nest|swiftself)}} %3704, %"{{.*}}/runtime/internal/runtime.eface" %3703) +// CHECK-NEXT: store %reflect.Value %3698, ptr %3691, align 8 +// CHECK-NEXT: store %reflect.Value %3706, ptr %3699, align 8 +// CHECK-NEXT: %3707 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %1, i64 245 +// CHECK-NEXT: %3708 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %3707, i32 0, i32 0 +// CHECK-NEXT: %3709 = load { ptr, ptr }, ptr @main.V, align 8 +// CHECK-NEXT: %3710 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 16) +// CHECK-NEXT: store %"{{.*}}/runtime/internal/runtime.String" { ptr @{{[0-9]+}}, i64 8 }, ptr %3710, align 8 +// CHECK-NEXT: %3711 = insertvalue %"{{.*}}/runtime/internal/runtime.eface" { ptr @_llgo_main.MyString, ptr undef }, ptr %3710, 1 +// CHECK-NEXT: %3712 = extractvalue { ptr, ptr } %3709, 1 +// CHECK-NEXT: %3713 = extractvalue { ptr, ptr } %3709, 0 +// CHECK-NEXT: %__llgo_funcval_code490 = call ptr asm "", "=r,0"(ptr %3713) +// CHECK-NEXT: %3714 = call %reflect.Value %__llgo_funcval_code490(ptr {{(nest|swiftself)}} %3712, %"{{.*}}/runtime/internal/runtime.eface" %3711) +// CHECK-NEXT: %3715 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %3707, i32 0, i32 1 +// CHECK-NEXT: %3716 = load { ptr, ptr }, ptr @main.V, align 8 +// CHECK-NEXT: %3717 = call %"{{.*}}/runtime/internal/runtime.Slice" @"{{.*}}/runtime/internal/runtime.StringToRunes"(%"{{.*}}/runtime/internal/runtime.String" { ptr @{{[0-9]+}}, i64 8 }) +// CHECK-NEXT: %3718 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 24) +// CHECK-NEXT: store %"{{.*}}/runtime/internal/runtime.Slice" %3717, ptr %3718, align 8 +// CHECK-NEXT: %3719 = insertvalue %"{{.*}}/runtime/internal/runtime.eface" { ptr @_llgo_main.MyRunes, ptr undef }, ptr %3718, 1 +// CHECK-NEXT: %3720 = extractvalue { ptr, ptr } %3716, 1 +// CHECK-NEXT: %3721 = extractvalue { ptr, ptr } %3716, 0 +// CHECK-NEXT: %__llgo_funcval_code491 = call ptr asm "", "=r,0"(ptr %3721) +// CHECK-NEXT: %3722 = call %reflect.Value %__llgo_funcval_code491(ptr {{(nest|swiftself)}} %3720, %"{{.*}}/runtime/internal/runtime.eface" %3719) +// CHECK-NEXT: store %reflect.Value %3714, ptr %3708, align 8 +// CHECK-NEXT: store %reflect.Value %3722, ptr %3715, align 8 +// CHECK-NEXT: %3723 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %1, i64 246 +// CHECK-NEXT: %3724 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %3723, i32 0, i32 0 +// CHECK-NEXT: %3725 = load { ptr, ptr }, ptr @main.V, align 8 +// CHECK-NEXT: %3726 = call %"{{.*}}/runtime/internal/runtime.Slice" @"{{.*}}/runtime/internal/runtime.StringToRunes"(%"{{.*}}/runtime/internal/runtime.String" { ptr @{{[0-9]+}}, i64 8 }) +// CHECK-NEXT: %3727 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 24) +// CHECK-NEXT: store %"{{.*}}/runtime/internal/runtime.Slice" %3726, ptr %3727, align 8 +// CHECK-NEXT: %3728 = insertvalue %"{{.*}}/runtime/internal/runtime.eface" { ptr @_llgo_main.MyRunes, ptr undef }, ptr %3727, 1 +// CHECK-NEXT: %3729 = extractvalue { ptr, ptr } %3725, 1 +// CHECK-NEXT: %3730 = extractvalue { ptr, ptr } %3725, 0 +// CHECK-NEXT: %__llgo_funcval_code492 = call ptr asm "", "=r,0"(ptr %3730) +// CHECK-NEXT: %3731 = call %reflect.Value %__llgo_funcval_code492(ptr {{(nest|swiftself)}} %3729, %"{{.*}}/runtime/internal/runtime.eface" %3728) +// CHECK-NEXT: %3732 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %3723, i32 0, i32 1 +// CHECK-NEXT: %3733 = load { ptr, ptr }, ptr @main.V, align 8 +// CHECK-NEXT: %3734 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 16) +// CHECK-NEXT: store %"{{.*}}/runtime/internal/runtime.String" { ptr @{{[0-9]+}}, i64 8 }, ptr %3734, align 8 +// CHECK-NEXT: %3735 = insertvalue %"{{.*}}/runtime/internal/runtime.eface" { ptr @_llgo_main.MyString, ptr undef }, ptr %3734, 1 +// CHECK-NEXT: %3736 = extractvalue { ptr, ptr } %3733, 1 +// CHECK-NEXT: %3737 = extractvalue { ptr, ptr } %3733, 0 +// CHECK-NEXT: %__llgo_funcval_code493 = call ptr asm "", "=r,0"(ptr %3737) +// CHECK-NEXT: %3738 = call %reflect.Value %__llgo_funcval_code493(ptr {{(nest|swiftself)}} %3736, %"{{.*}}/runtime/internal/runtime.eface" %3735) +// CHECK-NEXT: store %reflect.Value %3731, ptr %3724, align 8 +// CHECK-NEXT: store %reflect.Value %3738, ptr %3732, align 8 +// CHECK-NEXT: %3739 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %1, i64 247 +// CHECK-NEXT: %3740 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %3739, i32 0, i32 0 +// CHECK-NEXT: %3741 = load { ptr, ptr }, ptr @main.V, align 8 +// CHECK-NEXT: %3742 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 24) +// CHECK-NEXT: store %"{{.*}}/runtime/internal/runtime.Slice" zeroinitializer, ptr %3742, align 8 +// CHECK-NEXT: %3743 = insertvalue %"{{.*}}/runtime/internal/runtime.eface" { ptr @"[]_llgo_uint8", ptr undef }, ptr %3742, 1 +// CHECK-NEXT: %3744 = extractvalue { ptr, ptr } %3741, 1 +// CHECK-NEXT: %3745 = extractvalue { ptr, ptr } %3741, 0 +// CHECK-NEXT: %__llgo_funcval_code494 = call ptr asm "", "=r,0"(ptr %3745) +// CHECK-NEXT: %3746 = call %reflect.Value %__llgo_funcval_code494(ptr {{(nest|swiftself)}} %3744, %"{{.*}}/runtime/internal/runtime.eface" %3743) +// CHECK-NEXT: %3747 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %3739, i32 0, i32 1 +// CHECK-NEXT: %3748 = load { ptr, ptr }, ptr @main.V, align 8 +// CHECK-NEXT: %3749 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 0) +// CHECK-NEXT: store [0 x i8] zeroinitializer, ptr %3749, align 1 +// CHECK-NEXT: %3750 = insertvalue %"{{.*}}/runtime/internal/runtime.eface" { ptr @"[0]_llgo_uint8", ptr undef }, ptr %3749, 1 +// CHECK-NEXT: %3751 = extractvalue { ptr, ptr } %3748, 1 +// CHECK-NEXT: %3752 = extractvalue { ptr, ptr } %3748, 0 +// CHECK-NEXT: %__llgo_funcval_code495 = call ptr asm "", "=r,0"(ptr %3752) +// CHECK-NEXT: %3753 = call %reflect.Value %__llgo_funcval_code495(ptr {{(nest|swiftself)}} %3751, %"{{.*}}/runtime/internal/runtime.eface" %3750) +// CHECK-NEXT: store %reflect.Value %3746, ptr %3740, align 8 +// CHECK-NEXT: store %reflect.Value %3753, ptr %3747, align 8 +// CHECK-NEXT: %3754 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %1, i64 248 +// CHECK-NEXT: %3755 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %3754, i32 0, i32 0 +// CHECK-NEXT: %3756 = load { ptr, ptr }, ptr @main.V, align 8 +// CHECK-NEXT: %3757 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 24) +// CHECK-NEXT: store %"{{.*}}/runtime/internal/runtime.Slice" { ptr @"__llgo.moduleZeroSizedAlloc$", i64 0, i64 0 }, ptr %3757, align 8 +// CHECK-NEXT: %3758 = insertvalue %"{{.*}}/runtime/internal/runtime.eface" { ptr @"[]_llgo_uint8", ptr undef }, ptr %3757, 1 +// CHECK-NEXT: %3759 = extractvalue { ptr, ptr } %3756, 1 +// CHECK-NEXT: %3760 = extractvalue { ptr, ptr } %3756, 0 +// CHECK-NEXT: %__llgo_funcval_code496 = call ptr asm "", "=r,0"(ptr %3760) +// CHECK-NEXT: %3761 = call %reflect.Value %__llgo_funcval_code496(ptr {{(nest|swiftself)}} %3759, %"{{.*}}/runtime/internal/runtime.eface" %3758) +// CHECK-NEXT: %3762 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %3754, i32 0, i32 1 +// CHECK-NEXT: %3763 = load { ptr, ptr }, ptr @main.V, align 8 +// CHECK-NEXT: %3764 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 0) +// CHECK-NEXT: store [0 x i8] zeroinitializer, ptr %3764, align 1 +// CHECK-NEXT: %3765 = insertvalue %"{{.*}}/runtime/internal/runtime.eface" { ptr @"[0]_llgo_uint8", ptr undef }, ptr %3764, 1 +// CHECK-NEXT: %3766 = extractvalue { ptr, ptr } %3763, 1 +// CHECK-NEXT: %3767 = extractvalue { ptr, ptr } %3763, 0 +// CHECK-NEXT: %__llgo_funcval_code497 = call ptr asm "", "=r,0"(ptr %3767) +// CHECK-NEXT: %3768 = call %reflect.Value %__llgo_funcval_code497(ptr {{(nest|swiftself)}} %3766, %"{{.*}}/runtime/internal/runtime.eface" %3765) +// CHECK-NEXT: store %reflect.Value %3761, ptr %3755, align 8 +// CHECK-NEXT: store %reflect.Value %3768, ptr %3762, align 8 +// CHECK-NEXT: %3769 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %1, i64 249 +// CHECK-NEXT: %3770 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %3769, i32 0, i32 0 +// CHECK-NEXT: %3771 = load { ptr, ptr }, ptr @main.V, align 8 +// CHECK-NEXT: %3772 = call ptr @"{{.*}}/runtime/internal/runtime.AllocZ"(i64 1) +// CHECK-NEXT: %3773 = getelementptr inbounds i8, ptr %3772, i64 0 +// CHECK-NEXT: store i8 1, ptr %3773, align 1 +// CHECK-NEXT: %3774 = insertvalue %"{{.*}}/runtime/internal/runtime.Slice" undef, ptr %3772, 0 +// CHECK-NEXT: %3775 = insertvalue %"{{.*}}/runtime/internal/runtime.Slice" %3774, i64 1, 1 +// CHECK-NEXT: %3776 = insertvalue %"{{.*}}/runtime/internal/runtime.Slice" %3775, i64 1, 2 +// CHECK-NEXT: %3777 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 24) +// CHECK-NEXT: store %"{{.*}}/runtime/internal/runtime.Slice" %3776, ptr %3777, align 8 +// CHECK-NEXT: %3778 = insertvalue %"{{.*}}/runtime/internal/runtime.eface" { ptr @"[]_llgo_uint8", ptr undef }, ptr %3777, 1 +// CHECK-NEXT: %3779 = extractvalue { ptr, ptr } %3771, 1 +// CHECK-NEXT: %3780 = extractvalue { ptr, ptr } %3771, 0 +// CHECK-NEXT: %__llgo_funcval_code498 = call ptr asm "", "=r,0"(ptr %3780) +// CHECK-NEXT: %3781 = call %reflect.Value %__llgo_funcval_code498(ptr {{(nest|swiftself)}} %3779, %"{{.*}}/runtime/internal/runtime.eface" %3778) +// CHECK-NEXT: %3782 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %3769, i32 0, i32 1 +// CHECK-NEXT: %3783 = load { ptr, ptr }, ptr @main.V, align 8 +// CHECK-NEXT: %3784 = alloca [1 x i8], align 1 +// CHECK-NEXT: call void @llvm.memset.p0.i64(ptr %3784, i8 0, i64 1, i1 false) +// CHECK-NEXT: %3785 = getelementptr inbounds i8, ptr %3784, i64 0 +// CHECK-NEXT: store i8 1, ptr %3785, align 1 +// CHECK-NEXT: %3786 = load [1 x i8], ptr %3784, align 1 +// CHECK-NEXT: %3787 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 1) +// CHECK-NEXT: store [1 x i8] %3786, ptr %3787, align 1 +// CHECK-NEXT: %3788 = insertvalue %"{{.*}}/runtime/internal/runtime.eface" { ptr @"[1]_llgo_uint8", ptr undef }, ptr %3787, 1 +// CHECK-NEXT: %3789 = extractvalue { ptr, ptr } %3783, 1 +// CHECK-NEXT: %3790 = extractvalue { ptr, ptr } %3783, 0 +// CHECK-NEXT: %__llgo_funcval_code499 = call ptr asm "", "=r,0"(ptr %3790) +// CHECK-NEXT: %3791 = call %reflect.Value %__llgo_funcval_code499(ptr {{(nest|swiftself)}} %3789, %"{{.*}}/runtime/internal/runtime.eface" %3788) +// CHECK-NEXT: store %reflect.Value %3781, ptr %3770, align 8 +// CHECK-NEXT: store %reflect.Value %3791, ptr %3782, align 8 +// CHECK-NEXT: %3792 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %1, i64 250 +// CHECK-NEXT: %3793 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %3792, i32 0, i32 0 +// CHECK-NEXT: %3794 = load { ptr, ptr }, ptr @main.V, align 8 +// CHECK-NEXT: %3795 = call ptr @"{{.*}}/runtime/internal/runtime.AllocZ"(i64 2) +// CHECK-NEXT: %3796 = getelementptr inbounds i8, ptr %3795, i64 0 +// CHECK-NEXT: store i8 1, ptr %3796, align 1 +// CHECK-NEXT: %3797 = getelementptr inbounds i8, ptr %3795, i64 1 +// CHECK-NEXT: store i8 2, ptr %3797, align 1 +// CHECK-NEXT: %3798 = insertvalue %"{{.*}}/runtime/internal/runtime.Slice" undef, ptr %3795, 0 +// CHECK-NEXT: %3799 = insertvalue %"{{.*}}/runtime/internal/runtime.Slice" %3798, i64 2, 1 +// CHECK-NEXT: %3800 = insertvalue %"{{.*}}/runtime/internal/runtime.Slice" %3799, i64 2, 2 +// CHECK-NEXT: %3801 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 24) +// CHECK-NEXT: store %"{{.*}}/runtime/internal/runtime.Slice" %3800, ptr %3801, align 8 +// CHECK-NEXT: %3802 = insertvalue %"{{.*}}/runtime/internal/runtime.eface" { ptr @"[]_llgo_uint8", ptr undef }, ptr %3801, 1 +// CHECK-NEXT: %3803 = extractvalue { ptr, ptr } %3794, 1 +// CHECK-NEXT: %3804 = extractvalue { ptr, ptr } %3794, 0 +// CHECK-NEXT: %__llgo_funcval_code500 = call ptr asm "", "=r,0"(ptr %3804) +// CHECK-NEXT: %3805 = call %reflect.Value %__llgo_funcval_code500(ptr {{(nest|swiftself)}} %3803, %"{{.*}}/runtime/internal/runtime.eface" %3802) +// CHECK-NEXT: %3806 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %3792, i32 0, i32 1 +// CHECK-NEXT: %3807 = load { ptr, ptr }, ptr @main.V, align 8 +// CHECK-NEXT: %3808 = alloca [2 x i8], align 1 +// CHECK-NEXT: call void @llvm.memset.p0.i64(ptr %3808, i8 0, i64 2, i1 false) +// CHECK-NEXT: %3809 = getelementptr inbounds i8, ptr %3808, i64 0 +// CHECK-NEXT: %3810 = getelementptr inbounds i8, ptr %3808, i64 1 +// CHECK-NEXT: store i8 1, ptr %3809, align 1 +// CHECK-NEXT: store i8 2, ptr %3810, align 1 +// CHECK-NEXT: %3811 = load [2 x i8], ptr %3808, align 1 +// CHECK-NEXT: %3812 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 2) +// CHECK-NEXT: store [2 x i8] %3811, ptr %3812, align 1 +// CHECK-NEXT: %3813 = insertvalue %"{{.*}}/runtime/internal/runtime.eface" { ptr @"[2]_llgo_uint8", ptr undef }, ptr %3812, 1 +// CHECK-NEXT: %3814 = extractvalue { ptr, ptr } %3807, 1 +// CHECK-NEXT: %3815 = extractvalue { ptr, ptr } %3807, 0 +// CHECK-NEXT: %__llgo_funcval_code501 = call ptr asm "", "=r,0"(ptr %3815) +// CHECK-NEXT: %3816 = call %reflect.Value %__llgo_funcval_code501(ptr {{(nest|swiftself)}} %3814, %"{{.*}}/runtime/internal/runtime.eface" %3813) +// CHECK-NEXT: store %reflect.Value %3805, ptr %3793, align 8 +// CHECK-NEXT: store %reflect.Value %3816, ptr %3806, align 8 +// CHECK-NEXT: %3817 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %1, i64 251 +// CHECK-NEXT: %3818 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %3817, i32 0, i32 0 +// CHECK-NEXT: %3819 = load { ptr, ptr }, ptr @main.V, align 8 +// CHECK-NEXT: %3820 = call ptr @"{{.*}}/runtime/internal/runtime.AllocZ"(i64 3) +// CHECK-NEXT: %3821 = getelementptr inbounds i8, ptr %3820, i64 0 +// CHECK-NEXT: store i8 1, ptr %3821, align 1 +// CHECK-NEXT: %3822 = getelementptr inbounds i8, ptr %3820, i64 1 +// CHECK-NEXT: store i8 2, ptr %3822, align 1 +// CHECK-NEXT: %3823 = getelementptr inbounds i8, ptr %3820, i64 2 +// CHECK-NEXT: store i8 3, ptr %3823, align 1 +// CHECK-NEXT: %3824 = insertvalue %"{{.*}}/runtime/internal/runtime.Slice" undef, ptr %3820, 0 +// CHECK-NEXT: %3825 = insertvalue %"{{.*}}/runtime/internal/runtime.Slice" %3824, i64 3, 1 +// CHECK-NEXT: %3826 = insertvalue %"{{.*}}/runtime/internal/runtime.Slice" %3825, i64 3, 2 +// CHECK-NEXT: %3827 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 24) +// CHECK-NEXT: store %"{{.*}}/runtime/internal/runtime.Slice" %3826, ptr %3827, align 8 +// CHECK-NEXT: %3828 = insertvalue %"{{.*}}/runtime/internal/runtime.eface" { ptr @"[]_llgo_uint8", ptr undef }, ptr %3827, 1 +// CHECK-NEXT: %3829 = extractvalue { ptr, ptr } %3819, 1 +// CHECK-NEXT: %3830 = extractvalue { ptr, ptr } %3819, 0 +// CHECK-NEXT: %__llgo_funcval_code502 = call ptr asm "", "=r,0"(ptr %3830) +// CHECK-NEXT: %3831 = call %reflect.Value %__llgo_funcval_code502(ptr {{(nest|swiftself)}} %3829, %"{{.*}}/runtime/internal/runtime.eface" %3828) +// CHECK-NEXT: %3832 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %3817, i32 0, i32 1 +// CHECK-NEXT: %3833 = load { ptr, ptr }, ptr @main.V, align 8 +// CHECK-NEXT: %3834 = alloca [3 x i8], align 1 +// CHECK-NEXT: call void @llvm.memset.p0.i64(ptr %3834, i8 0, i64 3, i1 false) +// CHECK-NEXT: %3835 = getelementptr inbounds i8, ptr %3834, i64 0 +// CHECK-NEXT: %3836 = getelementptr inbounds i8, ptr %3834, i64 1 +// CHECK-NEXT: %3837 = getelementptr inbounds i8, ptr %3834, i64 2 +// CHECK-NEXT: store i8 1, ptr %3835, align 1 +// CHECK-NEXT: store i8 2, ptr %3836, align 1 +// CHECK-NEXT: store i8 3, ptr %3837, align 1 +// CHECK-NEXT: %3838 = load [3 x i8], ptr %3834, align 1 +// CHECK-NEXT: %3839 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 3) +// CHECK-NEXT: store [3 x i8] %3838, ptr %3839, align 1 +// CHECK-NEXT: %3840 = insertvalue %"{{.*}}/runtime/internal/runtime.eface" { ptr @"[3]_llgo_uint8", ptr undef }, ptr %3839, 1 +// CHECK-NEXT: %3841 = extractvalue { ptr, ptr } %3833, 1 +// CHECK-NEXT: %3842 = extractvalue { ptr, ptr } %3833, 0 +// CHECK-NEXT: %__llgo_funcval_code503 = call ptr asm "", "=r,0"(ptr %3842) +// CHECK-NEXT: %3843 = call %reflect.Value %__llgo_funcval_code503(ptr {{(nest|swiftself)}} %3841, %"{{.*}}/runtime/internal/runtime.eface" %3840) +// CHECK-NEXT: store %reflect.Value %3831, ptr %3818, align 8 +// CHECK-NEXT: store %reflect.Value %3843, ptr %3832, align 8 +// CHECK-NEXT: %3844 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %1, i64 252 +// CHECK-NEXT: %3845 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %3844, i32 0, i32 0 +// CHECK-NEXT: %3846 = load { ptr, ptr }, ptr @main.V, align 8 +// CHECK-NEXT: %3847 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 24) +// CHECK-NEXT: store %"{{.*}}/runtime/internal/runtime.Slice" zeroinitializer, ptr %3847, align 8 +// CHECK-NEXT: %3848 = insertvalue %"{{.*}}/runtime/internal/runtime.eface" { ptr @_llgo_main.MyBytes, ptr undef }, ptr %3847, 1 +// CHECK-NEXT: %3849 = extractvalue { ptr, ptr } %3846, 1 +// CHECK-NEXT: %3850 = extractvalue { ptr, ptr } %3846, 0 +// CHECK-NEXT: %__llgo_funcval_code504 = call ptr asm "", "=r,0"(ptr %3850) +// CHECK-NEXT: %3851 = call %reflect.Value %__llgo_funcval_code504(ptr {{(nest|swiftself)}} %3849, %"{{.*}}/runtime/internal/runtime.eface" %3848) +// CHECK-NEXT: %3852 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %3844, i32 0, i32 1 +// CHECK-NEXT: %3853 = load { ptr, ptr }, ptr @main.V, align 8 +// CHECK-NEXT: %3854 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 0) +// CHECK-NEXT: store [0 x i8] zeroinitializer, ptr %3854, align 1 +// CHECK-NEXT: %3855 = insertvalue %"{{.*}}/runtime/internal/runtime.eface" { ptr @"[0]_llgo_uint8", ptr undef }, ptr %3854, 1 +// CHECK-NEXT: %3856 = extractvalue { ptr, ptr } %3853, 1 +// CHECK-NEXT: %3857 = extractvalue { ptr, ptr } %3853, 0 +// CHECK-NEXT: %__llgo_funcval_code505 = call ptr asm "", "=r,0"(ptr %3857) +// CHECK-NEXT: %3858 = call %reflect.Value %__llgo_funcval_code505(ptr {{(nest|swiftself)}} %3856, %"{{.*}}/runtime/internal/runtime.eface" %3855) +// CHECK-NEXT: store %reflect.Value %3851, ptr %3845, align 8 +// CHECK-NEXT: store %reflect.Value %3858, ptr %3852, align 8 +// CHECK-NEXT: %3859 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %1, i64 253 +// CHECK-NEXT: %3860 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %3859, i32 0, i32 0 +// CHECK-NEXT: %3861 = load { ptr, ptr }, ptr @main.V, align 8 +// CHECK-NEXT: %3862 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 24) +// CHECK-NEXT: store %"{{.*}}/runtime/internal/runtime.Slice" { ptr @"__llgo.moduleZeroSizedAlloc$", i64 0, i64 0 }, ptr %3862, align 8 +// CHECK-NEXT: %3863 = insertvalue %"{{.*}}/runtime/internal/runtime.eface" { ptr @_llgo_main.MyBytes, ptr undef }, ptr %3862, 1 +// CHECK-NEXT: %3864 = extractvalue { ptr, ptr } %3861, 1 +// CHECK-NEXT: %3865 = extractvalue { ptr, ptr } %3861, 0 +// CHECK-NEXT: %__llgo_funcval_code506 = call ptr asm "", "=r,0"(ptr %3865) +// CHECK-NEXT: %3866 = call %reflect.Value %__llgo_funcval_code506(ptr {{(nest|swiftself)}} %3864, %"{{.*}}/runtime/internal/runtime.eface" %3863) +// CHECK-NEXT: %3867 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %3859, i32 0, i32 1 +// CHECK-NEXT: %3868 = load { ptr, ptr }, ptr @main.V, align 8 +// CHECK-NEXT: %3869 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 0) +// CHECK-NEXT: store [0 x i8] zeroinitializer, ptr %3869, align 1 +// CHECK-NEXT: %3870 = insertvalue %"{{.*}}/runtime/internal/runtime.eface" { ptr @"[0]_llgo_uint8", ptr undef }, ptr %3869, 1 +// CHECK-NEXT: %3871 = extractvalue { ptr, ptr } %3868, 1 +// CHECK-NEXT: %3872 = extractvalue { ptr, ptr } %3868, 0 +// CHECK-NEXT: %__llgo_funcval_code507 = call ptr asm "", "=r,0"(ptr %3872) +// CHECK-NEXT: %3873 = call %reflect.Value %__llgo_funcval_code507(ptr {{(nest|swiftself)}} %3871, %"{{.*}}/runtime/internal/runtime.eface" %3870) +// CHECK-NEXT: store %reflect.Value %3866, ptr %3860, align 8 +// CHECK-NEXT: store %reflect.Value %3873, ptr %3867, align 8 +// CHECK-NEXT: %3874 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %1, i64 254 +// CHECK-NEXT: %3875 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %3874, i32 0, i32 0 +// CHECK-NEXT: %3876 = load { ptr, ptr }, ptr @main.V, align 8 +// CHECK-NEXT: %3877 = call ptr @"{{.*}}/runtime/internal/runtime.AllocZ"(i64 1) +// CHECK-NEXT: %3878 = getelementptr inbounds i8, ptr %3877, i64 0 +// CHECK-NEXT: store i8 1, ptr %3878, align 1 +// CHECK-NEXT: %3879 = insertvalue %"{{.*}}/runtime/internal/runtime.Slice" undef, ptr %3877, 0 +// CHECK-NEXT: %3880 = insertvalue %"{{.*}}/runtime/internal/runtime.Slice" %3879, i64 1, 1 +// CHECK-NEXT: %3881 = insertvalue %"{{.*}}/runtime/internal/runtime.Slice" %3880, i64 1, 2 +// CHECK-NEXT: %3882 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 24) +// CHECK-NEXT: store %"{{.*}}/runtime/internal/runtime.Slice" %3881, ptr %3882, align 8 +// CHECK-NEXT: %3883 = insertvalue %"{{.*}}/runtime/internal/runtime.eface" { ptr @_llgo_main.MyBytes, ptr undef }, ptr %3882, 1 +// CHECK-NEXT: %3884 = extractvalue { ptr, ptr } %3876, 1 +// CHECK-NEXT: %3885 = extractvalue { ptr, ptr } %3876, 0 +// CHECK-NEXT: %__llgo_funcval_code508 = call ptr asm "", "=r,0"(ptr %3885) +// CHECK-NEXT: %3886 = call %reflect.Value %__llgo_funcval_code508(ptr {{(nest|swiftself)}} %3884, %"{{.*}}/runtime/internal/runtime.eface" %3883) +// CHECK-NEXT: %3887 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %3874, i32 0, i32 1 +// CHECK-NEXT: %3888 = load { ptr, ptr }, ptr @main.V, align 8 +// CHECK-NEXT: %3889 = alloca [1 x i8], align 1 +// CHECK-NEXT: call void @llvm.memset.p0.i64(ptr %3889, i8 0, i64 1, i1 false) +// CHECK-NEXT: %3890 = getelementptr inbounds i8, ptr %3889, i64 0 +// CHECK-NEXT: store i8 1, ptr %3890, align 1 +// CHECK-NEXT: %3891 = load [1 x i8], ptr %3889, align 1 +// CHECK-NEXT: %3892 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 1) +// CHECK-NEXT: store [1 x i8] %3891, ptr %3892, align 1 +// CHECK-NEXT: %3893 = insertvalue %"{{.*}}/runtime/internal/runtime.eface" { ptr @"[1]_llgo_uint8", ptr undef }, ptr %3892, 1 +// CHECK-NEXT: %3894 = extractvalue { ptr, ptr } %3888, 1 +// CHECK-NEXT: %3895 = extractvalue { ptr, ptr } %3888, 0 +// CHECK-NEXT: %__llgo_funcval_code509 = call ptr asm "", "=r,0"(ptr %3895) +// CHECK-NEXT: %3896 = call %reflect.Value %__llgo_funcval_code509(ptr {{(nest|swiftself)}} %3894, %"{{.*}}/runtime/internal/runtime.eface" %3893) +// CHECK-NEXT: store %reflect.Value %3886, ptr %3875, align 8 +// CHECK-NEXT: store %reflect.Value %3896, ptr %3887, align 8 +// CHECK-NEXT: %3897 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %1, i64 255 +// CHECK-NEXT: %3898 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %3897, i32 0, i32 0 +// CHECK-NEXT: %3899 = load { ptr, ptr }, ptr @main.V, align 8 +// CHECK-NEXT: %3900 = call ptr @"{{.*}}/runtime/internal/runtime.AllocZ"(i64 2) +// CHECK-NEXT: %3901 = getelementptr inbounds i8, ptr %3900, i64 0 +// CHECK-NEXT: store i8 1, ptr %3901, align 1 +// CHECK-NEXT: %3902 = getelementptr inbounds i8, ptr %3900, i64 1 +// CHECK-NEXT: store i8 2, ptr %3902, align 1 +// CHECK-NEXT: %3903 = insertvalue %"{{.*}}/runtime/internal/runtime.Slice" undef, ptr %3900, 0 +// CHECK-NEXT: %3904 = insertvalue %"{{.*}}/runtime/internal/runtime.Slice" %3903, i64 2, 1 +// CHECK-NEXT: %3905 = insertvalue %"{{.*}}/runtime/internal/runtime.Slice" %3904, i64 2, 2 +// CHECK-NEXT: %3906 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 24) +// CHECK-NEXT: store %"{{.*}}/runtime/internal/runtime.Slice" %3905, ptr %3906, align 8 +// CHECK-NEXT: %3907 = insertvalue %"{{.*}}/runtime/internal/runtime.eface" { ptr @_llgo_main.MyBytes, ptr undef }, ptr %3906, 1 +// CHECK-NEXT: %3908 = extractvalue { ptr, ptr } %3899, 1 +// CHECK-NEXT: %3909 = extractvalue { ptr, ptr } %3899, 0 +// CHECK-NEXT: %__llgo_funcval_code510 = call ptr asm "", "=r,0"(ptr %3909) +// CHECK-NEXT: %3910 = call %reflect.Value %__llgo_funcval_code510(ptr {{(nest|swiftself)}} %3908, %"{{.*}}/runtime/internal/runtime.eface" %3907) +// CHECK-NEXT: %3911 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %3897, i32 0, i32 1 +// CHECK-NEXT: %3912 = load { ptr, ptr }, ptr @main.V, align 8 +// CHECK-NEXT: %3913 = alloca [2 x i8], align 1 +// CHECK-NEXT: call void @llvm.memset.p0.i64(ptr %3913, i8 0, i64 2, i1 false) +// CHECK-NEXT: %3914 = getelementptr inbounds i8, ptr %3913, i64 0 +// CHECK-NEXT: %3915 = getelementptr inbounds i8, ptr %3913, i64 1 +// CHECK-NEXT: store i8 1, ptr %3914, align 1 +// CHECK-NEXT: store i8 2, ptr %3915, align 1 +// CHECK-NEXT: %3916 = load [2 x i8], ptr %3913, align 1 +// CHECK-NEXT: %3917 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 2) +// CHECK-NEXT: store [2 x i8] %3916, ptr %3917, align 1 +// CHECK-NEXT: %3918 = insertvalue %"{{.*}}/runtime/internal/runtime.eface" { ptr @"[2]_llgo_uint8", ptr undef }, ptr %3917, 1 +// CHECK-NEXT: %3919 = extractvalue { ptr, ptr } %3912, 1 +// CHECK-NEXT: %3920 = extractvalue { ptr, ptr } %3912, 0 +// CHECK-NEXT: %__llgo_funcval_code511 = call ptr asm "", "=r,0"(ptr %3920) +// CHECK-NEXT: %3921 = call %reflect.Value %__llgo_funcval_code511(ptr {{(nest|swiftself)}} %3919, %"{{.*}}/runtime/internal/runtime.eface" %3918) +// CHECK-NEXT: store %reflect.Value %3910, ptr %3898, align 8 +// CHECK-NEXT: store %reflect.Value %3921, ptr %3911, align 8 +// CHECK-NEXT: %3922 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %1, i64 256 +// CHECK-NEXT: %3923 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %3922, i32 0, i32 0 +// CHECK-NEXT: %3924 = load { ptr, ptr }, ptr @main.V, align 8 +// CHECK-NEXT: %3925 = call ptr @"{{.*}}/runtime/internal/runtime.AllocZ"(i64 3) +// CHECK-NEXT: %3926 = getelementptr inbounds i8, ptr %3925, i64 0 +// CHECK-NEXT: store i8 1, ptr %3926, align 1 +// CHECK-NEXT: %3927 = getelementptr inbounds i8, ptr %3925, i64 1 +// CHECK-NEXT: store i8 2, ptr %3927, align 1 +// CHECK-NEXT: %3928 = getelementptr inbounds i8, ptr %3925, i64 2 +// CHECK-NEXT: store i8 3, ptr %3928, align 1 +// CHECK-NEXT: %3929 = insertvalue %"{{.*}}/runtime/internal/runtime.Slice" undef, ptr %3925, 0 +// CHECK-NEXT: %3930 = insertvalue %"{{.*}}/runtime/internal/runtime.Slice" %3929, i64 3, 1 +// CHECK-NEXT: %3931 = insertvalue %"{{.*}}/runtime/internal/runtime.Slice" %3930, i64 3, 2 +// CHECK-NEXT: %3932 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 24) +// CHECK-NEXT: store %"{{.*}}/runtime/internal/runtime.Slice" %3931, ptr %3932, align 8 +// CHECK-NEXT: %3933 = insertvalue %"{{.*}}/runtime/internal/runtime.eface" { ptr @_llgo_main.MyBytes, ptr undef }, ptr %3932, 1 +// CHECK-NEXT: %3934 = extractvalue { ptr, ptr } %3924, 1 +// CHECK-NEXT: %3935 = extractvalue { ptr, ptr } %3924, 0 +// CHECK-NEXT: %__llgo_funcval_code512 = call ptr asm "", "=r,0"(ptr %3935) +// CHECK-NEXT: %3936 = call %reflect.Value %__llgo_funcval_code512(ptr {{(nest|swiftself)}} %3934, %"{{.*}}/runtime/internal/runtime.eface" %3933) +// CHECK-NEXT: %3937 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %3922, i32 0, i32 1 +// CHECK-NEXT: %3938 = load { ptr, ptr }, ptr @main.V, align 8 +// CHECK-NEXT: %3939 = alloca [3 x i8], align 1 +// CHECK-NEXT: call void @llvm.memset.p0.i64(ptr %3939, i8 0, i64 3, i1 false) +// CHECK-NEXT: %3940 = getelementptr inbounds i8, ptr %3939, i64 0 +// CHECK-NEXT: %3941 = getelementptr inbounds i8, ptr %3939, i64 1 +// CHECK-NEXT: %3942 = getelementptr inbounds i8, ptr %3939, i64 2 +// CHECK-NEXT: store i8 1, ptr %3940, align 1 +// CHECK-NEXT: store i8 2, ptr %3941, align 1 +// CHECK-NEXT: store i8 3, ptr %3942, align 1 +// CHECK-NEXT: %3943 = load [3 x i8], ptr %3939, align 1 +// CHECK-NEXT: %3944 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 3) +// CHECK-NEXT: store [3 x i8] %3943, ptr %3944, align 1 +// CHECK-NEXT: %3945 = insertvalue %"{{.*}}/runtime/internal/runtime.eface" { ptr @"[3]_llgo_uint8", ptr undef }, ptr %3944, 1 +// CHECK-NEXT: %3946 = extractvalue { ptr, ptr } %3938, 1 +// CHECK-NEXT: %3947 = extractvalue { ptr, ptr } %3938, 0 +// CHECK-NEXT: %__llgo_funcval_code513 = call ptr asm "", "=r,0"(ptr %3947) +// CHECK-NEXT: %3948 = call %reflect.Value %__llgo_funcval_code513(ptr {{(nest|swiftself)}} %3946, %"{{.*}}/runtime/internal/runtime.eface" %3945) +// CHECK-NEXT: store %reflect.Value %3936, ptr %3923, align 8 +// CHECK-NEXT: store %reflect.Value %3948, ptr %3937, align 8 +// CHECK-NEXT: %3949 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %1, i64 257 +// CHECK-NEXT: %3950 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %3949, i32 0, i32 0 +// CHECK-NEXT: %3951 = load { ptr, ptr }, ptr @main.V, align 8 +// CHECK-NEXT: %3952 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 24) +// CHECK-NEXT: store %"{{.*}}/runtime/internal/runtime.Slice" zeroinitializer, ptr %3952, align 8 +// CHECK-NEXT: %3953 = insertvalue %"{{.*}}/runtime/internal/runtime.eface" { ptr @"[]_llgo_uint8", ptr undef }, ptr %3952, 1 +// CHECK-NEXT: %3954 = extractvalue { ptr, ptr } %3951, 1 +// CHECK-NEXT: %3955 = extractvalue { ptr, ptr } %3951, 0 +// CHECK-NEXT: %__llgo_funcval_code514 = call ptr asm "", "=r,0"(ptr %3955) +// CHECK-NEXT: %3956 = call %reflect.Value %__llgo_funcval_code514(ptr {{(nest|swiftself)}} %3954, %"{{.*}}/runtime/internal/runtime.eface" %3953) +// CHECK-NEXT: %3957 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %3949, i32 0, i32 1 +// CHECK-NEXT: %3958 = load { ptr, ptr }, ptr @main.V, align 8 +// CHECK-NEXT: %3959 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 0) +// CHECK-NEXT: store [0 x i8] zeroinitializer, ptr %3959, align 1 +// CHECK-NEXT: %3960 = insertvalue %"{{.*}}/runtime/internal/runtime.eface" { ptr @_llgo_main.MyBytesArray0, ptr undef }, ptr %3959, 1 +// CHECK-NEXT: %3961 = extractvalue { ptr, ptr } %3958, 1 +// CHECK-NEXT: %3962 = extractvalue { ptr, ptr } %3958, 0 +// CHECK-NEXT: %__llgo_funcval_code515 = call ptr asm "", "=r,0"(ptr %3962) +// CHECK-NEXT: %3963 = call %reflect.Value %__llgo_funcval_code515(ptr {{(nest|swiftself)}} %3961, %"{{.*}}/runtime/internal/runtime.eface" %3960) +// CHECK-NEXT: store %reflect.Value %3956, ptr %3950, align 8 +// CHECK-NEXT: store %reflect.Value %3963, ptr %3957, align 8 +// CHECK-NEXT: %3964 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %1, i64 258 +// CHECK-NEXT: %3965 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %3964, i32 0, i32 0 +// CHECK-NEXT: %3966 = load { ptr, ptr }, ptr @main.V, align 8 +// CHECK-NEXT: %3967 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 24) +// CHECK-NEXT: store %"{{.*}}/runtime/internal/runtime.Slice" { ptr @"__llgo.moduleZeroSizedAlloc$", i64 0, i64 0 }, ptr %3967, align 8 +// CHECK-NEXT: %3968 = insertvalue %"{{.*}}/runtime/internal/runtime.eface" { ptr @"[]_llgo_uint8", ptr undef }, ptr %3967, 1 +// CHECK-NEXT: %3969 = extractvalue { ptr, ptr } %3966, 1 +// CHECK-NEXT: %3970 = extractvalue { ptr, ptr } %3966, 0 +// CHECK-NEXT: %__llgo_funcval_code516 = call ptr asm "", "=r,0"(ptr %3970) +// CHECK-NEXT: %3971 = call %reflect.Value %__llgo_funcval_code516(ptr {{(nest|swiftself)}} %3969, %"{{.*}}/runtime/internal/runtime.eface" %3968) +// CHECK-NEXT: %3972 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %3964, i32 0, i32 1 +// CHECK-NEXT: %3973 = load { ptr, ptr }, ptr @main.V, align 8 +// CHECK-NEXT: %3974 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 0) +// CHECK-NEXT: store [0 x i8] zeroinitializer, ptr %3974, align 1 +// CHECK-NEXT: %3975 = insertvalue %"{{.*}}/runtime/internal/runtime.eface" { ptr @_llgo_main.MyBytesArray0, ptr undef }, ptr %3974, 1 +// CHECK-NEXT: %3976 = extractvalue { ptr, ptr } %3973, 1 +// CHECK-NEXT: %3977 = extractvalue { ptr, ptr } %3973, 0 +// CHECK-NEXT: %__llgo_funcval_code517 = call ptr asm "", "=r,0"(ptr %3977) +// CHECK-NEXT: %3978 = call %reflect.Value %__llgo_funcval_code517(ptr {{(nest|swiftself)}} %3976, %"{{.*}}/runtime/internal/runtime.eface" %3975) +// CHECK-NEXT: store %reflect.Value %3971, ptr %3965, align 8 +// CHECK-NEXT: store %reflect.Value %3978, ptr %3972, align 8 +// CHECK-NEXT: %3979 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %1, i64 259 +// CHECK-NEXT: %3980 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %3979, i32 0, i32 0 +// CHECK-NEXT: %3981 = load { ptr, ptr }, ptr @main.V, align 8 +// CHECK-NEXT: %3982 = call ptr @"{{.*}}/runtime/internal/runtime.AllocZ"(i64 4) +// CHECK-NEXT: %3983 = getelementptr inbounds i8, ptr %3982, i64 0 +// CHECK-NEXT: store i8 1, ptr %3983, align 1 +// CHECK-NEXT: %3984 = getelementptr inbounds i8, ptr %3982, i64 1 +// CHECK-NEXT: store i8 2, ptr %3984, align 1 +// CHECK-NEXT: %3985 = getelementptr inbounds i8, ptr %3982, i64 2 +// CHECK-NEXT: store i8 3, ptr %3985, align 1 +// CHECK-NEXT: %3986 = getelementptr inbounds i8, ptr %3982, i64 3 +// CHECK-NEXT: store i8 4, ptr %3986, align 1 +// CHECK-NEXT: %3987 = insertvalue %"{{.*}}/runtime/internal/runtime.Slice" undef, ptr %3982, 0 +// CHECK-NEXT: %3988 = insertvalue %"{{.*}}/runtime/internal/runtime.Slice" %3987, i64 4, 1 +// CHECK-NEXT: %3989 = insertvalue %"{{.*}}/runtime/internal/runtime.Slice" %3988, i64 4, 2 +// CHECK-NEXT: %3990 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 24) +// CHECK-NEXT: store %"{{.*}}/runtime/internal/runtime.Slice" %3989, ptr %3990, align 8 +// CHECK-NEXT: %3991 = insertvalue %"{{.*}}/runtime/internal/runtime.eface" { ptr @"[]_llgo_uint8", ptr undef }, ptr %3990, 1 +// CHECK-NEXT: %3992 = extractvalue { ptr, ptr } %3981, 1 +// CHECK-NEXT: %3993 = extractvalue { ptr, ptr } %3981, 0 +// CHECK-NEXT: %__llgo_funcval_code518 = call ptr asm "", "=r,0"(ptr %3993) +// CHECK-NEXT: %3994 = call %reflect.Value %__llgo_funcval_code518(ptr {{(nest|swiftself)}} %3992, %"{{.*}}/runtime/internal/runtime.eface" %3991) +// CHECK-NEXT: %3995 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %3979, i32 0, i32 1 +// CHECK-NEXT: %3996 = load { ptr, ptr }, ptr @main.V, align 8 +// CHECK-NEXT: %3997 = alloca [4 x i8], align 1 +// CHECK-NEXT: call void @llvm.memset.p0.i64(ptr %3997, i8 0, i64 4, i1 false) +// CHECK-NEXT: %3998 = getelementptr inbounds i8, ptr %3997, i64 0 +// CHECK-NEXT: %3999 = getelementptr inbounds i8, ptr %3997, i64 1 +// CHECK-NEXT: %4000 = getelementptr inbounds i8, ptr %3997, i64 2 +// CHECK-NEXT: %4001 = getelementptr inbounds i8, ptr %3997, i64 3 +// CHECK-NEXT: store i8 1, ptr %3998, align 1 +// CHECK-NEXT: store i8 2, ptr %3999, align 1 +// CHECK-NEXT: store i8 3, ptr %4000, align 1 +// CHECK-NEXT: store i8 4, ptr %4001, align 1 +// CHECK-NEXT: %4002 = load [4 x i8], ptr %3997, align 1 +// CHECK-NEXT: %4003 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 4) +// CHECK-NEXT: store [4 x i8] %4002, ptr %4003, align 1 +// CHECK-NEXT: %4004 = insertvalue %"{{.*}}/runtime/internal/runtime.eface" { ptr @_llgo_main.MyBytesArray, ptr undef }, ptr %4003, 1 +// CHECK-NEXT: %4005 = extractvalue { ptr, ptr } %3996, 1 +// CHECK-NEXT: %4006 = extractvalue { ptr, ptr } %3996, 0 +// CHECK-NEXT: %__llgo_funcval_code519 = call ptr asm "", "=r,0"(ptr %4006) +// CHECK-NEXT: %4007 = call %reflect.Value %__llgo_funcval_code519(ptr {{(nest|swiftself)}} %4005, %"{{.*}}/runtime/internal/runtime.eface" %4004) +// CHECK-NEXT: store %reflect.Value %3994, ptr %3980, align 8 +// CHECK-NEXT: store %reflect.Value %4007, ptr %3995, align 8 +// CHECK-NEXT: %4008 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %1, i64 260 +// CHECK-NEXT: %4009 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %4008, i32 0, i32 0 +// CHECK-NEXT: %4010 = load { ptr, ptr }, ptr @main.V, align 8 +// CHECK-NEXT: %4011 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 24) +// CHECK-NEXT: store %"{{.*}}/runtime/internal/runtime.Slice" { ptr @"__llgo.moduleZeroSizedAlloc$", i64 0, i64 0 }, ptr %4011, align 8 +// CHECK-NEXT: %4012 = insertvalue %"{{.*}}/runtime/internal/runtime.eface" { ptr @_llgo_main.MyBytes, ptr undef }, ptr %4011, 1 +// CHECK-NEXT: %4013 = extractvalue { ptr, ptr } %4010, 1 +// CHECK-NEXT: %4014 = extractvalue { ptr, ptr } %4010, 0 +// CHECK-NEXT: %__llgo_funcval_code520 = call ptr asm "", "=r,0"(ptr %4014) +// CHECK-NEXT: %4015 = call %reflect.Value %__llgo_funcval_code520(ptr {{(nest|swiftself)}} %4013, %"{{.*}}/runtime/internal/runtime.eface" %4012) +// CHECK-NEXT: %4016 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %4008, i32 0, i32 1 +// CHECK-NEXT: %4017 = load { ptr, ptr }, ptr @main.V, align 8 +// CHECK-NEXT: %4018 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 0) +// CHECK-NEXT: store [0 x i8] zeroinitializer, ptr %4018, align 1 +// CHECK-NEXT: %4019 = insertvalue %"{{.*}}/runtime/internal/runtime.eface" { ptr @_llgo_main.MyBytesArray0, ptr undef }, ptr %4018, 1 +// CHECK-NEXT: %4020 = extractvalue { ptr, ptr } %4017, 1 +// CHECK-NEXT: %4021 = extractvalue { ptr, ptr } %4017, 0 +// CHECK-NEXT: %__llgo_funcval_code521 = call ptr asm "", "=r,0"(ptr %4021) +// CHECK-NEXT: %4022 = call %reflect.Value %__llgo_funcval_code521(ptr {{(nest|swiftself)}} %4020, %"{{.*}}/runtime/internal/runtime.eface" %4019) +// CHECK-NEXT: store %reflect.Value %4015, ptr %4009, align 8 +// CHECK-NEXT: store %reflect.Value %4022, ptr %4016, align 8 +// CHECK-NEXT: %4023 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %1, i64 261 +// CHECK-NEXT: %4024 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %4023, i32 0, i32 0 +// CHECK-NEXT: %4025 = load { ptr, ptr }, ptr @main.V, align 8 +// CHECK-NEXT: %4026 = call ptr @"{{.*}}/runtime/internal/runtime.AllocZ"(i64 4) +// CHECK-NEXT: %4027 = getelementptr inbounds i8, ptr %4026, i64 0 +// CHECK-NEXT: store i8 5, ptr %4027, align 1 +// CHECK-NEXT: %4028 = getelementptr inbounds i8, ptr %4026, i64 1 +// CHECK-NEXT: store i8 6, ptr %4028, align 1 +// CHECK-NEXT: %4029 = getelementptr inbounds i8, ptr %4026, i64 2 +// CHECK-NEXT: store i8 7, ptr %4029, align 1 +// CHECK-NEXT: %4030 = getelementptr inbounds i8, ptr %4026, i64 3 +// CHECK-NEXT: store i8 8, ptr %4030, align 1 +// CHECK-NEXT: %4031 = insertvalue %"{{.*}}/runtime/internal/runtime.Slice" undef, ptr %4026, 0 +// CHECK-NEXT: %4032 = insertvalue %"{{.*}}/runtime/internal/runtime.Slice" %4031, i64 4, 1 +// CHECK-NEXT: %4033 = insertvalue %"{{.*}}/runtime/internal/runtime.Slice" %4032, i64 4, 2 +// CHECK-NEXT: %4034 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 24) +// CHECK-NEXT: store %"{{.*}}/runtime/internal/runtime.Slice" %4033, ptr %4034, align 8 +// CHECK-NEXT: %4035 = insertvalue %"{{.*}}/runtime/internal/runtime.eface" { ptr @_llgo_main.MyBytes, ptr undef }, ptr %4034, 1 +// CHECK-NEXT: %4036 = extractvalue { ptr, ptr } %4025, 1 +// CHECK-NEXT: %4037 = extractvalue { ptr, ptr } %4025, 0 +// CHECK-NEXT: %__llgo_funcval_code522 = call ptr asm "", "=r,0"(ptr %4037) +// CHECK-NEXT: %4038 = call %reflect.Value %__llgo_funcval_code522(ptr {{(nest|swiftself)}} %4036, %"{{.*}}/runtime/internal/runtime.eface" %4035) +// CHECK-NEXT: %4039 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %4023, i32 0, i32 1 +// CHECK-NEXT: %4040 = load { ptr, ptr }, ptr @main.V, align 8 +// CHECK-NEXT: %4041 = alloca [4 x i8], align 1 +// CHECK-NEXT: call void @llvm.memset.p0.i64(ptr %4041, i8 0, i64 4, i1 false) +// CHECK-NEXT: %4042 = getelementptr inbounds i8, ptr %4041, i64 0 +// CHECK-NEXT: %4043 = getelementptr inbounds i8, ptr %4041, i64 1 +// CHECK-NEXT: %4044 = getelementptr inbounds i8, ptr %4041, i64 2 +// CHECK-NEXT: %4045 = getelementptr inbounds i8, ptr %4041, i64 3 +// CHECK-NEXT: store i8 5, ptr %4042, align 1 +// CHECK-NEXT: store i8 6, ptr %4043, align 1 +// CHECK-NEXT: store i8 7, ptr %4044, align 1 +// CHECK-NEXT: store i8 8, ptr %4045, align 1 +// CHECK-NEXT: %4046 = load [4 x i8], ptr %4041, align 1 +// CHECK-NEXT: %4047 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 4) +// CHECK-NEXT: store [4 x i8] %4046, ptr %4047, align 1 +// CHECK-NEXT: %4048 = insertvalue %"{{.*}}/runtime/internal/runtime.eface" { ptr @_llgo_main.MyBytesArray, ptr undef }, ptr %4047, 1 +// CHECK-NEXT: %4049 = extractvalue { ptr, ptr } %4040, 1 +// CHECK-NEXT: %4050 = extractvalue { ptr, ptr } %4040, 0 +// CHECK-NEXT: %__llgo_funcval_code523 = call ptr asm "", "=r,0"(ptr %4050) +// CHECK-NEXT: %4051 = call %reflect.Value %__llgo_funcval_code523(ptr {{(nest|swiftself)}} %4049, %"{{.*}}/runtime/internal/runtime.eface" %4048) +// CHECK-NEXT: store %reflect.Value %4038, ptr %4024, align 8 +// CHECK-NEXT: store %reflect.Value %4051, ptr %4039, align 8 +// CHECK-NEXT: %4052 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %1, i64 262 +// CHECK-NEXT: %4053 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %4052, i32 0, i32 0 +// CHECK-NEXT: %4054 = load { ptr, ptr }, ptr @main.V, align 8 +// CHECK-NEXT: %4055 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 24) +// CHECK-NEXT: store %"{{.*}}/runtime/internal/runtime.Slice" { ptr @"__llgo.moduleZeroSizedAlloc$", i64 0, i64 0 }, ptr %4055, align 8 +// CHECK-NEXT: %4056 = insertvalue %"{{.*}}/runtime/internal/runtime.eface" { ptr @"[]_llgo_main.MyByte", ptr undef }, ptr %4055, 1 +// CHECK-NEXT: %4057 = extractvalue { ptr, ptr } %4054, 1 +// CHECK-NEXT: %4058 = extractvalue { ptr, ptr } %4054, 0 +// CHECK-NEXT: %__llgo_funcval_code524 = call ptr asm "", "=r,0"(ptr %4058) +// CHECK-NEXT: %4059 = call %reflect.Value %__llgo_funcval_code524(ptr {{(nest|swiftself)}} %4057, %"{{.*}}/runtime/internal/runtime.eface" %4056) +// CHECK-NEXT: %4060 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %4052, i32 0, i32 1 +// CHECK-NEXT: %4061 = load { ptr, ptr }, ptr @main.V, align 8 +// CHECK-NEXT: %4062 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 0) +// CHECK-NEXT: store [0 x i8] zeroinitializer, ptr %4062, align 1 +// CHECK-NEXT: %4063 = insertvalue %"{{.*}}/runtime/internal/runtime.eface" { ptr @"[0]_llgo_main.MyByte", ptr undef }, ptr %4062, 1 +// CHECK-NEXT: %4064 = extractvalue { ptr, ptr } %4061, 1 +// CHECK-NEXT: %4065 = extractvalue { ptr, ptr } %4061, 0 +// CHECK-NEXT: %__llgo_funcval_code525 = call ptr asm "", "=r,0"(ptr %4065) +// CHECK-NEXT: %4066 = call %reflect.Value %__llgo_funcval_code525(ptr {{(nest|swiftself)}} %4064, %"{{.*}}/runtime/internal/runtime.eface" %4063) +// CHECK-NEXT: store %reflect.Value %4059, ptr %4053, align 8 +// CHECK-NEXT: store %reflect.Value %4066, ptr %4060, align 8 +// CHECK-NEXT: %4067 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %1, i64 263 +// CHECK-NEXT: %4068 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %4067, i32 0, i32 0 +// CHECK-NEXT: %4069 = load { ptr, ptr }, ptr @main.V, align 8 +// CHECK-NEXT: %4070 = call ptr @"{{.*}}/runtime/internal/runtime.AllocZ"(i64 2) +// CHECK-NEXT: %4071 = getelementptr inbounds i8, ptr %4070, i64 0 +// CHECK-NEXT: store i8 1, ptr %4071, align 1 +// CHECK-NEXT: %4072 = getelementptr inbounds i8, ptr %4070, i64 1 +// CHECK-NEXT: store i8 2, ptr %4072, align 1 +// CHECK-NEXT: %4073 = insertvalue %"{{.*}}/runtime/internal/runtime.Slice" undef, ptr %4070, 0 +// CHECK-NEXT: %4074 = insertvalue %"{{.*}}/runtime/internal/runtime.Slice" %4073, i64 2, 1 +// CHECK-NEXT: %4075 = insertvalue %"{{.*}}/runtime/internal/runtime.Slice" %4074, i64 2, 2 +// CHECK-NEXT: %4076 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 24) +// CHECK-NEXT: store %"{{.*}}/runtime/internal/runtime.Slice" %4075, ptr %4076, align 8 +// CHECK-NEXT: %4077 = insertvalue %"{{.*}}/runtime/internal/runtime.eface" { ptr @"[]_llgo_main.MyByte", ptr undef }, ptr %4076, 1 +// CHECK-NEXT: %4078 = extractvalue { ptr, ptr } %4069, 1 +// CHECK-NEXT: %4079 = extractvalue { ptr, ptr } %4069, 0 +// CHECK-NEXT: %__llgo_funcval_code526 = call ptr asm "", "=r,0"(ptr %4079) +// CHECK-NEXT: %4080 = call %reflect.Value %__llgo_funcval_code526(ptr {{(nest|swiftself)}} %4078, %"{{.*}}/runtime/internal/runtime.eface" %4077) +// CHECK-NEXT: %4081 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %4067, i32 0, i32 1 +// CHECK-NEXT: %4082 = load { ptr, ptr }, ptr @main.V, align 8 +// CHECK-NEXT: %4083 = alloca [2 x i8], align 1 +// CHECK-NEXT: call void @llvm.memset.p0.i64(ptr %4083, i8 0, i64 2, i1 false) +// CHECK-NEXT: %4084 = getelementptr inbounds i8, ptr %4083, i64 0 +// CHECK-NEXT: %4085 = getelementptr inbounds i8, ptr %4083, i64 1 +// CHECK-NEXT: store i8 1, ptr %4084, align 1 +// CHECK-NEXT: store i8 2, ptr %4085, align 1 +// CHECK-NEXT: %4086 = load [2 x i8], ptr %4083, align 1 +// CHECK-NEXT: %4087 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 2) +// CHECK-NEXT: store [2 x i8] %4086, ptr %4087, align 1 +// CHECK-NEXT: %4088 = insertvalue %"{{.*}}/runtime/internal/runtime.eface" { ptr @"[2]_llgo_main.MyByte", ptr undef }, ptr %4087, 1 +// CHECK-NEXT: %4089 = extractvalue { ptr, ptr } %4082, 1 +// CHECK-NEXT: %4090 = extractvalue { ptr, ptr } %4082, 0 +// CHECK-NEXT: %__llgo_funcval_code527 = call ptr asm "", "=r,0"(ptr %4090) +// CHECK-NEXT: %4091 = call %reflect.Value %__llgo_funcval_code527(ptr {{(nest|swiftself)}} %4089, %"{{.*}}/runtime/internal/runtime.eface" %4088) +// CHECK-NEXT: store %reflect.Value %4080, ptr %4068, align 8 +// CHECK-NEXT: store %reflect.Value %4091, ptr %4081, align 8 +// CHECK-NEXT: %4092 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %1, i64 264 +// CHECK-NEXT: %4093 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %4092, i32 0, i32 0 +// CHECK-NEXT: %4094 = load { ptr, ptr }, ptr @main.V, align 8 +// CHECK-NEXT: %4095 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 24) +// CHECK-NEXT: store %"{{.*}}/runtime/internal/runtime.Slice" zeroinitializer, ptr %4095, align 8 +// CHECK-NEXT: %4096 = insertvalue %"{{.*}}/runtime/internal/runtime.eface" { ptr @"[]_llgo_uint8", ptr undef }, ptr %4095, 1 +// CHECK-NEXT: %4097 = extractvalue { ptr, ptr } %4094, 1 +// CHECK-NEXT: %4098 = extractvalue { ptr, ptr } %4094, 0 +// CHECK-NEXT: %__llgo_funcval_code528 = call ptr asm "", "=r,0"(ptr %4098) +// CHECK-NEXT: %4099 = call %reflect.Value %__llgo_funcval_code528(ptr {{(nest|swiftself)}} %4097, %"{{.*}}/runtime/internal/runtime.eface" %4096) +// CHECK-NEXT: %4100 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %4092, i32 0, i32 1 +// CHECK-NEXT: %4101 = load { ptr, ptr }, ptr @main.V, align 8 +// CHECK-NEXT: %4102 = extractvalue { ptr, ptr } %4101, 1 +// CHECK-NEXT: %4103 = extractvalue { ptr, ptr } %4101, 0 +// CHECK-NEXT: %__llgo_funcval_code529 = call ptr asm "", "=r,0"(ptr %4103) +// CHECK-NEXT: %4104 = call %reflect.Value %__llgo_funcval_code529(ptr {{(nest|swiftself)}} %4102, %"{{.*}}/runtime/internal/runtime.eface" { ptr @"*[0]_llgo_uint8", ptr null }) +// CHECK-NEXT: store %reflect.Value %4099, ptr %4093, align 8 +// CHECK-NEXT: store %reflect.Value %4104, ptr %4100, align 8 +// CHECK-NEXT: %4105 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %1, i64 265 +// CHECK-NEXT: %4106 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %4105, i32 0, i32 0 +// CHECK-NEXT: %4107 = load { ptr, ptr }, ptr @main.V, align 8 +// CHECK-NEXT: %4108 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 24) +// CHECK-NEXT: store %"{{.*}}/runtime/internal/runtime.Slice" { ptr @"__llgo.moduleZeroSizedAlloc$", i64 0, i64 0 }, ptr %4108, align 8 +// CHECK-NEXT: %4109 = insertvalue %"{{.*}}/runtime/internal/runtime.eface" { ptr @"[]_llgo_uint8", ptr undef }, ptr %4108, 1 +// CHECK-NEXT: %4110 = extractvalue { ptr, ptr } %4107, 1 +// CHECK-NEXT: %4111 = extractvalue { ptr, ptr } %4107, 0 +// CHECK-NEXT: %__llgo_funcval_code530 = call ptr asm "", "=r,0"(ptr %4111) +// CHECK-NEXT: %4112 = call %reflect.Value %__llgo_funcval_code530(ptr {{(nest|swiftself)}} %4110, %"{{.*}}/runtime/internal/runtime.eface" %4109) +// CHECK-NEXT: %4113 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %4105, i32 0, i32 1 +// CHECK-NEXT: %4114 = load { ptr, ptr }, ptr @main.V, align 8 +// CHECK-NEXT: %4115 = extractvalue { ptr, ptr } %4114, 1 +// CHECK-NEXT: %4116 = extractvalue { ptr, ptr } %4114, 0 +// CHECK-NEXT: %__llgo_funcval_code531 = call ptr asm "", "=r,0"(ptr %4116) +// CHECK-NEXT: %4117 = call %reflect.Value %__llgo_funcval_code531(ptr {{(nest|swiftself)}} %4115, %"{{.*}}/runtime/internal/runtime.eface" { ptr @"*[0]_llgo_uint8", ptr @"__llgo.moduleZeroSizedAlloc$" }) +// CHECK-NEXT: store %reflect.Value %4112, ptr %4106, align 8 +// CHECK-NEXT: store %reflect.Value %4117, ptr %4113, align 8 +// CHECK-NEXT: %4118 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %1, i64 266 +// CHECK-NEXT: %4119 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %4118, i32 0, i32 0 +// CHECK-NEXT: %4120 = load { ptr, ptr }, ptr @main.V, align 8 +// CHECK-NEXT: %4121 = call ptr @"{{.*}}/runtime/internal/runtime.AllocZ"(i64 1) +// CHECK-NEXT: %4122 = getelementptr inbounds i8, ptr %4121, i64 0 +// CHECK-NEXT: store i8 7, ptr %4122, align 1 +// CHECK-NEXT: %4123 = insertvalue %"{{.*}}/runtime/internal/runtime.Slice" undef, ptr %4121, 0 +// CHECK-NEXT: %4124 = insertvalue %"{{.*}}/runtime/internal/runtime.Slice" %4123, i64 1, 1 +// CHECK-NEXT: %4125 = insertvalue %"{{.*}}/runtime/internal/runtime.Slice" %4124, i64 1, 2 +// CHECK-NEXT: %4126 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 24) +// CHECK-NEXT: store %"{{.*}}/runtime/internal/runtime.Slice" %4125, ptr %4126, align 8 +// CHECK-NEXT: %4127 = insertvalue %"{{.*}}/runtime/internal/runtime.eface" { ptr @"[]_llgo_uint8", ptr undef }, ptr %4126, 1 +// CHECK-NEXT: %4128 = extractvalue { ptr, ptr } %4120, 1 +// CHECK-NEXT: %4129 = extractvalue { ptr, ptr } %4120, 0 +// CHECK-NEXT: %__llgo_funcval_code532 = call ptr asm "", "=r,0"(ptr %4129) +// CHECK-NEXT: %4130 = call %reflect.Value %__llgo_funcval_code532(ptr {{(nest|swiftself)}} %4128, %"{{.*}}/runtime/internal/runtime.eface" %4127) +// CHECK-NEXT: %4131 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %4118, i32 0, i32 1 +// CHECK-NEXT: %4132 = load { ptr, ptr }, ptr @main.V, align 8 +// CHECK-NEXT: %4133 = call ptr @"{{.*}}/runtime/internal/runtime.AllocZ"(i64 1) +// CHECK-NEXT: %4134 = getelementptr inbounds i8, ptr %4133, i64 0 +// CHECK-NEXT: store i8 7, ptr %4134, align 1 +// CHECK-NEXT: %4135 = insertvalue %"{{.*}}/runtime/internal/runtime.eface" { ptr @"*[1]_llgo_uint8", ptr undef }, ptr %4133, 1 +// CHECK-NEXT: %4136 = extractvalue { ptr, ptr } %4132, 1 +// CHECK-NEXT: %4137 = extractvalue { ptr, ptr } %4132, 0 +// CHECK-NEXT: %__llgo_funcval_code533 = call ptr asm "", "=r,0"(ptr %4137) +// CHECK-NEXT: %4138 = call %reflect.Value %__llgo_funcval_code533(ptr {{(nest|swiftself)}} %4136, %"{{.*}}/runtime/internal/runtime.eface" %4135) +// CHECK-NEXT: store %reflect.Value %4130, ptr %4119, align 8 +// CHECK-NEXT: store %reflect.Value %4138, ptr %4131, align 8 +// CHECK-NEXT: %4139 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %1, i64 267 +// CHECK-NEXT: %4140 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %4139, i32 0, i32 0 +// CHECK-NEXT: %4141 = load { ptr, ptr }, ptr @main.V, align 8 +// CHECK-NEXT: %4142 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 24) +// CHECK-NEXT: store %"{{.*}}/runtime/internal/runtime.Slice" zeroinitializer, ptr %4142, align 8 +// CHECK-NEXT: %4143 = insertvalue %"{{.*}}/runtime/internal/runtime.eface" { ptr @_llgo_main.MyBytes, ptr undef }, ptr %4142, 1 +// CHECK-NEXT: %4144 = extractvalue { ptr, ptr } %4141, 1 +// CHECK-NEXT: %4145 = extractvalue { ptr, ptr } %4141, 0 +// CHECK-NEXT: %__llgo_funcval_code534 = call ptr asm "", "=r,0"(ptr %4145) +// CHECK-NEXT: %4146 = call %reflect.Value %__llgo_funcval_code534(ptr {{(nest|swiftself)}} %4144, %"{{.*}}/runtime/internal/runtime.eface" %4143) +// CHECK-NEXT: %4147 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %4139, i32 0, i32 1 +// CHECK-NEXT: %4148 = load { ptr, ptr }, ptr @main.V, align 8 +// CHECK-NEXT: %4149 = extractvalue { ptr, ptr } %4148, 1 +// CHECK-NEXT: %4150 = extractvalue { ptr, ptr } %4148, 0 +// CHECK-NEXT: %__llgo_funcval_code535 = call ptr asm "", "=r,0"(ptr %4150) +// CHECK-NEXT: %4151 = call %reflect.Value %__llgo_funcval_code535(ptr {{(nest|swiftself)}} %4149, %"{{.*}}/runtime/internal/runtime.eface" { ptr @"*[0]_llgo_uint8", ptr null }) +// CHECK-NEXT: store %reflect.Value %4146, ptr %4140, align 8 +// CHECK-NEXT: store %reflect.Value %4151, ptr %4147, align 8 +// CHECK-NEXT: %4152 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %1, i64 268 +// CHECK-NEXT: %4153 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %4152, i32 0, i32 0 +// CHECK-NEXT: %4154 = load { ptr, ptr }, ptr @main.V, align 8 +// CHECK-NEXT: %4155 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 24) +// CHECK-NEXT: store %"{{.*}}/runtime/internal/runtime.Slice" { ptr @"__llgo.moduleZeroSizedAlloc$", i64 0, i64 0 }, ptr %4155, align 8 +// CHECK-NEXT: %4156 = insertvalue %"{{.*}}/runtime/internal/runtime.eface" { ptr @_llgo_main.MyBytes, ptr undef }, ptr %4155, 1 +// CHECK-NEXT: %4157 = extractvalue { ptr, ptr } %4154, 1 +// CHECK-NEXT: %4158 = extractvalue { ptr, ptr } %4154, 0 +// CHECK-NEXT: %__llgo_funcval_code536 = call ptr asm "", "=r,0"(ptr %4158) +// CHECK-NEXT: %4159 = call %reflect.Value %__llgo_funcval_code536(ptr {{(nest|swiftself)}} %4157, %"{{.*}}/runtime/internal/runtime.eface" %4156) +// CHECK-NEXT: %4160 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %4152, i32 0, i32 1 +// CHECK-NEXT: %4161 = load { ptr, ptr }, ptr @main.V, align 8 +// CHECK-NEXT: %4162 = extractvalue { ptr, ptr } %4161, 1 +// CHECK-NEXT: %4163 = extractvalue { ptr, ptr } %4161, 0 +// CHECK-NEXT: %__llgo_funcval_code537 = call ptr asm "", "=r,0"(ptr %4163) +// CHECK-NEXT: %4164 = call %reflect.Value %__llgo_funcval_code537(ptr {{(nest|swiftself)}} %4162, %"{{.*}}/runtime/internal/runtime.eface" { ptr @"*[0]_llgo_uint8", ptr @"__llgo.moduleZeroSizedAlloc$" }) +// CHECK-NEXT: store %reflect.Value %4159, ptr %4153, align 8 +// CHECK-NEXT: store %reflect.Value %4164, ptr %4160, align 8 +// CHECK-NEXT: %4165 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %1, i64 269 +// CHECK-NEXT: %4166 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %4165, i32 0, i32 0 +// CHECK-NEXT: %4167 = load { ptr, ptr }, ptr @main.V, align 8 +// CHECK-NEXT: %4168 = call ptr @"{{.*}}/runtime/internal/runtime.AllocZ"(i64 1) +// CHECK-NEXT: %4169 = getelementptr inbounds i8, ptr %4168, i64 0 +// CHECK-NEXT: store i8 9, ptr %4169, align 1 +// CHECK-NEXT: %4170 = insertvalue %"{{.*}}/runtime/internal/runtime.Slice" undef, ptr %4168, 0 +// CHECK-NEXT: %4171 = insertvalue %"{{.*}}/runtime/internal/runtime.Slice" %4170, i64 1, 1 +// CHECK-NEXT: %4172 = insertvalue %"{{.*}}/runtime/internal/runtime.Slice" %4171, i64 1, 2 +// CHECK-NEXT: %4173 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 24) +// CHECK-NEXT: store %"{{.*}}/runtime/internal/runtime.Slice" %4172, ptr %4173, align 8 +// CHECK-NEXT: %4174 = insertvalue %"{{.*}}/runtime/internal/runtime.eface" { ptr @_llgo_main.MyBytes, ptr undef }, ptr %4173, 1 +// CHECK-NEXT: %4175 = extractvalue { ptr, ptr } %4167, 1 +// CHECK-NEXT: %4176 = extractvalue { ptr, ptr } %4167, 0 +// CHECK-NEXT: %__llgo_funcval_code538 = call ptr asm "", "=r,0"(ptr %4176) +// CHECK-NEXT: %4177 = call %reflect.Value %__llgo_funcval_code538(ptr {{(nest|swiftself)}} %4175, %"{{.*}}/runtime/internal/runtime.eface" %4174) +// CHECK-NEXT: %4178 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %4165, i32 0, i32 1 +// CHECK-NEXT: %4179 = load { ptr, ptr }, ptr @main.V, align 8 +// CHECK-NEXT: %4180 = call ptr @"{{.*}}/runtime/internal/runtime.AllocZ"(i64 1) +// CHECK-NEXT: %4181 = getelementptr inbounds i8, ptr %4180, i64 0 +// CHECK-NEXT: store i8 9, ptr %4181, align 1 +// CHECK-NEXT: %4182 = insertvalue %"{{.*}}/runtime/internal/runtime.eface" { ptr @"*[1]_llgo_uint8", ptr undef }, ptr %4180, 1 +// CHECK-NEXT: %4183 = extractvalue { ptr, ptr } %4179, 1 +// CHECK-NEXT: %4184 = extractvalue { ptr, ptr } %4179, 0 +// CHECK-NEXT: %__llgo_funcval_code539 = call ptr asm "", "=r,0"(ptr %4184) +// CHECK-NEXT: %4185 = call %reflect.Value %__llgo_funcval_code539(ptr {{(nest|swiftself)}} %4183, %"{{.*}}/runtime/internal/runtime.eface" %4182) +// CHECK-NEXT: store %reflect.Value %4177, ptr %4166, align 8 +// CHECK-NEXT: store %reflect.Value %4185, ptr %4178, align 8 +// CHECK-NEXT: %4186 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %1, i64 270 +// CHECK-NEXT: %4187 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %4186, i32 0, i32 0 +// CHECK-NEXT: %4188 = load { ptr, ptr }, ptr @main.V, align 8 +// CHECK-NEXT: %4189 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 24) +// CHECK-NEXT: store %"{{.*}}/runtime/internal/runtime.Slice" zeroinitializer, ptr %4189, align 8 +// CHECK-NEXT: %4190 = insertvalue %"{{.*}}/runtime/internal/runtime.eface" { ptr @"[]_llgo_uint8", ptr undef }, ptr %4189, 1 +// CHECK-NEXT: %4191 = extractvalue { ptr, ptr } %4188, 1 +// CHECK-NEXT: %4192 = extractvalue { ptr, ptr } %4188, 0 +// CHECK-NEXT: %__llgo_funcval_code540 = call ptr asm "", "=r,0"(ptr %4192) +// CHECK-NEXT: %4193 = call %reflect.Value %__llgo_funcval_code540(ptr {{(nest|swiftself)}} %4191, %"{{.*}}/runtime/internal/runtime.eface" %4190) +// CHECK-NEXT: %4194 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %4186, i32 0, i32 1 +// CHECK-NEXT: %4195 = load { ptr, ptr }, ptr @main.V, align 8 +// CHECK-NEXT: %4196 = extractvalue { ptr, ptr } %4195, 1 +// CHECK-NEXT: %4197 = extractvalue { ptr, ptr } %4195, 0 +// CHECK-NEXT: %__llgo_funcval_code541 = call ptr asm "", "=r,0"(ptr %4197) +// CHECK-NEXT: %4198 = call %reflect.Value %__llgo_funcval_code541(ptr {{(nest|swiftself)}} %4196, %"{{.*}}/runtime/internal/runtime.eface" { ptr @_llgo_main.MyBytesArrayPtr0, ptr null }) +// CHECK-NEXT: store %reflect.Value %4193, ptr %4187, align 8 +// CHECK-NEXT: store %reflect.Value %4198, ptr %4194, align 8 +// CHECK-NEXT: %4199 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %1, i64 271 +// CHECK-NEXT: %4200 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %4199, i32 0, i32 0 +// CHECK-NEXT: %4201 = load { ptr, ptr }, ptr @main.V, align 8 +// CHECK-NEXT: %4202 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 24) +// CHECK-NEXT: store %"{{.*}}/runtime/internal/runtime.Slice" { ptr @"__llgo.moduleZeroSizedAlloc$", i64 0, i64 0 }, ptr %4202, align 8 +// CHECK-NEXT: %4203 = insertvalue %"{{.*}}/runtime/internal/runtime.eface" { ptr @"[]_llgo_uint8", ptr undef }, ptr %4202, 1 +// CHECK-NEXT: %4204 = extractvalue { ptr, ptr } %4201, 1 +// CHECK-NEXT: %4205 = extractvalue { ptr, ptr } %4201, 0 +// CHECK-NEXT: %__llgo_funcval_code542 = call ptr asm "", "=r,0"(ptr %4205) +// CHECK-NEXT: %4206 = call %reflect.Value %__llgo_funcval_code542(ptr {{(nest|swiftself)}} %4204, %"{{.*}}/runtime/internal/runtime.eface" %4203) +// CHECK-NEXT: %4207 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %4199, i32 0, i32 1 +// CHECK-NEXT: %4208 = load { ptr, ptr }, ptr @main.V, align 8 +// CHECK-NEXT: %4209 = extractvalue { ptr, ptr } %4208, 1 +// CHECK-NEXT: %4210 = extractvalue { ptr, ptr } %4208, 0 +// CHECK-NEXT: %__llgo_funcval_code543 = call ptr asm "", "=r,0"(ptr %4210) +// CHECK-NEXT: %4211 = call %reflect.Value %__llgo_funcval_code543(ptr {{(nest|swiftself)}} %4209, %"{{.*}}/runtime/internal/runtime.eface" { ptr @_llgo_main.MyBytesArrayPtr0, ptr @"__llgo.moduleZeroSizedAlloc$" }) +// CHECK-NEXT: store %reflect.Value %4206, ptr %4200, align 8 +// CHECK-NEXT: store %reflect.Value %4211, ptr %4207, align 8 +// CHECK-NEXT: %4212 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %1, i64 272 +// CHECK-NEXT: %4213 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %4212, i32 0, i32 0 +// CHECK-NEXT: %4214 = load { ptr, ptr }, ptr @main.V, align 8 +// CHECK-NEXT: %4215 = call ptr @"{{.*}}/runtime/internal/runtime.AllocZ"(i64 4) +// CHECK-NEXT: %4216 = getelementptr inbounds i8, ptr %4215, i64 0 +// CHECK-NEXT: store i8 1, ptr %4216, align 1 +// CHECK-NEXT: %4217 = getelementptr inbounds i8, ptr %4215, i64 1 +// CHECK-NEXT: store i8 2, ptr %4217, align 1 +// CHECK-NEXT: %4218 = getelementptr inbounds i8, ptr %4215, i64 2 +// CHECK-NEXT: store i8 3, ptr %4218, align 1 +// CHECK-NEXT: %4219 = getelementptr inbounds i8, ptr %4215, i64 3 +// CHECK-NEXT: store i8 4, ptr %4219, align 1 +// CHECK-NEXT: %4220 = insertvalue %"{{.*}}/runtime/internal/runtime.Slice" undef, ptr %4215, 0 +// CHECK-NEXT: %4221 = insertvalue %"{{.*}}/runtime/internal/runtime.Slice" %4220, i64 4, 1 +// CHECK-NEXT: %4222 = insertvalue %"{{.*}}/runtime/internal/runtime.Slice" %4221, i64 4, 2 +// CHECK-NEXT: %4223 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 24) +// CHECK-NEXT: store %"{{.*}}/runtime/internal/runtime.Slice" %4222, ptr %4223, align 8 +// CHECK-NEXT: %4224 = insertvalue %"{{.*}}/runtime/internal/runtime.eface" { ptr @"[]_llgo_uint8", ptr undef }, ptr %4223, 1 +// CHECK-NEXT: %4225 = extractvalue { ptr, ptr } %4214, 1 +// CHECK-NEXT: %4226 = extractvalue { ptr, ptr } %4214, 0 +// CHECK-NEXT: %__llgo_funcval_code544 = call ptr asm "", "=r,0"(ptr %4226) +// CHECK-NEXT: %4227 = call %reflect.Value %__llgo_funcval_code544(ptr {{(nest|swiftself)}} %4225, %"{{.*}}/runtime/internal/runtime.eface" %4224) +// CHECK-NEXT: %4228 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %4212, i32 0, i32 1 +// CHECK-NEXT: %4229 = load { ptr, ptr }, ptr @main.V, align 8 +// CHECK-NEXT: %4230 = call ptr @"{{.*}}/runtime/internal/runtime.AllocZ"(i64 4) +// CHECK-NEXT: %4231 = getelementptr inbounds i8, ptr %4230, i64 0 +// CHECK-NEXT: %4232 = getelementptr inbounds i8, ptr %4230, i64 1 +// CHECK-NEXT: %4233 = getelementptr inbounds i8, ptr %4230, i64 2 +// CHECK-NEXT: %4234 = getelementptr inbounds i8, ptr %4230, i64 3 +// CHECK-NEXT: store i8 1, ptr %4231, align 1 +// CHECK-NEXT: store i8 2, ptr %4232, align 1 +// CHECK-NEXT: store i8 3, ptr %4233, align 1 +// CHECK-NEXT: store i8 4, ptr %4234, align 1 +// CHECK-NEXT: %4235 = insertvalue %"{{.*}}/runtime/internal/runtime.eface" { ptr @_llgo_main.MyBytesArrayPtr, ptr undef }, ptr %4230, 1 +// CHECK-NEXT: %4236 = extractvalue { ptr, ptr } %4229, 1 +// CHECK-NEXT: %4237 = extractvalue { ptr, ptr } %4229, 0 +// CHECK-NEXT: %__llgo_funcval_code545 = call ptr asm "", "=r,0"(ptr %4237) +// CHECK-NEXT: %4238 = call %reflect.Value %__llgo_funcval_code545(ptr {{(nest|swiftself)}} %4236, %"{{.*}}/runtime/internal/runtime.eface" %4235) +// CHECK-NEXT: store %reflect.Value %4227, ptr %4213, align 8 +// CHECK-NEXT: store %reflect.Value %4238, ptr %4228, align 8 +// CHECK-NEXT: %4239 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %1, i64 273 +// CHECK-NEXT: %4240 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %4239, i32 0, i32 0 +// CHECK-NEXT: %4241 = load { ptr, ptr }, ptr @main.V, align 8 +// CHECK-NEXT: %4242 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 24) +// CHECK-NEXT: store %"{{.*}}/runtime/internal/runtime.Slice" { ptr @"__llgo.moduleZeroSizedAlloc$", i64 0, i64 0 }, ptr %4242, align 8 +// CHECK-NEXT: %4243 = insertvalue %"{{.*}}/runtime/internal/runtime.eface" { ptr @_llgo_main.MyBytes, ptr undef }, ptr %4242, 1 +// CHECK-NEXT: %4244 = extractvalue { ptr, ptr } %4241, 1 +// CHECK-NEXT: %4245 = extractvalue { ptr, ptr } %4241, 0 +// CHECK-NEXT: %__llgo_funcval_code546 = call ptr asm "", "=r,0"(ptr %4245) +// CHECK-NEXT: %4246 = call %reflect.Value %__llgo_funcval_code546(ptr {{(nest|swiftself)}} %4244, %"{{.*}}/runtime/internal/runtime.eface" %4243) +// CHECK-NEXT: %4247 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %4239, i32 0, i32 1 +// CHECK-NEXT: %4248 = load { ptr, ptr }, ptr @main.V, align 8 +// CHECK-NEXT: %4249 = extractvalue { ptr, ptr } %4248, 1 +// CHECK-NEXT: %4250 = extractvalue { ptr, ptr } %4248, 0 +// CHECK-NEXT: %__llgo_funcval_code547 = call ptr asm "", "=r,0"(ptr %4250) +// CHECK-NEXT: %4251 = call %reflect.Value %__llgo_funcval_code547(ptr {{(nest|swiftself)}} %4249, %"{{.*}}/runtime/internal/runtime.eface" { ptr @_llgo_main.MyBytesArrayPtr0, ptr @"__llgo.moduleZeroSizedAlloc$" }) +// CHECK-NEXT: store %reflect.Value %4246, ptr %4240, align 8 +// CHECK-NEXT: store %reflect.Value %4251, ptr %4247, align 8 +// CHECK-NEXT: %4252 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %1, i64 274 +// CHECK-NEXT: %4253 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %4252, i32 0, i32 0 +// CHECK-NEXT: %4254 = load { ptr, ptr }, ptr @main.V, align 8 +// CHECK-NEXT: %4255 = call ptr @"{{.*}}/runtime/internal/runtime.AllocZ"(i64 4) +// CHECK-NEXT: %4256 = getelementptr inbounds i8, ptr %4255, i64 0 +// CHECK-NEXT: store i8 5, ptr %4256, align 1 +// CHECK-NEXT: %4257 = getelementptr inbounds i8, ptr %4255, i64 1 +// CHECK-NEXT: store i8 6, ptr %4257, align 1 +// CHECK-NEXT: %4258 = getelementptr inbounds i8, ptr %4255, i64 2 +// CHECK-NEXT: store i8 7, ptr %4258, align 1 +// CHECK-NEXT: %4259 = getelementptr inbounds i8, ptr %4255, i64 3 +// CHECK-NEXT: store i8 8, ptr %4259, align 1 +// CHECK-NEXT: %4260 = insertvalue %"{{.*}}/runtime/internal/runtime.Slice" undef, ptr %4255, 0 +// CHECK-NEXT: %4261 = insertvalue %"{{.*}}/runtime/internal/runtime.Slice" %4260, i64 4, 1 +// CHECK-NEXT: %4262 = insertvalue %"{{.*}}/runtime/internal/runtime.Slice" %4261, i64 4, 2 +// CHECK-NEXT: %4263 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 24) +// CHECK-NEXT: store %"{{.*}}/runtime/internal/runtime.Slice" %4262, ptr %4263, align 8 +// CHECK-NEXT: %4264 = insertvalue %"{{.*}}/runtime/internal/runtime.eface" { ptr @_llgo_main.MyBytes, ptr undef }, ptr %4263, 1 +// CHECK-NEXT: %4265 = extractvalue { ptr, ptr } %4254, 1 +// CHECK-NEXT: %4266 = extractvalue { ptr, ptr } %4254, 0 +// CHECK-NEXT: %__llgo_funcval_code548 = call ptr asm "", "=r,0"(ptr %4266) +// CHECK-NEXT: %4267 = call %reflect.Value %__llgo_funcval_code548(ptr {{(nest|swiftself)}} %4265, %"{{.*}}/runtime/internal/runtime.eface" %4264) +// CHECK-NEXT: %4268 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %4252, i32 0, i32 1 +// CHECK-NEXT: %4269 = load { ptr, ptr }, ptr @main.V, align 8 +// CHECK-NEXT: %4270 = call ptr @"{{.*}}/runtime/internal/runtime.AllocZ"(i64 4) +// CHECK-NEXT: %4271 = getelementptr inbounds i8, ptr %4270, i64 0 +// CHECK-NEXT: %4272 = getelementptr inbounds i8, ptr %4270, i64 1 +// CHECK-NEXT: %4273 = getelementptr inbounds i8, ptr %4270, i64 2 +// CHECK-NEXT: %4274 = getelementptr inbounds i8, ptr %4270, i64 3 +// CHECK-NEXT: store i8 5, ptr %4271, align 1 +// CHECK-NEXT: store i8 6, ptr %4272, align 1 +// CHECK-NEXT: store i8 7, ptr %4273, align 1 +// CHECK-NEXT: store i8 8, ptr %4274, align 1 +// CHECK-NEXT: %4275 = insertvalue %"{{.*}}/runtime/internal/runtime.eface" { ptr @_llgo_main.MyBytesArrayPtr, ptr undef }, ptr %4270, 1 +// CHECK-NEXT: %4276 = extractvalue { ptr, ptr } %4269, 1 +// CHECK-NEXT: %4277 = extractvalue { ptr, ptr } %4269, 0 +// CHECK-NEXT: %__llgo_funcval_code549 = call ptr asm "", "=r,0"(ptr %4277) +// CHECK-NEXT: %4278 = call %reflect.Value %__llgo_funcval_code549(ptr {{(nest|swiftself)}} %4276, %"{{.*}}/runtime/internal/runtime.eface" %4275) +// CHECK-NEXT: store %reflect.Value %4267, ptr %4253, align 8 +// CHECK-NEXT: store %reflect.Value %4278, ptr %4268, align 8 +// CHECK-NEXT: %4279 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %1, i64 275 +// CHECK-NEXT: %4280 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %4279, i32 0, i32 0 +// CHECK-NEXT: %4281 = load { ptr, ptr }, ptr @main.V, align 8 +// CHECK-NEXT: %4282 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 24) +// CHECK-NEXT: store %"{{.*}}/runtime/internal/runtime.Slice" zeroinitializer, ptr %4282, align 8 +// CHECK-NEXT: %4283 = insertvalue %"{{.*}}/runtime/internal/runtime.eface" { ptr @"[]_llgo_uint8", ptr undef }, ptr %4282, 1 +// CHECK-NEXT: %4284 = extractvalue { ptr, ptr } %4281, 1 +// CHECK-NEXT: %4285 = extractvalue { ptr, ptr } %4281, 0 +// CHECK-NEXT: %__llgo_funcval_code550 = call ptr asm "", "=r,0"(ptr %4285) +// CHECK-NEXT: %4286 = call %reflect.Value %__llgo_funcval_code550(ptr {{(nest|swiftself)}} %4284, %"{{.*}}/runtime/internal/runtime.eface" %4283) +// CHECK-NEXT: %4287 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %4279, i32 0, i32 1 +// CHECK-NEXT: %4288 = load { ptr, ptr }, ptr @main.V, align 8 +// CHECK-NEXT: %4289 = extractvalue { ptr, ptr } %4288, 1 +// CHECK-NEXT: %4290 = extractvalue { ptr, ptr } %4288, 0 +// CHECK-NEXT: %__llgo_funcval_code551 = call ptr asm "", "=r,0"(ptr %4290) +// CHECK-NEXT: %4291 = call %reflect.Value %__llgo_funcval_code551(ptr {{(nest|swiftself)}} %4289, %"{{.*}}/runtime/internal/runtime.eface" { ptr @"*_llgo_main.MyBytesArray0", ptr null }) +// CHECK-NEXT: store %reflect.Value %4286, ptr %4280, align 8 +// CHECK-NEXT: store %reflect.Value %4291, ptr %4287, align 8 +// CHECK-NEXT: %4292 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %1, i64 276 +// CHECK-NEXT: %4293 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %4292, i32 0, i32 0 +// CHECK-NEXT: %4294 = load { ptr, ptr }, ptr @main.V, align 8 +// CHECK-NEXT: %4295 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 24) +// CHECK-NEXT: store %"{{.*}}/runtime/internal/runtime.Slice" { ptr @"__llgo.moduleZeroSizedAlloc$", i64 0, i64 0 }, ptr %4295, align 8 +// CHECK-NEXT: %4296 = insertvalue %"{{.*}}/runtime/internal/runtime.eface" { ptr @"[]_llgo_uint8", ptr undef }, ptr %4295, 1 +// CHECK-NEXT: %4297 = extractvalue { ptr, ptr } %4294, 1 +// CHECK-NEXT: %4298 = extractvalue { ptr, ptr } %4294, 0 +// CHECK-NEXT: %__llgo_funcval_code552 = call ptr asm "", "=r,0"(ptr %4298) +// CHECK-NEXT: %4299 = call %reflect.Value %__llgo_funcval_code552(ptr {{(nest|swiftself)}} %4297, %"{{.*}}/runtime/internal/runtime.eface" %4296) +// CHECK-NEXT: %4300 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %4292, i32 0, i32 1 +// CHECK-NEXT: %4301 = load { ptr, ptr }, ptr @main.V, align 8 +// CHECK-NEXT: %4302 = extractvalue { ptr, ptr } %4301, 1 +// CHECK-NEXT: %4303 = extractvalue { ptr, ptr } %4301, 0 +// CHECK-NEXT: %__llgo_funcval_code553 = call ptr asm "", "=r,0"(ptr %4303) +// CHECK-NEXT: %4304 = call %reflect.Value %__llgo_funcval_code553(ptr {{(nest|swiftself)}} %4302, %"{{.*}}/runtime/internal/runtime.eface" { ptr @"*_llgo_main.MyBytesArray0", ptr @"__llgo.moduleZeroSizedAlloc$" }) +// CHECK-NEXT: store %reflect.Value %4299, ptr %4293, align 8 +// CHECK-NEXT: store %reflect.Value %4304, ptr %4300, align 8 +// CHECK-NEXT: %4305 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %1, i64 277 +// CHECK-NEXT: %4306 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %4305, i32 0, i32 0 +// CHECK-NEXT: %4307 = load { ptr, ptr }, ptr @main.V, align 8 +// CHECK-NEXT: %4308 = call ptr @"{{.*}}/runtime/internal/runtime.AllocZ"(i64 4) +// CHECK-NEXT: %4309 = getelementptr inbounds i8, ptr %4308, i64 0 +// CHECK-NEXT: store i8 1, ptr %4309, align 1 +// CHECK-NEXT: %4310 = getelementptr inbounds i8, ptr %4308, i64 1 +// CHECK-NEXT: store i8 2, ptr %4310, align 1 +// CHECK-NEXT: %4311 = getelementptr inbounds i8, ptr %4308, i64 2 +// CHECK-NEXT: store i8 3, ptr %4311, align 1 +// CHECK-NEXT: %4312 = getelementptr inbounds i8, ptr %4308, i64 3 +// CHECK-NEXT: store i8 4, ptr %4312, align 1 +// CHECK-NEXT: %4313 = insertvalue %"{{.*}}/runtime/internal/runtime.Slice" undef, ptr %4308, 0 +// CHECK-NEXT: %4314 = insertvalue %"{{.*}}/runtime/internal/runtime.Slice" %4313, i64 4, 1 +// CHECK-NEXT: %4315 = insertvalue %"{{.*}}/runtime/internal/runtime.Slice" %4314, i64 4, 2 +// CHECK-NEXT: %4316 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 24) +// CHECK-NEXT: store %"{{.*}}/runtime/internal/runtime.Slice" %4315, ptr %4316, align 8 +// CHECK-NEXT: %4317 = insertvalue %"{{.*}}/runtime/internal/runtime.eface" { ptr @"[]_llgo_uint8", ptr undef }, ptr %4316, 1 +// CHECK-NEXT: %4318 = extractvalue { ptr, ptr } %4307, 1 +// CHECK-NEXT: %4319 = extractvalue { ptr, ptr } %4307, 0 +// CHECK-NEXT: %__llgo_funcval_code554 = call ptr asm "", "=r,0"(ptr %4319) +// CHECK-NEXT: %4320 = call %reflect.Value %__llgo_funcval_code554(ptr {{(nest|swiftself)}} %4318, %"{{.*}}/runtime/internal/runtime.eface" %4317) +// CHECK-NEXT: %4321 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %4305, i32 0, i32 1 +// CHECK-NEXT: %4322 = load { ptr, ptr }, ptr @main.V, align 8 +// CHECK-NEXT: %4323 = call ptr @"{{.*}}/runtime/internal/runtime.AllocZ"(i64 4) +// CHECK-NEXT: %4324 = getelementptr inbounds i8, ptr %4323, i64 0 +// CHECK-NEXT: %4325 = getelementptr inbounds i8, ptr %4323, i64 1 +// CHECK-NEXT: %4326 = getelementptr inbounds i8, ptr %4323, i64 2 +// CHECK-NEXT: %4327 = getelementptr inbounds i8, ptr %4323, i64 3 +// CHECK-NEXT: store i8 1, ptr %4324, align 1 +// CHECK-NEXT: store i8 2, ptr %4325, align 1 +// CHECK-NEXT: store i8 3, ptr %4326, align 1 +// CHECK-NEXT: store i8 4, ptr %4327, align 1 +// CHECK-NEXT: %4328 = insertvalue %"{{.*}}/runtime/internal/runtime.eface" { ptr @"*_llgo_main.MyBytesArray", ptr undef }, ptr %4323, 1 +// CHECK-NEXT: %4329 = extractvalue { ptr, ptr } %4322, 1 +// CHECK-NEXT: %4330 = extractvalue { ptr, ptr } %4322, 0 +// CHECK-NEXT: %__llgo_funcval_code555 = call ptr asm "", "=r,0"(ptr %4330) +// CHECK-NEXT: %4331 = call %reflect.Value %__llgo_funcval_code555(ptr {{(nest|swiftself)}} %4329, %"{{.*}}/runtime/internal/runtime.eface" %4328) +// CHECK-NEXT: store %reflect.Value %4320, ptr %4306, align 8 +// CHECK-NEXT: store %reflect.Value %4331, ptr %4321, align 8 +// CHECK-NEXT: %4332 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %1, i64 278 +// CHECK-NEXT: %4333 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %4332, i32 0, i32 0 +// CHECK-NEXT: %4334 = load { ptr, ptr }, ptr @main.V, align 8 +// CHECK-NEXT: %4335 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 24) +// CHECK-NEXT: store %"{{.*}}/runtime/internal/runtime.Slice" zeroinitializer, ptr %4335, align 8 +// CHECK-NEXT: %4336 = insertvalue %"{{.*}}/runtime/internal/runtime.eface" { ptr @_llgo_main.MyBytes, ptr undef }, ptr %4335, 1 +// CHECK-NEXT: %4337 = extractvalue { ptr, ptr } %4334, 1 +// CHECK-NEXT: %4338 = extractvalue { ptr, ptr } %4334, 0 +// CHECK-NEXT: %__llgo_funcval_code556 = call ptr asm "", "=r,0"(ptr %4338) +// CHECK-NEXT: %4339 = call %reflect.Value %__llgo_funcval_code556(ptr {{(nest|swiftself)}} %4337, %"{{.*}}/runtime/internal/runtime.eface" %4336) +// CHECK-NEXT: %4340 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %4332, i32 0, i32 1 +// CHECK-NEXT: %4341 = load { ptr, ptr }, ptr @main.V, align 8 +// CHECK-NEXT: %4342 = extractvalue { ptr, ptr } %4341, 1 +// CHECK-NEXT: %4343 = extractvalue { ptr, ptr } %4341, 0 +// CHECK-NEXT: %__llgo_funcval_code557 = call ptr asm "", "=r,0"(ptr %4343) +// CHECK-NEXT: %4344 = call %reflect.Value %__llgo_funcval_code557(ptr {{(nest|swiftself)}} %4342, %"{{.*}}/runtime/internal/runtime.eface" { ptr @"*_llgo_main.MyBytesArray0", ptr null }) +// CHECK-NEXT: store %reflect.Value %4339, ptr %4333, align 8 +// CHECK-NEXT: store %reflect.Value %4344, ptr %4340, align 8 +// CHECK-NEXT: %4345 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %1, i64 279 +// CHECK-NEXT: %4346 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %4345, i32 0, i32 0 +// CHECK-NEXT: %4347 = load { ptr, ptr }, ptr @main.V, align 8 +// CHECK-NEXT: %4348 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 24) +// CHECK-NEXT: store %"{{.*}}/runtime/internal/runtime.Slice" { ptr @"__llgo.moduleZeroSizedAlloc$", i64 0, i64 0 }, ptr %4348, align 8 +// CHECK-NEXT: %4349 = insertvalue %"{{.*}}/runtime/internal/runtime.eface" { ptr @_llgo_main.MyBytes, ptr undef }, ptr %4348, 1 +// CHECK-NEXT: %4350 = extractvalue { ptr, ptr } %4347, 1 +// CHECK-NEXT: %4351 = extractvalue { ptr, ptr } %4347, 0 +// CHECK-NEXT: %__llgo_funcval_code558 = call ptr asm "", "=r,0"(ptr %4351) +// CHECK-NEXT: %4352 = call %reflect.Value %__llgo_funcval_code558(ptr {{(nest|swiftself)}} %4350, %"{{.*}}/runtime/internal/runtime.eface" %4349) +// CHECK-NEXT: %4353 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %4345, i32 0, i32 1 +// CHECK-NEXT: %4354 = load { ptr, ptr }, ptr @main.V, align 8 +// CHECK-NEXT: %4355 = extractvalue { ptr, ptr } %4354, 1 +// CHECK-NEXT: %4356 = extractvalue { ptr, ptr } %4354, 0 +// CHECK-NEXT: %__llgo_funcval_code559 = call ptr asm "", "=r,0"(ptr %4356) +// CHECK-NEXT: %4357 = call %reflect.Value %__llgo_funcval_code559(ptr {{(nest|swiftself)}} %4355, %"{{.*}}/runtime/internal/runtime.eface" { ptr @"*_llgo_main.MyBytesArray0", ptr @"__llgo.moduleZeroSizedAlloc$" }) +// CHECK-NEXT: store %reflect.Value %4352, ptr %4346, align 8 +// CHECK-NEXT: store %reflect.Value %4357, ptr %4353, align 8 +// CHECK-NEXT: %4358 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %1, i64 280 +// CHECK-NEXT: %4359 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %4358, i32 0, i32 0 +// CHECK-NEXT: %4360 = load { ptr, ptr }, ptr @main.V, align 8 +// CHECK-NEXT: %4361 = call ptr @"{{.*}}/runtime/internal/runtime.AllocZ"(i64 4) +// CHECK-NEXT: %4362 = getelementptr inbounds i8, ptr %4361, i64 0 +// CHECK-NEXT: store i8 5, ptr %4362, align 1 +// CHECK-NEXT: %4363 = getelementptr inbounds i8, ptr %4361, i64 1 +// CHECK-NEXT: store i8 6, ptr %4363, align 1 +// CHECK-NEXT: %4364 = getelementptr inbounds i8, ptr %4361, i64 2 +// CHECK-NEXT: store i8 7, ptr %4364, align 1 +// CHECK-NEXT: %4365 = getelementptr inbounds i8, ptr %4361, i64 3 +// CHECK-NEXT: store i8 8, ptr %4365, align 1 +// CHECK-NEXT: %4366 = insertvalue %"{{.*}}/runtime/internal/runtime.Slice" undef, ptr %4361, 0 +// CHECK-NEXT: %4367 = insertvalue %"{{.*}}/runtime/internal/runtime.Slice" %4366, i64 4, 1 +// CHECK-NEXT: %4368 = insertvalue %"{{.*}}/runtime/internal/runtime.Slice" %4367, i64 4, 2 +// CHECK-NEXT: %4369 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 24) +// CHECK-NEXT: store %"{{.*}}/runtime/internal/runtime.Slice" %4368, ptr %4369, align 8 +// CHECK-NEXT: %4370 = insertvalue %"{{.*}}/runtime/internal/runtime.eface" { ptr @_llgo_main.MyBytes, ptr undef }, ptr %4369, 1 +// CHECK-NEXT: %4371 = extractvalue { ptr, ptr } %4360, 1 +// CHECK-NEXT: %4372 = extractvalue { ptr, ptr } %4360, 0 +// CHECK-NEXT: %__llgo_funcval_code560 = call ptr asm "", "=r,0"(ptr %4372) +// CHECK-NEXT: %4373 = call %reflect.Value %__llgo_funcval_code560(ptr {{(nest|swiftself)}} %4371, %"{{.*}}/runtime/internal/runtime.eface" %4370) +// CHECK-NEXT: %4374 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %4358, i32 0, i32 1 +// CHECK-NEXT: %4375 = load { ptr, ptr }, ptr @main.V, align 8 +// CHECK-NEXT: %4376 = call ptr @"{{.*}}/runtime/internal/runtime.AllocZ"(i64 4) +// CHECK-NEXT: %4377 = getelementptr inbounds i8, ptr %4376, i64 0 +// CHECK-NEXT: %4378 = getelementptr inbounds i8, ptr %4376, i64 1 +// CHECK-NEXT: %4379 = getelementptr inbounds i8, ptr %4376, i64 2 +// CHECK-NEXT: %4380 = getelementptr inbounds i8, ptr %4376, i64 3 +// CHECK-NEXT: store i8 5, ptr %4377, align 1 +// CHECK-NEXT: store i8 6, ptr %4378, align 1 +// CHECK-NEXT: store i8 7, ptr %4379, align 1 +// CHECK-NEXT: store i8 8, ptr %4380, align 1 +// CHECK-NEXT: %4381 = insertvalue %"{{.*}}/runtime/internal/runtime.eface" { ptr @"*_llgo_main.MyBytesArray", ptr undef }, ptr %4376, 1 +// CHECK-NEXT: %4382 = extractvalue { ptr, ptr } %4375, 1 +// CHECK-NEXT: %4383 = extractvalue { ptr, ptr } %4375, 0 +// CHECK-NEXT: %__llgo_funcval_code561 = call ptr asm "", "=r,0"(ptr %4383) +// CHECK-NEXT: %4384 = call %reflect.Value %__llgo_funcval_code561(ptr {{(nest|swiftself)}} %4382, %"{{.*}}/runtime/internal/runtime.eface" %4381) +// CHECK-NEXT: store %reflect.Value %4373, ptr %4359, align 8 +// CHECK-NEXT: store %reflect.Value %4384, ptr %4374, align 8 +// CHECK-NEXT: %4385 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %1, i64 281 +// CHECK-NEXT: %4386 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %4385, i32 0, i32 0 +// CHECK-NEXT: %4387 = load { ptr, ptr }, ptr @main.V, align 8 +// CHECK-NEXT: %4388 = extractvalue { ptr, ptr } %4387, 1 +// CHECK-NEXT: %4389 = extractvalue { ptr, ptr } %4387, 0 +// CHECK-NEXT: %__llgo_funcval_code562 = call ptr asm "", "=r,0"(ptr %4389) +// CHECK-NEXT: %4390 = call %reflect.Value %__llgo_funcval_code562(ptr {{(nest|swiftself)}} %4388, %"{{.*}}/runtime/internal/runtime.eface" { ptr @"*[0]_llgo_uint8", ptr @"__llgo.moduleZeroSizedAlloc$" }) +// CHECK-NEXT: %4391 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %4385, i32 0, i32 1 +// CHECK-NEXT: %4392 = load { ptr, ptr }, ptr @main.V, align 8 +// CHECK-NEXT: %4393 = extractvalue { ptr, ptr } %4392, 1 +// CHECK-NEXT: %4394 = extractvalue { ptr, ptr } %4392, 0 +// CHECK-NEXT: %__llgo_funcval_code563 = call ptr asm "", "=r,0"(ptr %4394) +// CHECK-NEXT: %4395 = call %reflect.Value %__llgo_funcval_code563(ptr {{(nest|swiftself)}} %4393, %"{{.*}}/runtime/internal/runtime.eface" { ptr @"*_llgo_main.MyBytesArray0", ptr @"__llgo.moduleZeroSizedAlloc$" }) +// CHECK-NEXT: store %reflect.Value %4390, ptr %4386, align 8 +// CHECK-NEXT: store %reflect.Value %4395, ptr %4391, align 8 +// CHECK-NEXT: %4396 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %1, i64 282 +// CHECK-NEXT: %4397 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %4396, i32 0, i32 0 +// CHECK-NEXT: %4398 = load { ptr, ptr }, ptr @main.V, align 8 +// CHECK-NEXT: %4399 = extractvalue { ptr, ptr } %4398, 1 +// CHECK-NEXT: %4400 = extractvalue { ptr, ptr } %4398, 0 +// CHECK-NEXT: %__llgo_funcval_code564 = call ptr asm "", "=r,0"(ptr %4400) +// CHECK-NEXT: %4401 = call %reflect.Value %__llgo_funcval_code564(ptr {{(nest|swiftself)}} %4399, %"{{.*}}/runtime/internal/runtime.eface" { ptr @"*_llgo_main.MyBytesArray0", ptr @"__llgo.moduleZeroSizedAlloc$" }) +// CHECK-NEXT: %4402 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %4396, i32 0, i32 1 +// CHECK-NEXT: %4403 = load { ptr, ptr }, ptr @main.V, align 8 +// CHECK-NEXT: %4404 = extractvalue { ptr, ptr } %4403, 1 +// CHECK-NEXT: %4405 = extractvalue { ptr, ptr } %4403, 0 +// CHECK-NEXT: %__llgo_funcval_code565 = call ptr asm "", "=r,0"(ptr %4405) +// CHECK-NEXT: %4406 = call %reflect.Value %__llgo_funcval_code565(ptr {{(nest|swiftself)}} %4404, %"{{.*}}/runtime/internal/runtime.eface" { ptr @"*[0]_llgo_uint8", ptr @"__llgo.moduleZeroSizedAlloc$" }) +// CHECK-NEXT: store %reflect.Value %4401, ptr %4397, align 8 +// CHECK-NEXT: store %reflect.Value %4406, ptr %4402, align 8 +// CHECK-NEXT: %4407 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %1, i64 283 +// CHECK-NEXT: %4408 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %4407, i32 0, i32 0 +// CHECK-NEXT: %4409 = load { ptr, ptr }, ptr @main.V, align 8 +// CHECK-NEXT: %4410 = extractvalue { ptr, ptr } %4409, 1 +// CHECK-NEXT: %4411 = extractvalue { ptr, ptr } %4409, 0 +// CHECK-NEXT: %__llgo_funcval_code566 = call ptr asm "", "=r,0"(ptr %4411) +// CHECK-NEXT: %4412 = call %reflect.Value %__llgo_funcval_code566(ptr {{(nest|swiftself)}} %4410, %"{{.*}}/runtime/internal/runtime.eface" { ptr @_llgo_main.MyBytesArrayPtr0, ptr null }) +// CHECK-NEXT: %4413 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %4407, i32 0, i32 1 +// CHECK-NEXT: %4414 = load { ptr, ptr }, ptr @main.V, align 8 +// CHECK-NEXT: %4415 = extractvalue { ptr, ptr } %4414, 1 +// CHECK-NEXT: %4416 = extractvalue { ptr, ptr } %4414, 0 +// CHECK-NEXT: %__llgo_funcval_code567 = call ptr asm "", "=r,0"(ptr %4416) +// CHECK-NEXT: %4417 = call %reflect.Value %__llgo_funcval_code567(ptr {{(nest|swiftself)}} %4415, %"{{.*}}/runtime/internal/runtime.eface" { ptr @"*[0]_llgo_uint8", ptr null }) +// CHECK-NEXT: store %reflect.Value %4412, ptr %4408, align 8 +// CHECK-NEXT: store %reflect.Value %4417, ptr %4413, align 8 +// CHECK-NEXT: %4418 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %1, i64 284 +// CHECK-NEXT: %4419 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %4418, i32 0, i32 0 +// CHECK-NEXT: %4420 = load { ptr, ptr }, ptr @main.V, align 8 +// CHECK-NEXT: %4421 = extractvalue { ptr, ptr } %4420, 1 +// CHECK-NEXT: %4422 = extractvalue { ptr, ptr } %4420, 0 +// CHECK-NEXT: %__llgo_funcval_code568 = call ptr asm "", "=r,0"(ptr %4422) +// CHECK-NEXT: %4423 = call %reflect.Value %__llgo_funcval_code568(ptr {{(nest|swiftself)}} %4421, %"{{.*}}/runtime/internal/runtime.eface" { ptr @"*[0]_llgo_uint8", ptr null }) +// CHECK-NEXT: %4424 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %4418, i32 0, i32 1 +// CHECK-NEXT: %4425 = load { ptr, ptr }, ptr @main.V, align 8 +// CHECK-NEXT: %4426 = extractvalue { ptr, ptr } %4425, 1 +// CHECK-NEXT: %4427 = extractvalue { ptr, ptr } %4425, 0 +// CHECK-NEXT: %__llgo_funcval_code569 = call ptr asm "", "=r,0"(ptr %4427) +// CHECK-NEXT: %4428 = call %reflect.Value %__llgo_funcval_code569(ptr {{(nest|swiftself)}} %4426, %"{{.*}}/runtime/internal/runtime.eface" { ptr @_llgo_main.MyBytesArrayPtr0, ptr null }) +// CHECK-NEXT: store %reflect.Value %4423, ptr %4419, align 8 +// CHECK-NEXT: store %reflect.Value %4428, ptr %4424, align 8 +// CHECK-NEXT: %4429 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %1, i64 285 +// CHECK-NEXT: %4430 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %4429, i32 0, i32 0 +// CHECK-NEXT: %4431 = load { ptr, ptr }, ptr @main.V, align 8 +// CHECK-NEXT: %4432 = call ptr @"{{.*}}/runtime/internal/runtime.AllocZ"(i64 8) +// CHECK-NEXT: %4433 = insertvalue %"{{.*}}/runtime/internal/runtime.eface" { ptr @"*_llgo_int", ptr undef }, ptr %4432, 1 +// CHECK-NEXT: %4434 = extractvalue { ptr, ptr } %4431, 1 +// CHECK-NEXT: %4435 = extractvalue { ptr, ptr } %4431, 0 +// CHECK-NEXT: %__llgo_funcval_code570 = call ptr asm "", "=r,0"(ptr %4435) +// CHECK-NEXT: %4436 = call %reflect.Value %__llgo_funcval_code570(ptr {{(nest|swiftself)}} %4434, %"{{.*}}/runtime/internal/runtime.eface" %4433) +// CHECK-NEXT: %4437 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %4429, i32 0, i32 1 +// CHECK-NEXT: %4438 = load { ptr, ptr }, ptr @main.V, align 8 +// CHECK-NEXT: %4439 = call ptr @"{{.*}}/runtime/internal/runtime.AllocZ"(i64 8) +// CHECK-NEXT: %4440 = insertvalue %"{{.*}}/runtime/internal/runtime.eface" { ptr @"*_llgo_main.integer", ptr undef }, ptr %4439, 1 +// CHECK-NEXT: %4441 = extractvalue { ptr, ptr } %4438, 1 +// CHECK-NEXT: %4442 = extractvalue { ptr, ptr } %4438, 0 +// CHECK-NEXT: %__llgo_funcval_code571 = call ptr asm "", "=r,0"(ptr %4442) +// CHECK-NEXT: %4443 = call %reflect.Value %__llgo_funcval_code571(ptr {{(nest|swiftself)}} %4441, %"{{.*}}/runtime/internal/runtime.eface" %4440) +// CHECK-NEXT: store %reflect.Value %4436, ptr %4430, align 8 +// CHECK-NEXT: store %reflect.Value %4443, ptr %4437, align 8 +// CHECK-NEXT: %4444 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %1, i64 286 +// CHECK-NEXT: %4445 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %4444, i32 0, i32 0 +// CHECK-NEXT: %4446 = load { ptr, ptr }, ptr @main.V, align 8 +// CHECK-NEXT: %4447 = call ptr @"{{.*}}/runtime/internal/runtime.AllocZ"(i64 8) +// CHECK-NEXT: %4448 = insertvalue %"{{.*}}/runtime/internal/runtime.eface" { ptr @"*_llgo_main.integer", ptr undef }, ptr %4447, 1 +// CHECK-NEXT: %4449 = extractvalue { ptr, ptr } %4446, 1 +// CHECK-NEXT: %4450 = extractvalue { ptr, ptr } %4446, 0 +// CHECK-NEXT: %__llgo_funcval_code572 = call ptr asm "", "=r,0"(ptr %4450) +// CHECK-NEXT: %4451 = call %reflect.Value %__llgo_funcval_code572(ptr {{(nest|swiftself)}} %4449, %"{{.*}}/runtime/internal/runtime.eface" %4448) +// CHECK-NEXT: %4452 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %4444, i32 0, i32 1 +// CHECK-NEXT: %4453 = load { ptr, ptr }, ptr @main.V, align 8 +// CHECK-NEXT: %4454 = call ptr @"{{.*}}/runtime/internal/runtime.AllocZ"(i64 8) +// CHECK-NEXT: %4455 = insertvalue %"{{.*}}/runtime/internal/runtime.eface" { ptr @"*_llgo_int", ptr undef }, ptr %4454, 1 +// CHECK-NEXT: %4456 = extractvalue { ptr, ptr } %4453, 1 +// CHECK-NEXT: %4457 = extractvalue { ptr, ptr } %4453, 0 +// CHECK-NEXT: %__llgo_funcval_code573 = call ptr asm "", "=r,0"(ptr %4457) +// CHECK-NEXT: %4458 = call %reflect.Value %__llgo_funcval_code573(ptr {{(nest|swiftself)}} %4456, %"{{.*}}/runtime/internal/runtime.eface" %4455) +// CHECK-NEXT: store %reflect.Value %4451, ptr %4445, align 8 +// CHECK-NEXT: store %reflect.Value %4458, ptr %4452, align 8 +// CHECK-NEXT: %4459 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %1, i64 287 +// CHECK-NEXT: %4460 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %4459, i32 0, i32 0 +// CHECK-NEXT: %4461 = load { ptr, ptr }, ptr @main.V, align 8 +// CHECK-NEXT: %4462 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 0) +// CHECK-NEXT: store %main.Empty zeroinitializer, ptr %4462, align 1 +// CHECK-NEXT: %4463 = insertvalue %"{{.*}}/runtime/internal/runtime.eface" { ptr @_llgo_main.Empty, ptr undef }, ptr %4462, 1 +// CHECK-NEXT: %4464 = extractvalue { ptr, ptr } %4461, 1 +// CHECK-NEXT: %4465 = extractvalue { ptr, ptr } %4461, 0 +// CHECK-NEXT: %__llgo_funcval_code574 = call ptr asm "", "=r,0"(ptr %4465) +// CHECK-NEXT: %4466 = call %reflect.Value %__llgo_funcval_code574(ptr {{(nest|swiftself)}} %4464, %"{{.*}}/runtime/internal/runtime.eface" %4463) +// CHECK-NEXT: %4467 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %4459, i32 0, i32 1 +// CHECK-NEXT: %4468 = load { ptr, ptr }, ptr @main.V, align 8 +// CHECK-NEXT: %4469 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 0) +// CHECK-NEXT: store {} zeroinitializer, ptr %4469, align 1 +// CHECK-NEXT: %4470 = insertvalue %"{{.*}}/runtime/internal/runtime.eface" { ptr @"_llgo_struct$n1H8J_3prDN3firMwPxBLVTkE5hJ9Di-AqNvaC9jczw", ptr undef }, ptr %4469, 1 +// CHECK-NEXT: %4471 = extractvalue { ptr, ptr } %4468, 1 +// CHECK-NEXT: %4472 = extractvalue { ptr, ptr } %4468, 0 +// CHECK-NEXT: %__llgo_funcval_code575 = call ptr asm "", "=r,0"(ptr %4472) +// CHECK-NEXT: %4473 = call %reflect.Value %__llgo_funcval_code575(ptr {{(nest|swiftself)}} %4471, %"{{.*}}/runtime/internal/runtime.eface" %4470) +// CHECK-NEXT: store %reflect.Value %4466, ptr %4460, align 8 +// CHECK-NEXT: store %reflect.Value %4473, ptr %4467, align 8 +// CHECK-NEXT: %4474 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %1, i64 288 +// CHECK-NEXT: %4475 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %4474, i32 0, i32 0 +// CHECK-NEXT: %4476 = load { ptr, ptr }, ptr @main.V, align 8 +// CHECK-NEXT: %4477 = extractvalue { ptr, ptr } %4476, 1 +// CHECK-NEXT: %4478 = extractvalue { ptr, ptr } %4476, 0 +// CHECK-NEXT: %__llgo_funcval_code576 = call ptr asm "", "=r,0"(ptr %4478) +// CHECK-NEXT: %4479 = call %reflect.Value %__llgo_funcval_code576(ptr {{(nest|swiftself)}} %4477, %"{{.*}}/runtime/internal/runtime.eface" { ptr @"*_llgo_main.Empty", ptr @"__llgo.moduleZeroSizedAlloc$" }) +// CHECK-NEXT: %4480 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %4474, i32 0, i32 1 +// CHECK-NEXT: %4481 = load { ptr, ptr }, ptr @main.V, align 8 +// CHECK-NEXT: %4482 = extractvalue { ptr, ptr } %4481, 1 +// CHECK-NEXT: %4483 = extractvalue { ptr, ptr } %4481, 0 +// CHECK-NEXT: %__llgo_funcval_code577 = call ptr asm "", "=r,0"(ptr %4483) +// CHECK-NEXT: %4484 = call %reflect.Value %__llgo_funcval_code577(ptr {{(nest|swiftself)}} %4482, %"{{.*}}/runtime/internal/runtime.eface" { ptr @"*_llgo_struct$n1H8J_3prDN3firMwPxBLVTkE5hJ9Di-AqNvaC9jczw", ptr @"__llgo.moduleZeroSizedAlloc$" }) +// CHECK-NEXT: store %reflect.Value %4479, ptr %4475, align 8 +// CHECK-NEXT: store %reflect.Value %4484, ptr %4480, align 8 +// CHECK-NEXT: %4485 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %1, i64 289 +// CHECK-NEXT: %4486 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %4485, i32 0, i32 0 +// CHECK-NEXT: %4487 = load { ptr, ptr }, ptr @main.V, align 8 +// CHECK-NEXT: %4488 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 0) +// CHECK-NEXT: store {} zeroinitializer, ptr %4488, align 1 +// CHECK-NEXT: %4489 = insertvalue %"{{.*}}/runtime/internal/runtime.eface" { ptr @"_llgo_struct$n1H8J_3prDN3firMwPxBLVTkE5hJ9Di-AqNvaC9jczw", ptr undef }, ptr %4488, 1 +// CHECK-NEXT: %4490 = extractvalue { ptr, ptr } %4487, 1 +// CHECK-NEXT: %4491 = extractvalue { ptr, ptr } %4487, 0 +// CHECK-NEXT: %__llgo_funcval_code578 = call ptr asm "", "=r,0"(ptr %4491) +// CHECK-NEXT: %4492 = call %reflect.Value %__llgo_funcval_code578(ptr {{(nest|swiftself)}} %4490, %"{{.*}}/runtime/internal/runtime.eface" %4489) +// CHECK-NEXT: %4493 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %4485, i32 0, i32 1 +// CHECK-NEXT: %4494 = load { ptr, ptr }, ptr @main.V, align 8 +// CHECK-NEXT: %4495 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 0) +// CHECK-NEXT: store %main.Empty zeroinitializer, ptr %4495, align 1 +// CHECK-NEXT: %4496 = insertvalue %"{{.*}}/runtime/internal/runtime.eface" { ptr @_llgo_main.Empty, ptr undef }, ptr %4495, 1 +// CHECK-NEXT: %4497 = extractvalue { ptr, ptr } %4494, 1 +// CHECK-NEXT: %4498 = extractvalue { ptr, ptr } %4494, 0 +// CHECK-NEXT: %__llgo_funcval_code579 = call ptr asm "", "=r,0"(ptr %4498) +// CHECK-NEXT: %4499 = call %reflect.Value %__llgo_funcval_code579(ptr {{(nest|swiftself)}} %4497, %"{{.*}}/runtime/internal/runtime.eface" %4496) +// CHECK-NEXT: store %reflect.Value %4492, ptr %4486, align 8 +// CHECK-NEXT: store %reflect.Value %4499, ptr %4493, align 8 +// CHECK-NEXT: %4500 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %1, i64 290 +// CHECK-NEXT: %4501 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %4500, i32 0, i32 0 +// CHECK-NEXT: %4502 = load { ptr, ptr }, ptr @main.V, align 8 +// CHECK-NEXT: %4503 = extractvalue { ptr, ptr } %4502, 1 +// CHECK-NEXT: %4504 = extractvalue { ptr, ptr } %4502, 0 +// CHECK-NEXT: %__llgo_funcval_code580 = call ptr asm "", "=r,0"(ptr %4504) +// CHECK-NEXT: %4505 = call %reflect.Value %__llgo_funcval_code580(ptr {{(nest|swiftself)}} %4503, %"{{.*}}/runtime/internal/runtime.eface" { ptr @"*_llgo_struct$n1H8J_3prDN3firMwPxBLVTkE5hJ9Di-AqNvaC9jczw", ptr @"__llgo.moduleZeroSizedAlloc$" }) +// CHECK-NEXT: %4506 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %4500, i32 0, i32 1 +// CHECK-NEXT: %4507 = load { ptr, ptr }, ptr @main.V, align 8 +// CHECK-NEXT: %4508 = extractvalue { ptr, ptr } %4507, 1 +// CHECK-NEXT: %4509 = extractvalue { ptr, ptr } %4507, 0 +// CHECK-NEXT: %__llgo_funcval_code581 = call ptr asm "", "=r,0"(ptr %4509) +// CHECK-NEXT: %4510 = call %reflect.Value %__llgo_funcval_code581(ptr {{(nest|swiftself)}} %4508, %"{{.*}}/runtime/internal/runtime.eface" { ptr @"*_llgo_main.Empty", ptr @"__llgo.moduleZeroSizedAlloc$" }) +// CHECK-NEXT: store %reflect.Value %4505, ptr %4501, align 8 +// CHECK-NEXT: store %reflect.Value %4510, ptr %4506, align 8 +// CHECK-NEXT: %4511 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %1, i64 291 +// CHECK-NEXT: %4512 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %4511, i32 0, i32 0 +// CHECK-NEXT: %4513 = load { ptr, ptr }, ptr @main.V, align 8 +// CHECK-NEXT: %4514 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 0) +// CHECK-NEXT: store %main.Empty zeroinitializer, ptr %4514, align 1 +// CHECK-NEXT: %4515 = insertvalue %"{{.*}}/runtime/internal/runtime.eface" { ptr @_llgo_main.Empty, ptr undef }, ptr %4514, 1 +// CHECK-NEXT: %4516 = extractvalue { ptr, ptr } %4513, 1 +// CHECK-NEXT: %4517 = extractvalue { ptr, ptr } %4513, 0 +// CHECK-NEXT: %__llgo_funcval_code582 = call ptr asm "", "=r,0"(ptr %4517) +// CHECK-NEXT: %4518 = call %reflect.Value %__llgo_funcval_code582(ptr {{(nest|swiftself)}} %4516, %"{{.*}}/runtime/internal/runtime.eface" %4515) +// CHECK-NEXT: %4519 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %4511, i32 0, i32 1 +// CHECK-NEXT: %4520 = load { ptr, ptr }, ptr @main.V, align 8 +// CHECK-NEXT: %4521 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 0) +// CHECK-NEXT: store %main.Empty zeroinitializer, ptr %4521, align 1 +// CHECK-NEXT: %4522 = insertvalue %"{{.*}}/runtime/internal/runtime.eface" { ptr @_llgo_main.Empty, ptr undef }, ptr %4521, 1 +// CHECK-NEXT: %4523 = extractvalue { ptr, ptr } %4520, 1 +// CHECK-NEXT: %4524 = extractvalue { ptr, ptr } %4520, 0 +// CHECK-NEXT: %__llgo_funcval_code583 = call ptr asm "", "=r,0"(ptr %4524) +// CHECK-NEXT: %4525 = call %reflect.Value %__llgo_funcval_code583(ptr {{(nest|swiftself)}} %4523, %"{{.*}}/runtime/internal/runtime.eface" %4522) +// CHECK-NEXT: store %reflect.Value %4518, ptr %4512, align 8 +// CHECK-NEXT: store %reflect.Value %4525, ptr %4519, align 8 +// CHECK-NEXT: %4526 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %1, i64 292 +// CHECK-NEXT: %4527 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %4526, i32 0, i32 0 +// CHECK-NEXT: %4528 = load { ptr, ptr }, ptr @main.V, align 8 +// CHECK-NEXT: %4529 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 24) +// CHECK-NEXT: store %"{{.*}}/runtime/internal/runtime.Slice" { ptr @"__llgo.moduleZeroSizedAlloc$", i64 0, i64 0 }, ptr %4529, align 8 +// CHECK-NEXT: %4530 = insertvalue %"{{.*}}/runtime/internal/runtime.eface" { ptr @_llgo_main.MyBytes, ptr undef }, ptr %4529, 1 +// CHECK-NEXT: %4531 = extractvalue { ptr, ptr } %4528, 1 +// CHECK-NEXT: %4532 = extractvalue { ptr, ptr } %4528, 0 +// CHECK-NEXT: %__llgo_funcval_code584 = call ptr asm "", "=r,0"(ptr %4532) +// CHECK-NEXT: %4533 = call %reflect.Value %__llgo_funcval_code584(ptr {{(nest|swiftself)}} %4531, %"{{.*}}/runtime/internal/runtime.eface" %4530) +// CHECK-NEXT: %4534 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %4526, i32 0, i32 1 +// CHECK-NEXT: %4535 = load { ptr, ptr }, ptr @main.V, align 8 +// CHECK-NEXT: %4536 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 24) +// CHECK-NEXT: store %"{{.*}}/runtime/internal/runtime.Slice" { ptr @"__llgo.moduleZeroSizedAlloc$", i64 0, i64 0 }, ptr %4536, align 8 +// CHECK-NEXT: %4537 = insertvalue %"{{.*}}/runtime/internal/runtime.eface" { ptr @"[]_llgo_uint8", ptr undef }, ptr %4536, 1 +// CHECK-NEXT: %4538 = extractvalue { ptr, ptr } %4535, 1 +// CHECK-NEXT: %4539 = extractvalue { ptr, ptr } %4535, 0 +// CHECK-NEXT: %__llgo_funcval_code585 = call ptr asm "", "=r,0"(ptr %4539) +// CHECK-NEXT: %4540 = call %reflect.Value %__llgo_funcval_code585(ptr {{(nest|swiftself)}} %4538, %"{{.*}}/runtime/internal/runtime.eface" %4537) +// CHECK-NEXT: store %reflect.Value %4533, ptr %4527, align 8 +// CHECK-NEXT: store %reflect.Value %4540, ptr %4534, align 8 +// CHECK-NEXT: %4541 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %1, i64 293 +// CHECK-NEXT: %4542 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %4541, i32 0, i32 0 +// CHECK-NEXT: %4543 = load { ptr, ptr }, ptr @main.V, align 8 +// CHECK-NEXT: %4544 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 24) +// CHECK-NEXT: store %"{{.*}}/runtime/internal/runtime.Slice" { ptr @"__llgo.moduleZeroSizedAlloc$", i64 0, i64 0 }, ptr %4544, align 8 +// CHECK-NEXT: %4545 = insertvalue %"{{.*}}/runtime/internal/runtime.eface" { ptr @"[]_llgo_uint8", ptr undef }, ptr %4544, 1 +// CHECK-NEXT: %4546 = extractvalue { ptr, ptr } %4543, 1 +// CHECK-NEXT: %4547 = extractvalue { ptr, ptr } %4543, 0 +// CHECK-NEXT: %__llgo_funcval_code586 = call ptr asm "", "=r,0"(ptr %4547) +// CHECK-NEXT: %4548 = call %reflect.Value %__llgo_funcval_code586(ptr {{(nest|swiftself)}} %4546, %"{{.*}}/runtime/internal/runtime.eface" %4545) +// CHECK-NEXT: %4549 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %4541, i32 0, i32 1 +// CHECK-NEXT: %4550 = load { ptr, ptr }, ptr @main.V, align 8 +// CHECK-NEXT: %4551 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 24) +// CHECK-NEXT: store %"{{.*}}/runtime/internal/runtime.Slice" { ptr @"__llgo.moduleZeroSizedAlloc$", i64 0, i64 0 }, ptr %4551, align 8 +// CHECK-NEXT: %4552 = insertvalue %"{{.*}}/runtime/internal/runtime.eface" { ptr @_llgo_main.MyBytes, ptr undef }, ptr %4551, 1 +// CHECK-NEXT: %4553 = extractvalue { ptr, ptr } %4550, 1 +// CHECK-NEXT: %4554 = extractvalue { ptr, ptr } %4550, 0 +// CHECK-NEXT: %__llgo_funcval_code587 = call ptr asm "", "=r,0"(ptr %4554) +// CHECK-NEXT: %4555 = call %reflect.Value %__llgo_funcval_code587(ptr {{(nest|swiftself)}} %4553, %"{{.*}}/runtime/internal/runtime.eface" %4552) +// CHECK-NEXT: store %reflect.Value %4548, ptr %4542, align 8 +// CHECK-NEXT: store %reflect.Value %4555, ptr %4549, align 8 +// CHECK-NEXT: %4556 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %1, i64 294 +// CHECK-NEXT: %4557 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %4556, i32 0, i32 0 +// CHECK-NEXT: %4558 = load { ptr, ptr }, ptr @main.V, align 8 +// CHECK-NEXT: %4559 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 16) +// CHECK-NEXT: store { ptr, ptr } zeroinitializer, ptr %4559, align 8 +// CHECK-NEXT: %4560 = insertvalue %"{{.*}}/runtime/internal/runtime.eface" { ptr @"_llgo_closure$b7Su1hWaFih-M0M9hMk6nO_RD1K_GQu5WjIXQp6Q2e8", ptr undef }, ptr %4559, 1 +// CHECK-NEXT: %4561 = extractvalue { ptr, ptr } %4558, 1 +// CHECK-NEXT: %4562 = extractvalue { ptr, ptr } %4558, 0 +// CHECK-NEXT: %__llgo_funcval_code588 = call ptr asm "", "=r,0"(ptr %4562) +// CHECK-NEXT: %4563 = call %reflect.Value %__llgo_funcval_code588(ptr {{(nest|swiftself)}} %4561, %"{{.*}}/runtime/internal/runtime.eface" %4560) +// CHECK-NEXT: %4564 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %4556, i32 0, i32 1 +// CHECK-NEXT: %4565 = load { ptr, ptr }, ptr @main.V, align 8 +// CHECK-NEXT: %4566 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 16) +// CHECK-NEXT: store %main.MyFunc zeroinitializer, ptr %4566, align 8 +// CHECK-NEXT: %4567 = insertvalue %"{{.*}}/runtime/internal/runtime.eface" { ptr @_llgo_main.MyFunc, ptr undef }, ptr %4566, 1 +// CHECK-NEXT: %4568 = extractvalue { ptr, ptr } %4565, 1 +// CHECK-NEXT: %4569 = extractvalue { ptr, ptr } %4565, 0 +// CHECK-NEXT: %__llgo_funcval_code589 = call ptr asm "", "=r,0"(ptr %4569) +// CHECK-NEXT: %4570 = call %reflect.Value %__llgo_funcval_code589(ptr {{(nest|swiftself)}} %4568, %"{{.*}}/runtime/internal/runtime.eface" %4567) +// CHECK-NEXT: store %reflect.Value %4563, ptr %4557, align 8 +// CHECK-NEXT: store %reflect.Value %4570, ptr %4564, align 8 +// CHECK-NEXT: %4571 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %1, i64 295 +// CHECK-NEXT: %4572 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %4571, i32 0, i32 0 +// CHECK-NEXT: %4573 = load { ptr, ptr }, ptr @main.V, align 8 +// CHECK-NEXT: %4574 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 16) +// CHECK-NEXT: store %main.MyFunc zeroinitializer, ptr %4574, align 8 +// CHECK-NEXT: %4575 = insertvalue %"{{.*}}/runtime/internal/runtime.eface" { ptr @_llgo_main.MyFunc, ptr undef }, ptr %4574, 1 +// CHECK-NEXT: %4576 = extractvalue { ptr, ptr } %4573, 1 +// CHECK-NEXT: %4577 = extractvalue { ptr, ptr } %4573, 0 +// CHECK-NEXT: %__llgo_funcval_code590 = call ptr asm "", "=r,0"(ptr %4577) +// CHECK-NEXT: %4578 = call %reflect.Value %__llgo_funcval_code590(ptr {{(nest|swiftself)}} %4576, %"{{.*}}/runtime/internal/runtime.eface" %4575) +// CHECK-NEXT: %4579 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %4571, i32 0, i32 1 +// CHECK-NEXT: %4580 = load { ptr, ptr }, ptr @main.V, align 8 +// CHECK-NEXT: %4581 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 16) +// CHECK-NEXT: store { ptr, ptr } zeroinitializer, ptr %4581, align 8 +// CHECK-NEXT: %4582 = insertvalue %"{{.*}}/runtime/internal/runtime.eface" { ptr @"_llgo_closure$b7Su1hWaFih-M0M9hMk6nO_RD1K_GQu5WjIXQp6Q2e8", ptr undef }, ptr %4581, 1 +// CHECK-NEXT: %4583 = extractvalue { ptr, ptr } %4580, 1 +// CHECK-NEXT: %4584 = extractvalue { ptr, ptr } %4580, 0 +// CHECK-NEXT: %__llgo_funcval_code591 = call ptr asm "", "=r,0"(ptr %4584) +// CHECK-NEXT: %4585 = call %reflect.Value %__llgo_funcval_code591(ptr {{(nest|swiftself)}} %4583, %"{{.*}}/runtime/internal/runtime.eface" %4582) +// CHECK-NEXT: store %reflect.Value %4578, ptr %4572, align 8 +// CHECK-NEXT: store %reflect.Value %4585, ptr %4579, align 8 +// CHECK-NEXT: %4586 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %1, i64 296 +// CHECK-NEXT: %4587 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %4586, i32 0, i32 0 +// CHECK-NEXT: %4588 = load { ptr, ptr }, ptr @main.V, align 8 +// CHECK-NEXT: %4589 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 8) +// CHECK-NEXT: store { i64 } zeroinitializer, ptr %4589, align 8 +// CHECK-NEXT: %4590 = insertvalue %"{{.*}}/runtime/internal/runtime.eface" { ptr @"{{.*}}/cl/_testgo/reflectconv.struct$qCYMduDqkoVspSDbQftiUv7WF_sipKSWG3oLt28TNlI", ptr undef }, ptr %4589, 1 +// CHECK-NEXT: %4591 = extractvalue { ptr, ptr } %4588, 1 +// CHECK-NEXT: %4592 = extractvalue { ptr, ptr } %4588, 0 +// CHECK-NEXT: %__llgo_funcval_code592 = call ptr asm "", "=r,0"(ptr %4592) +// CHECK-NEXT: %4593 = call %reflect.Value %__llgo_funcval_code592(ptr {{(nest|swiftself)}} %4591, %"{{.*}}/runtime/internal/runtime.eface" %4590) +// CHECK-NEXT: %4594 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %4586, i32 0, i32 1 +// CHECK-NEXT: %4595 = load { ptr, ptr }, ptr @main.V, align 8 +// CHECK-NEXT: %4596 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 8) +// CHECK-NEXT: store { i64 } zeroinitializer, ptr %4596, align 8 +// CHECK-NEXT: %4597 = insertvalue %"{{.*}}/runtime/internal/runtime.eface" { ptr @"{{.*}}/cl/_testgo/reflectconv.struct$8xdZyDeCx3tqPdt33CJnJ-JMAObkKtPXr9OL-lBc3yU", ptr undef }, ptr %4596, 1 +// CHECK-NEXT: %4598 = extractvalue { ptr, ptr } %4595, 1 +// CHECK-NEXT: %4599 = extractvalue { ptr, ptr } %4595, 0 +// CHECK-NEXT: %__llgo_funcval_code593 = call ptr asm "", "=r,0"(ptr %4599) +// CHECK-NEXT: %4600 = call %reflect.Value %__llgo_funcval_code593(ptr {{(nest|swiftself)}} %4598, %"{{.*}}/runtime/internal/runtime.eface" %4597) +// CHECK-NEXT: store %reflect.Value %4593, ptr %4587, align 8 +// CHECK-NEXT: store %reflect.Value %4600, ptr %4594, align 8 +// CHECK-NEXT: %4601 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %1, i64 297 +// CHECK-NEXT: %4602 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %4601, i32 0, i32 0 +// CHECK-NEXT: %4603 = load { ptr, ptr }, ptr @main.V, align 8 +// CHECK-NEXT: %4604 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 8) +// CHECK-NEXT: store { i64 } zeroinitializer, ptr %4604, align 8 +// CHECK-NEXT: %4605 = insertvalue %"{{.*}}/runtime/internal/runtime.eface" { ptr @"{{.*}}/cl/_testgo/reflectconv.struct$8xdZyDeCx3tqPdt33CJnJ-JMAObkKtPXr9OL-lBc3yU", ptr undef }, ptr %4604, 1 +// CHECK-NEXT: %4606 = extractvalue { ptr, ptr } %4603, 1 +// CHECK-NEXT: %4607 = extractvalue { ptr, ptr } %4603, 0 +// CHECK-NEXT: %__llgo_funcval_code594 = call ptr asm "", "=r,0"(ptr %4607) +// CHECK-NEXT: %4608 = call %reflect.Value %__llgo_funcval_code594(ptr {{(nest|swiftself)}} %4606, %"{{.*}}/runtime/internal/runtime.eface" %4605) +// CHECK-NEXT: %4609 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %4601, i32 0, i32 1 +// CHECK-NEXT: %4610 = load { ptr, ptr }, ptr @main.V, align 8 +// CHECK-NEXT: %4611 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 8) +// CHECK-NEXT: store { i64 } zeroinitializer, ptr %4611, align 8 +// CHECK-NEXT: %4612 = insertvalue %"{{.*}}/runtime/internal/runtime.eface" { ptr @"{{.*}}/cl/_testgo/reflectconv.struct$qCYMduDqkoVspSDbQftiUv7WF_sipKSWG3oLt28TNlI", ptr undef }, ptr %4611, 1 +// CHECK-NEXT: %4613 = extractvalue { ptr, ptr } %4610, 1 +// CHECK-NEXT: %4614 = extractvalue { ptr, ptr } %4610, 0 +// CHECK-NEXT: %__llgo_funcval_code595 = call ptr asm "", "=r,0"(ptr %4614) +// CHECK-NEXT: %4615 = call %reflect.Value %__llgo_funcval_code595(ptr {{(nest|swiftself)}} %4613, %"{{.*}}/runtime/internal/runtime.eface" %4612) +// CHECK-NEXT: store %reflect.Value %4608, ptr %4602, align 8 +// CHECK-NEXT: store %reflect.Value %4615, ptr %4609, align 8 +// CHECK-NEXT: %4616 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %1, i64 298 +// CHECK-NEXT: %4617 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %4616, i32 0, i32 0 +// CHECK-NEXT: %4618 = load { ptr, ptr }, ptr @main.V, align 8 +// CHECK-NEXT: %4619 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 8) +// CHECK-NEXT: store %main.MyStruct zeroinitializer, ptr %4619, align 8 +// CHECK-NEXT: %4620 = insertvalue %"{{.*}}/runtime/internal/runtime.eface" { ptr @_llgo_main.MyStruct, ptr undef }, ptr %4619, 1 +// CHECK-NEXT: %4621 = extractvalue { ptr, ptr } %4618, 1 +// CHECK-NEXT: %4622 = extractvalue { ptr, ptr } %4618, 0 +// CHECK-NEXT: %__llgo_funcval_code596 = call ptr asm "", "=r,0"(ptr %4622) +// CHECK-NEXT: %4623 = call %reflect.Value %__llgo_funcval_code596(ptr {{(nest|swiftself)}} %4621, %"{{.*}}/runtime/internal/runtime.eface" %4620) +// CHECK-NEXT: %4624 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %4616, i32 0, i32 1 +// CHECK-NEXT: %4625 = load { ptr, ptr }, ptr @main.V, align 8 +// CHECK-NEXT: %4626 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 8) +// CHECK-NEXT: store { i64 } zeroinitializer, ptr %4626, align 8 +// CHECK-NEXT: %4627 = insertvalue %"{{.*}}/runtime/internal/runtime.eface" { ptr @"{{.*}}/cl/_testgo/reflectconv.struct$qCYMduDqkoVspSDbQftiUv7WF_sipKSWG3oLt28TNlI", ptr undef }, ptr %4626, 1 +// CHECK-NEXT: %4628 = extractvalue { ptr, ptr } %4625, 1 +// CHECK-NEXT: %4629 = extractvalue { ptr, ptr } %4625, 0 +// CHECK-NEXT: %__llgo_funcval_code597 = call ptr asm "", "=r,0"(ptr %4629) +// CHECK-NEXT: %4630 = call %reflect.Value %__llgo_funcval_code597(ptr {{(nest|swiftself)}} %4628, %"{{.*}}/runtime/internal/runtime.eface" %4627) +// CHECK-NEXT: store %reflect.Value %4623, ptr %4617, align 8 +// CHECK-NEXT: store %reflect.Value %4630, ptr %4624, align 8 +// CHECK-NEXT: %4631 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %1, i64 299 +// CHECK-NEXT: %4632 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %4631, i32 0, i32 0 +// CHECK-NEXT: %4633 = load { ptr, ptr }, ptr @main.V, align 8 +// CHECK-NEXT: %4634 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 8) +// CHECK-NEXT: store { i64 } zeroinitializer, ptr %4634, align 8 +// CHECK-NEXT: %4635 = insertvalue %"{{.*}}/runtime/internal/runtime.eface" { ptr @"{{.*}}/cl/_testgo/reflectconv.struct$qCYMduDqkoVspSDbQftiUv7WF_sipKSWG3oLt28TNlI", ptr undef }, ptr %4634, 1 +// CHECK-NEXT: %4636 = extractvalue { ptr, ptr } %4633, 1 +// CHECK-NEXT: %4637 = extractvalue { ptr, ptr } %4633, 0 +// CHECK-NEXT: %__llgo_funcval_code598 = call ptr asm "", "=r,0"(ptr %4637) +// CHECK-NEXT: %4638 = call %reflect.Value %__llgo_funcval_code598(ptr {{(nest|swiftself)}} %4636, %"{{.*}}/runtime/internal/runtime.eface" %4635) +// CHECK-NEXT: %4639 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %4631, i32 0, i32 1 +// CHECK-NEXT: %4640 = load { ptr, ptr }, ptr @main.V, align 8 +// CHECK-NEXT: %4641 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 8) +// CHECK-NEXT: store %main.MyStruct zeroinitializer, ptr %4641, align 8 +// CHECK-NEXT: %4642 = insertvalue %"{{.*}}/runtime/internal/runtime.eface" { ptr @_llgo_main.MyStruct, ptr undef }, ptr %4641, 1 +// CHECK-NEXT: %4643 = extractvalue { ptr, ptr } %4640, 1 +// CHECK-NEXT: %4644 = extractvalue { ptr, ptr } %4640, 0 +// CHECK-NEXT: %__llgo_funcval_code599 = call ptr asm "", "=r,0"(ptr %4644) +// CHECK-NEXT: %4645 = call %reflect.Value %__llgo_funcval_code599(ptr {{(nest|swiftself)}} %4643, %"{{.*}}/runtime/internal/runtime.eface" %4642) +// CHECK-NEXT: store %reflect.Value %4638, ptr %4632, align 8 +// CHECK-NEXT: store %reflect.Value %4645, ptr %4639, align 8 +// CHECK-NEXT: %4646 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %1, i64 300 +// CHECK-NEXT: %4647 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %4646, i32 0, i32 0 +// CHECK-NEXT: %4648 = load { ptr, ptr }, ptr @main.V, align 8 +// CHECK-NEXT: %4649 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 8) +// CHECK-NEXT: store %main.MyStruct zeroinitializer, ptr %4649, align 8 +// CHECK-NEXT: %4650 = insertvalue %"{{.*}}/runtime/internal/runtime.eface" { ptr @_llgo_main.MyStruct, ptr undef }, ptr %4649, 1 +// CHECK-NEXT: %4651 = extractvalue { ptr, ptr } %4648, 1 +// CHECK-NEXT: %4652 = extractvalue { ptr, ptr } %4648, 0 +// CHECK-NEXT: %__llgo_funcval_code600 = call ptr asm "", "=r,0"(ptr %4652) +// CHECK-NEXT: %4653 = call %reflect.Value %__llgo_funcval_code600(ptr {{(nest|swiftself)}} %4651, %"{{.*}}/runtime/internal/runtime.eface" %4650) +// CHECK-NEXT: %4654 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %4646, i32 0, i32 1 +// CHECK-NEXT: %4655 = load { ptr, ptr }, ptr @main.V, align 8 +// CHECK-NEXT: %4656 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 8) +// CHECK-NEXT: store { i64 } zeroinitializer, ptr %4656, align 8 +// CHECK-NEXT: %4657 = insertvalue %"{{.*}}/runtime/internal/runtime.eface" { ptr @"{{.*}}/cl/_testgo/reflectconv.struct$8xdZyDeCx3tqPdt33CJnJ-JMAObkKtPXr9OL-lBc3yU", ptr undef }, ptr %4656, 1 +// CHECK-NEXT: %4658 = extractvalue { ptr, ptr } %4655, 1 +// CHECK-NEXT: %4659 = extractvalue { ptr, ptr } %4655, 0 +// CHECK-NEXT: %__llgo_funcval_code601 = call ptr asm "", "=r,0"(ptr %4659) +// CHECK-NEXT: %4660 = call %reflect.Value %__llgo_funcval_code601(ptr {{(nest|swiftself)}} %4658, %"{{.*}}/runtime/internal/runtime.eface" %4657) +// CHECK-NEXT: store %reflect.Value %4653, ptr %4647, align 8 +// CHECK-NEXT: store %reflect.Value %4660, ptr %4654, align 8 +// CHECK-NEXT: %4661 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %1, i64 301 +// CHECK-NEXT: %4662 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %4661, i32 0, i32 0 +// CHECK-NEXT: %4663 = load { ptr, ptr }, ptr @main.V, align 8 +// CHECK-NEXT: %4664 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 8) +// CHECK-NEXT: store { i64 } zeroinitializer, ptr %4664, align 8 +// CHECK-NEXT: %4665 = insertvalue %"{{.*}}/runtime/internal/runtime.eface" { ptr @"{{.*}}/cl/_testgo/reflectconv.struct$8xdZyDeCx3tqPdt33CJnJ-JMAObkKtPXr9OL-lBc3yU", ptr undef }, ptr %4664, 1 +// CHECK-NEXT: %4666 = extractvalue { ptr, ptr } %4663, 1 +// CHECK-NEXT: %4667 = extractvalue { ptr, ptr } %4663, 0 +// CHECK-NEXT: %__llgo_funcval_code602 = call ptr asm "", "=r,0"(ptr %4667) +// CHECK-NEXT: %4668 = call %reflect.Value %__llgo_funcval_code602(ptr {{(nest|swiftself)}} %4666, %"{{.*}}/runtime/internal/runtime.eface" %4665) +// CHECK-NEXT: %4669 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %4661, i32 0, i32 1 +// CHECK-NEXT: %4670 = load { ptr, ptr }, ptr @main.V, align 8 +// CHECK-NEXT: %4671 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 8) +// CHECK-NEXT: store %main.MyStruct zeroinitializer, ptr %4671, align 8 +// CHECK-NEXT: %4672 = insertvalue %"{{.*}}/runtime/internal/runtime.eface" { ptr @_llgo_main.MyStruct, ptr undef }, ptr %4671, 1 +// CHECK-NEXT: %4673 = extractvalue { ptr, ptr } %4670, 1 +// CHECK-NEXT: %4674 = extractvalue { ptr, ptr } %4670, 0 +// CHECK-NEXT: %__llgo_funcval_code603 = call ptr asm "", "=r,0"(ptr %4674) +// CHECK-NEXT: %4675 = call %reflect.Value %__llgo_funcval_code603(ptr {{(nest|swiftself)}} %4673, %"{{.*}}/runtime/internal/runtime.eface" %4672) +// CHECK-NEXT: store %reflect.Value %4668, ptr %4662, align 8 +// CHECK-NEXT: store %reflect.Value %4675, ptr %4669, align 8 +// CHECK-NEXT: %4676 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %1, i64 302 +// CHECK-NEXT: %4677 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %4676, i32 0, i32 0 +// CHECK-NEXT: %4678 = load { ptr, ptr }, ptr @main.V, align 8 +// CHECK-NEXT: %4679 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 8) +// CHECK-NEXT: store %main.MyStruct1 zeroinitializer, ptr %4679, align 8 +// CHECK-NEXT: %4680 = insertvalue %"{{.*}}/runtime/internal/runtime.eface" { ptr @_llgo_main.MyStruct1, ptr undef }, ptr %4679, 1 +// CHECK-NEXT: %4681 = extractvalue { ptr, ptr } %4678, 1 +// CHECK-NEXT: %4682 = extractvalue { ptr, ptr } %4678, 0 +// CHECK-NEXT: %__llgo_funcval_code604 = call ptr asm "", "=r,0"(ptr %4682) +// CHECK-NEXT: %4683 = call %reflect.Value %__llgo_funcval_code604(ptr {{(nest|swiftself)}} %4681, %"{{.*}}/runtime/internal/runtime.eface" %4680) +// CHECK-NEXT: %4684 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %4676, i32 0, i32 1 +// CHECK-NEXT: %4685 = load { ptr, ptr }, ptr @main.V, align 8 +// CHECK-NEXT: %4686 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 8) +// CHECK-NEXT: store %main.MyStruct2 zeroinitializer, ptr %4686, align 8 +// CHECK-NEXT: %4687 = insertvalue %"{{.*}}/runtime/internal/runtime.eface" { ptr @_llgo_main.MyStruct2, ptr undef }, ptr %4686, 1 +// CHECK-NEXT: %4688 = extractvalue { ptr, ptr } %4685, 1 +// CHECK-NEXT: %4689 = extractvalue { ptr, ptr } %4685, 0 +// CHECK-NEXT: %__llgo_funcval_code605 = call ptr asm "", "=r,0"(ptr %4689) +// CHECK-NEXT: %4690 = call %reflect.Value %__llgo_funcval_code605(ptr {{(nest|swiftself)}} %4688, %"{{.*}}/runtime/internal/runtime.eface" %4687) +// CHECK-NEXT: store %reflect.Value %4683, ptr %4677, align 8 +// CHECK-NEXT: store %reflect.Value %4690, ptr %4684, align 8 +// CHECK-NEXT: %4691 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %1, i64 303 +// CHECK-NEXT: %4692 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %4691, i32 0, i32 0 +// CHECK-NEXT: %4693 = load { ptr, ptr }, ptr @main.V, align 8 +// CHECK-NEXT: %4694 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 8) +// CHECK-NEXT: store %main.MyStruct2 zeroinitializer, ptr %4694, align 8 +// CHECK-NEXT: %4695 = insertvalue %"{{.*}}/runtime/internal/runtime.eface" { ptr @_llgo_main.MyStruct2, ptr undef }, ptr %4694, 1 +// CHECK-NEXT: %4696 = extractvalue { ptr, ptr } %4693, 1 +// CHECK-NEXT: %4697 = extractvalue { ptr, ptr } %4693, 0 +// CHECK-NEXT: %__llgo_funcval_code606 = call ptr asm "", "=r,0"(ptr %4697) +// CHECK-NEXT: %4698 = call %reflect.Value %__llgo_funcval_code606(ptr {{(nest|swiftself)}} %4696, %"{{.*}}/runtime/internal/runtime.eface" %4695) +// CHECK-NEXT: %4699 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %4691, i32 0, i32 1 +// CHECK-NEXT: %4700 = load { ptr, ptr }, ptr @main.V, align 8 +// CHECK-NEXT: %4701 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 8) +// CHECK-NEXT: store %main.MyStruct1 zeroinitializer, ptr %4701, align 8 +// CHECK-NEXT: %4702 = insertvalue %"{{.*}}/runtime/internal/runtime.eface" { ptr @_llgo_main.MyStruct1, ptr undef }, ptr %4701, 1 +// CHECK-NEXT: %4703 = extractvalue { ptr, ptr } %4700, 1 +// CHECK-NEXT: %4704 = extractvalue { ptr, ptr } %4700, 0 +// CHECK-NEXT: %__llgo_funcval_code607 = call ptr asm "", "=r,0"(ptr %4704) +// CHECK-NEXT: %4705 = call %reflect.Value %__llgo_funcval_code607(ptr {{(nest|swiftself)}} %4703, %"{{.*}}/runtime/internal/runtime.eface" %4702) +// CHECK-NEXT: store %reflect.Value %4698, ptr %4692, align 8 +// CHECK-NEXT: store %reflect.Value %4705, ptr %4699, align 8 +// CHECK-NEXT: %4706 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %1, i64 304 +// CHECK-NEXT: %4707 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %4706, i32 0, i32 0 +// CHECK-NEXT: %4708 = load { ptr, ptr }, ptr @main.V, align 8 +// CHECK-NEXT: %4709 = extractvalue { ptr, ptr } %4708, 1 +// CHECK-NEXT: %4710 = extractvalue { ptr, ptr } %4708, 0 +// CHECK-NEXT: %__llgo_funcval_code608 = call ptr asm "", "=r,0"(ptr %4710) +// CHECK-NEXT: %4711 = call %reflect.Value %__llgo_funcval_code608(ptr {{(nest|swiftself)}} %4709, %"{{.*}}/runtime/internal/runtime.eface" { ptr @"*_llgo_uint8", ptr null }) +// CHECK-NEXT: %4712 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %4706, i32 0, i32 1 +// CHECK-NEXT: %4713 = load { ptr, ptr }, ptr @main.V, align 8 +// CHECK-NEXT: %4714 = extractvalue { ptr, ptr } %4713, 1 +// CHECK-NEXT: %4715 = extractvalue { ptr, ptr } %4713, 0 +// CHECK-NEXT: %__llgo_funcval_code609 = call ptr asm "", "=r,0"(ptr %4715) +// CHECK-NEXT: %4716 = call %reflect.Value %__llgo_funcval_code609(ptr {{(nest|swiftself)}} %4714, %"{{.*}}/runtime/internal/runtime.eface" { ptr @"*_llgo_main.MyByte", ptr null }) +// CHECK-NEXT: store %reflect.Value %4711, ptr %4707, align 8 +// CHECK-NEXT: store %reflect.Value %4716, ptr %4712, align 8 +// CHECK-NEXT: %4717 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %1, i64 305 +// CHECK-NEXT: %4718 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %4717, i32 0, i32 0 +// CHECK-NEXT: %4719 = load { ptr, ptr }, ptr @main.V, align 8 +// CHECK-NEXT: %4720 = extractvalue { ptr, ptr } %4719, 1 +// CHECK-NEXT: %4721 = extractvalue { ptr, ptr } %4719, 0 +// CHECK-NEXT: %__llgo_funcval_code610 = call ptr asm "", "=r,0"(ptr %4721) +// CHECK-NEXT: %4722 = call %reflect.Value %__llgo_funcval_code610(ptr {{(nest|swiftself)}} %4720, %"{{.*}}/runtime/internal/runtime.eface" { ptr @"*_llgo_main.MyByte", ptr null }) +// CHECK-NEXT: %4723 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %4717, i32 0, i32 1 +// CHECK-NEXT: %4724 = load { ptr, ptr }, ptr @main.V, align 8 +// CHECK-NEXT: %4725 = extractvalue { ptr, ptr } %4724, 1 +// CHECK-NEXT: %4726 = extractvalue { ptr, ptr } %4724, 0 +// CHECK-NEXT: %__llgo_funcval_code611 = call ptr asm "", "=r,0"(ptr %4726) +// CHECK-NEXT: %4727 = call %reflect.Value %__llgo_funcval_code611(ptr {{(nest|swiftself)}} %4725, %"{{.*}}/runtime/internal/runtime.eface" { ptr @"*_llgo_uint8", ptr null }) +// CHECK-NEXT: store %reflect.Value %4722, ptr %4718, align 8 +// CHECK-NEXT: store %reflect.Value %4727, ptr %4723, align 8 +// CHECK-NEXT: %4728 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %1, i64 306 +// CHECK-NEXT: %4729 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %4728, i32 0, i32 0 +// CHECK-NEXT: %4730 = load { ptr, ptr }, ptr @main.V, align 8 +// CHECK-NEXT: %4731 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 2) +// CHECK-NEXT: store [2 x i8] zeroinitializer, ptr %4731, align 1 +// CHECK-NEXT: %4732 = insertvalue %"{{.*}}/runtime/internal/runtime.eface" { ptr @"[2]_llgo_uint8", ptr undef }, ptr %4731, 1 +// CHECK-NEXT: %4733 = extractvalue { ptr, ptr } %4730, 1 +// CHECK-NEXT: %4734 = extractvalue { ptr, ptr } %4730, 0 +// CHECK-NEXT: %__llgo_funcval_code612 = call ptr asm "", "=r,0"(ptr %4734) +// CHECK-NEXT: %4735 = call %reflect.Value %__llgo_funcval_code612(ptr {{(nest|swiftself)}} %4733, %"{{.*}}/runtime/internal/runtime.eface" %4732) +// CHECK-NEXT: %4736 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %4728, i32 0, i32 1 +// CHECK-NEXT: %4737 = load { ptr, ptr }, ptr @main.V, align 8 +// CHECK-NEXT: %4738 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 2) +// CHECK-NEXT: store [2 x i8] zeroinitializer, ptr %4738, align 1 +// CHECK-NEXT: %4739 = insertvalue %"{{.*}}/runtime/internal/runtime.eface" { ptr @"[2]_llgo_uint8", ptr undef }, ptr %4738, 1 +// CHECK-NEXT: %4740 = extractvalue { ptr, ptr } %4737, 1 +// CHECK-NEXT: %4741 = extractvalue { ptr, ptr } %4737, 0 +// CHECK-NEXT: %__llgo_funcval_code613 = call ptr asm "", "=r,0"(ptr %4741) +// CHECK-NEXT: %4742 = call %reflect.Value %__llgo_funcval_code613(ptr {{(nest|swiftself)}} %4740, %"{{.*}}/runtime/internal/runtime.eface" %4739) +// CHECK-NEXT: store %reflect.Value %4735, ptr %4729, align 8 +// CHECK-NEXT: store %reflect.Value %4742, ptr %4736, align 8 +// CHECK-NEXT: %4743 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %1, i64 307 +// CHECK-NEXT: %4744 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %4743, i32 0, i32 0 +// CHECK-NEXT: %4745 = load { ptr, ptr }, ptr @main.V, align 8 +// CHECK-NEXT: %4746 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 3) +// CHECK-NEXT: store [3 x i8] zeroinitializer, ptr %4746, align 1 +// CHECK-NEXT: %4747 = insertvalue %"{{.*}}/runtime/internal/runtime.eface" { ptr @"[3]_llgo_uint8", ptr undef }, ptr %4746, 1 +// CHECK-NEXT: %4748 = extractvalue { ptr, ptr } %4745, 1 +// CHECK-NEXT: %4749 = extractvalue { ptr, ptr } %4745, 0 +// CHECK-NEXT: %__llgo_funcval_code614 = call ptr asm "", "=r,0"(ptr %4749) +// CHECK-NEXT: %4750 = call %reflect.Value %__llgo_funcval_code614(ptr {{(nest|swiftself)}} %4748, %"{{.*}}/runtime/internal/runtime.eface" %4747) +// CHECK-NEXT: %4751 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %4743, i32 0, i32 1 +// CHECK-NEXT: %4752 = load { ptr, ptr }, ptr @main.V, align 8 +// CHECK-NEXT: %4753 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 3) +// CHECK-NEXT: store [3 x i8] zeroinitializer, ptr %4753, align 1 +// CHECK-NEXT: %4754 = insertvalue %"{{.*}}/runtime/internal/runtime.eface" { ptr @"[3]_llgo_uint8", ptr undef }, ptr %4753, 1 +// CHECK-NEXT: %4755 = extractvalue { ptr, ptr } %4752, 1 +// CHECK-NEXT: %4756 = extractvalue { ptr, ptr } %4752, 0 +// CHECK-NEXT: %__llgo_funcval_code615 = call ptr asm "", "=r,0"(ptr %4756) +// CHECK-NEXT: %4757 = call %reflect.Value %__llgo_funcval_code615(ptr {{(nest|swiftself)}} %4755, %"{{.*}}/runtime/internal/runtime.eface" %4754) +// CHECK-NEXT: store %reflect.Value %4750, ptr %4744, align 8 +// CHECK-NEXT: store %reflect.Value %4757, ptr %4751, align 8 +// CHECK-NEXT: %4758 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %1, i64 308 +// CHECK-NEXT: %4759 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %4758, i32 0, i32 0 +// CHECK-NEXT: %4760 = load { ptr, ptr }, ptr @main.V, align 8 +// CHECK-NEXT: %4761 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 0) +// CHECK-NEXT: store [0 x i8] zeroinitializer, ptr %4761, align 1 +// CHECK-NEXT: %4762 = insertvalue %"{{.*}}/runtime/internal/runtime.eface" { ptr @_llgo_main.MyBytesArray0, ptr undef }, ptr %4761, 1 +// CHECK-NEXT: %4763 = extractvalue { ptr, ptr } %4760, 1 +// CHECK-NEXT: %4764 = extractvalue { ptr, ptr } %4760, 0 +// CHECK-NEXT: %__llgo_funcval_code616 = call ptr asm "", "=r,0"(ptr %4764) +// CHECK-NEXT: %4765 = call %reflect.Value %__llgo_funcval_code616(ptr {{(nest|swiftself)}} %4763, %"{{.*}}/runtime/internal/runtime.eface" %4762) +// CHECK-NEXT: %4766 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %4758, i32 0, i32 1 +// CHECK-NEXT: %4767 = load { ptr, ptr }, ptr @main.V, align 8 +// CHECK-NEXT: %4768 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 0) +// CHECK-NEXT: store [0 x i8] zeroinitializer, ptr %4768, align 1 +// CHECK-NEXT: %4769 = insertvalue %"{{.*}}/runtime/internal/runtime.eface" { ptr @"[0]_llgo_uint8", ptr undef }, ptr %4768, 1 +// CHECK-NEXT: %4770 = extractvalue { ptr, ptr } %4767, 1 +// CHECK-NEXT: %4771 = extractvalue { ptr, ptr } %4767, 0 +// CHECK-NEXT: %__llgo_funcval_code617 = call ptr asm "", "=r,0"(ptr %4771) +// CHECK-NEXT: %4772 = call %reflect.Value %__llgo_funcval_code617(ptr {{(nest|swiftself)}} %4770, %"{{.*}}/runtime/internal/runtime.eface" %4769) +// CHECK-NEXT: store %reflect.Value %4765, ptr %4759, align 8 +// CHECK-NEXT: store %reflect.Value %4772, ptr %4766, align 8 +// CHECK-NEXT: %4773 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %1, i64 309 +// CHECK-NEXT: %4774 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %4773, i32 0, i32 0 +// CHECK-NEXT: %4775 = load { ptr, ptr }, ptr @main.V, align 8 +// CHECK-NEXT: %4776 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 0) +// CHECK-NEXT: store [0 x i8] zeroinitializer, ptr %4776, align 1 +// CHECK-NEXT: %4777 = insertvalue %"{{.*}}/runtime/internal/runtime.eface" { ptr @"[0]_llgo_uint8", ptr undef }, ptr %4776, 1 +// CHECK-NEXT: %4778 = extractvalue { ptr, ptr } %4775, 1 +// CHECK-NEXT: %4779 = extractvalue { ptr, ptr } %4775, 0 +// CHECK-NEXT: %__llgo_funcval_code618 = call ptr asm "", "=r,0"(ptr %4779) +// CHECK-NEXT: %4780 = call %reflect.Value %__llgo_funcval_code618(ptr {{(nest|swiftself)}} %4778, %"{{.*}}/runtime/internal/runtime.eface" %4777) +// CHECK-NEXT: %4781 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %4773, i32 0, i32 1 +// CHECK-NEXT: %4782 = load { ptr, ptr }, ptr @main.V, align 8 +// CHECK-NEXT: %4783 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 0) +// CHECK-NEXT: store [0 x i8] zeroinitializer, ptr %4783, align 1 +// CHECK-NEXT: %4784 = insertvalue %"{{.*}}/runtime/internal/runtime.eface" { ptr @_llgo_main.MyBytesArray0, ptr undef }, ptr %4783, 1 +// CHECK-NEXT: %4785 = extractvalue { ptr, ptr } %4782, 1 +// CHECK-NEXT: %4786 = extractvalue { ptr, ptr } %4782, 0 +// CHECK-NEXT: %__llgo_funcval_code619 = call ptr asm "", "=r,0"(ptr %4786) +// CHECK-NEXT: %4787 = call %reflect.Value %__llgo_funcval_code619(ptr {{(nest|swiftself)}} %4785, %"{{.*}}/runtime/internal/runtime.eface" %4784) +// CHECK-NEXT: store %reflect.Value %4780, ptr %4774, align 8 +// CHECK-NEXT: store %reflect.Value %4787, ptr %4781, align 8 +// CHECK-NEXT: %4788 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %1, i64 310 +// CHECK-NEXT: %4789 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %4788, i32 0, i32 0 +// CHECK-NEXT: %4790 = load { ptr, ptr }, ptr @main.V, align 8 +// CHECK-NEXT: %4791 = extractvalue { ptr, ptr } %4790, 1 +// CHECK-NEXT: %4792 = extractvalue { ptr, ptr } %4790, 0 +// CHECK-NEXT: %__llgo_funcval_code620 = call ptr asm "", "=r,0"(ptr %4792) +// CHECK-NEXT: %4793 = call %reflect.Value %__llgo_funcval_code620(ptr {{(nest|swiftself)}} %4791, %"{{.*}}/runtime/internal/runtime.eface" { ptr @"**_llgo_uint8", ptr null }) +// CHECK-NEXT: %4794 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %4788, i32 0, i32 1 +// CHECK-NEXT: %4795 = load { ptr, ptr }, ptr @main.V, align 8 +// CHECK-NEXT: %4796 = extractvalue { ptr, ptr } %4795, 1 +// CHECK-NEXT: %4797 = extractvalue { ptr, ptr } %4795, 0 +// CHECK-NEXT: %__llgo_funcval_code621 = call ptr asm "", "=r,0"(ptr %4797) +// CHECK-NEXT: %4798 = call %reflect.Value %__llgo_funcval_code621(ptr {{(nest|swiftself)}} %4796, %"{{.*}}/runtime/internal/runtime.eface" { ptr @"**_llgo_uint8", ptr null }) +// CHECK-NEXT: store %reflect.Value %4793, ptr %4789, align 8 +// CHECK-NEXT: store %reflect.Value %4798, ptr %4794, align 8 +// CHECK-NEXT: %4799 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %1, i64 311 +// CHECK-NEXT: %4800 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %4799, i32 0, i32 0 +// CHECK-NEXT: %4801 = load { ptr, ptr }, ptr @main.V, align 8 +// CHECK-NEXT: %4802 = extractvalue { ptr, ptr } %4801, 1 +// CHECK-NEXT: %4803 = extractvalue { ptr, ptr } %4801, 0 +// CHECK-NEXT: %__llgo_funcval_code622 = call ptr asm "", "=r,0"(ptr %4803) +// CHECK-NEXT: %4804 = call %reflect.Value %__llgo_funcval_code622(ptr {{(nest|swiftself)}} %4802, %"{{.*}}/runtime/internal/runtime.eface" { ptr @"**_llgo_main.MyByte", ptr null }) +// CHECK-NEXT: %4805 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %4799, i32 0, i32 1 +// CHECK-NEXT: %4806 = load { ptr, ptr }, ptr @main.V, align 8 +// CHECK-NEXT: %4807 = extractvalue { ptr, ptr } %4806, 1 +// CHECK-NEXT: %4808 = extractvalue { ptr, ptr } %4806, 0 +// CHECK-NEXT: %__llgo_funcval_code623 = call ptr asm "", "=r,0"(ptr %4808) +// CHECK-NEXT: %4809 = call %reflect.Value %__llgo_funcval_code623(ptr {{(nest|swiftself)}} %4807, %"{{.*}}/runtime/internal/runtime.eface" { ptr @"**_llgo_main.MyByte", ptr null }) +// CHECK-NEXT: store %reflect.Value %4804, ptr %4800, align 8 +// CHECK-NEXT: store %reflect.Value %4809, ptr %4805, align 8 +// CHECK-NEXT: %4810 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %1, i64 312 +// CHECK-NEXT: %4811 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %4810, i32 0, i32 0 +// CHECK-NEXT: %4812 = load { ptr, ptr }, ptr @main.V, align 8 +// CHECK-NEXT: %4813 = extractvalue { ptr, ptr } %4812, 1 +// CHECK-NEXT: %4814 = extractvalue { ptr, ptr } %4812, 0 +// CHECK-NEXT: %__llgo_funcval_code624 = call ptr asm "", "=r,0"(ptr %4814) +// CHECK-NEXT: %4815 = call %reflect.Value %__llgo_funcval_code624(ptr {{(nest|swiftself)}} %4813, %"{{.*}}/runtime/internal/runtime.eface" { ptr @"chan _llgo_uint8", ptr null }) +// CHECK-NEXT: %4816 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %4810, i32 0, i32 1 +// CHECK-NEXT: %4817 = load { ptr, ptr }, ptr @main.V, align 8 +// CHECK-NEXT: %4818 = extractvalue { ptr, ptr } %4817, 1 +// CHECK-NEXT: %4819 = extractvalue { ptr, ptr } %4817, 0 +// CHECK-NEXT: %__llgo_funcval_code625 = call ptr asm "", "=r,0"(ptr %4819) +// CHECK-NEXT: %4820 = call %reflect.Value %__llgo_funcval_code625(ptr {{(nest|swiftself)}} %4818, %"{{.*}}/runtime/internal/runtime.eface" { ptr @"chan _llgo_uint8", ptr null }) +// CHECK-NEXT: store %reflect.Value %4815, ptr %4811, align 8 +// CHECK-NEXT: store %reflect.Value %4820, ptr %4816, align 8 +// CHECK-NEXT: %4821 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %1, i64 313 +// CHECK-NEXT: %4822 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %4821, i32 0, i32 0 +// CHECK-NEXT: %4823 = load { ptr, ptr }, ptr @main.V, align 8 +// CHECK-NEXT: %4824 = extractvalue { ptr, ptr } %4823, 1 +// CHECK-NEXT: %4825 = extractvalue { ptr, ptr } %4823, 0 +// CHECK-NEXT: %__llgo_funcval_code626 = call ptr asm "", "=r,0"(ptr %4825) +// CHECK-NEXT: %4826 = call %reflect.Value %__llgo_funcval_code626(ptr {{(nest|swiftself)}} %4824, %"{{.*}}/runtime/internal/runtime.eface" { ptr @"chan _llgo_main.MyByte", ptr null }) +// CHECK-NEXT: %4827 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %4821, i32 0, i32 1 +// CHECK-NEXT: %4828 = load { ptr, ptr }, ptr @main.V, align 8 +// CHECK-NEXT: %4829 = extractvalue { ptr, ptr } %4828, 1 +// CHECK-NEXT: %4830 = extractvalue { ptr, ptr } %4828, 0 +// CHECK-NEXT: %__llgo_funcval_code627 = call ptr asm "", "=r,0"(ptr %4830) +// CHECK-NEXT: %4831 = call %reflect.Value %__llgo_funcval_code627(ptr {{(nest|swiftself)}} %4829, %"{{.*}}/runtime/internal/runtime.eface" { ptr @"chan _llgo_main.MyByte", ptr null }) +// CHECK-NEXT: store %reflect.Value %4826, ptr %4822, align 8 +// CHECK-NEXT: store %reflect.Value %4831, ptr %4827, align 8 +// CHECK-NEXT: %4832 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %1, i64 314 +// CHECK-NEXT: %4833 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %4832, i32 0, i32 0 +// CHECK-NEXT: %4834 = load { ptr, ptr }, ptr @main.V, align 8 +// CHECK-NEXT: %4835 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 24) +// CHECK-NEXT: store %"{{.*}}/runtime/internal/runtime.Slice" zeroinitializer, ptr %4835, align 8 +// CHECK-NEXT: %4836 = insertvalue %"{{.*}}/runtime/internal/runtime.eface" { ptr @"[]_llgo_uint8", ptr undef }, ptr %4835, 1 +// CHECK-NEXT: %4837 = extractvalue { ptr, ptr } %4834, 1 +// CHECK-NEXT: %4838 = extractvalue { ptr, ptr } %4834, 0 +// CHECK-NEXT: %__llgo_funcval_code628 = call ptr asm "", "=r,0"(ptr %4838) +// CHECK-NEXT: %4839 = call %reflect.Value %__llgo_funcval_code628(ptr {{(nest|swiftself)}} %4837, %"{{.*}}/runtime/internal/runtime.eface" %4836) +// CHECK-NEXT: %4840 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %4832, i32 0, i32 1 +// CHECK-NEXT: %4841 = load { ptr, ptr }, ptr @main.V, align 8 +// CHECK-NEXT: %4842 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 24) +// CHECK-NEXT: store %"{{.*}}/runtime/internal/runtime.Slice" zeroinitializer, ptr %4842, align 8 +// CHECK-NEXT: %4843 = insertvalue %"{{.*}}/runtime/internal/runtime.eface" { ptr @"[]_llgo_uint8", ptr undef }, ptr %4842, 1 +// CHECK-NEXT: %4844 = extractvalue { ptr, ptr } %4841, 1 +// CHECK-NEXT: %4845 = extractvalue { ptr, ptr } %4841, 0 +// CHECK-NEXT: %__llgo_funcval_code629 = call ptr asm "", "=r,0"(ptr %4845) +// CHECK-NEXT: %4846 = call %reflect.Value %__llgo_funcval_code629(ptr {{(nest|swiftself)}} %4844, %"{{.*}}/runtime/internal/runtime.eface" %4843) +// CHECK-NEXT: store %reflect.Value %4839, ptr %4833, align 8 +// CHECK-NEXT: store %reflect.Value %4846, ptr %4840, align 8 +// CHECK-NEXT: %4847 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %1, i64 315 +// CHECK-NEXT: %4848 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %4847, i32 0, i32 0 +// CHECK-NEXT: %4849 = load { ptr, ptr }, ptr @main.V, align 8 +// CHECK-NEXT: %4850 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 24) +// CHECK-NEXT: store %"{{.*}}/runtime/internal/runtime.Slice" zeroinitializer, ptr %4850, align 8 +// CHECK-NEXT: %4851 = insertvalue %"{{.*}}/runtime/internal/runtime.eface" { ptr @"[]_llgo_main.MyByte", ptr undef }, ptr %4850, 1 +// CHECK-NEXT: %4852 = extractvalue { ptr, ptr } %4849, 1 +// CHECK-NEXT: %4853 = extractvalue { ptr, ptr } %4849, 0 +// CHECK-NEXT: %__llgo_funcval_code630 = call ptr asm "", "=r,0"(ptr %4853) +// CHECK-NEXT: %4854 = call %reflect.Value %__llgo_funcval_code630(ptr {{(nest|swiftself)}} %4852, %"{{.*}}/runtime/internal/runtime.eface" %4851) +// CHECK-NEXT: %4855 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %4847, i32 0, i32 1 +// CHECK-NEXT: %4856 = load { ptr, ptr }, ptr @main.V, align 8 +// CHECK-NEXT: %4857 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 24) +// CHECK-NEXT: store %"{{.*}}/runtime/internal/runtime.Slice" zeroinitializer, ptr %4857, align 8 +// CHECK-NEXT: %4858 = insertvalue %"{{.*}}/runtime/internal/runtime.eface" { ptr @"[]_llgo_main.MyByte", ptr undef }, ptr %4857, 1 +// CHECK-NEXT: %4859 = extractvalue { ptr, ptr } %4856, 1 +// CHECK-NEXT: %4860 = extractvalue { ptr, ptr } %4856, 0 +// CHECK-NEXT: %__llgo_funcval_code631 = call ptr asm "", "=r,0"(ptr %4860) +// CHECK-NEXT: %4861 = call %reflect.Value %__llgo_funcval_code631(ptr {{(nest|swiftself)}} %4859, %"{{.*}}/runtime/internal/runtime.eface" %4858) +// CHECK-NEXT: store %reflect.Value %4854, ptr %4848, align 8 +// CHECK-NEXT: store %reflect.Value %4861, ptr %4855, align 8 +// CHECK-NEXT: %4862 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %1, i64 316 +// CHECK-NEXT: %4863 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %4862, i32 0, i32 0 +// CHECK-NEXT: %4864 = load { ptr, ptr }, ptr @main.V, align 8 +// CHECK-NEXT: %4865 = extractvalue { ptr, ptr } %4864, 1 +// CHECK-NEXT: %4866 = extractvalue { ptr, ptr } %4864, 0 +// CHECK-NEXT: %__llgo_funcval_code632 = call ptr asm "", "=r,0"(ptr %4866) +// CHECK-NEXT: %4867 = call %reflect.Value %__llgo_funcval_code632(ptr {{(nest|swiftself)}} %4865, %"{{.*}}/runtime/internal/runtime.eface" { ptr @"map[_llgo_int]_llgo_uint8", ptr null }) +// CHECK-NEXT: %4868 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %4862, i32 0, i32 1 +// CHECK-NEXT: %4869 = load { ptr, ptr }, ptr @main.V, align 8 +// CHECK-NEXT: %4870 = extractvalue { ptr, ptr } %4869, 1 +// CHECK-NEXT: %4871 = extractvalue { ptr, ptr } %4869, 0 +// CHECK-NEXT: %__llgo_funcval_code633 = call ptr asm "", "=r,0"(ptr %4871) +// CHECK-NEXT: %4872 = call %reflect.Value %__llgo_funcval_code633(ptr {{(nest|swiftself)}} %4870, %"{{.*}}/runtime/internal/runtime.eface" { ptr @"map[_llgo_int]_llgo_uint8", ptr null }) +// CHECK-NEXT: store %reflect.Value %4867, ptr %4863, align 8 +// CHECK-NEXT: store %reflect.Value %4872, ptr %4868, align 8 +// CHECK-NEXT: %4873 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %1, i64 317 +// CHECK-NEXT: %4874 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %4873, i32 0, i32 0 +// CHECK-NEXT: %4875 = load { ptr, ptr }, ptr @main.V, align 8 +// CHECK-NEXT: %4876 = extractvalue { ptr, ptr } %4875, 1 +// CHECK-NEXT: %4877 = extractvalue { ptr, ptr } %4875, 0 +// CHECK-NEXT: %__llgo_funcval_code634 = call ptr asm "", "=r,0"(ptr %4877) +// CHECK-NEXT: %4878 = call %reflect.Value %__llgo_funcval_code634(ptr {{(nest|swiftself)}} %4876, %"{{.*}}/runtime/internal/runtime.eface" { ptr @"map[_llgo_int]_llgo_main.MyByte", ptr null }) +// CHECK-NEXT: %4879 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %4873, i32 0, i32 1 +// CHECK-NEXT: %4880 = load { ptr, ptr }, ptr @main.V, align 8 +// CHECK-NEXT: %4881 = extractvalue { ptr, ptr } %4880, 1 +// CHECK-NEXT: %4882 = extractvalue { ptr, ptr } %4880, 0 +// CHECK-NEXT: %__llgo_funcval_code635 = call ptr asm "", "=r,0"(ptr %4882) +// CHECK-NEXT: %4883 = call %reflect.Value %__llgo_funcval_code635(ptr {{(nest|swiftself)}} %4881, %"{{.*}}/runtime/internal/runtime.eface" { ptr @"map[_llgo_int]_llgo_main.MyByte", ptr null }) +// CHECK-NEXT: store %reflect.Value %4878, ptr %4874, align 8 +// CHECK-NEXT: store %reflect.Value %4883, ptr %4879, align 8 +// CHECK-NEXT: %4884 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %1, i64 318 +// CHECK-NEXT: %4885 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %4884, i32 0, i32 0 +// CHECK-NEXT: %4886 = load { ptr, ptr }, ptr @main.V, align 8 +// CHECK-NEXT: %4887 = extractvalue { ptr, ptr } %4886, 1 +// CHECK-NEXT: %4888 = extractvalue { ptr, ptr } %4886, 0 +// CHECK-NEXT: %__llgo_funcval_code636 = call ptr asm "", "=r,0"(ptr %4888) +// CHECK-NEXT: %4889 = call %reflect.Value %__llgo_funcval_code636(ptr {{(nest|swiftself)}} %4887, %"{{.*}}/runtime/internal/runtime.eface" { ptr @"map[_llgo_uint8]_llgo_int", ptr null }) +// CHECK-NEXT: %4890 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %4884, i32 0, i32 1 +// CHECK-NEXT: %4891 = load { ptr, ptr }, ptr @main.V, align 8 +// CHECK-NEXT: %4892 = extractvalue { ptr, ptr } %4891, 1 +// CHECK-NEXT: %4893 = extractvalue { ptr, ptr } %4891, 0 +// CHECK-NEXT: %__llgo_funcval_code637 = call ptr asm "", "=r,0"(ptr %4893) +// CHECK-NEXT: %4894 = call %reflect.Value %__llgo_funcval_code637(ptr {{(nest|swiftself)}} %4892, %"{{.*}}/runtime/internal/runtime.eface" { ptr @"map[_llgo_uint8]_llgo_int", ptr null }) +// CHECK-NEXT: store %reflect.Value %4889, ptr %4885, align 8 +// CHECK-NEXT: store %reflect.Value %4894, ptr %4890, align 8 +// CHECK-NEXT: %4895 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %1, i64 319 +// CHECK-NEXT: %4896 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %4895, i32 0, i32 0 +// CHECK-NEXT: %4897 = load { ptr, ptr }, ptr @main.V, align 8 +// CHECK-NEXT: %4898 = extractvalue { ptr, ptr } %4897, 1 +// CHECK-NEXT: %4899 = extractvalue { ptr, ptr } %4897, 0 +// CHECK-NEXT: %__llgo_funcval_code638 = call ptr asm "", "=r,0"(ptr %4899) +// CHECK-NEXT: %4900 = call %reflect.Value %__llgo_funcval_code638(ptr {{(nest|swiftself)}} %4898, %"{{.*}}/runtime/internal/runtime.eface" { ptr @"map[_llgo_main.MyByte]_llgo_int", ptr null }) +// CHECK-NEXT: %4901 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %4895, i32 0, i32 1 +// CHECK-NEXT: %4902 = load { ptr, ptr }, ptr @main.V, align 8 +// CHECK-NEXT: %4903 = extractvalue { ptr, ptr } %4902, 1 +// CHECK-NEXT: %4904 = extractvalue { ptr, ptr } %4902, 0 +// CHECK-NEXT: %__llgo_funcval_code639 = call ptr asm "", "=r,0"(ptr %4904) +// CHECK-NEXT: %4905 = call %reflect.Value %__llgo_funcval_code639(ptr {{(nest|swiftself)}} %4903, %"{{.*}}/runtime/internal/runtime.eface" { ptr @"map[_llgo_main.MyByte]_llgo_int", ptr null }) +// CHECK-NEXT: store %reflect.Value %4900, ptr %4896, align 8 +// CHECK-NEXT: store %reflect.Value %4905, ptr %4901, align 8 +// CHECK-NEXT: %4906 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %1, i64 320 +// CHECK-NEXT: %4907 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %4906, i32 0, i32 0 +// CHECK-NEXT: %4908 = load { ptr, ptr }, ptr @main.V, align 8 +// CHECK-NEXT: %4909 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 2) +// CHECK-NEXT: store [2 x i8] zeroinitializer, ptr %4909, align 1 +// CHECK-NEXT: %4910 = insertvalue %"{{.*}}/runtime/internal/runtime.eface" { ptr @"[2]_llgo_uint8", ptr undef }, ptr %4909, 1 +// CHECK-NEXT: %4911 = extractvalue { ptr, ptr } %4908, 1 +// CHECK-NEXT: %4912 = extractvalue { ptr, ptr } %4908, 0 +// CHECK-NEXT: %__llgo_funcval_code640 = call ptr asm "", "=r,0"(ptr %4912) +// CHECK-NEXT: %4913 = call %reflect.Value %__llgo_funcval_code640(ptr {{(nest|swiftself)}} %4911, %"{{.*}}/runtime/internal/runtime.eface" %4910) +// CHECK-NEXT: %4914 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %4906, i32 0, i32 1 +// CHECK-NEXT: %4915 = load { ptr, ptr }, ptr @main.V, align 8 +// CHECK-NEXT: %4916 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 2) +// CHECK-NEXT: store [2 x i8] zeroinitializer, ptr %4916, align 1 +// CHECK-NEXT: %4917 = insertvalue %"{{.*}}/runtime/internal/runtime.eface" { ptr @"[2]_llgo_uint8", ptr undef }, ptr %4916, 1 +// CHECK-NEXT: %4918 = extractvalue { ptr, ptr } %4915, 1 +// CHECK-NEXT: %4919 = extractvalue { ptr, ptr } %4915, 0 +// CHECK-NEXT: %__llgo_funcval_code641 = call ptr asm "", "=r,0"(ptr %4919) +// CHECK-NEXT: %4920 = call %reflect.Value %__llgo_funcval_code641(ptr {{(nest|swiftself)}} %4918, %"{{.*}}/runtime/internal/runtime.eface" %4917) +// CHECK-NEXT: store %reflect.Value %4913, ptr %4907, align 8 +// CHECK-NEXT: store %reflect.Value %4920, ptr %4914, align 8 +// CHECK-NEXT: %4921 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %1, i64 321 +// CHECK-NEXT: %4922 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %4921, i32 0, i32 0 +// CHECK-NEXT: %4923 = load { ptr, ptr }, ptr @main.V, align 8 +// CHECK-NEXT: %4924 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 2) +// CHECK-NEXT: store [2 x i8] zeroinitializer, ptr %4924, align 1 +// CHECK-NEXT: %4925 = insertvalue %"{{.*}}/runtime/internal/runtime.eface" { ptr @"[2]_llgo_main.MyByte", ptr undef }, ptr %4924, 1 +// CHECK-NEXT: %4926 = extractvalue { ptr, ptr } %4923, 1 +// CHECK-NEXT: %4927 = extractvalue { ptr, ptr } %4923, 0 +// CHECK-NEXT: %__llgo_funcval_code642 = call ptr asm "", "=r,0"(ptr %4927) +// CHECK-NEXT: %4928 = call %reflect.Value %__llgo_funcval_code642(ptr {{(nest|swiftself)}} %4926, %"{{.*}}/runtime/internal/runtime.eface" %4925) +// CHECK-NEXT: %4929 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %4921, i32 0, i32 1 +// CHECK-NEXT: %4930 = load { ptr, ptr }, ptr @main.V, align 8 +// CHECK-NEXT: %4931 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 2) +// CHECK-NEXT: store [2 x i8] zeroinitializer, ptr %4931, align 1 +// CHECK-NEXT: %4932 = insertvalue %"{{.*}}/runtime/internal/runtime.eface" { ptr @"[2]_llgo_main.MyByte", ptr undef }, ptr %4931, 1 +// CHECK-NEXT: %4933 = extractvalue { ptr, ptr } %4930, 1 +// CHECK-NEXT: %4934 = extractvalue { ptr, ptr } %4930, 0 +// CHECK-NEXT: %__llgo_funcval_code643 = call ptr asm "", "=r,0"(ptr %4934) +// CHECK-NEXT: %4935 = call %reflect.Value %__llgo_funcval_code643(ptr {{(nest|swiftself)}} %4933, %"{{.*}}/runtime/internal/runtime.eface" %4932) +// CHECK-NEXT: store %reflect.Value %4928, ptr %4922, align 8 +// CHECK-NEXT: store %reflect.Value %4935, ptr %4929, align 8 +// CHECK-NEXT: %4936 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %1, i64 322 +// CHECK-NEXT: %4937 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %4936, i32 0, i32 0 +// CHECK-NEXT: %4938 = load { ptr, ptr }, ptr @main.V, align 8 +// CHECK-NEXT: %4939 = extractvalue { ptr, ptr } %4938, 1 +// CHECK-NEXT: %4940 = extractvalue { ptr, ptr } %4938, 0 +// CHECK-NEXT: %__llgo_funcval_code644 = call ptr asm "", "=r,0"(ptr %4940) +// CHECK-NEXT: %4941 = call %reflect.Value %__llgo_funcval_code644(ptr {{(nest|swiftself)}} %4939, %"{{.*}}/runtime/internal/runtime.eface" { ptr @"***_llgo_int", ptr null }) +// CHECK-NEXT: %4942 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %4936, i32 0, i32 1 +// CHECK-NEXT: %4943 = load { ptr, ptr }, ptr @main.V, align 8 +// CHECK-NEXT: %4944 = extractvalue { ptr, ptr } %4943, 1 +// CHECK-NEXT: %4945 = extractvalue { ptr, ptr } %4943, 0 +// CHECK-NEXT: %__llgo_funcval_code645 = call ptr asm "", "=r,0"(ptr %4945) +// CHECK-NEXT: %4946 = call %reflect.Value %__llgo_funcval_code645(ptr {{(nest|swiftself)}} %4944, %"{{.*}}/runtime/internal/runtime.eface" { ptr @"***_llgo_int", ptr null }) +// CHECK-NEXT: store %reflect.Value %4941, ptr %4937, align 8 +// CHECK-NEXT: store %reflect.Value %4946, ptr %4942, align 8 +// CHECK-NEXT: %4947 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %1, i64 323 +// CHECK-NEXT: %4948 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %4947, i32 0, i32 0 +// CHECK-NEXT: %4949 = load { ptr, ptr }, ptr @main.V, align 8 +// CHECK-NEXT: %4950 = extractvalue { ptr, ptr } %4949, 1 +// CHECK-NEXT: %4951 = extractvalue { ptr, ptr } %4949, 0 +// CHECK-NEXT: %__llgo_funcval_code646 = call ptr asm "", "=r,0"(ptr %4951) +// CHECK-NEXT: %4952 = call %reflect.Value %__llgo_funcval_code646(ptr {{(nest|swiftself)}} %4950, %"{{.*}}/runtime/internal/runtime.eface" { ptr @"***_llgo_uint8", ptr null }) +// CHECK-NEXT: %4953 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %4947, i32 0, i32 1 +// CHECK-NEXT: %4954 = load { ptr, ptr }, ptr @main.V, align 8 +// CHECK-NEXT: %4955 = extractvalue { ptr, ptr } %4954, 1 +// CHECK-NEXT: %4956 = extractvalue { ptr, ptr } %4954, 0 +// CHECK-NEXT: %__llgo_funcval_code647 = call ptr asm "", "=r,0"(ptr %4956) +// CHECK-NEXT: %4957 = call %reflect.Value %__llgo_funcval_code647(ptr {{(nest|swiftself)}} %4955, %"{{.*}}/runtime/internal/runtime.eface" { ptr @"***_llgo_uint8", ptr null }) +// CHECK-NEXT: store %reflect.Value %4952, ptr %4948, align 8 +// CHECK-NEXT: store %reflect.Value %4957, ptr %4953, align 8 +// CHECK-NEXT: %4958 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %1, i64 324 +// CHECK-NEXT: %4959 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %4958, i32 0, i32 0 +// CHECK-NEXT: %4960 = load { ptr, ptr }, ptr @main.V, align 8 +// CHECK-NEXT: %4961 = extractvalue { ptr, ptr } %4960, 1 +// CHECK-NEXT: %4962 = extractvalue { ptr, ptr } %4960, 0 +// CHECK-NEXT: %__llgo_funcval_code648 = call ptr asm "", "=r,0"(ptr %4962) +// CHECK-NEXT: %4963 = call %reflect.Value %__llgo_funcval_code648(ptr {{(nest|swiftself)}} %4961, %"{{.*}}/runtime/internal/runtime.eface" { ptr @"***_llgo_int32", ptr null }) +// CHECK-NEXT: %4964 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %4958, i32 0, i32 1 +// CHECK-NEXT: %4965 = load { ptr, ptr }, ptr @main.V, align 8 +// CHECK-NEXT: %4966 = extractvalue { ptr, ptr } %4965, 1 +// CHECK-NEXT: %4967 = extractvalue { ptr, ptr } %4965, 0 +// CHECK-NEXT: %__llgo_funcval_code649 = call ptr asm "", "=r,0"(ptr %4967) +// CHECK-NEXT: %4968 = call %reflect.Value %__llgo_funcval_code649(ptr {{(nest|swiftself)}} %4966, %"{{.*}}/runtime/internal/runtime.eface" { ptr @"***_llgo_int32", ptr null }) +// CHECK-NEXT: store %reflect.Value %4963, ptr %4959, align 8 +// CHECK-NEXT: store %reflect.Value %4968, ptr %4964, align 8 +// CHECK-NEXT: %4969 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %1, i64 325 +// CHECK-NEXT: %4970 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %4969, i32 0, i32 0 +// CHECK-NEXT: %4971 = load { ptr, ptr }, ptr @main.V, align 8 +// CHECK-NEXT: %4972 = extractvalue { ptr, ptr } %4971, 1 +// CHECK-NEXT: %4973 = extractvalue { ptr, ptr } %4971, 0 +// CHECK-NEXT: %__llgo_funcval_code650 = call ptr asm "", "=r,0"(ptr %4973) +// CHECK-NEXT: %4974 = call %reflect.Value %__llgo_funcval_code650(ptr {{(nest|swiftself)}} %4972, %"{{.*}}/runtime/internal/runtime.eface" { ptr @"***_llgo_int64", ptr null }) +// CHECK-NEXT: %4975 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %4969, i32 0, i32 1 +// CHECK-NEXT: %4976 = load { ptr, ptr }, ptr @main.V, align 8 +// CHECK-NEXT: %4977 = extractvalue { ptr, ptr } %4976, 1 +// CHECK-NEXT: %4978 = extractvalue { ptr, ptr } %4976, 0 +// CHECK-NEXT: %__llgo_funcval_code651 = call ptr asm "", "=r,0"(ptr %4978) +// CHECK-NEXT: %4979 = call %reflect.Value %__llgo_funcval_code651(ptr {{(nest|swiftself)}} %4977, %"{{.*}}/runtime/internal/runtime.eface" { ptr @"***_llgo_int64", ptr null }) +// CHECK-NEXT: store %reflect.Value %4974, ptr %4970, align 8 +// CHECK-NEXT: store %reflect.Value %4979, ptr %4975, align 8 +// CHECK-NEXT: %4980 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %1, i64 326 +// CHECK-NEXT: %4981 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %4980, i32 0, i32 0 +// CHECK-NEXT: %4982 = load { ptr, ptr }, ptr @main.V, align 8 +// CHECK-NEXT: %4983 = extractvalue { ptr, ptr } %4982, 1 +// CHECK-NEXT: %4984 = extractvalue { ptr, ptr } %4982, 0 +// CHECK-NEXT: %__llgo_funcval_code652 = call ptr asm "", "=r,0"(ptr %4984) +// CHECK-NEXT: %4985 = call %reflect.Value %__llgo_funcval_code652(ptr {{(nest|swiftself)}} %4983, %"{{.*}}/runtime/internal/runtime.eface" { ptr @"chan _llgo_uint8", ptr null }) +// CHECK-NEXT: %4986 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %4980, i32 0, i32 1 +// CHECK-NEXT: %4987 = load { ptr, ptr }, ptr @main.V, align 8 +// CHECK-NEXT: %4988 = extractvalue { ptr, ptr } %4987, 1 +// CHECK-NEXT: %4989 = extractvalue { ptr, ptr } %4987, 0 +// CHECK-NEXT: %__llgo_funcval_code653 = call ptr asm "", "=r,0"(ptr %4989) +// CHECK-NEXT: %4990 = call %reflect.Value %__llgo_funcval_code653(ptr {{(nest|swiftself)}} %4988, %"{{.*}}/runtime/internal/runtime.eface" { ptr @"chan _llgo_uint8", ptr null }) +// CHECK-NEXT: store %reflect.Value %4985, ptr %4981, align 8 +// CHECK-NEXT: store %reflect.Value %4990, ptr %4986, align 8 +// CHECK-NEXT: %4991 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %1, i64 327 +// CHECK-NEXT: %4992 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %4991, i32 0, i32 0 +// CHECK-NEXT: %4993 = load { ptr, ptr }, ptr @main.V, align 8 +// CHECK-NEXT: %4994 = extractvalue { ptr, ptr } %4993, 1 +// CHECK-NEXT: %4995 = extractvalue { ptr, ptr } %4993, 0 +// CHECK-NEXT: %__llgo_funcval_code654 = call ptr asm "", "=r,0"(ptr %4995) +// CHECK-NEXT: %4996 = call %reflect.Value %__llgo_funcval_code654(ptr {{(nest|swiftself)}} %4994, %"{{.*}}/runtime/internal/runtime.eface" { ptr @"chan _llgo_main.MyByte", ptr null }) +// CHECK-NEXT: %4997 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %4991, i32 0, i32 1 +// CHECK-NEXT: %4998 = load { ptr, ptr }, ptr @main.V, align 8 +// CHECK-NEXT: %4999 = extractvalue { ptr, ptr } %4998, 1 +// CHECK-NEXT: %5000 = extractvalue { ptr, ptr } %4998, 0 +// CHECK-NEXT: %__llgo_funcval_code655 = call ptr asm "", "=r,0"(ptr %5000) +// CHECK-NEXT: %5001 = call %reflect.Value %__llgo_funcval_code655(ptr {{(nest|swiftself)}} %4999, %"{{.*}}/runtime/internal/runtime.eface" { ptr @"chan _llgo_main.MyByte", ptr null }) +// CHECK-NEXT: store %reflect.Value %4996, ptr %4992, align 8 +// CHECK-NEXT: store %reflect.Value %5001, ptr %4997, align 8 +// CHECK-NEXT: %5002 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %1, i64 328 +// CHECK-NEXT: %5003 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %5002, i32 0, i32 0 +// CHECK-NEXT: %5004 = load { ptr, ptr }, ptr @main.V, align 8 +// CHECK-NEXT: %5005 = extractvalue { ptr, ptr } %5004, 1 +// CHECK-NEXT: %5006 = extractvalue { ptr, ptr } %5004, 0 +// CHECK-NEXT: %__llgo_funcval_code656 = call ptr asm "", "=r,0"(ptr %5006) +// CHECK-NEXT: %5007 = call %reflect.Value %__llgo_funcval_code656(ptr {{(nest|swiftself)}} %5005, %"{{.*}}/runtime/internal/runtime.eface" { ptr @"map[_llgo_int]_llgo_bool", ptr null }) +// CHECK-NEXT: %5008 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %5002, i32 0, i32 1 +// CHECK-NEXT: %5009 = load { ptr, ptr }, ptr @main.V, align 8 +// CHECK-NEXT: %5010 = extractvalue { ptr, ptr } %5009, 1 +// CHECK-NEXT: %5011 = extractvalue { ptr, ptr } %5009, 0 +// CHECK-NEXT: %__llgo_funcval_code657 = call ptr asm "", "=r,0"(ptr %5011) +// CHECK-NEXT: %5012 = call %reflect.Value %__llgo_funcval_code657(ptr {{(nest|swiftself)}} %5010, %"{{.*}}/runtime/internal/runtime.eface" { ptr @"map[_llgo_int]_llgo_bool", ptr null }) +// CHECK-NEXT: store %reflect.Value %5007, ptr %5003, align 8 +// CHECK-NEXT: store %reflect.Value %5012, ptr %5008, align 8 +// CHECK-NEXT: %5013 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %1, i64 329 +// CHECK-NEXT: %5014 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %5013, i32 0, i32 0 +// CHECK-NEXT: %5015 = load { ptr, ptr }, ptr @main.V, align 8 +// CHECK-NEXT: %5016 = extractvalue { ptr, ptr } %5015, 1 +// CHECK-NEXT: %5017 = extractvalue { ptr, ptr } %5015, 0 +// CHECK-NEXT: %__llgo_funcval_code658 = call ptr asm "", "=r,0"(ptr %5017) +// CHECK-NEXT: %5018 = call %reflect.Value %__llgo_funcval_code658(ptr {{(nest|swiftself)}} %5016, %"{{.*}}/runtime/internal/runtime.eface" { ptr @"map[_llgo_int]_llgo_uint8", ptr null }) +// CHECK-NEXT: %5019 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %5013, i32 0, i32 1 +// CHECK-NEXT: %5020 = load { ptr, ptr }, ptr @main.V, align 8 +// CHECK-NEXT: %5021 = extractvalue { ptr, ptr } %5020, 1 +// CHECK-NEXT: %5022 = extractvalue { ptr, ptr } %5020, 0 +// CHECK-NEXT: %__llgo_funcval_code659 = call ptr asm "", "=r,0"(ptr %5022) +// CHECK-NEXT: %5023 = call %reflect.Value %__llgo_funcval_code659(ptr {{(nest|swiftself)}} %5021, %"{{.*}}/runtime/internal/runtime.eface" { ptr @"map[_llgo_int]_llgo_uint8", ptr null }) +// CHECK-NEXT: store %reflect.Value %5018, ptr %5014, align 8 +// CHECK-NEXT: store %reflect.Value %5023, ptr %5019, align 8 +// CHECK-NEXT: %5024 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %1, i64 330 +// CHECK-NEXT: %5025 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %5024, i32 0, i32 0 +// CHECK-NEXT: %5026 = load { ptr, ptr }, ptr @main.V, align 8 +// CHECK-NEXT: %5027 = extractvalue { ptr, ptr } %5026, 1 +// CHECK-NEXT: %5028 = extractvalue { ptr, ptr } %5026, 0 +// CHECK-NEXT: %__llgo_funcval_code660 = call ptr asm "", "=r,0"(ptr %5028) +// CHECK-NEXT: %5029 = call %reflect.Value %__llgo_funcval_code660(ptr {{(nest|swiftself)}} %5027, %"{{.*}}/runtime/internal/runtime.eface" { ptr @"map[_llgo_uint]_llgo_bool", ptr null }) +// CHECK-NEXT: %5030 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %5024, i32 0, i32 1 +// CHECK-NEXT: %5031 = load { ptr, ptr }, ptr @main.V, align 8 +// CHECK-NEXT: %5032 = extractvalue { ptr, ptr } %5031, 1 +// CHECK-NEXT: %5033 = extractvalue { ptr, ptr } %5031, 0 +// CHECK-NEXT: %__llgo_funcval_code661 = call ptr asm "", "=r,0"(ptr %5033) +// CHECK-NEXT: %5034 = call %reflect.Value %__llgo_funcval_code661(ptr {{(nest|swiftself)}} %5032, %"{{.*}}/runtime/internal/runtime.eface" { ptr @"map[_llgo_uint]_llgo_bool", ptr null }) +// CHECK-NEXT: store %reflect.Value %5029, ptr %5025, align 8 +// CHECK-NEXT: store %reflect.Value %5034, ptr %5030, align 8 +// CHECK-NEXT: %5035 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %1, i64 331 +// CHECK-NEXT: %5036 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %5035, i32 0, i32 0 +// CHECK-NEXT: %5037 = load { ptr, ptr }, ptr @main.V, align 8 +// CHECK-NEXT: %5038 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 24) +// CHECK-NEXT: store %"{{.*}}/runtime/internal/runtime.Slice" zeroinitializer, ptr %5038, align 8 +// CHECK-NEXT: %5039 = insertvalue %"{{.*}}/runtime/internal/runtime.eface" { ptr @"[]_llgo_uint", ptr undef }, ptr %5038, 1 +// CHECK-NEXT: %5040 = extractvalue { ptr, ptr } %5037, 1 +// CHECK-NEXT: %5041 = extractvalue { ptr, ptr } %5037, 0 +// CHECK-NEXT: %__llgo_funcval_code662 = call ptr asm "", "=r,0"(ptr %5041) +// CHECK-NEXT: %5042 = call %reflect.Value %__llgo_funcval_code662(ptr {{(nest|swiftself)}} %5040, %"{{.*}}/runtime/internal/runtime.eface" %5039) +// CHECK-NEXT: %5043 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %5035, i32 0, i32 1 +// CHECK-NEXT: %5044 = load { ptr, ptr }, ptr @main.V, align 8 +// CHECK-NEXT: %5045 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 24) +// CHECK-NEXT: store %"{{.*}}/runtime/internal/runtime.Slice" zeroinitializer, ptr %5045, align 8 +// CHECK-NEXT: %5046 = insertvalue %"{{.*}}/runtime/internal/runtime.eface" { ptr @"[]_llgo_uint", ptr undef }, ptr %5045, 1 +// CHECK-NEXT: %5047 = extractvalue { ptr, ptr } %5044, 1 +// CHECK-NEXT: %5048 = extractvalue { ptr, ptr } %5044, 0 +// CHECK-NEXT: %__llgo_funcval_code663 = call ptr asm "", "=r,0"(ptr %5048) +// CHECK-NEXT: %5049 = call %reflect.Value %__llgo_funcval_code663(ptr {{(nest|swiftself)}} %5047, %"{{.*}}/runtime/internal/runtime.eface" %5046) +// CHECK-NEXT: store %reflect.Value %5042, ptr %5036, align 8 +// CHECK-NEXT: store %reflect.Value %5049, ptr %5043, align 8 +// CHECK-NEXT: %5050 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %1, i64 332 +// CHECK-NEXT: %5051 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %5050, i32 0, i32 0 +// CHECK-NEXT: %5052 = load { ptr, ptr }, ptr @main.V, align 8 +// CHECK-NEXT: %5053 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 24) +// CHECK-NEXT: store %"{{.*}}/runtime/internal/runtime.Slice" zeroinitializer, ptr %5053, align 8 +// CHECK-NEXT: %5054 = insertvalue %"{{.*}}/runtime/internal/runtime.eface" { ptr @"[]_llgo_int", ptr undef }, ptr %5053, 1 +// CHECK-NEXT: %5055 = extractvalue { ptr, ptr } %5052, 1 +// CHECK-NEXT: %5056 = extractvalue { ptr, ptr } %5052, 0 +// CHECK-NEXT: %__llgo_funcval_code664 = call ptr asm "", "=r,0"(ptr %5056) +// CHECK-NEXT: %5057 = call %reflect.Value %__llgo_funcval_code664(ptr {{(nest|swiftself)}} %5055, %"{{.*}}/runtime/internal/runtime.eface" %5054) +// CHECK-NEXT: %5058 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %5050, i32 0, i32 1 +// CHECK-NEXT: %5059 = load { ptr, ptr }, ptr @main.V, align 8 +// CHECK-NEXT: %5060 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 24) +// CHECK-NEXT: store %"{{.*}}/runtime/internal/runtime.Slice" zeroinitializer, ptr %5060, align 8 +// CHECK-NEXT: %5061 = insertvalue %"{{.*}}/runtime/internal/runtime.eface" { ptr @"[]_llgo_int", ptr undef }, ptr %5060, 1 +// CHECK-NEXT: %5062 = extractvalue { ptr, ptr } %5059, 1 +// CHECK-NEXT: %5063 = extractvalue { ptr, ptr } %5059, 0 +// CHECK-NEXT: %__llgo_funcval_code665 = call ptr asm "", "=r,0"(ptr %5063) +// CHECK-NEXT: %5064 = call %reflect.Value %__llgo_funcval_code665(ptr {{(nest|swiftself)}} %5062, %"{{.*}}/runtime/internal/runtime.eface" %5061) +// CHECK-NEXT: store %reflect.Value %5057, ptr %5051, align 8 +// CHECK-NEXT: store %reflect.Value %5064, ptr %5058, align 8 +// CHECK-NEXT: %5065 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %1, i64 333 +// CHECK-NEXT: %5066 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %5065, i32 0, i32 0 +// CHECK-NEXT: %5067 = load { ptr, ptr }, ptr @main.V, align 8 +// CHECK-NEXT: %5068 = call ptr @"{{.*}}/runtime/internal/runtime.AllocZ"(i64 16) +// CHECK-NEXT: %5069 = insertvalue %"{{.*}}/runtime/internal/runtime.eface" { ptr @"*_llgo_any", ptr undef }, ptr %5068, 1 +// CHECK-NEXT: %5070 = extractvalue { ptr, ptr } %5067, 1 +// CHECK-NEXT: %5071 = extractvalue { ptr, ptr } %5067, 0 +// CHECK-NEXT: %__llgo_funcval_code666 = call ptr asm "", "=r,0"(ptr %5071) +// CHECK-NEXT: %5072 = call %reflect.Value %__llgo_funcval_code666(ptr {{(nest|swiftself)}} %5070, %"{{.*}}/runtime/internal/runtime.eface" %5069) +// CHECK-NEXT: %5073 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %5065, i32 0, i32 1 +// CHECK-NEXT: %5074 = load { ptr, ptr }, ptr @main.V, align 8 +// CHECK-NEXT: %5075 = call ptr @"{{.*}}/runtime/internal/runtime.AllocZ"(i64 16) +// CHECK-NEXT: %5076 = insertvalue %"{{.*}}/runtime/internal/runtime.eface" { ptr @"*_llgo_any", ptr undef }, ptr %5075, 1 +// CHECK-NEXT: %5077 = extractvalue { ptr, ptr } %5074, 1 +// CHECK-NEXT: %5078 = extractvalue { ptr, ptr } %5074, 0 +// CHECK-NEXT: %__llgo_funcval_code667 = call ptr asm "", "=r,0"(ptr %5078) +// CHECK-NEXT: %5079 = call %reflect.Value %__llgo_funcval_code667(ptr {{(nest|swiftself)}} %5077, %"{{.*}}/runtime/internal/runtime.eface" %5076) +// CHECK-NEXT: store %reflect.Value %5072, ptr %5066, align 8 +// CHECK-NEXT: store %reflect.Value %5079, ptr %5073, align 8 +// CHECK-NEXT: %5080 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %1, i64 334 +// CHECK-NEXT: %5081 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %5080, i32 0, i32 0 +// CHECK-NEXT: %5082 = load { ptr, ptr }, ptr @main.V, align 8 +// CHECK-NEXT: %5083 = call ptr @"{{.*}}/runtime/internal/runtime.AllocZ"(i64 16) +// CHECK-NEXT: %5084 = insertvalue %"{{.*}}/runtime/internal/runtime.eface" { ptr @"*_llgo_io.Reader", ptr undef }, ptr %5083, 1 +// CHECK-NEXT: %5085 = extractvalue { ptr, ptr } %5082, 1 +// CHECK-NEXT: %5086 = extractvalue { ptr, ptr } %5082, 0 +// CHECK-NEXT: %__llgo_funcval_code668 = call ptr asm "", "=r,0"(ptr %5086) +// CHECK-NEXT: %5087 = call %reflect.Value %__llgo_funcval_code668(ptr {{(nest|swiftself)}} %5085, %"{{.*}}/runtime/internal/runtime.eface" %5084) +// CHECK-NEXT: %5088 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %5080, i32 0, i32 1 +// CHECK-NEXT: %5089 = load { ptr, ptr }, ptr @main.V, align 8 +// CHECK-NEXT: %5090 = call ptr @"{{.*}}/runtime/internal/runtime.AllocZ"(i64 16) +// CHECK-NEXT: %5091 = insertvalue %"{{.*}}/runtime/internal/runtime.eface" { ptr @"*_llgo_io.Reader", ptr undef }, ptr %5090, 1 +// CHECK-NEXT: %5092 = extractvalue { ptr, ptr } %5089, 1 +// CHECK-NEXT: %5093 = extractvalue { ptr, ptr } %5089, 0 +// CHECK-NEXT: %__llgo_funcval_code669 = call ptr asm "", "=r,0"(ptr %5093) +// CHECK-NEXT: %5094 = call %reflect.Value %__llgo_funcval_code669(ptr {{(nest|swiftself)}} %5092, %"{{.*}}/runtime/internal/runtime.eface" %5091) +// CHECK-NEXT: store %reflect.Value %5087, ptr %5081, align 8 +// CHECK-NEXT: store %reflect.Value %5094, ptr %5088, align 8 +// CHECK-NEXT: %5095 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %1, i64 335 +// CHECK-NEXT: %5096 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %5095, i32 0, i32 0 +// CHECK-NEXT: %5097 = load { ptr, ptr }, ptr @main.V, align 8 +// CHECK-NEXT: %5098 = call ptr @"{{.*}}/runtime/internal/runtime.AllocZ"(i64 16) +// CHECK-NEXT: %5099 = insertvalue %"{{.*}}/runtime/internal/runtime.eface" { ptr @"*_llgo_io.Writer", ptr undef }, ptr %5098, 1 +// CHECK-NEXT: %5100 = extractvalue { ptr, ptr } %5097, 1 +// CHECK-NEXT: %5101 = extractvalue { ptr, ptr } %5097, 0 +// CHECK-NEXT: %__llgo_funcval_code670 = call ptr asm "", "=r,0"(ptr %5101) +// CHECK-NEXT: %5102 = call %reflect.Value %__llgo_funcval_code670(ptr {{(nest|swiftself)}} %5100, %"{{.*}}/runtime/internal/runtime.eface" %5099) +// CHECK-NEXT: %5103 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %5095, i32 0, i32 1 +// CHECK-NEXT: %5104 = load { ptr, ptr }, ptr @main.V, align 8 +// CHECK-NEXT: %5105 = call ptr @"{{.*}}/runtime/internal/runtime.AllocZ"(i64 16) +// CHECK-NEXT: %5106 = insertvalue %"{{.*}}/runtime/internal/runtime.eface" { ptr @"*_llgo_io.Writer", ptr undef }, ptr %5105, 1 +// CHECK-NEXT: %5107 = extractvalue { ptr, ptr } %5104, 1 +// CHECK-NEXT: %5108 = extractvalue { ptr, ptr } %5104, 0 +// CHECK-NEXT: %__llgo_funcval_code671 = call ptr asm "", "=r,0"(ptr %5108) +// CHECK-NEXT: %5109 = call %reflect.Value %__llgo_funcval_code671(ptr {{(nest|swiftself)}} %5107, %"{{.*}}/runtime/internal/runtime.eface" %5106) +// CHECK-NEXT: store %reflect.Value %5102, ptr %5096, align 8 +// CHECK-NEXT: store %reflect.Value %5109, ptr %5103, align 8 +// CHECK-NEXT: %5110 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %1, i64 336 +// CHECK-NEXT: %5111 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %5110, i32 0, i32 0 +// CHECK-NEXT: %5112 = load { ptr, ptr }, ptr @main.V, align 8 +// CHECK-NEXT: %5113 = extractvalue { ptr, ptr } %5112, 1 +// CHECK-NEXT: %5114 = extractvalue { ptr, ptr } %5112, 0 +// CHECK-NEXT: %__llgo_funcval_code672 = call ptr asm "", "=r,0"(ptr %5114) +// CHECK-NEXT: %5115 = call %reflect.Value %__llgo_funcval_code672(ptr {{(nest|swiftself)}} %5113, %"{{.*}}/runtime/internal/runtime.eface" { ptr @_llgo_main.IntChan, ptr null }) +// CHECK-NEXT: %5116 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %5110, i32 0, i32 1 +// CHECK-NEXT: %5117 = load { ptr, ptr }, ptr @main.V, align 8 +// CHECK-NEXT: %5118 = extractvalue { ptr, ptr } %5117, 1 +// CHECK-NEXT: %5119 = extractvalue { ptr, ptr } %5117, 0 +// CHECK-NEXT: %__llgo_funcval_code673 = call ptr asm "", "=r,0"(ptr %5119) +// CHECK-NEXT: %5120 = call %reflect.Value %__llgo_funcval_code673(ptr {{(nest|swiftself)}} %5118, %"{{.*}}/runtime/internal/runtime.eface" { ptr @"chan<- _llgo_int", ptr null }) +// CHECK-NEXT: store %reflect.Value %5115, ptr %5111, align 8 +// CHECK-NEXT: store %reflect.Value %5120, ptr %5116, align 8 +// CHECK-NEXT: %5121 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %1, i64 337 +// CHECK-NEXT: %5122 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %5121, i32 0, i32 0 +// CHECK-NEXT: %5123 = load { ptr, ptr }, ptr @main.V, align 8 +// CHECK-NEXT: %5124 = extractvalue { ptr, ptr } %5123, 1 +// CHECK-NEXT: %5125 = extractvalue { ptr, ptr } %5123, 0 +// CHECK-NEXT: %__llgo_funcval_code674 = call ptr asm "", "=r,0"(ptr %5125) +// CHECK-NEXT: %5126 = call %reflect.Value %__llgo_funcval_code674(ptr {{(nest|swiftself)}} %5124, %"{{.*}}/runtime/internal/runtime.eface" { ptr @_llgo_main.IntChan, ptr null }) +// CHECK-NEXT: %5127 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %5121, i32 0, i32 1 +// CHECK-NEXT: %5128 = load { ptr, ptr }, ptr @main.V, align 8 +// CHECK-NEXT: %5129 = extractvalue { ptr, ptr } %5128, 1 +// CHECK-NEXT: %5130 = extractvalue { ptr, ptr } %5128, 0 +// CHECK-NEXT: %__llgo_funcval_code675 = call ptr asm "", "=r,0"(ptr %5130) +// CHECK-NEXT: %5131 = call %reflect.Value %__llgo_funcval_code675(ptr {{(nest|swiftself)}} %5129, %"{{.*}}/runtime/internal/runtime.eface" { ptr @"<-chan _llgo_int", ptr null }) +// CHECK-NEXT: store %reflect.Value %5126, ptr %5122, align 8 +// CHECK-NEXT: store %reflect.Value %5131, ptr %5127, align 8 +// CHECK-NEXT: %5132 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %1, i64 338 +// CHECK-NEXT: %5133 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %5132, i32 0, i32 0 +// CHECK-NEXT: %5134 = load { ptr, ptr }, ptr @main.V, align 8 +// CHECK-NEXT: %5135 = extractvalue { ptr, ptr } %5134, 1 +// CHECK-NEXT: %5136 = extractvalue { ptr, ptr } %5134, 0 +// CHECK-NEXT: %__llgo_funcval_code676 = call ptr asm "", "=r,0"(ptr %5136) +// CHECK-NEXT: %5137 = call %reflect.Value %__llgo_funcval_code676(ptr {{(nest|swiftself)}} %5135, %"{{.*}}/runtime/internal/runtime.eface" { ptr @"chan _llgo_int", ptr null }) +// CHECK-NEXT: %5138 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %5132, i32 0, i32 1 +// CHECK-NEXT: %5139 = load { ptr, ptr }, ptr @main.V, align 8 +// CHECK-NEXT: %5140 = extractvalue { ptr, ptr } %5139, 1 +// CHECK-NEXT: %5141 = extractvalue { ptr, ptr } %5139, 0 +// CHECK-NEXT: %__llgo_funcval_code677 = call ptr asm "", "=r,0"(ptr %5141) +// CHECK-NEXT: %5142 = call %reflect.Value %__llgo_funcval_code677(ptr {{(nest|swiftself)}} %5140, %"{{.*}}/runtime/internal/runtime.eface" { ptr @_llgo_main.IntChanRecv, ptr null }) +// CHECK-NEXT: store %reflect.Value %5137, ptr %5133, align 8 +// CHECK-NEXT: store %reflect.Value %5142, ptr %5138, align 8 +// CHECK-NEXT: %5143 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %1, i64 339 +// CHECK-NEXT: %5144 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %5143, i32 0, i32 0 +// CHECK-NEXT: %5145 = load { ptr, ptr }, ptr @main.V, align 8 +// CHECK-NEXT: %5146 = extractvalue { ptr, ptr } %5145, 1 +// CHECK-NEXT: %5147 = extractvalue { ptr, ptr } %5145, 0 +// CHECK-NEXT: %__llgo_funcval_code678 = call ptr asm "", "=r,0"(ptr %5147) +// CHECK-NEXT: %5148 = call %reflect.Value %__llgo_funcval_code678(ptr {{(nest|swiftself)}} %5146, %"{{.*}}/runtime/internal/runtime.eface" { ptr @"chan _llgo_int", ptr null }) +// CHECK-NEXT: %5149 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %5143, i32 0, i32 1 +// CHECK-NEXT: %5150 = load { ptr, ptr }, ptr @main.V, align 8 +// CHECK-NEXT: %5151 = extractvalue { ptr, ptr } %5150, 1 +// CHECK-NEXT: %5152 = extractvalue { ptr, ptr } %5150, 0 +// CHECK-NEXT: %__llgo_funcval_code679 = call ptr asm "", "=r,0"(ptr %5152) +// CHECK-NEXT: %5153 = call %reflect.Value %__llgo_funcval_code679(ptr {{(nest|swiftself)}} %5151, %"{{.*}}/runtime/internal/runtime.eface" { ptr @_llgo_main.IntChanSend, ptr null }) +// CHECK-NEXT: store %reflect.Value %5148, ptr %5144, align 8 +// CHECK-NEXT: store %reflect.Value %5153, ptr %5149, align 8 +// CHECK-NEXT: %5154 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %1, i64 340 +// CHECK-NEXT: %5155 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %5154, i32 0, i32 0 +// CHECK-NEXT: %5156 = load { ptr, ptr }, ptr @main.V, align 8 +// CHECK-NEXT: %5157 = extractvalue { ptr, ptr } %5156, 1 +// CHECK-NEXT: %5158 = extractvalue { ptr, ptr } %5156, 0 +// CHECK-NEXT: %__llgo_funcval_code680 = call ptr asm "", "=r,0"(ptr %5158) +// CHECK-NEXT: %5159 = call %reflect.Value %__llgo_funcval_code680(ptr {{(nest|swiftself)}} %5157, %"{{.*}}/runtime/internal/runtime.eface" { ptr @_llgo_main.IntChanRecv, ptr null }) +// CHECK-NEXT: %5160 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %5154, i32 0, i32 1 +// CHECK-NEXT: %5161 = load { ptr, ptr }, ptr @main.V, align 8 +// CHECK-NEXT: %5162 = extractvalue { ptr, ptr } %5161, 1 +// CHECK-NEXT: %5163 = extractvalue { ptr, ptr } %5161, 0 +// CHECK-NEXT: %__llgo_funcval_code681 = call ptr asm "", "=r,0"(ptr %5163) +// CHECK-NEXT: %5164 = call %reflect.Value %__llgo_funcval_code681(ptr {{(nest|swiftself)}} %5162, %"{{.*}}/runtime/internal/runtime.eface" { ptr @"<-chan _llgo_int", ptr null }) +// CHECK-NEXT: store %reflect.Value %5159, ptr %5155, align 8 +// CHECK-NEXT: store %reflect.Value %5164, ptr %5160, align 8 +// CHECK-NEXT: %5165 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %1, i64 341 +// CHECK-NEXT: %5166 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %5165, i32 0, i32 0 +// CHECK-NEXT: %5167 = load { ptr, ptr }, ptr @main.V, align 8 +// CHECK-NEXT: %5168 = extractvalue { ptr, ptr } %5167, 1 +// CHECK-NEXT: %5169 = extractvalue { ptr, ptr } %5167, 0 +// CHECK-NEXT: %__llgo_funcval_code682 = call ptr asm "", "=r,0"(ptr %5169) +// CHECK-NEXT: %5170 = call %reflect.Value %__llgo_funcval_code682(ptr {{(nest|swiftself)}} %5168, %"{{.*}}/runtime/internal/runtime.eface" { ptr @"<-chan _llgo_int", ptr null }) +// CHECK-NEXT: %5171 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %5165, i32 0, i32 1 +// CHECK-NEXT: %5172 = load { ptr, ptr }, ptr @main.V, align 8 +// CHECK-NEXT: %5173 = extractvalue { ptr, ptr } %5172, 1 +// CHECK-NEXT: %5174 = extractvalue { ptr, ptr } %5172, 0 +// CHECK-NEXT: %__llgo_funcval_code683 = call ptr asm "", "=r,0"(ptr %5174) +// CHECK-NEXT: %5175 = call %reflect.Value %__llgo_funcval_code683(ptr {{(nest|swiftself)}} %5173, %"{{.*}}/runtime/internal/runtime.eface" { ptr @_llgo_main.IntChanRecv, ptr null }) +// CHECK-NEXT: store %reflect.Value %5170, ptr %5166, align 8 +// CHECK-NEXT: store %reflect.Value %5175, ptr %5171, align 8 +// CHECK-NEXT: %5176 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %1, i64 342 +// CHECK-NEXT: %5177 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %5176, i32 0, i32 0 +// CHECK-NEXT: %5178 = load { ptr, ptr }, ptr @main.V, align 8 +// CHECK-NEXT: %5179 = extractvalue { ptr, ptr } %5178, 1 +// CHECK-NEXT: %5180 = extractvalue { ptr, ptr } %5178, 0 +// CHECK-NEXT: %__llgo_funcval_code684 = call ptr asm "", "=r,0"(ptr %5180) +// CHECK-NEXT: %5181 = call %reflect.Value %__llgo_funcval_code684(ptr {{(nest|swiftself)}} %5179, %"{{.*}}/runtime/internal/runtime.eface" { ptr @_llgo_main.IntChanSend, ptr null }) +// CHECK-NEXT: %5182 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %5176, i32 0, i32 1 +// CHECK-NEXT: %5183 = load { ptr, ptr }, ptr @main.V, align 8 +// CHECK-NEXT: %5184 = extractvalue { ptr, ptr } %5183, 1 +// CHECK-NEXT: %5185 = extractvalue { ptr, ptr } %5183, 0 +// CHECK-NEXT: %__llgo_funcval_code685 = call ptr asm "", "=r,0"(ptr %5185) +// CHECK-NEXT: %5186 = call %reflect.Value %__llgo_funcval_code685(ptr {{(nest|swiftself)}} %5184, %"{{.*}}/runtime/internal/runtime.eface" { ptr @"chan<- _llgo_int", ptr null }) +// CHECK-NEXT: store %reflect.Value %5181, ptr %5177, align 8 +// CHECK-NEXT: store %reflect.Value %5186, ptr %5182, align 8 +// CHECK-NEXT: %5187 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %1, i64 343 +// CHECK-NEXT: %5188 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %5187, i32 0, i32 0 +// CHECK-NEXT: %5189 = load { ptr, ptr }, ptr @main.V, align 8 +// CHECK-NEXT: %5190 = extractvalue { ptr, ptr } %5189, 1 +// CHECK-NEXT: %5191 = extractvalue { ptr, ptr } %5189, 0 +// CHECK-NEXT: %__llgo_funcval_code686 = call ptr asm "", "=r,0"(ptr %5191) +// CHECK-NEXT: %5192 = call %reflect.Value %__llgo_funcval_code686(ptr {{(nest|swiftself)}} %5190, %"{{.*}}/runtime/internal/runtime.eface" { ptr @"chan<- _llgo_int", ptr null }) +// CHECK-NEXT: %5193 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %5187, i32 0, i32 1 +// CHECK-NEXT: %5194 = load { ptr, ptr }, ptr @main.V, align 8 +// CHECK-NEXT: %5195 = extractvalue { ptr, ptr } %5194, 1 +// CHECK-NEXT: %5196 = extractvalue { ptr, ptr } %5194, 0 +// CHECK-NEXT: %__llgo_funcval_code687 = call ptr asm "", "=r,0"(ptr %5196) +// CHECK-NEXT: %5197 = call %reflect.Value %__llgo_funcval_code687(ptr {{(nest|swiftself)}} %5195, %"{{.*}}/runtime/internal/runtime.eface" { ptr @_llgo_main.IntChanSend, ptr null }) +// CHECK-NEXT: store %reflect.Value %5192, ptr %5188, align 8 +// CHECK-NEXT: store %reflect.Value %5197, ptr %5193, align 8 +// CHECK-NEXT: %5198 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %1, i64 344 +// CHECK-NEXT: %5199 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %5198, i32 0, i32 0 +// CHECK-NEXT: %5200 = load { ptr, ptr }, ptr @main.V, align 8 +// CHECK-NEXT: %5201 = extractvalue { ptr, ptr } %5200, 1 +// CHECK-NEXT: %5202 = extractvalue { ptr, ptr } %5200, 0 +// CHECK-NEXT: %__llgo_funcval_code688 = call ptr asm "", "=r,0"(ptr %5202) +// CHECK-NEXT: %5203 = call %reflect.Value %__llgo_funcval_code688(ptr {{(nest|swiftself)}} %5201, %"{{.*}}/runtime/internal/runtime.eface" { ptr @_llgo_main.IntChan, ptr null }) +// CHECK-NEXT: %5204 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %5198, i32 0, i32 1 +// CHECK-NEXT: %5205 = load { ptr, ptr }, ptr @main.V, align 8 +// CHECK-NEXT: %5206 = extractvalue { ptr, ptr } %5205, 1 +// CHECK-NEXT: %5207 = extractvalue { ptr, ptr } %5205, 0 +// CHECK-NEXT: %__llgo_funcval_code689 = call ptr asm "", "=r,0"(ptr %5207) +// CHECK-NEXT: %5208 = call %reflect.Value %__llgo_funcval_code689(ptr {{(nest|swiftself)}} %5206, %"{{.*}}/runtime/internal/runtime.eface" { ptr @"chan _llgo_int", ptr null }) +// CHECK-NEXT: store %reflect.Value %5203, ptr %5199, align 8 +// CHECK-NEXT: store %reflect.Value %5208, ptr %5204, align 8 +// CHECK-NEXT: %5209 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %1, i64 345 +// CHECK-NEXT: %5210 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %5209, i32 0, i32 0 +// CHECK-NEXT: %5211 = load { ptr, ptr }, ptr @main.V, align 8 +// CHECK-NEXT: %5212 = extractvalue { ptr, ptr } %5211, 1 +// CHECK-NEXT: %5213 = extractvalue { ptr, ptr } %5211, 0 +// CHECK-NEXT: %__llgo_funcval_code690 = call ptr asm "", "=r,0"(ptr %5213) +// CHECK-NEXT: %5214 = call %reflect.Value %__llgo_funcval_code690(ptr {{(nest|swiftself)}} %5212, %"{{.*}}/runtime/internal/runtime.eface" { ptr @"chan _llgo_int", ptr null }) +// CHECK-NEXT: %5215 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %5209, i32 0, i32 1 +// CHECK-NEXT: %5216 = load { ptr, ptr }, ptr @main.V, align 8 +// CHECK-NEXT: %5217 = extractvalue { ptr, ptr } %5216, 1 +// CHECK-NEXT: %5218 = extractvalue { ptr, ptr } %5216, 0 +// CHECK-NEXT: %__llgo_funcval_code691 = call ptr asm "", "=r,0"(ptr %5218) +// CHECK-NEXT: %5219 = call %reflect.Value %__llgo_funcval_code691(ptr {{(nest|swiftself)}} %5217, %"{{.*}}/runtime/internal/runtime.eface" { ptr @_llgo_main.IntChan, ptr null }) +// CHECK-NEXT: store %reflect.Value %5214, ptr %5210, align 8 +// CHECK-NEXT: store %reflect.Value %5219, ptr %5215, align 8 +// CHECK-NEXT: %5220 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %1, i64 346 +// CHECK-NEXT: %5221 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %5220, i32 0, i32 0 +// CHECK-NEXT: %5222 = load { ptr, ptr }, ptr @main.V, align 8 +// CHECK-NEXT: %5223 = extractvalue { ptr, ptr } %5222, 1 +// CHECK-NEXT: %5224 = extractvalue { ptr, ptr } %5222, 0 +// CHECK-NEXT: %__llgo_funcval_code692 = call ptr asm "", "=r,0"(ptr %5224) +// CHECK-NEXT: %5225 = call %reflect.Value %__llgo_funcval_code692(ptr {{(nest|swiftself)}} %5223, %"{{.*}}/runtime/internal/runtime.eface" { ptr @"chan _llgo_int", ptr null }) +// CHECK-NEXT: %5226 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %5220, i32 0, i32 1 +// CHECK-NEXT: %5227 = load { ptr, ptr }, ptr @main.V, align 8 +// CHECK-NEXT: %5228 = extractvalue { ptr, ptr } %5227, 1 +// CHECK-NEXT: %5229 = extractvalue { ptr, ptr } %5227, 0 +// CHECK-NEXT: %__llgo_funcval_code693 = call ptr asm "", "=r,0"(ptr %5229) +// CHECK-NEXT: %5230 = call %reflect.Value %__llgo_funcval_code693(ptr {{(nest|swiftself)}} %5228, %"{{.*}}/runtime/internal/runtime.eface" { ptr @"<-chan _llgo_int", ptr null }) +// CHECK-NEXT: store %reflect.Value %5225, ptr %5221, align 8 +// CHECK-NEXT: store %reflect.Value %5230, ptr %5226, align 8 +// CHECK-NEXT: %5231 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %1, i64 347 +// CHECK-NEXT: %5232 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %5231, i32 0, i32 0 +// CHECK-NEXT: %5233 = load { ptr, ptr }, ptr @main.V, align 8 +// CHECK-NEXT: %5234 = extractvalue { ptr, ptr } %5233, 1 +// CHECK-NEXT: %5235 = extractvalue { ptr, ptr } %5233, 0 +// CHECK-NEXT: %__llgo_funcval_code694 = call ptr asm "", "=r,0"(ptr %5235) +// CHECK-NEXT: %5236 = call %reflect.Value %__llgo_funcval_code694(ptr {{(nest|swiftself)}} %5234, %"{{.*}}/runtime/internal/runtime.eface" { ptr @"chan _llgo_int", ptr null }) +// CHECK-NEXT: %5237 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %5231, i32 0, i32 1 +// CHECK-NEXT: %5238 = load { ptr, ptr }, ptr @main.V, align 8 +// CHECK-NEXT: %5239 = extractvalue { ptr, ptr } %5238, 1 +// CHECK-NEXT: %5240 = extractvalue { ptr, ptr } %5238, 0 +// CHECK-NEXT: %__llgo_funcval_code695 = call ptr asm "", "=r,0"(ptr %5240) +// CHECK-NEXT: %5241 = call %reflect.Value %__llgo_funcval_code695(ptr {{(nest|swiftself)}} %5239, %"{{.*}}/runtime/internal/runtime.eface" { ptr @"chan<- _llgo_int", ptr null }) +// CHECK-NEXT: store %reflect.Value %5236, ptr %5232, align 8 +// CHECK-NEXT: store %reflect.Value %5241, ptr %5237, align 8 +// CHECK-NEXT: %5242 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %1, i64 348 +// CHECK-NEXT: %5243 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %5242, i32 0, i32 0 +// CHECK-NEXT: %5244 = load { ptr, ptr }, ptr @main.V, align 8 +// CHECK-NEXT: %5245 = extractvalue { ptr, ptr } %5244, 1 +// CHECK-NEXT: %5246 = extractvalue { ptr, ptr } %5244, 0 +// CHECK-NEXT: %__llgo_funcval_code696 = call ptr asm "", "=r,0"(ptr %5246) +// CHECK-NEXT: %5247 = call %reflect.Value %__llgo_funcval_code696(ptr {{(nest|swiftself)}} %5245, %"{{.*}}/runtime/internal/runtime.eface" { ptr @_llgo_main.BytesChan, ptr null }) +// CHECK-NEXT: %5248 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %5242, i32 0, i32 1 +// CHECK-NEXT: %5249 = load { ptr, ptr }, ptr @main.V, align 8 +// CHECK-NEXT: %5250 = extractvalue { ptr, ptr } %5249, 1 +// CHECK-NEXT: %5251 = extractvalue { ptr, ptr } %5249, 0 +// CHECK-NEXT: %__llgo_funcval_code697 = call ptr asm "", "=r,0"(ptr %5251) +// CHECK-NEXT: %5252 = call %reflect.Value %__llgo_funcval_code697(ptr {{(nest|swiftself)}} %5250, %"{{.*}}/runtime/internal/runtime.eface" { ptr @"chan<- []_llgo_uint8", ptr null }) +// CHECK-NEXT: store %reflect.Value %5247, ptr %5243, align 8 +// CHECK-NEXT: store %reflect.Value %5252, ptr %5248, align 8 +// CHECK-NEXT: %5253 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %1, i64 349 +// CHECK-NEXT: %5254 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %5253, i32 0, i32 0 +// CHECK-NEXT: %5255 = load { ptr, ptr }, ptr @main.V, align 8 +// CHECK-NEXT: %5256 = extractvalue { ptr, ptr } %5255, 1 +// CHECK-NEXT: %5257 = extractvalue { ptr, ptr } %5255, 0 +// CHECK-NEXT: %__llgo_funcval_code698 = call ptr asm "", "=r,0"(ptr %5257) +// CHECK-NEXT: %5258 = call %reflect.Value %__llgo_funcval_code698(ptr {{(nest|swiftself)}} %5256, %"{{.*}}/runtime/internal/runtime.eface" { ptr @_llgo_main.BytesChan, ptr null }) +// CHECK-NEXT: %5259 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %5253, i32 0, i32 1 +// CHECK-NEXT: %5260 = load { ptr, ptr }, ptr @main.V, align 8 +// CHECK-NEXT: %5261 = extractvalue { ptr, ptr } %5260, 1 +// CHECK-NEXT: %5262 = extractvalue { ptr, ptr } %5260, 0 +// CHECK-NEXT: %__llgo_funcval_code699 = call ptr asm "", "=r,0"(ptr %5262) +// CHECK-NEXT: %5263 = call %reflect.Value %__llgo_funcval_code699(ptr {{(nest|swiftself)}} %5261, %"{{.*}}/runtime/internal/runtime.eface" { ptr @"<-chan []_llgo_uint8", ptr null }) +// CHECK-NEXT: store %reflect.Value %5258, ptr %5254, align 8 +// CHECK-NEXT: store %reflect.Value %5263, ptr %5259, align 8 +// CHECK-NEXT: %5264 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %1, i64 350 +// CHECK-NEXT: %5265 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %5264, i32 0, i32 0 +// CHECK-NEXT: %5266 = load { ptr, ptr }, ptr @main.V, align 8 +// CHECK-NEXT: %5267 = extractvalue { ptr, ptr } %5266, 1 +// CHECK-NEXT: %5268 = extractvalue { ptr, ptr } %5266, 0 +// CHECK-NEXT: %__llgo_funcval_code700 = call ptr asm "", "=r,0"(ptr %5268) +// CHECK-NEXT: %5269 = call %reflect.Value %__llgo_funcval_code700(ptr {{(nest|swiftself)}} %5267, %"{{.*}}/runtime/internal/runtime.eface" { ptr @"chan []_llgo_uint8", ptr null }) +// CHECK-NEXT: %5270 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %5264, i32 0, i32 1 +// CHECK-NEXT: %5271 = load { ptr, ptr }, ptr @main.V, align 8 +// CHECK-NEXT: %5272 = extractvalue { ptr, ptr } %5271, 1 +// CHECK-NEXT: %5273 = extractvalue { ptr, ptr } %5271, 0 +// CHECK-NEXT: %__llgo_funcval_code701 = call ptr asm "", "=r,0"(ptr %5273) +// CHECK-NEXT: %5274 = call %reflect.Value %__llgo_funcval_code701(ptr {{(nest|swiftself)}} %5272, %"{{.*}}/runtime/internal/runtime.eface" { ptr @_llgo_main.BytesChanRecv, ptr null }) +// CHECK-NEXT: store %reflect.Value %5269, ptr %5265, align 8 +// CHECK-NEXT: store %reflect.Value %5274, ptr %5270, align 8 +// CHECK-NEXT: %5275 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %1, i64 351 +// CHECK-NEXT: %5276 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %5275, i32 0, i32 0 +// CHECK-NEXT: %5277 = load { ptr, ptr }, ptr @main.V, align 8 +// CHECK-NEXT: %5278 = extractvalue { ptr, ptr } %5277, 1 +// CHECK-NEXT: %5279 = extractvalue { ptr, ptr } %5277, 0 +// CHECK-NEXT: %__llgo_funcval_code702 = call ptr asm "", "=r,0"(ptr %5279) +// CHECK-NEXT: %5280 = call %reflect.Value %__llgo_funcval_code702(ptr {{(nest|swiftself)}} %5278, %"{{.*}}/runtime/internal/runtime.eface" { ptr @"chan []_llgo_uint8", ptr null }) +// CHECK-NEXT: %5281 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %5275, i32 0, i32 1 +// CHECK-NEXT: %5282 = load { ptr, ptr }, ptr @main.V, align 8 +// CHECK-NEXT: %5283 = extractvalue { ptr, ptr } %5282, 1 +// CHECK-NEXT: %5284 = extractvalue { ptr, ptr } %5282, 0 +// CHECK-NEXT: %__llgo_funcval_code703 = call ptr asm "", "=r,0"(ptr %5284) +// CHECK-NEXT: %5285 = call %reflect.Value %__llgo_funcval_code703(ptr {{(nest|swiftself)}} %5283, %"{{.*}}/runtime/internal/runtime.eface" { ptr @_llgo_main.BytesChanSend, ptr null }) +// CHECK-NEXT: store %reflect.Value %5280, ptr %5276, align 8 +// CHECK-NEXT: store %reflect.Value %5285, ptr %5281, align 8 +// CHECK-NEXT: %5286 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %1, i64 352 +// CHECK-NEXT: %5287 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %5286, i32 0, i32 0 +// CHECK-NEXT: %5288 = load { ptr, ptr }, ptr @main.V, align 8 +// CHECK-NEXT: %5289 = extractvalue { ptr, ptr } %5288, 1 +// CHECK-NEXT: %5290 = extractvalue { ptr, ptr } %5288, 0 +// CHECK-NEXT: %__llgo_funcval_code704 = call ptr asm "", "=r,0"(ptr %5290) +// CHECK-NEXT: %5291 = call %reflect.Value %__llgo_funcval_code704(ptr {{(nest|swiftself)}} %5289, %"{{.*}}/runtime/internal/runtime.eface" { ptr @_llgo_main.BytesChanRecv, ptr null }) +// CHECK-NEXT: %5292 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %5286, i32 0, i32 1 +// CHECK-NEXT: %5293 = load { ptr, ptr }, ptr @main.V, align 8 +// CHECK-NEXT: %5294 = extractvalue { ptr, ptr } %5293, 1 +// CHECK-NEXT: %5295 = extractvalue { ptr, ptr } %5293, 0 +// CHECK-NEXT: %__llgo_funcval_code705 = call ptr asm "", "=r,0"(ptr %5295) +// CHECK-NEXT: %5296 = call %reflect.Value %__llgo_funcval_code705(ptr {{(nest|swiftself)}} %5294, %"{{.*}}/runtime/internal/runtime.eface" { ptr @"<-chan []_llgo_uint8", ptr null }) +// CHECK-NEXT: store %reflect.Value %5291, ptr %5287, align 8 +// CHECK-NEXT: store %reflect.Value %5296, ptr %5292, align 8 +// CHECK-NEXT: %5297 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %1, i64 353 +// CHECK-NEXT: %5298 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %5297, i32 0, i32 0 +// CHECK-NEXT: %5299 = load { ptr, ptr }, ptr @main.V, align 8 +// CHECK-NEXT: %5300 = extractvalue { ptr, ptr } %5299, 1 +// CHECK-NEXT: %5301 = extractvalue { ptr, ptr } %5299, 0 +// CHECK-NEXT: %__llgo_funcval_code706 = call ptr asm "", "=r,0"(ptr %5301) +// CHECK-NEXT: %5302 = call %reflect.Value %__llgo_funcval_code706(ptr {{(nest|swiftself)}} %5300, %"{{.*}}/runtime/internal/runtime.eface" { ptr @"<-chan []_llgo_uint8", ptr null }) +// CHECK-NEXT: %5303 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %5297, i32 0, i32 1 +// CHECK-NEXT: %5304 = load { ptr, ptr }, ptr @main.V, align 8 +// CHECK-NEXT: %5305 = extractvalue { ptr, ptr } %5304, 1 +// CHECK-NEXT: %5306 = extractvalue { ptr, ptr } %5304, 0 +// CHECK-NEXT: %__llgo_funcval_code707 = call ptr asm "", "=r,0"(ptr %5306) +// CHECK-NEXT: %5307 = call %reflect.Value %__llgo_funcval_code707(ptr {{(nest|swiftself)}} %5305, %"{{.*}}/runtime/internal/runtime.eface" { ptr @_llgo_main.BytesChanRecv, ptr null }) +// CHECK-NEXT: store %reflect.Value %5302, ptr %5298, align 8 +// CHECK-NEXT: store %reflect.Value %5307, ptr %5303, align 8 +// CHECK-NEXT: %5308 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %1, i64 354 +// CHECK-NEXT: %5309 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %5308, i32 0, i32 0 +// CHECK-NEXT: %5310 = load { ptr, ptr }, ptr @main.V, align 8 +// CHECK-NEXT: %5311 = extractvalue { ptr, ptr } %5310, 1 +// CHECK-NEXT: %5312 = extractvalue { ptr, ptr } %5310, 0 +// CHECK-NEXT: %__llgo_funcval_code708 = call ptr asm "", "=r,0"(ptr %5312) +// CHECK-NEXT: %5313 = call %reflect.Value %__llgo_funcval_code708(ptr {{(nest|swiftself)}} %5311, %"{{.*}}/runtime/internal/runtime.eface" { ptr @_llgo_main.BytesChanSend, ptr null }) +// CHECK-NEXT: %5314 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %5308, i32 0, i32 1 +// CHECK-NEXT: %5315 = load { ptr, ptr }, ptr @main.V, align 8 +// CHECK-NEXT: %5316 = extractvalue { ptr, ptr } %5315, 1 +// CHECK-NEXT: %5317 = extractvalue { ptr, ptr } %5315, 0 +// CHECK-NEXT: %__llgo_funcval_code709 = call ptr asm "", "=r,0"(ptr %5317) +// CHECK-NEXT: %5318 = call %reflect.Value %__llgo_funcval_code709(ptr {{(nest|swiftself)}} %5316, %"{{.*}}/runtime/internal/runtime.eface" { ptr @"chan<- []_llgo_uint8", ptr null }) +// CHECK-NEXT: store %reflect.Value %5313, ptr %5309, align 8 +// CHECK-NEXT: store %reflect.Value %5318, ptr %5314, align 8 +// CHECK-NEXT: %5319 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %1, i64 355 +// CHECK-NEXT: %5320 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %5319, i32 0, i32 0 +// CHECK-NEXT: %5321 = load { ptr, ptr }, ptr @main.V, align 8 +// CHECK-NEXT: %5322 = extractvalue { ptr, ptr } %5321, 1 +// CHECK-NEXT: %5323 = extractvalue { ptr, ptr } %5321, 0 +// CHECK-NEXT: %__llgo_funcval_code710 = call ptr asm "", "=r,0"(ptr %5323) +// CHECK-NEXT: %5324 = call %reflect.Value %__llgo_funcval_code710(ptr {{(nest|swiftself)}} %5322, %"{{.*}}/runtime/internal/runtime.eface" { ptr @"chan<- []_llgo_uint8", ptr null }) +// CHECK-NEXT: %5325 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %5319, i32 0, i32 1 +// CHECK-NEXT: %5326 = load { ptr, ptr }, ptr @main.V, align 8 +// CHECK-NEXT: %5327 = extractvalue { ptr, ptr } %5326, 1 +// CHECK-NEXT: %5328 = extractvalue { ptr, ptr } %5326, 0 +// CHECK-NEXT: %__llgo_funcval_code711 = call ptr asm "", "=r,0"(ptr %5328) +// CHECK-NEXT: %5329 = call %reflect.Value %__llgo_funcval_code711(ptr {{(nest|swiftself)}} %5327, %"{{.*}}/runtime/internal/runtime.eface" { ptr @_llgo_main.BytesChanSend, ptr null }) +// CHECK-NEXT: store %reflect.Value %5324, ptr %5320, align 8 +// CHECK-NEXT: store %reflect.Value %5329, ptr %5325, align 8 +// CHECK-NEXT: %5330 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %1, i64 356 +// CHECK-NEXT: %5331 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %5330, i32 0, i32 0 +// CHECK-NEXT: %5332 = load { ptr, ptr }, ptr @main.V, align 8 +// CHECK-NEXT: %5333 = extractvalue { ptr, ptr } %5332, 1 +// CHECK-NEXT: %5334 = extractvalue { ptr, ptr } %5332, 0 +// CHECK-NEXT: %__llgo_funcval_code712 = call ptr asm "", "=r,0"(ptr %5334) +// CHECK-NEXT: %5335 = call %reflect.Value %__llgo_funcval_code712(ptr {{(nest|swiftself)}} %5333, %"{{.*}}/runtime/internal/runtime.eface" { ptr @_llgo_main.BytesChan, ptr null }) +// CHECK-NEXT: %5336 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %5330, i32 0, i32 1 +// CHECK-NEXT: %5337 = load { ptr, ptr }, ptr @main.V, align 8 +// CHECK-NEXT: %5338 = extractvalue { ptr, ptr } %5337, 1 +// CHECK-NEXT: %5339 = extractvalue { ptr, ptr } %5337, 0 +// CHECK-NEXT: %__llgo_funcval_code713 = call ptr asm "", "=r,0"(ptr %5339) +// CHECK-NEXT: %5340 = call %reflect.Value %__llgo_funcval_code713(ptr {{(nest|swiftself)}} %5338, %"{{.*}}/runtime/internal/runtime.eface" { ptr @"chan []_llgo_uint8", ptr null }) +// CHECK-NEXT: store %reflect.Value %5335, ptr %5331, align 8 +// CHECK-NEXT: store %reflect.Value %5340, ptr %5336, align 8 +// CHECK-NEXT: %5341 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %1, i64 357 +// CHECK-NEXT: %5342 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %5341, i32 0, i32 0 +// CHECK-NEXT: %5343 = load { ptr, ptr }, ptr @main.V, align 8 +// CHECK-NEXT: %5344 = extractvalue { ptr, ptr } %5343, 1 +// CHECK-NEXT: %5345 = extractvalue { ptr, ptr } %5343, 0 +// CHECK-NEXT: %__llgo_funcval_code714 = call ptr asm "", "=r,0"(ptr %5345) +// CHECK-NEXT: %5346 = call %reflect.Value %__llgo_funcval_code714(ptr {{(nest|swiftself)}} %5344, %"{{.*}}/runtime/internal/runtime.eface" { ptr @"chan []_llgo_uint8", ptr null }) +// CHECK-NEXT: %5347 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %5341, i32 0, i32 1 +// CHECK-NEXT: %5348 = load { ptr, ptr }, ptr @main.V, align 8 +// CHECK-NEXT: %5349 = extractvalue { ptr, ptr } %5348, 1 +// CHECK-NEXT: %5350 = extractvalue { ptr, ptr } %5348, 0 +// CHECK-NEXT: %__llgo_funcval_code715 = call ptr asm "", "=r,0"(ptr %5350) +// CHECK-NEXT: %5351 = call %reflect.Value %__llgo_funcval_code715(ptr {{(nest|swiftself)}} %5349, %"{{.*}}/runtime/internal/runtime.eface" { ptr @_llgo_main.BytesChan, ptr null }) +// CHECK-NEXT: store %reflect.Value %5346, ptr %5342, align 8 +// CHECK-NEXT: store %reflect.Value %5351, ptr %5347, align 8 +// CHECK-NEXT: %5352 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %1, i64 358 +// CHECK-NEXT: %5353 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %5352, i32 0, i32 0 +// CHECK-NEXT: %5354 = load { ptr, ptr }, ptr @main.V, align 8 +// CHECK-NEXT: %5355 = extractvalue { ptr, ptr } %5354, 1 +// CHECK-NEXT: %5356 = extractvalue { ptr, ptr } %5354, 0 +// CHECK-NEXT: %__llgo_funcval_code716 = call ptr asm "", "=r,0"(ptr %5356) +// CHECK-NEXT: %5357 = call %reflect.Value %__llgo_funcval_code716(ptr {{(nest|swiftself)}} %5355, %"{{.*}}/runtime/internal/runtime.eface" { ptr @"chan []_llgo_uint8", ptr null }) +// CHECK-NEXT: %5358 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %5352, i32 0, i32 1 +// CHECK-NEXT: %5359 = load { ptr, ptr }, ptr @main.V, align 8 +// CHECK-NEXT: %5360 = extractvalue { ptr, ptr } %5359, 1 +// CHECK-NEXT: %5361 = extractvalue { ptr, ptr } %5359, 0 +// CHECK-NEXT: %__llgo_funcval_code717 = call ptr asm "", "=r,0"(ptr %5361) +// CHECK-NEXT: %5362 = call %reflect.Value %__llgo_funcval_code717(ptr {{(nest|swiftself)}} %5360, %"{{.*}}/runtime/internal/runtime.eface" { ptr @"<-chan []_llgo_uint8", ptr null }) +// CHECK-NEXT: store %reflect.Value %5357, ptr %5353, align 8 +// CHECK-NEXT: store %reflect.Value %5362, ptr %5358, align 8 +// CHECK-NEXT: %5363 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %1, i64 359 +// CHECK-NEXT: %5364 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %5363, i32 0, i32 0 +// CHECK-NEXT: %5365 = load { ptr, ptr }, ptr @main.V, align 8 +// CHECK-NEXT: %5366 = extractvalue { ptr, ptr } %5365, 1 +// CHECK-NEXT: %5367 = extractvalue { ptr, ptr } %5365, 0 +// CHECK-NEXT: %__llgo_funcval_code718 = call ptr asm "", "=r,0"(ptr %5367) +// CHECK-NEXT: %5368 = call %reflect.Value %__llgo_funcval_code718(ptr {{(nest|swiftself)}} %5366, %"{{.*}}/runtime/internal/runtime.eface" { ptr @"chan []_llgo_uint8", ptr null }) +// CHECK-NEXT: %5369 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %5363, i32 0, i32 1 +// CHECK-NEXT: %5370 = load { ptr, ptr }, ptr @main.V, align 8 +// CHECK-NEXT: %5371 = extractvalue { ptr, ptr } %5370, 1 +// CHECK-NEXT: %5372 = extractvalue { ptr, ptr } %5370, 0 +// CHECK-NEXT: %__llgo_funcval_code719 = call ptr asm "", "=r,0"(ptr %5372) +// CHECK-NEXT: %5373 = call %reflect.Value %__llgo_funcval_code719(ptr {{(nest|swiftself)}} %5371, %"{{.*}}/runtime/internal/runtime.eface" { ptr @"chan<- []_llgo_uint8", ptr null }) +// CHECK-NEXT: store %reflect.Value %5368, ptr %5364, align 8 +// CHECK-NEXT: store %reflect.Value %5373, ptr %5369, align 8 +// CHECK-NEXT: %5374 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %1, i64 360 +// CHECK-NEXT: %5375 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %5374, i32 0, i32 0 +// CHECK-NEXT: %5376 = load { ptr, ptr }, ptr @main.V, align 8 +// CHECK-NEXT: %5377 = extractvalue { ptr, ptr } %5376, 1 +// CHECK-NEXT: %5378 = extractvalue { ptr, ptr } %5376, 0 +// CHECK-NEXT: %__llgo_funcval_code720 = call ptr asm "", "=r,0"(ptr %5378) +// CHECK-NEXT: %5379 = call %reflect.Value %__llgo_funcval_code720(ptr {{(nest|swiftself)}} %5377, %"{{.*}}/runtime/internal/runtime.eface" { ptr @_llgo_main.IntChan, ptr null }) +// CHECK-NEXT: %5380 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %5374, i32 0, i32 1 +// CHECK-NEXT: %5381 = load { ptr, ptr }, ptr @main.V, align 8 +// CHECK-NEXT: %5382 = extractvalue { ptr, ptr } %5381, 1 +// CHECK-NEXT: %5383 = extractvalue { ptr, ptr } %5381, 0 +// CHECK-NEXT: %__llgo_funcval_code721 = call ptr asm "", "=r,0"(ptr %5383) +// CHECK-NEXT: %5384 = call %reflect.Value %__llgo_funcval_code721(ptr {{(nest|swiftself)}} %5382, %"{{.*}}/runtime/internal/runtime.eface" { ptr @_llgo_main.IntChan, ptr null }) +// CHECK-NEXT: store %reflect.Value %5379, ptr %5375, align 8 +// CHECK-NEXT: store %reflect.Value %5384, ptr %5380, align 8 +// CHECK-NEXT: %5385 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %1, i64 361 +// CHECK-NEXT: %5386 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %5385, i32 0, i32 0 +// CHECK-NEXT: %5387 = load { ptr, ptr }, ptr @main.V, align 8 +// CHECK-NEXT: %5388 = extractvalue { ptr, ptr } %5387, 1 +// CHECK-NEXT: %5389 = extractvalue { ptr, ptr } %5387, 0 +// CHECK-NEXT: %__llgo_funcval_code722 = call ptr asm "", "=r,0"(ptr %5389) +// CHECK-NEXT: %5390 = call %reflect.Value %__llgo_funcval_code722(ptr {{(nest|swiftself)}} %5388, %"{{.*}}/runtime/internal/runtime.eface" { ptr @_llgo_main.IntChanRecv, ptr null }) +// CHECK-NEXT: %5391 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %5385, i32 0, i32 1 +// CHECK-NEXT: %5392 = load { ptr, ptr }, ptr @main.V, align 8 +// CHECK-NEXT: %5393 = extractvalue { ptr, ptr } %5392, 1 +// CHECK-NEXT: %5394 = extractvalue { ptr, ptr } %5392, 0 +// CHECK-NEXT: %__llgo_funcval_code723 = call ptr asm "", "=r,0"(ptr %5394) +// CHECK-NEXT: %5395 = call %reflect.Value %__llgo_funcval_code723(ptr {{(nest|swiftself)}} %5393, %"{{.*}}/runtime/internal/runtime.eface" { ptr @_llgo_main.IntChanRecv, ptr null }) +// CHECK-NEXT: store %reflect.Value %5390, ptr %5386, align 8 +// CHECK-NEXT: store %reflect.Value %5395, ptr %5391, align 8 +// CHECK-NEXT: %5396 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %1, i64 362 +// CHECK-NEXT: %5397 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %5396, i32 0, i32 0 +// CHECK-NEXT: %5398 = load { ptr, ptr }, ptr @main.V, align 8 +// CHECK-NEXT: %5399 = extractvalue { ptr, ptr } %5398, 1 +// CHECK-NEXT: %5400 = extractvalue { ptr, ptr } %5398, 0 +// CHECK-NEXT: %__llgo_funcval_code724 = call ptr asm "", "=r,0"(ptr %5400) +// CHECK-NEXT: %5401 = call %reflect.Value %__llgo_funcval_code724(ptr {{(nest|swiftself)}} %5399, %"{{.*}}/runtime/internal/runtime.eface" { ptr @_llgo_main.IntChanSend, ptr null }) +// CHECK-NEXT: %5402 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %5396, i32 0, i32 1 +// CHECK-NEXT: %5403 = load { ptr, ptr }, ptr @main.V, align 8 +// CHECK-NEXT: %5404 = extractvalue { ptr, ptr } %5403, 1 +// CHECK-NEXT: %5405 = extractvalue { ptr, ptr } %5403, 0 +// CHECK-NEXT: %__llgo_funcval_code725 = call ptr asm "", "=r,0"(ptr %5405) +// CHECK-NEXT: %5406 = call %reflect.Value %__llgo_funcval_code725(ptr {{(nest|swiftself)}} %5404, %"{{.*}}/runtime/internal/runtime.eface" { ptr @_llgo_main.IntChanSend, ptr null }) +// CHECK-NEXT: store %reflect.Value %5401, ptr %5397, align 8 +// CHECK-NEXT: store %reflect.Value %5406, ptr %5402, align 8 +// CHECK-NEXT: %5407 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %1, i64 363 +// CHECK-NEXT: %5408 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %5407, i32 0, i32 0 +// CHECK-NEXT: %5409 = load { ptr, ptr }, ptr @main.V, align 8 +// CHECK-NEXT: %5410 = extractvalue { ptr, ptr } %5409, 1 +// CHECK-NEXT: %5411 = extractvalue { ptr, ptr } %5409, 0 +// CHECK-NEXT: %__llgo_funcval_code726 = call ptr asm "", "=r,0"(ptr %5411) +// CHECK-NEXT: %5412 = call %reflect.Value %__llgo_funcval_code726(ptr {{(nest|swiftself)}} %5410, %"{{.*}}/runtime/internal/runtime.eface" { ptr @_llgo_main.BytesChan, ptr null }) +// CHECK-NEXT: %5413 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %5407, i32 0, i32 1 +// CHECK-NEXT: %5414 = load { ptr, ptr }, ptr @main.V, align 8 +// CHECK-NEXT: %5415 = extractvalue { ptr, ptr } %5414, 1 +// CHECK-NEXT: %5416 = extractvalue { ptr, ptr } %5414, 0 +// CHECK-NEXT: %__llgo_funcval_code727 = call ptr asm "", "=r,0"(ptr %5416) +// CHECK-NEXT: %5417 = call %reflect.Value %__llgo_funcval_code727(ptr {{(nest|swiftself)}} %5415, %"{{.*}}/runtime/internal/runtime.eface" { ptr @_llgo_main.BytesChan, ptr null }) +// CHECK-NEXT: store %reflect.Value %5412, ptr %5408, align 8 +// CHECK-NEXT: store %reflect.Value %5417, ptr %5413, align 8 +// CHECK-NEXT: %5418 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %1, i64 364 +// CHECK-NEXT: %5419 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %5418, i32 0, i32 0 +// CHECK-NEXT: %5420 = load { ptr, ptr }, ptr @main.V, align 8 +// CHECK-NEXT: %5421 = extractvalue { ptr, ptr } %5420, 1 +// CHECK-NEXT: %5422 = extractvalue { ptr, ptr } %5420, 0 +// CHECK-NEXT: %__llgo_funcval_code728 = call ptr asm "", "=r,0"(ptr %5422) +// CHECK-NEXT: %5423 = call %reflect.Value %__llgo_funcval_code728(ptr {{(nest|swiftself)}} %5421, %"{{.*}}/runtime/internal/runtime.eface" { ptr @_llgo_main.BytesChanRecv, ptr null }) +// CHECK-NEXT: %5424 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %5418, i32 0, i32 1 +// CHECK-NEXT: %5425 = load { ptr, ptr }, ptr @main.V, align 8 +// CHECK-NEXT: %5426 = extractvalue { ptr, ptr } %5425, 1 +// CHECK-NEXT: %5427 = extractvalue { ptr, ptr } %5425, 0 +// CHECK-NEXT: %__llgo_funcval_code729 = call ptr asm "", "=r,0"(ptr %5427) +// CHECK-NEXT: %5428 = call %reflect.Value %__llgo_funcval_code729(ptr {{(nest|swiftself)}} %5426, %"{{.*}}/runtime/internal/runtime.eface" { ptr @_llgo_main.BytesChanRecv, ptr null }) +// CHECK-NEXT: store %reflect.Value %5423, ptr %5419, align 8 +// CHECK-NEXT: store %reflect.Value %5428, ptr %5424, align 8 +// CHECK-NEXT: %5429 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %1, i64 365 +// CHECK-NEXT: %5430 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %5429, i32 0, i32 0 +// CHECK-NEXT: %5431 = load { ptr, ptr }, ptr @main.V, align 8 +// CHECK-NEXT: %5432 = extractvalue { ptr, ptr } %5431, 1 +// CHECK-NEXT: %5433 = extractvalue { ptr, ptr } %5431, 0 +// CHECK-NEXT: %__llgo_funcval_code730 = call ptr asm "", "=r,0"(ptr %5433) +// CHECK-NEXT: %5434 = call %reflect.Value %__llgo_funcval_code730(ptr {{(nest|swiftself)}} %5432, %"{{.*}}/runtime/internal/runtime.eface" { ptr @_llgo_main.BytesChanSend, ptr null }) +// CHECK-NEXT: %5435 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %5429, i32 0, i32 1 +// CHECK-NEXT: %5436 = load { ptr, ptr }, ptr @main.V, align 8 +// CHECK-NEXT: %5437 = extractvalue { ptr, ptr } %5436, 1 +// CHECK-NEXT: %5438 = extractvalue { ptr, ptr } %5436, 0 +// CHECK-NEXT: %__llgo_funcval_code731 = call ptr asm "", "=r,0"(ptr %5438) +// CHECK-NEXT: %5439 = call %reflect.Value %__llgo_funcval_code731(ptr {{(nest|swiftself)}} %5437, %"{{.*}}/runtime/internal/runtime.eface" { ptr @_llgo_main.BytesChanSend, ptr null }) +// CHECK-NEXT: store %reflect.Value %5434, ptr %5430, align 8 +// CHECK-NEXT: store %reflect.Value %5439, ptr %5435, align 8 +// CHECK-NEXT: %5440 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %1, i64 366 +// CHECK-NEXT: %5441 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %5440, i32 0, i32 0 +// CHECK-NEXT: %5442 = load { ptr, ptr }, ptr @main.V, align 8 +// CHECK-NEXT: %5443 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 8) +// CHECK-NEXT: store i64 1, ptr %5443, align 8 +// CHECK-NEXT: %5444 = insertvalue %"{{.*}}/runtime/internal/runtime.eface" { ptr @_llgo_int, ptr undef }, ptr %5443, 1 +// CHECK-NEXT: %5445 = extractvalue { ptr, ptr } %5442, 1 +// CHECK-NEXT: %5446 = extractvalue { ptr, ptr } %5442, 0 +// CHECK-NEXT: %__llgo_funcval_code732 = call ptr asm "", "=r,0"(ptr %5446) +// CHECK-NEXT: %5447 = call %reflect.Value %__llgo_funcval_code732(ptr {{(nest|swiftself)}} %5445, %"{{.*}}/runtime/internal/runtime.eface" %5444) +// CHECK-NEXT: %5448 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %5440, i32 0, i32 1 +// CHECK-NEXT: %5449 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 8) +// CHECK-NEXT: store i64 1, ptr %5449, align 8 +// CHECK-NEXT: %5450 = insertvalue %"{{.*}}/runtime/internal/runtime.eface" { ptr @_llgo_int, ptr undef }, ptr %5449, 1 +// CHECK-NEXT: %5451 = call %reflect.Value @main.EmptyInterfaceV(%"{{.*}}/runtime/internal/runtime.eface" %5450) +// CHECK-NEXT: store %reflect.Value %5447, ptr %5441, align 8 +// CHECK-NEXT: store %reflect.Value %5451, ptr %5448, align 8 +// CHECK-NEXT: %5452 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %1, i64 367 +// CHECK-NEXT: %5453 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %5452, i32 0, i32 0 +// CHECK-NEXT: %5454 = load { ptr, ptr }, ptr @main.V, align 8 +// CHECK-NEXT: %5455 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 16) +// CHECK-NEXT: store %"{{.*}}/runtime/internal/runtime.String" { ptr @{{[0-9]+}}, i64 5 }, ptr %5455, align 8 +// CHECK-NEXT: %5456 = insertvalue %"{{.*}}/runtime/internal/runtime.eface" { ptr @_llgo_string, ptr undef }, ptr %5455, 1 +// CHECK-NEXT: %5457 = extractvalue { ptr, ptr } %5454, 1 +// CHECK-NEXT: %5458 = extractvalue { ptr, ptr } %5454, 0 +// CHECK-NEXT: %__llgo_funcval_code733 = call ptr asm "", "=r,0"(ptr %5458) +// CHECK-NEXT: %5459 = call %reflect.Value %__llgo_funcval_code733(ptr {{(nest|swiftself)}} %5457, %"{{.*}}/runtime/internal/runtime.eface" %5456) +// CHECK-NEXT: %5460 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %5452, i32 0, i32 1 +// CHECK-NEXT: %5461 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 16) +// CHECK-NEXT: store %"{{.*}}/runtime/internal/runtime.String" { ptr @{{[0-9]+}}, i64 5 }, ptr %5461, align 8 +// CHECK-NEXT: %5462 = insertvalue %"{{.*}}/runtime/internal/runtime.eface" { ptr @_llgo_string, ptr undef }, ptr %5461, 1 +// CHECK-NEXT: %5463 = call %reflect.Value @main.EmptyInterfaceV(%"{{.*}}/runtime/internal/runtime.eface" %5462) +// CHECK-NEXT: store %reflect.Value %5459, ptr %5453, align 8 +// CHECK-NEXT: store %reflect.Value %5463, ptr %5460, align 8 +// CHECK-NEXT: %5464 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %1, i64 368 +// CHECK-NEXT: %5465 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %5464, i32 0, i32 0 +// CHECK-NEXT: %5466 = load { ptr, ptr }, ptr @main.V, align 8 +// CHECK-NEXT: %5467 = call ptr @"{{.*}}/runtime/internal/runtime.AllocZ"(i64 40) +// CHECK-NEXT: %5468 = insertvalue %"{{.*}}/runtime/internal/runtime.eface" { ptr @"*_llgo_bytes.Buffer", ptr undef }, ptr %5467, 1 +// CHECK-NEXT: %5469 = extractvalue { ptr, ptr } %5466, 1 +// CHECK-NEXT: %5470 = extractvalue { ptr, ptr } %5466, 0 +// CHECK-NEXT: %__llgo_funcval_code734 = call ptr asm "", "=r,0"(ptr %5470) +// CHECK-NEXT: %5471 = call %reflect.Value %__llgo_funcval_code734(ptr {{(nest|swiftself)}} %5469, %"{{.*}}/runtime/internal/runtime.eface" %5468) +// CHECK-NEXT: %5472 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %5464, i32 0, i32 1 +// CHECK-NEXT: %5473 = call ptr @"{{.*}}/runtime/internal/runtime.AllocZ"(i64 40) +// CHECK-NEXT: %5474 = call ptr @"{{.*}}/runtime/internal/runtime.NewItab"(ptr @"_llgo_iface$uycIKA3bbxRhudEjW1hHKWKdLqHQsCVy8NdW1bkQmNw", ptr @"*_llgo_bytes.Buffer") +// CHECK-NEXT: %5475 = insertvalue %"{{.*}}/runtime/internal/runtime.iface" undef, ptr %5474, 0 +// CHECK-NEXT: %5476 = insertvalue %"{{.*}}/runtime/internal/runtime.iface" %5475, ptr %5473, 1 +// CHECK-NEXT: %5477 = call %reflect.Value @main.ReaderV(%"{{.*}}/runtime/internal/runtime.iface" %5476) +// CHECK-NEXT: store %reflect.Value %5471, ptr %5465, align 8 +// CHECK-NEXT: store %reflect.Value %5477, ptr %5472, align 8 +// CHECK-NEXT: %5478 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %1, i64 369 +// CHECK-NEXT: %5479 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %5478, i32 0, i32 0 +// CHECK-NEXT: %5480 = call ptr @"{{.*}}/runtime/internal/runtime.AllocZ"(i64 40) +// CHECK-NEXT: %5481 = call ptr @"{{.*}}/runtime/internal/runtime.NewItab"(ptr @"_llgo_iface$Zutt7i_AwOTtBOIzyS7ZA5vhcNcbk0kRAoRC98HJDos", ptr @"*_llgo_bytes.Buffer") +// CHECK-NEXT: %5482 = insertvalue %"{{.*}}/runtime/internal/runtime.iface" undef, ptr %5481, 0 +// CHECK-NEXT: %5483 = insertvalue %"{{.*}}/runtime/internal/runtime.iface" %5482, ptr %5480, 1 +// CHECK-NEXT: %5484 = call %reflect.Value @main.ReadWriterV(%"{{.*}}/runtime/internal/runtime.iface" %5483) +// CHECK-NEXT: %5485 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %5478, i32 0, i32 1 +// CHECK-NEXT: %5486 = call ptr @"{{.*}}/runtime/internal/runtime.AllocZ"(i64 40) +// CHECK-NEXT: %5487 = call ptr @"{{.*}}/runtime/internal/runtime.NewItab"(ptr @"_llgo_iface$uycIKA3bbxRhudEjW1hHKWKdLqHQsCVy8NdW1bkQmNw", ptr @"*_llgo_bytes.Buffer") +// CHECK-NEXT: %5488 = insertvalue %"{{.*}}/runtime/internal/runtime.iface" undef, ptr %5487, 0 +// CHECK-NEXT: %5489 = insertvalue %"{{.*}}/runtime/internal/runtime.iface" %5488, ptr %5486, 1 +// CHECK-NEXT: %5490 = call %reflect.Value @main.ReaderV(%"{{.*}}/runtime/internal/runtime.iface" %5489) +// CHECK-NEXT: store %reflect.Value %5484, ptr %5479, align 8 +// CHECK-NEXT: store %reflect.Value %5490, ptr %5485, align 8 +// CHECK-NEXT: %5491 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %1, i64 370 +// CHECK-NEXT: %5492 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %5491, i32 0, i32 0 +// CHECK-NEXT: %5493 = load { ptr, ptr }, ptr @main.V, align 8 +// CHECK-NEXT: %5494 = call ptr @"{{.*}}/runtime/internal/runtime.AllocZ"(i64 40) +// CHECK-NEXT: %5495 = insertvalue %"{{.*}}/runtime/internal/runtime.eface" { ptr @"*_llgo_bytes.Buffer", ptr undef }, ptr %5494, 1 +// CHECK-NEXT: %5496 = extractvalue { ptr, ptr } %5493, 1 +// CHECK-NEXT: %5497 = extractvalue { ptr, ptr } %5493, 0 +// CHECK-NEXT: %__llgo_funcval_code735 = call ptr asm "", "=r,0"(ptr %5497) +// CHECK-NEXT: %5498 = call %reflect.Value %__llgo_funcval_code735(ptr {{(nest|swiftself)}} %5496, %"{{.*}}/runtime/internal/runtime.eface" %5495) +// CHECK-NEXT: %5499 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %5491, i32 0, i32 1 +// CHECK-NEXT: %5500 = call ptr @"{{.*}}/runtime/internal/runtime.AllocZ"(i64 40) +// CHECK-NEXT: %5501 = call ptr @"{{.*}}/runtime/internal/runtime.NewItab"(ptr @"_llgo_iface$Zutt7i_AwOTtBOIzyS7ZA5vhcNcbk0kRAoRC98HJDos", ptr @"*_llgo_bytes.Buffer") +// CHECK-NEXT: %5502 = insertvalue %"{{.*}}/runtime/internal/runtime.iface" undef, ptr %5501, 0 +// CHECK-NEXT: %5503 = insertvalue %"{{.*}}/runtime/internal/runtime.iface" %5502, ptr %5500, 1 +// CHECK-NEXT: %5504 = call %reflect.Value @main.ReadWriterV(%"{{.*}}/runtime/internal/runtime.iface" %5503) +// CHECK-NEXT: store %reflect.Value %5498, ptr %5492, align 8 +// CHECK-NEXT: store %reflect.Value %5504, ptr %5499, align 8 +// CHECK-NEXT: %5505 = insertvalue %"{{.*}}/runtime/internal/runtime.Slice" undef, ptr %1, 0 +// CHECK-NEXT: %5506 = insertvalue %"{{.*}}/runtime/internal/runtime.Slice" %5505, i64 371, 1 +// CHECK-NEXT: %5507 = insertvalue %"{{.*}}/runtime/internal/runtime.Slice" %5506, i64 371, 2 +// CHECK-NEXT: store %"{{.*}}/runtime/internal/runtime.Slice" %5507, ptr @main.convertTests, align 8 +// CHECK-NEXT: br label %_llgo_2 +// CHECK-EMPTY: +// CHECK-NEXT: _llgo_2: ; preds = %_llgo_1, %_llgo_0 +// CHECK-NEXT: ret void +// CHECK-NEXT: } + +// CHECK-LABEL: define void @main.main(){{.*}} { +// CHECK-NEXT: _llgo_0: +// CHECK-NEXT: call void @main.TestConvert(ptr @"__llgo.moduleZeroSizedAlloc$") +// CHECK-NEXT: call void @main.TestConvertPanic(ptr @"__llgo.moduleZeroSizedAlloc$") +// CHECK-NEXT: call void @main.TestConvertSlice2Array(ptr @"__llgo.moduleZeroSizedAlloc$") +// CHECK-NEXT: call void @main.TestConvertNaNs(ptr @"__llgo.moduleZeroSizedAlloc$") +// CHECK-NEXT: ret void +// CHECK-NEXT: } + +// CHECK-LABEL: define void @main.shouldPanic(%"{{.*}}/runtime/internal/runtime.String" %0, { ptr, ptr } %1){{.*}} { +// CHECK-NEXT: _llgo_0: +// CHECK-NEXT: %2 = call ptr @"{{.*}}/runtime/internal/runtime.AllocZ"(i64 16) +// CHECK-NEXT: store %"{{.*}}/runtime/internal/runtime.String" %0, ptr %2, align 8 +// CHECK-NEXT: %3 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 8) +// CHECK-NEXT: %4 = getelementptr inbounds { ptr }, ptr %3, i32 0, i32 0 +// CHECK-NEXT: store ptr %2, ptr %4, align 8 +// CHECK-NEXT: %5 = insertvalue { ptr, ptr } { ptr @"main.shouldPanic$1", ptr undef }, ptr %3, 1 +// CHECK-NEXT: %6 = call ptr @"{{.*}}/runtime/internal/runtime.GetThreadDefer"() +// CHECK-NEXT: %7 = alloca i8 +// CHECK-NEXT: %8 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 48) +// CHECK-NEXT: %9 = getelementptr inbounds %"{{.*}}/runtime/internal/runtime.Defer", ptr %8, i32 0, i32 0 +// CHECK-NEXT: store ptr %7, ptr %9, align 8 +// CHECK-NEXT: %10 = getelementptr inbounds %"{{.*}}/runtime/internal/runtime.Defer", ptr %8, i32 0, i32 1 +// CHECK-NEXT: store i64 0, ptr %10, align 8 +// CHECK-NEXT: %11 = getelementptr inbounds %"{{.*}}/runtime/internal/runtime.Defer", ptr %8, i32 0, i32 2 +// CHECK-NEXT: store ptr %6, ptr %11, align 8 +// CHECK-NEXT: %12 = getelementptr inbounds %"{{.*}}/runtime/internal/runtime.Defer", ptr %8, i32 0, i32 3 +// CHECK-NEXT: store ptr blockaddress(@main.shouldPanic, %_llgo_2), ptr %12, align 8 +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.SetThreadDefer"(ptr %8) +// CHECK-NEXT: %13 = getelementptr inbounds %"{{.*}}/runtime/internal/runtime.Defer", ptr %8, i32 0, i32 1 +// CHECK-NEXT: %14 = getelementptr inbounds %"{{.*}}/runtime/internal/runtime.Defer", ptr %8, i32 0, i32 3 +// CHECK-NEXT: %15 = getelementptr inbounds %"{{.*}}/runtime/internal/runtime.Defer", ptr %8, i32 0, i32 4 +// CHECK-NEXT: %16 = getelementptr inbounds %"{{.*}}/runtime/internal/runtime.Defer", ptr %8, i32 0, i32 5 +// CHECK-NEXT: store ptr null, ptr %16, align 8 +// CHECK-NEXT: %17 = call i32 @{{(__)?}}sigsetjmp(ptr %7, i32 0) +// CHECK-NEXT: %18 = icmp eq i32 %17, 0 +// CHECK-NEXT: br i1 %18, label %_llgo_4, label %_llgo_5 +// CHECK-EMPTY: +// CHECK-NEXT: _llgo_1: ; preds = %_llgo_3 +// CHECK-NEXT: ret void +// CHECK-EMPTY: +// CHECK-NEXT: _llgo_2: ; preds = %_llgo_5, %_llgo_4 +// CHECK-NEXT: store ptr blockaddress(@main.shouldPanic, %_llgo_3), ptr %14, align 8 +// CHECK-NEXT: %19 = load i64, ptr %13, align 8 +// CHECK-NEXT: %20 = load ptr, ptr %16, align 8 +// CHECK-NEXT: %21 = icmp ne ptr %20, null +// CHECK-NEXT: br i1 %21, label %_llgo_7, label %_llgo_8 +// CHECK-EMPTY: +// CHECK-NEXT: _llgo_3: ; preds = %_llgo_5, %_llgo_8 +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.Rethrow"(ptr %6) +// CHECK-NEXT: br label %_llgo_1 +// CHECK-EMPTY: +// CHECK-NEXT: _llgo_4: ; preds = %_llgo_0 +// CHECK-NEXT: %22 = load ptr, ptr %16, align 8 +// CHECK-NEXT: %23 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 32) +// CHECK-NEXT: %24 = getelementptr inbounds { ptr, i64, { ptr, ptr } }, ptr %23, i32 0, i32 0 +// CHECK-NEXT: store ptr %22, ptr %24, align 8 +// CHECK-NEXT: %25 = getelementptr inbounds { ptr, i64, { ptr, ptr } }, ptr %23, i32 0, i32 1 +// CHECK-NEXT: store i64 0, ptr %25, align 8 +// CHECK-NEXT: %26 = getelementptr inbounds { ptr, i64, { ptr, ptr } }, ptr %23, i32 0, i32 2 +// CHECK-NEXT: store { ptr, ptr } %5, ptr %26, align 8 +// CHECK-NEXT: store ptr %23, ptr %16, align 8 +// CHECK-NEXT: %27 = extractvalue { ptr, ptr } %1, 1 +// CHECK-NEXT: %28 = extractvalue { ptr, ptr } %1, 0 +// CHECK-NEXT: %__llgo_funcval_code = call ptr asm "", "=r,0"(ptr %28) +// CHECK-NEXT: call void %__llgo_funcval_code(ptr {{(nest|swiftself)}} %27) +// CHECK-NEXT: store ptr blockaddress(@main.shouldPanic, %_llgo_6), ptr %15, align 8 +// CHECK-NEXT: br label %_llgo_2 +// CHECK-EMPTY: +// CHECK-NEXT: _llgo_5: ; preds = %_llgo_0 +// CHECK-NEXT: store ptr blockaddress(@main.shouldPanic, %_llgo_3), ptr %15, align 8 +// CHECK-NEXT: %29 = load ptr, ptr %14, align 8 +// CHECK-NEXT: indirectbr ptr %29, [label %_llgo_3, label %_llgo_2] +// CHECK-EMPTY: +// CHECK-NEXT: _llgo_6: ; preds = %_llgo_8 +// CHECK-NEXT: ret void +// CHECK-EMPTY: +// CHECK-NEXT: _llgo_7: ; preds = %_llgo_2 +// CHECK-NEXT: %30 = load ptr, ptr %16, align 8 +// CHECK-NEXT: %31 = load { ptr, i64, { ptr, ptr } }, ptr %30, align 8 +// CHECK-NEXT: %32 = extractvalue { ptr, i64, { ptr, ptr } } %31, 0 +// CHECK-NEXT: store ptr %32, ptr %16, align 8 +// CHECK-NEXT: %33 = extractvalue { ptr, i64, { ptr, ptr } } %31, 2 +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.FreeDeferNode"(ptr %30) +// CHECK-NEXT: %34 = extractvalue { ptr, ptr } %33, 1 +// CHECK-NEXT: %35 = extractvalue { ptr, ptr } %33, 0 +// CHECK-NEXT: %__llgo_funcval_code1 = call ptr asm "", "=r,0"(ptr %35) +// CHECK-NEXT: call void %__llgo_funcval_code1(ptr {{(nest|swiftself)}} %34) +// CHECK-NEXT: br label %_llgo_8 +// CHECK-EMPTY: +// CHECK-NEXT: _llgo_8: ; preds = %_llgo_7, %_llgo_2 +// CHECK-NEXT: %36 = load %"{{.*}}/runtime/internal/runtime.Defer", ptr %8, align 8 +// CHECK-NEXT: %37 = extractvalue %"{{.*}}/runtime/internal/runtime.Defer" %36, 2 +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.SetThreadDefer"(ptr %37) +// CHECK-NEXT: %38 = load ptr, ptr %15, align 8 +// CHECK-NEXT: indirectbr ptr %38, [label %_llgo_3, label %_llgo_6] +// CHECK-NEXT: } + +// CHECK-LABEL: define void @"main.shouldPanic$1"(ptr {{(nest|swiftself)}} %0){{.*}} { +// CHECK-NEXT: _llgo_0: +// CHECK-NEXT: %1 = load { ptr }, ptr %0, align 8 +// CHECK-NEXT: %2 = call %"{{.*}}/runtime/internal/runtime.eface" @"{{.*}}/runtime/internal/runtime.Recover"() +// CHECK-NEXT: %3 = call i1 @"{{.*}}/runtime/internal/runtime.EfaceEqual"(%"{{.*}}/runtime/internal/runtime.eface" %2, %"{{.*}}/runtime/internal/runtime.eface" zeroinitializer) +// CHECK-NEXT: br i1 %3, label %_llgo_1, label %_llgo_2 +// CHECK-EMPTY: +// CHECK-NEXT: _llgo_1: ; preds = %_llgo_0 +// CHECK-NEXT: %4 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 16) +// CHECK-NEXT: store %"{{.*}}/runtime/internal/runtime.String" { ptr @{{[0-9]+}}, i64 13 }, ptr %4, align 8 +// CHECK-NEXT: %5 = insertvalue %"{{.*}}/runtime/internal/runtime.eface" { ptr @_llgo_string, ptr undef }, ptr %4, 1 +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.Panic"(%"{{.*}}/runtime/internal/runtime.eface" %5) +// CHECK-NEXT: unreachable +// CHECK-EMPTY: +// CHECK-NEXT: _llgo_2: ; preds = %_llgo_0 +// CHECK-NEXT: %6 = extractvalue { ptr } %1, 0 +// CHECK-NEXT: %7 = load %"{{.*}}/runtime/internal/runtime.String", ptr %6, align 8 +// CHECK-NEXT: %8 = call i1 @"{{.*}}/runtime/internal/runtime.StringEqual"(%"{{.*}}/runtime/internal/runtime.String" %7, %"{{.*}}/runtime/internal/runtime.String" zeroinitializer) +// CHECK-NEXT: %9 = xor i1 %8, true +// CHECK-NEXT: br i1 %9, label %_llgo_3, label %_llgo_4 +// CHECK-EMPTY: +// CHECK-NEXT: _llgo_3: ; preds = %_llgo_2 +// CHECK-NEXT: %10 = extractvalue %"{{.*}}/runtime/internal/runtime.eface" %2, 0 +// CHECK-NEXT: %11 = icmp eq ptr %10, @_llgo_string +// CHECK-NEXT: br i1 %11, label %_llgo_13, label %_llgo_14 +// CHECK-EMPTY: +// CHECK-NEXT: _llgo_4: ; preds = %_llgo_11, %_llgo_2 +// CHECK-NEXT: ret void +// CHECK-EMPTY: +// CHECK-NEXT: _llgo_5: ; preds = %_llgo_8, %_llgo_6 +// CHECK-NEXT: %12 = phi %"{{.*}}/runtime/internal/runtime.String" [ %43, %_llgo_6 ], [ %16, %_llgo_8 ] +// CHECK-NEXT: %13 = call i1 @strings.HasPrefix(%"{{.*}}/runtime/internal/runtime.String" %12, %"{{.*}}/runtime/internal/runtime.String" { ptr @{{[0-9]+}}, i64 7 }) +// CHECK-NEXT: br i1 %13, label %_llgo_11, label %_llgo_10 +// CHECK-EMPTY: +// CHECK-NEXT: _llgo_6: ; preds = %_llgo_15 +// CHECK-NEXT: br label %_llgo_5 +// CHECK-EMPTY: +// CHECK-NEXT: _llgo_7: ; preds = %_llgo_15 +// CHECK-NEXT: %14 = extractvalue %"{{.*}}/runtime/internal/runtime.eface" %2, 0 +// CHECK-NEXT: %15 = icmp eq ptr %14, @"*_llgo_reflect.ValueError" +// CHECK-NEXT: br i1 %15, label %_llgo_16, label %_llgo_17 +// CHECK-EMPTY: +// CHECK-NEXT: _llgo_8: ; preds = %_llgo_18 +// CHECK-NEXT: %16 = call %"{{.*}}/runtime/internal/runtime.String" @"reflect.(*ValueError).Error"(ptr %49) +// CHECK-NEXT: br label %_llgo_5 +// CHECK-EMPTY: +// CHECK-NEXT: _llgo_9: ; preds = %_llgo_18 +// CHECK-NEXT: %17 = call ptr @"{{.*}}/runtime/internal/runtime.AllocZ"(i64 16) +// CHECK-NEXT: %18 = getelementptr inbounds %"{{.*}}/runtime/internal/runtime.eface", ptr %17, i64 0 +// CHECK-NEXT: store %"{{.*}}/runtime/internal/runtime.eface" %2, ptr %18, align 8 +// CHECK-NEXT: %19 = insertvalue %"{{.*}}/runtime/internal/runtime.Slice" undef, ptr %17, 0 +// CHECK-NEXT: %20 = insertvalue %"{{.*}}/runtime/internal/runtime.Slice" %19, i64 1, 1 +// CHECK-NEXT: %21 = insertvalue %"{{.*}}/runtime/internal/runtime.Slice" %20, i64 1, 2 +// CHECK-NEXT: %22 = call %"{{.*}}/runtime/internal/runtime.String" @fmt.Sprintf(%"{{.*}}/runtime/internal/runtime.String" { ptr @{{[0-9]+}}, i64 32 }, %"{{.*}}/runtime/internal/runtime.Slice" %21) +// CHECK-NEXT: %23 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 16) +// CHECK-NEXT: store %"{{.*}}/runtime/internal/runtime.String" %22, ptr %23, align 8 +// CHECK-NEXT: %24 = insertvalue %"{{.*}}/runtime/internal/runtime.eface" { ptr @_llgo_string, ptr undef }, ptr %23, 1 +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.Panic"(%"{{.*}}/runtime/internal/runtime.eface" %24) +// CHECK-NEXT: unreachable +// CHECK-EMPTY: +// CHECK-NEXT: _llgo_10: ; preds = %_llgo_5 +// CHECK-NEXT: %25 = call %"{{.*}}/runtime/internal/runtime.String" @"{{.*}}/runtime/internal/runtime.StringCat"(%"{{.*}}/runtime/internal/runtime.String" { ptr @{{[0-9]+}}, i64 44 }, %"{{.*}}/runtime/internal/runtime.String" %12) +// CHECK-NEXT: %26 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 16) +// CHECK-NEXT: store %"{{.*}}/runtime/internal/runtime.String" %25, ptr %26, align 8 +// CHECK-NEXT: %27 = insertvalue %"{{.*}}/runtime/internal/runtime.eface" { ptr @_llgo_string, ptr undef }, ptr %26, 1 +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.Panic"(%"{{.*}}/runtime/internal/runtime.eface" %27) +// CHECK-NEXT: unreachable +// CHECK-EMPTY: +// CHECK-NEXT: _llgo_11: ; preds = %_llgo_5 +// CHECK-NEXT: %28 = extractvalue { ptr } %1, 0 +// CHECK-NEXT: %29 = load %"{{.*}}/runtime/internal/runtime.String", ptr %28, align 8 +// CHECK-NEXT: %30 = call i1 @strings.Contains(%"{{.*}}/runtime/internal/runtime.String" %12, %"{{.*}}/runtime/internal/runtime.String" %29) +// CHECK-NEXT: br i1 %30, label %_llgo_4, label %_llgo_12 +// CHECK-EMPTY: +// CHECK-NEXT: _llgo_12: ; preds = %_llgo_11 +// CHECK-NEXT: %31 = extractvalue { ptr } %1, 0 +// CHECK-NEXT: %32 = load %"{{.*}}/runtime/internal/runtime.String", ptr %31, align 8 +// CHECK-NEXT: %33 = call %"{{.*}}/runtime/internal/runtime.String" @"{{.*}}/runtime/internal/runtime.StringCat"(%"{{.*}}/runtime/internal/runtime.String" { ptr @{{[0-9]+}}, i64 31 }, %"{{.*}}/runtime/internal/runtime.String" %32) +// CHECK-NEXT: %34 = call %"{{.*}}/runtime/internal/runtime.String" @"{{.*}}/runtime/internal/runtime.StringCat"(%"{{.*}}/runtime/internal/runtime.String" %33, %"{{.*}}/runtime/internal/runtime.String" { ptr @{{[0-9]+}}, i64 3 }) +// CHECK-NEXT: %35 = call %"{{.*}}/runtime/internal/runtime.String" @"{{.*}}/runtime/internal/runtime.StringCat"(%"{{.*}}/runtime/internal/runtime.String" %34, %"{{.*}}/runtime/internal/runtime.String" %12) +// CHECK-NEXT: %36 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 16) +// CHECK-NEXT: store %"{{.*}}/runtime/internal/runtime.String" %35, ptr %36, align 8 +// CHECK-NEXT: %37 = insertvalue %"{{.*}}/runtime/internal/runtime.eface" { ptr @_llgo_string, ptr undef }, ptr %36, 1 +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.Panic"(%"{{.*}}/runtime/internal/runtime.eface" %37) +// CHECK-NEXT: unreachable +// CHECK-EMPTY: +// CHECK-NEXT: _llgo_13: ; preds = %_llgo_3 +// CHECK-NEXT: %38 = extractvalue %"{{.*}}/runtime/internal/runtime.eface" %2, 1 +// CHECK-NEXT: %39 = load %"{{.*}}/runtime/internal/runtime.String", ptr %38, align 8 +// CHECK-NEXT: %40 = insertvalue { %"{{.*}}/runtime/internal/runtime.String", i1 } undef, %"{{.*}}/runtime/internal/runtime.String" %39, 0 +// CHECK-NEXT: %41 = insertvalue { %"{{.*}}/runtime/internal/runtime.String", i1 } %40, i1 true, 1 +// CHECK-NEXT: br label %_llgo_15 +// CHECK-EMPTY: +// CHECK-NEXT: _llgo_14: ; preds = %_llgo_3 +// CHECK-NEXT: br label %_llgo_15 +// CHECK-EMPTY: +// CHECK-NEXT: _llgo_15: ; preds = %_llgo_14, %_llgo_13 +// CHECK-NEXT: %42 = phi { %"{{.*}}/runtime/internal/runtime.String", i1 } [ %41, %_llgo_13 ], [ zeroinitializer, %_llgo_14 ] +// CHECK-NEXT: %43 = extractvalue { %"{{.*}}/runtime/internal/runtime.String", i1 } %42, 0 +// CHECK-NEXT: %44 = extractvalue { %"{{.*}}/runtime/internal/runtime.String", i1 } %42, 1 +// CHECK-NEXT: br i1 %44, label %_llgo_6, label %_llgo_7 +// CHECK-EMPTY: +// CHECK-NEXT: _llgo_16: ; preds = %_llgo_7 +// CHECK-NEXT: %45 = extractvalue %"{{.*}}/runtime/internal/runtime.eface" %2, 1 +// CHECK-NEXT: %46 = insertvalue { ptr, i1 } undef, ptr %45, 0 +// CHECK-NEXT: %47 = insertvalue { ptr, i1 } %46, i1 true, 1 +// CHECK-NEXT: br label %_llgo_18 +// CHECK-EMPTY: +// CHECK-NEXT: _llgo_17: ; preds = %_llgo_7 +// CHECK-NEXT: br label %_llgo_18 +// CHECK-EMPTY: +// CHECK-NEXT: _llgo_18: ; preds = %_llgo_17, %_llgo_16 +// CHECK-NEXT: %48 = phi { ptr, i1 } [ %47, %_llgo_16 ], [ zeroinitializer, %_llgo_17 ] +// CHECK-NEXT: %49 = extractvalue { ptr, i1 } %48, 0 +// CHECK-NEXT: %50 = extractvalue { ptr, i1 } %48, 1 +// CHECK-NEXT: br i1 %50, label %_llgo_8, label %_llgo_9 +// CHECK-NEXT: } + +// CHECK-LABEL: define void @"main.(*testingT).Errorf"(ptr %0, %"{{.*}}/runtime/internal/runtime.String" %1, %"{{.*}}/runtime/internal/runtime.Slice" %2){{.*}} { +// CHECK-NEXT: _llgo_0: +// CHECK-NEXT: %3 = call %"{{.*}}/runtime/internal/runtime.String" @fmt.Sprintf(%"{{.*}}/runtime/internal/runtime.String" %1, %"{{.*}}/runtime/internal/runtime.Slice" %2) +// CHECK-NEXT: %4 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 16) +// CHECK-NEXT: store %"{{.*}}/runtime/internal/runtime.String" %3, ptr %4, align 8 +// CHECK-NEXT: %5 = insertvalue %"{{.*}}/runtime/internal/runtime.eface" { ptr @_llgo_string, ptr undef }, ptr %4, 1 +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.Panic"(%"{{.*}}/runtime/internal/runtime.eface" %5) +// CHECK-NEXT: unreachable +// CHECK-NEXT: } + +// CHECK-LABEL: define void @"main.(*testingT).Fatalf"(ptr %0, %"{{.*}}/runtime/internal/runtime.String" %1, %"{{.*}}/runtime/internal/runtime.Slice" %2){{.*}} { +// CHECK-NEXT: _llgo_0: +// CHECK-NEXT: %3 = call %"{{.*}}/runtime/internal/runtime.String" @fmt.Sprintf(%"{{.*}}/runtime/internal/runtime.String" %1, %"{{.*}}/runtime/internal/runtime.Slice" %2) +// CHECK-NEXT: %4 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 16) +// CHECK-NEXT: store %"{{.*}}/runtime/internal/runtime.String" %3, ptr %4, align 8 +// CHECK-NEXT: %5 = insertvalue %"{{.*}}/runtime/internal/runtime.eface" { ptr @_llgo_string, ptr undef }, ptr %4, 1 +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.Panic"(%"{{.*}}/runtime/internal/runtime.eface" %5) +// CHECK-NEXT: unreachable +// CHECK-NEXT: } diff --git a/cl/_testgo/rewrite/main.go b/cl/_testgo/rewrite/main.go index 433148a695..6a5de10b1f 100644 --- a/cl/_testgo/rewrite/main.go +++ b/cl/_testgo/rewrite/main.go @@ -1,10 +1,6 @@ // LITTEST package main -// CHECK-DAG: @main.VarName = global %"{{.*}}/runtime/internal/runtime.String" { ptr @{{.*}}, {{(i32|i64)}} 12 } -// CHECK-DAG: @main.VarPlain = global %"{{.*}}/runtime/internal/runtime.String" zeroinitializer -// CHECK-DAG: call void @"{{.*}}/cl/_testgo/rewrite/dep.PrintVar"() - import ( "fmt" "runtime" @@ -12,6 +8,12 @@ import ( dep "github.com/goplus/llgo/cl/_testgo/rewrite/dep" ) +// CHECK: {{^}}@{{[0-9]+}} = private unnamed_addr constant [12 x i8] c"main.VarName", align 1{{$}} +// CHECK: {{^}}@{{[0-9]+}} = private unnamed_addr constant [13 x i8] c"main.VarPlain", align 1{{$}} +// CHECK: {{^}}@{{[0-9]+}} = private unnamed_addr constant [16 x i8] c"runtime.GOROOT()", align 1{{$}} +// CHECK: {{^}}@{{[0-9]+}} = private unnamed_addr constant [17 x i8] c"runtime.Version()", align 1{{$}} +// CHECK: {{^}}@{{[0-9]+}} = private unnamed_addr constant [7 x i8] c"%s: %s\0A", align 1{{$}} + var VarName = "main-default" var VarPlain string @@ -26,3 +28,52 @@ func main() { printLine("runtime.GOROOT()", runtime.GOROOT()) printLine("runtime.Version()", runtime.Version()) } + +// CHECK-LABEL: define void @main.init(){{.*}} { +// CHECK-NEXT: _llgo_0: +// CHECK-NEXT: %0 = load i1, ptr @"main.init$guard", align 1 +// CHECK-NEXT: br i1 %0, label %_llgo_2, label %_llgo_1 +// CHECK-EMPTY: +// CHECK-NEXT: _llgo_1: ; preds = %_llgo_0 +// CHECK-NEXT: store i1 true, ptr @"main.init$guard", align 1 +// CHECK-NEXT: call void @fmt.init() +// CHECK-NEXT: call void @"{{.*}}/cl/_testgo/rewrite/dep.init"() +// CHECK-NEXT: br label %_llgo_2 +// CHECK-EMPTY: +// CHECK-NEXT: _llgo_2: ; preds = %_llgo_1, %_llgo_0 +// CHECK-NEXT: ret void +// CHECK-NEXT: } + +// CHECK-LABEL: define void @main.main(){{.*}} { +// CHECK-NEXT: _llgo_0: +// CHECK-NEXT: %0 = load %"{{.*}}/runtime/internal/runtime.String", ptr @main.VarName, align 8 +// CHECK-NEXT: call void @main.printLine(%"{{.*}}/runtime/internal/runtime.String" { ptr @{{[0-9]+}}, i64 12 }, %"{{.*}}/runtime/internal/runtime.String" %0) +// CHECK-NEXT: %1 = load %"{{.*}}/runtime/internal/runtime.String", ptr @main.VarPlain, align 8 +// CHECK-NEXT: call void @main.printLine(%"{{.*}}/runtime/internal/runtime.String" { ptr @{{[0-9]+}}, i64 13 }, %"{{.*}}/runtime/internal/runtime.String" %1) +// CHECK-NEXT: call void @"{{.*}}/cl/_testgo/rewrite/dep.PrintVar"() +// CHECK-NEXT: %2 = call %"{{.*}}/runtime/internal/runtime.String" @runtime.GOROOT() +// CHECK-NEXT: call void @main.printLine(%"{{.*}}/runtime/internal/runtime.String" { ptr @{{[0-9]+}}, i64 16 }, %"{{.*}}/runtime/internal/runtime.String" %2) +// CHECK-NEXT: %3 = call %"{{.*}}/runtime/internal/runtime.String" @runtime.Version() +// CHECK-NEXT: call void @main.printLine(%"{{.*}}/runtime/internal/runtime.String" { ptr @{{[0-9]+}}, i64 17 }, %"{{.*}}/runtime/internal/runtime.String" %3) +// CHECK-NEXT: ret void +// CHECK-NEXT: } + +// CHECK-LABEL: define void @main.printLine(%"{{.*}}/runtime/internal/runtime.String" %0, %"{{.*}}/runtime/internal/runtime.String" %1){{.*}} { +// CHECK-NEXT: _llgo_0: +// CHECK-NEXT: %2 = call ptr @"{{.*}}/runtime/internal/runtime.AllocZ"(i64 32) +// CHECK-NEXT: %3 = getelementptr inbounds %"{{.*}}/runtime/internal/runtime.eface", ptr %2, i64 0 +// CHECK-NEXT: %4 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 16) +// CHECK-NEXT: store %"{{.*}}/runtime/internal/runtime.String" %0, ptr %4, align 8 +// CHECK-NEXT: %5 = insertvalue %"{{.*}}/runtime/internal/runtime.eface" { ptr @_llgo_string, ptr undef }, ptr %4, 1 +// CHECK-NEXT: store %"{{.*}}/runtime/internal/runtime.eface" %5, ptr %3, align 8 +// CHECK-NEXT: %6 = getelementptr inbounds %"{{.*}}/runtime/internal/runtime.eface", ptr %2, i64 1 +// CHECK-NEXT: %7 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 16) +// CHECK-NEXT: store %"{{.*}}/runtime/internal/runtime.String" %1, ptr %7, align 8 +// CHECK-NEXT: %8 = insertvalue %"{{.*}}/runtime/internal/runtime.eface" { ptr @_llgo_string, ptr undef }, ptr %7, 1 +// CHECK-NEXT: store %"{{.*}}/runtime/internal/runtime.eface" %8, ptr %6, align 8 +// CHECK-NEXT: %9 = insertvalue %"{{.*}}/runtime/internal/runtime.Slice" undef, ptr %2, 0 +// CHECK-NEXT: %10 = insertvalue %"{{.*}}/runtime/internal/runtime.Slice" %9, i64 2, 1 +// CHECK-NEXT: %11 = insertvalue %"{{.*}}/runtime/internal/runtime.Slice" %10, i64 2, 2 +// CHECK-NEXT: %12 = call { i64, %"{{.*}}/runtime/internal/runtime.iface" } @fmt.Printf(%"{{.*}}/runtime/internal/runtime.String" { ptr @{{[0-9]+}}, i64 7 }, %"{{.*}}/runtime/internal/runtime.Slice" %11) +// CHECK-NEXT: ret void +// CHECK-NEXT: } diff --git a/cl/_testgo/runextest/main.go b/cl/_testgo/runextest/main.go index dbefabd8e1..693054653e 100644 --- a/cl/_testgo/runextest/main.go +++ b/cl/_testgo/runextest/main.go @@ -1,15 +1,15 @@ // LITTEST package main -// CHECK-DAG: define {{(i32|i64)}} @main.Zoo(){{.*}} { -// CHECK-DAG: call {{(i32|i64)}} @"{{.*}}/cl/_testgo/runextest/foo.Foo"() -// CHECK-DAG: call {{(i32|i64)}} @"{{.*}}/cl/_testgo/runextest/bar.Bar"() - import ( "github.com/goplus/llgo/cl/_testgo/runextest/bar" "github.com/goplus/llgo/cl/_testgo/runextest/foo" ) +// CHECK: {{^}}@{{[0-9]+}} = private unnamed_addr constant [9 x i8] c"foo.Foo()", align 1{{$}} +// CHECK: {{^}}@{{[0-9]+}} = private unnamed_addr constant [9 x i8] c"bar.Bar()", align 1{{$}} +// CHECK: {{^}}@{{[0-9]+}} = private unnamed_addr constant [5 x i8] c"Zoo()", align 1{{$}} + func Zoo() int { return 3 } @@ -19,3 +19,43 @@ func main() { println("bar.Bar()", bar.Bar()) println("Zoo()", Zoo()) } + +// CHECK-LABEL: define i64 @main.Zoo(){{.*}} { +// CHECK-NEXT: _llgo_0: +// CHECK-NEXT: ret i64 3 +// CHECK-NEXT: } + +// CHECK-LABEL: define void @main.init(){{.*}} { +// CHECK-NEXT: _llgo_0: +// CHECK-NEXT: %0 = load i1, ptr @"main.init$guard", align 1 +// CHECK-NEXT: br i1 %0, label %_llgo_2, label %_llgo_1 +// CHECK-EMPTY: +// CHECK-NEXT: _llgo_1: ; preds = %_llgo_0 +// CHECK-NEXT: store i1 true, ptr @"main.init$guard", align 1 +// CHECK-NEXT: call void @"{{.*}}/cl/_testgo/runextest/bar.init"() +// CHECK-NEXT: call void @"{{.*}}/cl/_testgo/runextest/foo.init"() +// CHECK-NEXT: br label %_llgo_2 +// CHECK-EMPTY: +// CHECK-NEXT: _llgo_2: ; preds = %_llgo_1, %_llgo_0 +// CHECK-NEXT: ret void +// CHECK-NEXT: } + +// CHECK-LABEL: define void @main.main(){{.*}} { +// CHECK-NEXT: _llgo_0: +// CHECK-NEXT: %0 = call i64 @"{{.*}}/cl/_testgo/runextest/foo.Foo"() +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.PrintString"(%"{{.*}}/runtime/internal/runtime.String" { ptr @{{[0-9]+}}, i64 9 }) +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.PrintByte"(i8 32) +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.PrintInt"(i64 %0) +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.PrintByte"(i8 10) +// CHECK-NEXT: %1 = call i64 @"{{.*}}/cl/_testgo/runextest/bar.Bar"() +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.PrintString"(%"{{.*}}/runtime/internal/runtime.String" { ptr @{{[0-9]+}}, i64 9 }) +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.PrintByte"(i8 32) +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.PrintInt"(i64 %1) +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.PrintByte"(i8 10) +// CHECK-NEXT: %2 = call i64 @main.Zoo() +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.PrintString"(%"{{.*}}/runtime/internal/runtime.String" { ptr @{{[0-9]+}}, i64 5 }) +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.PrintByte"(i8 32) +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.PrintInt"(i64 %2) +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.PrintByte"(i8 10) +// CHECK-NEXT: ret void +// CHECK-NEXT: } diff --git a/cl/_testgo/runtest/main.go b/cl/_testgo/runtest/main.go index 9ed816ace4..50bbb0cafa 100644 --- a/cl/_testgo/runtest/main.go +++ b/cl/_testgo/runtest/main.go @@ -1,15 +1,15 @@ // LITTEST package main -// CHECK-DAG: define {{(i32|i64)}} @main.Zoo(){{.*}} { -// CHECK-DAG: call {{(i32|i64)}} @"{{.*}}/cl/_testgo/runtest/foo.Foo"() -// CHECK-DAG: call {{(i32|i64)}} @"{{.*}}/cl/_testgo/runtest/bar.Bar"() - import ( "github.com/goplus/llgo/cl/_testgo/runtest/bar" "github.com/goplus/llgo/cl/_testgo/runtest/foo" ) +// CHECK: {{^}}@{{[0-9]+}} = private unnamed_addr constant [9 x i8] c"foo.Foo()", align 1{{$}} +// CHECK: {{^}}@{{[0-9]+}} = private unnamed_addr constant [9 x i8] c"bar.Bar()", align 1{{$}} +// CHECK: {{^}}@{{[0-9]+}} = private unnamed_addr constant [5 x i8] c"Zoo()", align 1{{$}} + func Zoo() int { return 3 } @@ -19,3 +19,43 @@ func main() { println("bar.Bar()", bar.Bar()) println("Zoo()", Zoo()) } + +// CHECK-LABEL: define i64 @main.Zoo(){{.*}} { +// CHECK-NEXT: _llgo_0: +// CHECK-NEXT: ret i64 3 +// CHECK-NEXT: } + +// CHECK-LABEL: define void @main.init(){{.*}} { +// CHECK-NEXT: _llgo_0: +// CHECK-NEXT: %0 = load i1, ptr @"main.init$guard", align 1 +// CHECK-NEXT: br i1 %0, label %_llgo_2, label %_llgo_1 +// CHECK-EMPTY: +// CHECK-NEXT: _llgo_1: ; preds = %_llgo_0 +// CHECK-NEXT: store i1 true, ptr @"main.init$guard", align 1 +// CHECK-NEXT: call void @"{{.*}}/cl/_testgo/runtest/bar.init"() +// CHECK-NEXT: call void @"{{.*}}/cl/_testgo/runtest/foo.init"() +// CHECK-NEXT: br label %_llgo_2 +// CHECK-EMPTY: +// CHECK-NEXT: _llgo_2: ; preds = %_llgo_1, %_llgo_0 +// CHECK-NEXT: ret void +// CHECK-NEXT: } + +// CHECK-LABEL: define void @main.main(){{.*}} { +// CHECK-NEXT: _llgo_0: +// CHECK-NEXT: %0 = call i64 @"{{.*}}/cl/_testgo/runtest/foo.Foo"() +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.PrintString"(%"{{.*}}/runtime/internal/runtime.String" { ptr @{{[0-9]+}}, i64 9 }) +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.PrintByte"(i8 32) +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.PrintInt"(i64 %0) +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.PrintByte"(i8 10) +// CHECK-NEXT: %1 = call i64 @"{{.*}}/cl/_testgo/runtest/bar.Bar"() +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.PrintString"(%"{{.*}}/runtime/internal/runtime.String" { ptr @{{[0-9]+}}, i64 9 }) +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.PrintByte"(i8 32) +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.PrintInt"(i64 %1) +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.PrintByte"(i8 10) +// CHECK-NEXT: %2 = call i64 @main.Zoo() +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.PrintString"(%"{{.*}}/runtime/internal/runtime.String" { ptr @{{[0-9]+}}, i64 5 }) +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.PrintByte"(i8 32) +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.PrintInt"(i64 %2) +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.PrintByte"(i8 10) +// CHECK-NEXT: ret void +// CHECK-NEXT: } diff --git a/cl/_testgo/select/in.go b/cl/_testgo/select/in.go index c3d80220e4..0ead117209 100644 --- a/cl/_testgo/select/in.go +++ b/cl/_testgo/select/in.go @@ -1,9 +1,10 @@ // LITTEST package main -// CHECK-DAG: call ptr @"{{.*}}/runtime/internal/runtime.NewChan"({{.*}}) -// CHECK-DAG: call void @"{{.*}}/runtime/internal/runtime.NewProc"({{.*}}) -// CHECK-DAG: call { {{(i32|i64)}}, i1 } @"{{.*}}/runtime/internal/runtime.Select"({{.*}}) +// CHECK: {{^}}@{{[0-9]+}} = private unnamed_addr constant [4 x i8] c"exit", align 1{{$}} +// CHECK: {{^}}@{{[0-9]+}} = private unnamed_addr constant [3 x i8] c"ch1", align 1{{$}} +// CHECK: {{^}}@{{[0-9]+}} = private unnamed_addr constant [3 x i8] c"ch2", align 1{{$}} +// CHECK: {{^}}@{{[0-9]+}} = private unnamed_addr constant [31 x i8] c"blocking select matched no case", align 1{{$}} func main() { send() @@ -48,3 +49,307 @@ func recv() { } } } + +// CHECK-LABEL: define void @main.init(){{.*}} { +// CHECK-NEXT: _llgo_0: +// CHECK-NEXT: %0 = load i1, ptr @"main.init$guard", align 1 +// CHECK-NEXT: br i1 %0, label %_llgo_2, label %_llgo_1 +// CHECK-EMPTY: +// CHECK-NEXT: _llgo_1: ; preds = %_llgo_0 +// CHECK-NEXT: store i1 true, ptr @"main.init$guard", align 1 +// CHECK-NEXT: br label %_llgo_2 +// CHECK-EMPTY: +// CHECK-NEXT: _llgo_2: ; preds = %_llgo_1, %_llgo_0 +// CHECK-NEXT: ret void +// CHECK-NEXT: } + +// CHECK-LABEL: define void @main.main(){{.*}} { +// CHECK-NEXT: _llgo_0: +// CHECK-NEXT: call void @main.send() +// CHECK-NEXT: call void @main.recv() +// CHECK-NEXT: ret void +// CHECK-NEXT: } + +// CHECK-LABEL: define void @main.recv(){{.*}} { +// CHECK-NEXT: _llgo_0: +// CHECK-NEXT: %0 = call ptr @"{{.*}}/runtime/internal/runtime.AllocZ"(i64 8) +// CHECK-NEXT: %1 = call ptr @"{{.*}}/runtime/internal/runtime.NewChan"(i64 16, i64 0) +// CHECK-NEXT: store ptr %1, ptr %0, align 8 +// CHECK-NEXT: %2 = call ptr @"{{.*}}/runtime/internal/runtime.AllocZ"(i64 8) +// CHECK-NEXT: %3 = call ptr @"{{.*}}/runtime/internal/runtime.NewChan"(i64 16, i64 0) +// CHECK-NEXT: store ptr %3, ptr %2, align 8 +// CHECK-NEXT: %4 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 8) +// CHECK-NEXT: %5 = getelementptr inbounds { ptr }, ptr %4, i32 0, i32 0 +// CHECK-NEXT: store ptr %0, ptr %5, align 8 +// CHECK-NEXT: %6 = insertvalue { ptr, ptr } { ptr @"main.recv$1", ptr undef }, ptr %4, 1 +// CHECK-NEXT: %7 = call ptr @"{{.*}}/runtime/internal/runtime.AllocRoot"(i64 16) +// CHECK-NEXT: %8 = getelementptr inbounds { { ptr, ptr } }, ptr %7, i32 0, i32 0 +// CHECK-NEXT: store { ptr, ptr } %6, ptr %8, align 8 +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.NewProc"(ptr @"main._llgo_routine$1", ptr %7, i64 0) +// CHECK-NEXT: %9 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 8) +// CHECK-NEXT: %10 = getelementptr inbounds { ptr }, ptr %9, i32 0, i32 0 +// CHECK-NEXT: store ptr %2, ptr %10, align 8 +// CHECK-NEXT: %11 = insertvalue { ptr, ptr } { ptr @"main.recv$2", ptr undef }, ptr %9, 1 +// CHECK-NEXT: %12 = call ptr @"{{.*}}/runtime/internal/runtime.AllocRoot"(i64 16) +// CHECK-NEXT: %13 = getelementptr inbounds { { ptr, ptr } }, ptr %12, i32 0, i32 0 +// CHECK-NEXT: store { ptr, ptr } %11, ptr %13, align 8 +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.NewProc"(ptr @"main._llgo_routine$2", ptr %12, i64 0) +// CHECK-NEXT: br label %_llgo_1 +// CHECK-EMPTY: +// CHECK-NEXT: _llgo_1: ; preds = %_llgo_4, %_llgo_0 +// CHECK-NEXT: %14 = phi i64 [ 0, %_llgo_0 ], [ %50, %_llgo_4 ] +// CHECK-NEXT: %15 = icmp slt i64 %14, 2 +// CHECK-NEXT: br i1 %15, label %_llgo_2, label %_llgo_3 +// CHECK-EMPTY: +// CHECK-NEXT: _llgo_2: ; preds = %_llgo_1 +// CHECK-NEXT: %16 = load ptr, ptr %0, align 8 +// CHECK-NEXT: %17 = load ptr, ptr %2, align 8 +// CHECK-NEXT: %18 = call ptr @llvm.stacksave.p0() +// CHECK-NEXT: %19 = alloca %"{{.*}}/runtime/internal/runtime.String", align 8 +// CHECK-NEXT: call void @llvm.memset.p0.i64(ptr %19, i8 0, i64 16, i1 false) +// CHECK-NEXT: %20 = insertvalue %"{{.*}}/runtime/internal/runtime.ChanOp" undef, ptr %16, 0 +// CHECK-NEXT: %21 = insertvalue %"{{.*}}/runtime/internal/runtime.ChanOp" %20, ptr %19, 1 +// CHECK-NEXT: %22 = insertvalue %"{{.*}}/runtime/internal/runtime.ChanOp" %21, i32 16, 2 +// CHECK-NEXT: %23 = insertvalue %"{{.*}}/runtime/internal/runtime.ChanOp" %22, i1 false, 3 +// CHECK-NEXT: %24 = alloca %"{{.*}}/runtime/internal/runtime.String", align 8 +// CHECK-NEXT: call void @llvm.memset.p0.i64(ptr %24, i8 0, i64 16, i1 false) +// CHECK-NEXT: %25 = insertvalue %"{{.*}}/runtime/internal/runtime.ChanOp" undef, ptr %17, 0 +// CHECK-NEXT: %26 = insertvalue %"{{.*}}/runtime/internal/runtime.ChanOp" %25, ptr %24, 1 +// CHECK-NEXT: %27 = insertvalue %"{{.*}}/runtime/internal/runtime.ChanOp" %26, i32 16, 2 +// CHECK-NEXT: %28 = insertvalue %"{{.*}}/runtime/internal/runtime.ChanOp" %27, i1 false, 3 +// CHECK-NEXT: %29 = alloca i8, i64 48, align 1 +// CHECK-NEXT: %30 = getelementptr %"{{.*}}/runtime/internal/runtime.ChanOp", ptr %29, i64 0 +// CHECK-NEXT: store %"{{.*}}/runtime/internal/runtime.ChanOp" %23, ptr %30, align 8 +// CHECK-NEXT: %31 = getelementptr %"{{.*}}/runtime/internal/runtime.ChanOp", ptr %29, i64 1 +// CHECK-NEXT: store %"{{.*}}/runtime/internal/runtime.ChanOp" %28, ptr %31, align 8 +// CHECK-NEXT: %32 = insertvalue %"{{.*}}/runtime/internal/runtime.Slice" undef, ptr %29, 0 +// CHECK-NEXT: %33 = insertvalue %"{{.*}}/runtime/internal/runtime.Slice" %32, i64 2, 1 +// CHECK-NEXT: %34 = insertvalue %"{{.*}}/runtime/internal/runtime.Slice" %33, i64 2, 2 +// CHECK-NEXT: %35 = call { i64, i1, i1 } @"{{.*}}/runtime/internal/runtime.TrySelect"(%"{{.*}}/runtime/internal/runtime.Slice" %34) +// CHECK-NEXT: %36 = extractvalue { i64, i1, i1 } %35, 0 +// CHECK-NEXT: %37 = extractvalue { i64, i1, i1 } %35, 1 +// CHECK-NEXT: %38 = extractvalue { i64, i1, i1 } %35, 2 +// CHECK-NEXT: %39 = select i1 %38, i64 %36, i64 -1 +// CHECK-NEXT: %40 = extractvalue %"{{.*}}/runtime/internal/runtime.ChanOp" %23, 1 +// CHECK-NEXT: %41 = load %"{{.*}}/runtime/internal/runtime.String", ptr %40, align 8 +// CHECK-NEXT: %42 = extractvalue %"{{.*}}/runtime/internal/runtime.ChanOp" %28, 1 +// CHECK-NEXT: %43 = load %"{{.*}}/runtime/internal/runtime.String", ptr %42, align 8 +// CHECK-NEXT: call void @llvm.stackrestore.p0(ptr %18) +// CHECK-NEXT: %44 = insertvalue { i64, i1, %"{{.*}}/runtime/internal/runtime.String", %"{{.*}}/runtime/internal/runtime.String" } undef, i64 %39, 0 +// CHECK-NEXT: %45 = insertvalue { i64, i1, %"{{.*}}/runtime/internal/runtime.String", %"{{.*}}/runtime/internal/runtime.String" } %44, i1 %37, 1 +// CHECK-NEXT: %46 = insertvalue { i64, i1, %"{{.*}}/runtime/internal/runtime.String", %"{{.*}}/runtime/internal/runtime.String" } %45, %"{{.*}}/runtime/internal/runtime.String" %41, 2 +// CHECK-NEXT: %47 = insertvalue { i64, i1, %"{{.*}}/runtime/internal/runtime.String", %"{{.*}}/runtime/internal/runtime.String" } %46, %"{{.*}}/runtime/internal/runtime.String" %43, 3 +// CHECK-NEXT: %48 = extractvalue { i64, i1, %"{{.*}}/runtime/internal/runtime.String", %"{{.*}}/runtime/internal/runtime.String" } %47, 0 +// CHECK-NEXT: %49 = icmp eq i64 %48, 0 +// CHECK-NEXT: br i1 %49, label %_llgo_5, label %_llgo_6 +// CHECK-EMPTY: +// CHECK-NEXT: _llgo_3: ; preds = %_llgo_1 +// CHECK-NEXT: ret void +// CHECK-EMPTY: +// CHECK-NEXT: _llgo_4: ; preds = %_llgo_8, %_llgo_7, %_llgo_5 +// CHECK-NEXT: %50 = add i64 %14, 1 +// CHECK-NEXT: br label %_llgo_1 +// CHECK-EMPTY: +// CHECK-NEXT: _llgo_5: ; preds = %_llgo_2 +// CHECK-NEXT: %51 = extractvalue { i64, i1, %"{{.*}}/runtime/internal/runtime.String", %"{{.*}}/runtime/internal/runtime.String" } %47, 2 +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.PrintString"(%"{{.*}}/runtime/internal/runtime.String" %51) +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.PrintByte"(i8 10) +// CHECK-NEXT: br label %_llgo_4 +// CHECK-EMPTY: +// CHECK-NEXT: _llgo_6: ; preds = %_llgo_2 +// CHECK-NEXT: %52 = icmp eq i64 %48, 1 +// CHECK-NEXT: br i1 %52, label %_llgo_7, label %_llgo_8 +// CHECK-EMPTY: +// CHECK-NEXT: _llgo_7: ; preds = %_llgo_6 +// CHECK-NEXT: %53 = extractvalue { i64, i1, %"{{.*}}/runtime/internal/runtime.String", %"{{.*}}/runtime/internal/runtime.String" } %47, 3 +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.PrintString"(%"{{.*}}/runtime/internal/runtime.String" %53) +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.PrintByte"(i8 10) +// CHECK-NEXT: br label %_llgo_4 +// CHECK-EMPTY: +// CHECK-NEXT: _llgo_8: ; preds = %_llgo_6 +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.PrintString"(%"{{.*}}/runtime/internal/runtime.String" { ptr @{{[0-9]+}}, i64 4 }) +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.PrintByte"(i8 10) +// CHECK-NEXT: br label %_llgo_4 +// CHECK-NEXT: } + +// CHECK-LABEL: define void @"main.recv$1"(ptr {{(nest|swiftself)}} %0){{.*}} { +// CHECK-NEXT: _llgo_0: +// CHECK-NEXT: %1 = load { ptr }, ptr %0, align 8 +// CHECK-NEXT: %2 = extractvalue { ptr } %1, 0 +// CHECK-NEXT: %3 = load ptr, ptr %2, align 8 +// CHECK-NEXT: %4 = call ptr @llvm.stacksave.p0() +// CHECK-NEXT: %5 = alloca %"{{.*}}/runtime/internal/runtime.String", align 8 +// CHECK-NEXT: call void @llvm.memset.p0.i64(ptr %5, i8 0, i64 16, i1 false) +// CHECK-NEXT: store %"{{.*}}/runtime/internal/runtime.String" { ptr @{{[0-9]+}}, i64 3 }, ptr %5, align 8 +// CHECK-NEXT: %6 = call i1 @"{{.*}}/runtime/internal/runtime.ChanSend"(ptr %3, ptr %5, i64 16) +// CHECK-NEXT: call void @llvm.stackrestore.p0(ptr %4) +// CHECK-NEXT: ret void +// CHECK-NEXT: } + +// CHECK-LABEL: define void @"main.recv$2"(ptr {{(nest|swiftself)}} %0){{.*}} { +// CHECK-NEXT: _llgo_0: +// CHECK-NEXT: %1 = load { ptr }, ptr %0, align 8 +// CHECK-NEXT: %2 = extractvalue { ptr } %1, 0 +// CHECK-NEXT: %3 = load ptr, ptr %2, align 8 +// CHECK-NEXT: %4 = call ptr @llvm.stacksave.p0() +// CHECK-NEXT: %5 = alloca %"{{.*}}/runtime/internal/runtime.String", align 8 +// CHECK-NEXT: call void @llvm.memset.p0.i64(ptr %5, i8 0, i64 16, i1 false) +// CHECK-NEXT: store %"{{.*}}/runtime/internal/runtime.String" { ptr @{{[0-9]+}}, i64 3 }, ptr %5, align 8 +// CHECK-NEXT: %6 = call i1 @"{{.*}}/runtime/internal/runtime.ChanSend"(ptr %3, ptr %5, i64 16) +// CHECK-NEXT: call void @llvm.stackrestore.p0(ptr %4) +// CHECK-NEXT: ret void +// CHECK-NEXT: } + +// CHECK-LABEL: define void @main.send(){{.*}} { +// CHECK-NEXT: _llgo_0: +// CHECK-NEXT: %0 = call ptr @"{{.*}}/runtime/internal/runtime.AllocZ"(i64 8) +// CHECK-NEXT: %1 = call ptr @"{{.*}}/runtime/internal/runtime.NewChan"(i64 8, i64 0) +// CHECK-NEXT: store ptr %1, ptr %0, align 8 +// CHECK-NEXT: %2 = call ptr @"{{.*}}/runtime/internal/runtime.AllocZ"(i64 8) +// CHECK-NEXT: %3 = call ptr @"{{.*}}/runtime/internal/runtime.NewChan"(i64 8, i64 0) +// CHECK-NEXT: store ptr %3, ptr %2, align 8 +// CHECK-NEXT: %4 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 8) +// CHECK-NEXT: %5 = getelementptr inbounds { ptr }, ptr %4, i32 0, i32 0 +// CHECK-NEXT: store ptr %0, ptr %5, align 8 +// CHECK-NEXT: %6 = insertvalue { ptr, ptr } { ptr @"main.send$1", ptr undef }, ptr %4, 1 +// CHECK-NEXT: %7 = call ptr @"{{.*}}/runtime/internal/runtime.AllocRoot"(i64 16) +// CHECK-NEXT: %8 = getelementptr inbounds { { ptr, ptr } }, ptr %7, i32 0, i32 0 +// CHECK-NEXT: store { ptr, ptr } %6, ptr %8, align 8 +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.NewProc"(ptr @"main._llgo_routine$3", ptr %7, i64 0) +// CHECK-NEXT: %9 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 8) +// CHECK-NEXT: %10 = getelementptr inbounds { ptr }, ptr %9, i32 0, i32 0 +// CHECK-NEXT: store ptr %2, ptr %10, align 8 +// CHECK-NEXT: %11 = insertvalue { ptr, ptr } { ptr @"main.send$2", ptr undef }, ptr %9, 1 +// CHECK-NEXT: %12 = call ptr @"{{.*}}/runtime/internal/runtime.AllocRoot"(i64 16) +// CHECK-NEXT: %13 = getelementptr inbounds { { ptr, ptr } }, ptr %12, i32 0, i32 0 +// CHECK-NEXT: store { ptr, ptr } %11, ptr %13, align 8 +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.NewProc"(ptr @"main._llgo_routine$4", ptr %12, i64 0) +// CHECK-NEXT: %14 = load ptr, ptr %0, align 8 +// CHECK-NEXT: %15 = load ptr, ptr %2, align 8 +// CHECK-NEXT: %16 = call ptr @llvm.stacksave.p0() +// CHECK-NEXT: %17 = alloca i64, align 8 +// CHECK-NEXT: call void @llvm.memset.p0.i64(ptr %17, i8 0, i64 8, i1 false) +// CHECK-NEXT: store i64 100, ptr %17, align 8 +// CHECK-NEXT: %18 = insertvalue %"{{.*}}/runtime/internal/runtime.ChanOp" undef, ptr %14, 0 +// CHECK-NEXT: %19 = insertvalue %"{{.*}}/runtime/internal/runtime.ChanOp" %18, ptr %17, 1 +// CHECK-NEXT: %20 = insertvalue %"{{.*}}/runtime/internal/runtime.ChanOp" %19, i32 8, 2 +// CHECK-NEXT: %21 = insertvalue %"{{.*}}/runtime/internal/runtime.ChanOp" %20, i1 true, 3 +// CHECK-NEXT: %22 = alloca i64, align 8 +// CHECK-NEXT: call void @llvm.memset.p0.i64(ptr %22, i8 0, i64 8, i1 false) +// CHECK-NEXT: store i64 200, ptr %22, align 8 +// CHECK-NEXT: %23 = insertvalue %"{{.*}}/runtime/internal/runtime.ChanOp" undef, ptr %15, 0 +// CHECK-NEXT: %24 = insertvalue %"{{.*}}/runtime/internal/runtime.ChanOp" %23, ptr %22, 1 +// CHECK-NEXT: %25 = insertvalue %"{{.*}}/runtime/internal/runtime.ChanOp" %24, i32 8, 2 +// CHECK-NEXT: %26 = insertvalue %"{{.*}}/runtime/internal/runtime.ChanOp" %25, i1 true, 3 +// CHECK-NEXT: %27 = alloca i8, i64 48, align 1 +// CHECK-NEXT: %28 = getelementptr %"{{.*}}/runtime/internal/runtime.ChanOp", ptr %27, i64 0 +// CHECK-NEXT: store %"{{.*}}/runtime/internal/runtime.ChanOp" %21, ptr %28, align 8 +// CHECK-NEXT: %29 = getelementptr %"{{.*}}/runtime/internal/runtime.ChanOp", ptr %27, i64 1 +// CHECK-NEXT: store %"{{.*}}/runtime/internal/runtime.ChanOp" %26, ptr %29, align 8 +// CHECK-NEXT: %30 = insertvalue %"{{.*}}/runtime/internal/runtime.Slice" undef, ptr %27, 0 +// CHECK-NEXT: %31 = insertvalue %"{{.*}}/runtime/internal/runtime.Slice" %30, i64 2, 1 +// CHECK-NEXT: %32 = insertvalue %"{{.*}}/runtime/internal/runtime.Slice" %31, i64 2, 2 +// CHECK-NEXT: %33 = call { i64, i1 } @"{{.*}}/runtime/internal/runtime.Select"(%"{{.*}}/runtime/internal/runtime.Slice" %32) +// CHECK-NEXT: %34 = extractvalue { i64, i1 } %33, 0 +// CHECK-NEXT: %35 = extractvalue { i64, i1 } %33, 1 +// CHECK-NEXT: call void @llvm.stackrestore.p0(ptr %16) +// CHECK-NEXT: %36 = insertvalue { i64, i1 } undef, i64 %34, 0 +// CHECK-NEXT: %37 = insertvalue { i64, i1 } %36, i1 %35, 1 +// CHECK-NEXT: %38 = extractvalue { i64, i1 } %37, 0 +// CHECK-NEXT: %39 = icmp eq i64 %38, 0 +// CHECK-NEXT: br i1 %39, label %_llgo_1, label %_llgo_2 +// CHECK-EMPTY: +// CHECK-NEXT: _llgo_1: ; preds = %_llgo_2, %_llgo_0 +// CHECK-NEXT: ret void +// CHECK-EMPTY: +// CHECK-NEXT: _llgo_2: ; preds = %_llgo_0 +// CHECK-NEXT: %40 = icmp eq i64 %38, 1 +// CHECK-NEXT: br i1 %40, label %_llgo_1, label %_llgo_3 +// CHECK-EMPTY: +// CHECK-NEXT: _llgo_3: ; preds = %_llgo_2 +// CHECK-NEXT: %41 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 16) +// CHECK-NEXT: store %"{{.*}}/runtime/internal/runtime.String" { ptr @{{[0-9]+}}, i64 31 }, ptr %41, align 8 +// CHECK-NEXT: %42 = insertvalue %"{{.*}}/runtime/internal/runtime.eface" { ptr @_llgo_string, ptr undef }, ptr %41, 1 +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.Panic"(%"{{.*}}/runtime/internal/runtime.eface" %42) +// CHECK-NEXT: unreachable +// CHECK-NEXT: } + +// CHECK-LABEL: define void @"main.send$1"(ptr {{(nest|swiftself)}} %0){{.*}} { +// CHECK-NEXT: _llgo_0: +// CHECK-NEXT: %1 = load { ptr }, ptr %0, align 8 +// CHECK-NEXT: %2 = extractvalue { ptr } %1, 0 +// CHECK-NEXT: %3 = load ptr, ptr %2, align 8 +// CHECK-NEXT: %4 = call ptr @llvm.stacksave.p0() +// CHECK-NEXT: %5 = alloca i64, align 8 +// CHECK-NEXT: call void @llvm.memset.p0.i64(ptr %5, i8 0, i64 8, i1 false) +// CHECK-NEXT: %6 = call i1 @"{{.*}}/runtime/internal/runtime.ChanRecv"(ptr %3, ptr %5, i64 8) +// CHECK-NEXT: %7 = load i64, ptr %5, align 8 +// CHECK-NEXT: call void @llvm.stackrestore.p0(ptr %4) +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.PrintInt"(i64 %7) +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.PrintByte"(i8 10) +// CHECK-NEXT: ret void +// CHECK-NEXT: } + +// CHECK-LABEL: define void @"main.send$2"(ptr {{(nest|swiftself)}} %0){{.*}} { +// CHECK-NEXT: _llgo_0: +// CHECK-NEXT: %1 = load { ptr }, ptr %0, align 8 +// CHECK-NEXT: %2 = extractvalue { ptr } %1, 0 +// CHECK-NEXT: %3 = load ptr, ptr %2, align 8 +// CHECK-NEXT: %4 = call ptr @llvm.stacksave.p0() +// CHECK-NEXT: %5 = alloca i64, align 8 +// CHECK-NEXT: call void @llvm.memset.p0.i64(ptr %5, i8 0, i64 8, i1 false) +// CHECK-NEXT: %6 = call i1 @"{{.*}}/runtime/internal/runtime.ChanRecv"(ptr %3, ptr %5, i64 8) +// CHECK-NEXT: %7 = load i64, ptr %5, align 8 +// CHECK-NEXT: call void @llvm.stackrestore.p0(ptr %4) +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.PrintInt"(i64 %7) +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.PrintByte"(i8 10) +// CHECK-NEXT: ret void +// CHECK-NEXT: } + +// CHECK-LABEL: define ptr @"main._llgo_routine$1"(ptr %0){{.*}} { +// CHECK-NEXT: _llgo_0: +// CHECK-NEXT: %1 = load { { ptr, ptr } }, ptr %0, align 8 +// CHECK-NEXT: %2 = extractvalue { { ptr, ptr } } %1, 0 +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.FreeRoot"(ptr %0) +// CHECK-NEXT: %3 = extractvalue { ptr, ptr } %2, 1 +// CHECK-NEXT: %4 = extractvalue { ptr, ptr } %2, 0 +// CHECK-NEXT: %__llgo_funcval_code = call ptr asm "", "=r,0"(ptr %4) +// CHECK-NEXT: call void %__llgo_funcval_code(ptr {{(nest|swiftself)}} %3) +// CHECK-NEXT: ret ptr null +// CHECK-NEXT: } + +// CHECK-LABEL: define ptr @"main._llgo_routine$2"(ptr %0){{.*}} { +// CHECK-NEXT: _llgo_0: +// CHECK-NEXT: %1 = load { { ptr, ptr } }, ptr %0, align 8 +// CHECK-NEXT: %2 = extractvalue { { ptr, ptr } } %1, 0 +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.FreeRoot"(ptr %0) +// CHECK-NEXT: %3 = extractvalue { ptr, ptr } %2, 1 +// CHECK-NEXT: %4 = extractvalue { ptr, ptr } %2, 0 +// CHECK-NEXT: %__llgo_funcval_code = call ptr asm "", "=r,0"(ptr %4) +// CHECK-NEXT: call void %__llgo_funcval_code(ptr {{(nest|swiftself)}} %3) +// CHECK-NEXT: ret ptr null +// CHECK-NEXT: } + +// CHECK-LABEL: define ptr @"main._llgo_routine$3"(ptr %0){{.*}} { +// CHECK-NEXT: _llgo_0: +// CHECK-NEXT: %1 = load { { ptr, ptr } }, ptr %0, align 8 +// CHECK-NEXT: %2 = extractvalue { { ptr, ptr } } %1, 0 +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.FreeRoot"(ptr %0) +// CHECK-NEXT: %3 = extractvalue { ptr, ptr } %2, 1 +// CHECK-NEXT: %4 = extractvalue { ptr, ptr } %2, 0 +// CHECK-NEXT: %__llgo_funcval_code = call ptr asm "", "=r,0"(ptr %4) +// CHECK-NEXT: call void %__llgo_funcval_code(ptr {{(nest|swiftself)}} %3) +// CHECK-NEXT: ret ptr null +// CHECK-NEXT: } + +// CHECK-LABEL: define ptr @"main._llgo_routine$4"(ptr %0){{.*}} { +// CHECK-NEXT: _llgo_0: +// CHECK-NEXT: %1 = load { { ptr, ptr } }, ptr %0, align 8 +// CHECK-NEXT: %2 = extractvalue { { ptr, ptr } } %1, 0 +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.FreeRoot"(ptr %0) +// CHECK-NEXT: %3 = extractvalue { ptr, ptr } %2, 1 +// CHECK-NEXT: %4 = extractvalue { ptr, ptr } %2, 0 +// CHECK-NEXT: %__llgo_funcval_code = call ptr asm "", "=r,0"(ptr %4) +// CHECK-NEXT: call void %__llgo_funcval_code(ptr {{(nest|swiftself)}} %3) +// CHECK-NEXT: ret ptr null +// CHECK-NEXT: } diff --git a/cl/_testgo/syncmap/in.go b/cl/_testgo/syncmap/in.go index 6e6881405f..b5c0ccd613 100644 --- a/cl/_testgo/syncmap/in.go +++ b/cl/_testgo/syncmap/in.go @@ -1,15 +1,15 @@ // LITTEST package main -// CHECK-DAG: call {{.*}}sync{{.*}}Map{{.*}}Store{{.*}} -// CHECK-DAG: call {{.*}}sync{{.*}}Map{{.*}}Load{{.*}} -// CHECK-DAG: call {{.*}}sync{{.*}}Map{{.*}}Range{{.*}} - import ( "fmt" "sync" ) +// CHECK: {{^}}@{{[0-9]+}} = private unnamed_addr constant [5 x i8] c"hello", align 1{{$}} +// CHECK: {{^}}@{{[0-9]+}} = private unnamed_addr constant [1 x i8] c"1", align 1{{$}} +// CHECK: {{^}}@{{[0-9]+}} = private unnamed_addr constant [7 x i8] c"%#v %v\0A", align 1{{$}} + func main() { var m sync.Map m.Store(1, "hello") @@ -21,3 +21,71 @@ func main() { return true }) } + +// CHECK-LABEL: define void @main.init(){{.*}} { +// CHECK-NEXT: _llgo_0: +// CHECK-NEXT: %0 = load i1, ptr @"main.init$guard", align 1 +// CHECK-NEXT: br i1 %0, label %_llgo_2, label %_llgo_1 +// CHECK-EMPTY: +// CHECK-NEXT: _llgo_1: ; preds = %_llgo_0 +// CHECK-NEXT: store i1 true, ptr @"main.init$guard", align 1 +// CHECK-NEXT: call void @fmt.init() +// CHECK-NEXT: call void @sync.init() +// CHECK-NEXT: br label %_llgo_2 +// CHECK-EMPTY: +// CHECK-NEXT: _llgo_2: ; preds = %_llgo_1, %_llgo_0 +// CHECK-NEXT: ret void +// CHECK-NEXT: } + +// CHECK-LABEL: define void @main.main(){{.*}} { +// CHECK-NEXT: _llgo_0: +// CHECK-NEXT: %0 = call ptr @"{{.*}}/runtime/internal/runtime.AllocZ"(i64 {{(64|96)}}) +// CHECK-NEXT: %1 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 8) +// CHECK-NEXT: store i64 1, ptr %1, align 8 +// CHECK-NEXT: %2 = insertvalue %"{{.*}}/runtime/internal/runtime.eface" { ptr @_llgo_int, ptr undef }, ptr %1, 1 +// CHECK-NEXT: %3 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 16) +// CHECK-NEXT: store %"{{.*}}/runtime/internal/runtime.String" { ptr @{{[0-9]+}}, i64 5 }, ptr %3, align 8 +// CHECK-NEXT: %4 = insertvalue %"{{.*}}/runtime/internal/runtime.eface" { ptr @_llgo_string, ptr undef }, ptr %3, 1 +// CHECK-NEXT: call void @"sync.(*Map).Store"(ptr %0, %"{{.*}}/runtime/internal/runtime.eface" %2, %"{{.*}}/runtime/internal/runtime.eface" %4) +// CHECK-NEXT: %5 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 16) +// CHECK-NEXT: store %"{{.*}}/runtime/internal/runtime.String" { ptr @{{[0-9]+}}, i64 1 }, ptr %5, align 8 +// CHECK-NEXT: %6 = insertvalue %"{{.*}}/runtime/internal/runtime.eface" { ptr @_llgo_string, ptr undef }, ptr %5, 1 +// CHECK-NEXT: %7 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 8) +// CHECK-NEXT: store i64 100, ptr %7, align 8 +// CHECK-NEXT: %8 = insertvalue %"{{.*}}/runtime/internal/runtime.eface" { ptr @_llgo_int, ptr undef }, ptr %7, 1 +// CHECK-NEXT: call void @"sync.(*Map).Store"(ptr %0, %"{{.*}}/runtime/internal/runtime.eface" %6, %"{{.*}}/runtime/internal/runtime.eface" %8) +// CHECK-NEXT: %9 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 16) +// CHECK-NEXT: store %"{{.*}}/runtime/internal/runtime.String" { ptr @{{[0-9]+}}, i64 1 }, ptr %9, align 8 +// CHECK-NEXT: %10 = insertvalue %"{{.*}}/runtime/internal/runtime.eface" { ptr @_llgo_string, ptr undef }, ptr %9, 1 +// CHECK-NEXT: %11 = call { %"{{.*}}/runtime/internal/runtime.eface", i1 } @"sync.(*Map).Load"(ptr %0, %"{{.*}}/runtime/internal/runtime.eface" %10) +// CHECK-NEXT: %12 = extractvalue { %"{{.*}}/runtime/internal/runtime.eface", i1 } %11, 0 +// CHECK-NEXT: %13 = extractvalue { %"{{.*}}/runtime/internal/runtime.eface", i1 } %11, 1 +// CHECK-NEXT: %14 = call ptr @"{{.*}}/runtime/internal/runtime.AllocZ"(i64 32) +// CHECK-NEXT: %15 = getelementptr inbounds %"{{.*}}/runtime/internal/runtime.eface", ptr %14, i64 0 +// CHECK-NEXT: store %"{{.*}}/runtime/internal/runtime.eface" %12, ptr %15, align 8 +// CHECK-NEXT: %16 = getelementptr inbounds %"{{.*}}/runtime/internal/runtime.eface", ptr %14, i64 1 +// CHECK-NEXT: %17 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 1) +// CHECK-NEXT: store i1 %13, ptr %17, align 1 +// CHECK-NEXT: %18 = insertvalue %"{{.*}}/runtime/internal/runtime.eface" { ptr @_llgo_bool, ptr undef }, ptr %17, 1 +// CHECK-NEXT: store %"{{.*}}/runtime/internal/runtime.eface" %18, ptr %16, align 8 +// CHECK-NEXT: %19 = insertvalue %"{{.*}}/runtime/internal/runtime.Slice" undef, ptr %14, 0 +// CHECK-NEXT: %20 = insertvalue %"{{.*}}/runtime/internal/runtime.Slice" %19, i64 2, 1 +// CHECK-NEXT: %21 = insertvalue %"{{.*}}/runtime/internal/runtime.Slice" %20, i64 2, 2 +// CHECK-NEXT: %22 = call { i64, %"{{.*}}/runtime/internal/runtime.iface" } @fmt.Println(%"{{.*}}/runtime/internal/runtime.Slice" %21) +// CHECK-NEXT: call void @"sync.(*Map).Range"(ptr %0, { ptr, ptr } { ptr @"main.main$1", ptr null }) +// CHECK-NEXT: ret void +// CHECK-NEXT: } + +// CHECK-LABEL: define i1 @"main.main$1"(%"{{.*}}/runtime/internal/runtime.eface" %0, %"{{.*}}/runtime/internal/runtime.eface" %1){{.*}} { +// CHECK-NEXT: _llgo_0: +// CHECK-NEXT: %2 = call ptr @"{{.*}}/runtime/internal/runtime.AllocZ"(i64 32) +// CHECK-NEXT: %3 = getelementptr inbounds %"{{.*}}/runtime/internal/runtime.eface", ptr %2, i64 0 +// CHECK-NEXT: store %"{{.*}}/runtime/internal/runtime.eface" %0, ptr %3, align 8 +// CHECK-NEXT: %4 = getelementptr inbounds %"{{.*}}/runtime/internal/runtime.eface", ptr %2, i64 1 +// CHECK-NEXT: store %"{{.*}}/runtime/internal/runtime.eface" %1, ptr %4, align 8 +// CHECK-NEXT: %5 = insertvalue %"{{.*}}/runtime/internal/runtime.Slice" undef, ptr %2, 0 +// CHECK-NEXT: %6 = insertvalue %"{{.*}}/runtime/internal/runtime.Slice" %5, i64 2, 1 +// CHECK-NEXT: %7 = insertvalue %"{{.*}}/runtime/internal/runtime.Slice" %6, i64 2, 2 +// CHECK-NEXT: %8 = call { i64, %"{{.*}}/runtime/internal/runtime.iface" } @fmt.Printf(%"{{.*}}/runtime/internal/runtime.String" { ptr @{{[0-9]+}}, i64 7 }, %"{{.*}}/runtime/internal/runtime.Slice" %7) +// CHECK-NEXT: ret i1 true +// CHECK-NEXT: } diff --git a/cl/_testlibc/complex/in.go b/cl/_testlibc/complex/in.go index 35427c1793..7b96b704c7 100644 --- a/cl/_testlibc/complex/in.go +++ b/cl/_testlibc/complex/in.go @@ -1,14 +1,16 @@ // LITTEST package main -// CHECK-DAG: call float @cabsf({{.*}}) -// CHECK-DAG: call void @main.f({{.*}}, ptr @main.f) - import ( "github.com/goplus/lib/c" "github.com/goplus/lib/c/math/cmplx" ) +// CHECK: {{^}}@{{[0-9]+}} = private unnamed_addr constant [5 x i8] c"addr:", align 1{{$}} +// CHECK: {{^}}@{{[0-9]+}} = private unnamed_addr constant [10 x i8] c"abs(3+4i):", align 1{{$}} +// CHECK: {{^}}@{{[0-9]+}} = private unnamed_addr constant [11 x i8] c"real(3+4i):", align 1{{$}} +// CHECK: {{^}}@{{[0-9]+}} = private unnamed_addr constant [11 x i8] c"imag(3+4i):", align 1{{$}} + func f(c, z complex64, addr c.Pointer) { println("addr:", addr) println("abs(3+4i):", cmplx.Absf(c)) @@ -23,3 +25,49 @@ func main() { x := complex(re, im) f(x, z, c.Func(f)) } + +// CHECK-LABEL: define void @main.f({ float, float } %0, { float, float } %1, ptr %2){{.*}} { +// CHECK-NEXT: _llgo_0: +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.PrintString"(%"{{.*}}/runtime/internal/runtime.String" { ptr @{{[0-9]+}}, i64 5 }) +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.PrintByte"(i8 32) +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.PrintPointer"(ptr %2) +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.PrintByte"(i8 10) +// CHECK-NEXT: %3 = call float @cabsf({ float, float } %0) +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.PrintString"(%"{{.*}}/runtime/internal/runtime.String" { ptr @{{[0-9]+}}, i64 10 }) +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.PrintByte"(i8 32) +// CHECK-NEXT: %4 = fpext float %3 to double +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.PrintFloat"(double %4) +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.PrintByte"(i8 10) +// CHECK-NEXT: %5 = extractvalue { float, float } %1, 0 +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.PrintString"(%"{{.*}}/runtime/internal/runtime.String" { ptr @{{[0-9]+}}, i64 11 }) +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.PrintByte"(i8 32) +// CHECK-NEXT: %6 = fpext float %5 to double +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.PrintFloat"(double %6) +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.PrintByte"(i8 10) +// CHECK-NEXT: %7 = extractvalue { float, float } %1, 1 +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.PrintString"(%"{{.*}}/runtime/internal/runtime.String" { ptr @{{[0-9]+}}, i64 11 }) +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.PrintByte"(i8 32) +// CHECK-NEXT: %8 = fpext float %7 to double +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.PrintFloat"(double %8) +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.PrintByte"(i8 10) +// CHECK-NEXT: ret void +// CHECK-NEXT: } + +// CHECK-LABEL: define void @main.init(){{.*}} { +// CHECK-NEXT: _llgo_0: +// CHECK-NEXT: %0 = load i1, ptr @"main.init$guard", align 1 +// CHECK-NEXT: br i1 %0, label %_llgo_2, label %_llgo_1 +// CHECK-EMPTY: +// CHECK-NEXT: _llgo_1: ; preds = %_llgo_0 +// CHECK-NEXT: store i1 true, ptr @"main.init$guard", align 1 +// CHECK-NEXT: br label %_llgo_2 +// CHECK-EMPTY: +// CHECK-NEXT: _llgo_2: ; preds = %_llgo_1, %_llgo_0 +// CHECK-NEXT: ret void +// CHECK-NEXT: } + +// CHECK-LABEL: define void @main.main(){{.*}} { +// CHECK-NEXT: _llgo_0: +// CHECK-NEXT: call void @main.f({ float, float } { float 3.000000e+00, float 4.000000e+00 }, { float, float } { float 3.000000e+00, float 4.000000e+00 }, ptr @main.f) +// CHECK-NEXT: ret void +// CHECK-NEXT: } diff --git a/cl/_testlibc/defer/in.go b/cl/_testlibc/defer/in.go index 5910a7c38e..b6279ee4f9 100644 --- a/cl/_testlibc/defer/in.go +++ b/cl/_testlibc/defer/in.go @@ -1,12 +1,13 @@ // LITTEST package main -// CHECK-DAG: call ptr @"{{.*}}/runtime/internal/runtime.GetThreadDefer"() -// CHECK-DAG: call i32 @{{.*}}setjmp(ptr %{{.*}}{{.*}}) -// CHECK-DAG: call i32 (ptr, ...) @printf({{.*}}) - import "github.com/goplus/lib/c" +// CHECK: {{^}}@{{[0-9]+}} = private unnamed_addr constant [5 x i8] c"hello", align 1{{$}} +// CHECK: {{^}}@{{[0-9]+}} = private unnamed_addr constant [4 x i8] c"%s\0A\00", align 1{{$}} +// CHECK: {{^}}@{{[0-9]+}} = private unnamed_addr constant [7 x i8] c"world\0A\00", align 1{{$}} +// CHECK: {{^}}@{{[0-9]+}} = private unnamed_addr constant [5 x i8] c"bye\0A\00", align 1{{$}} + func f(s string) bool { return len(s) > 2 } @@ -20,3 +21,195 @@ func main() { } defer c.Printf(c.Str("bye\n")) } + +// CHECK-LABEL: define i1 @main.f(%"{{.*}}/runtime/internal/runtime.String" %0){{.*}} { +// CHECK-NEXT: _llgo_0: +// CHECK-NEXT: %1 = extractvalue %"{{.*}}/runtime/internal/runtime.String" %0, 1 +// CHECK-NEXT: %2 = icmp sgt i64 %1, 2 +// CHECK-NEXT: ret i1 %2 +// CHECK-NEXT: } + +// CHECK-LABEL: define void @main.init(){{.*}} { +// CHECK-NEXT: _llgo_0: +// CHECK-NEXT: %0 = load i1, ptr @"main.init$guard", align 1 +// CHECK-NEXT: br i1 %0, label %_llgo_2, label %_llgo_1 +// CHECK-EMPTY: +// CHECK-NEXT: _llgo_1: ; preds = %_llgo_0 +// CHECK-NEXT: store i1 true, ptr @"main.init$guard", align 1 +// CHECK-NEXT: br label %_llgo_2 +// CHECK-EMPTY: +// CHECK-NEXT: _llgo_2: ; preds = %_llgo_1, %_llgo_0 +// CHECK-NEXT: ret void +// CHECK-NEXT: } + +// CHECK-LABEL: define void @main.main(){{.*}} { +// CHECK-NEXT: _llgo_0: +// CHECK-NEXT: %0 = call ptr @"{{.*}}/runtime/internal/runtime.GetThreadDefer"() +// CHECK-NEXT: %1 = call i1 @main.f(%"{{.*}}/runtime/internal/runtime.String" { ptr @{{[0-9]+}}, i64 5 }) +// CHECK-NEXT: %2 = call ptr @"{{.*}}/runtime/internal/runtime.GetThreadDefer"() +// CHECK-NEXT: %3 = alloca i8 +// CHECK-NEXT: %4 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 48) +// CHECK-NEXT: %5 = getelementptr inbounds %"{{.*}}/runtime/internal/runtime.Defer", ptr %4, i32 0, i32 0 +// CHECK-NEXT: store ptr %3, ptr %5, align 8 +// CHECK-NEXT: %6 = getelementptr inbounds %"{{.*}}/runtime/internal/runtime.Defer", ptr %4, i32 0, i32 1 +// CHECK-NEXT: store i64 0, ptr %6, align 8 +// CHECK-NEXT: %7 = getelementptr inbounds %"{{.*}}/runtime/internal/runtime.Defer", ptr %4, i32 0, i32 2 +// CHECK-NEXT: store ptr %2, ptr %7, align 8 +// CHECK-NEXT: %8 = getelementptr inbounds %"{{.*}}/runtime/internal/runtime.Defer", ptr %4, i32 0, i32 3 +// CHECK-NEXT: store ptr blockaddress(@main.main, %_llgo_6), ptr %8, align 8 +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.SetThreadDefer"(ptr %4) +// CHECK-NEXT: %9 = getelementptr inbounds %"{{.*}}/runtime/internal/runtime.Defer", ptr %4, i32 0, i32 1 +// CHECK-NEXT: %10 = getelementptr inbounds %"{{.*}}/runtime/internal/runtime.Defer", ptr %4, i32 0, i32 3 +// CHECK-NEXT: %11 = getelementptr inbounds %"{{.*}}/runtime/internal/runtime.Defer", ptr %4, i32 0, i32 4 +// CHECK-NEXT: %12 = getelementptr inbounds %"{{.*}}/runtime/internal/runtime.Defer", ptr %4, i32 0, i32 5 +// CHECK-NEXT: store ptr null, ptr %12, align 8 +// CHECK-NEXT: %13 = call i32 @{{(__)?}}sigsetjmp(ptr %3, i32 0) +// CHECK-NEXT: %14 = icmp eq i32 %13, 0 +// CHECK-NEXT: br i1 %14, label %_llgo_5, label %_llgo_8 +// CHECK-EMPTY: +// CHECK-NEXT: _llgo_1: ; preds = %_llgo_5 +// CHECK-NEXT: %15 = alloca i8, i64 6, align 1 +// CHECK-NEXT: %16 = call ptr @"{{.*}}/runtime/internal/runtime.CStrCopy"(ptr %15, %"{{.*}}/runtime/internal/runtime.String" { ptr @{{[0-9]+}}, i64 5 }) +// CHECK-NEXT: %17 = load i64, ptr %9, align 8 +// CHECK-NEXT: %18 = or i64 %17, 1 +// CHECK-NEXT: store i64 %18, ptr %9, align 8 +// CHECK-NEXT: %19 = load ptr, ptr %12, align 8 +// CHECK-NEXT: %20 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 32) +// CHECK-NEXT: %21 = getelementptr inbounds { ptr, i64, ptr, ptr }, ptr %20, i32 0, i32 0 +// CHECK-NEXT: store ptr %19, ptr %21, align 8 +// CHECK-NEXT: %22 = getelementptr inbounds { ptr, i64, ptr, ptr }, ptr %20, i32 0, i32 1 +// CHECK-NEXT: store i64 0, ptr %22, align 8 +// CHECK-NEXT: %23 = getelementptr inbounds { ptr, i64, ptr, ptr }, ptr %20, i32 0, i32 2 +// CHECK-NEXT: store ptr @{{[0-9]+}}, ptr %23, align 8 +// CHECK-NEXT: %24 = getelementptr inbounds { ptr, i64, ptr, ptr }, ptr %20, i32 0, i32 3 +// CHECK-NEXT: store ptr %16, ptr %24, align 8 +// CHECK-NEXT: store ptr %20, ptr %12, align 8 +// CHECK-NEXT: br label %_llgo_2 +// CHECK-EMPTY: +// CHECK-NEXT: _llgo_2: ; preds = %_llgo_3, %_llgo_1 +// CHECK-NEXT: %25 = load ptr, ptr %12, align 8 +// CHECK-NEXT: %26 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 24) +// CHECK-NEXT: %27 = getelementptr inbounds { ptr, i64, ptr }, ptr %26, i32 0, i32 0 +// CHECK-NEXT: store ptr %25, ptr %27, align 8 +// CHECK-NEXT: %28 = getelementptr inbounds { ptr, i64, ptr }, ptr %26, i32 0, i32 1 +// CHECK-NEXT: store i64 2, ptr %28, align 8 +// CHECK-NEXT: %29 = getelementptr inbounds { ptr, i64, ptr }, ptr %26, i32 0, i32 2 +// CHECK-NEXT: store ptr @{{[0-9]+}}, ptr %29, align 8 +// CHECK-NEXT: store ptr %26, ptr %12, align 8 +// CHECK-NEXT: store ptr blockaddress(@main.main, %_llgo_9), ptr %11, align 8 +// CHECK-NEXT: br label %_llgo_6 +// CHECK-EMPTY: +// CHECK-NEXT: _llgo_3: ; preds = %_llgo_5 +// CHECK-NEXT: %30 = load i64, ptr %9, align 8 +// CHECK-NEXT: %31 = or i64 %30, 2 +// CHECK-NEXT: store i64 %31, ptr %9, align 8 +// CHECK-NEXT: %32 = load ptr, ptr %12, align 8 +// CHECK-NEXT: %33 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 24) +// CHECK-NEXT: %34 = getelementptr inbounds { ptr, i64, ptr }, ptr %33, i32 0, i32 0 +// CHECK-NEXT: store ptr %32, ptr %34, align 8 +// CHECK-NEXT: %35 = getelementptr inbounds { ptr, i64, ptr }, ptr %33, i32 0, i32 1 +// CHECK-NEXT: store i64 1, ptr %35, align 8 +// CHECK-NEXT: %36 = getelementptr inbounds { ptr, i64, ptr }, ptr %33, i32 0, i32 2 +// CHECK-NEXT: store ptr @{{[0-9]+}}, ptr %36, align 8 +// CHECK-NEXT: store ptr %33, ptr %12, align 8 +// CHECK-NEXT: br label %_llgo_2 +// CHECK-EMPTY: +// CHECK-NEXT: _llgo_4: ; preds = %_llgo_7 +// CHECK-NEXT: ret void +// CHECK-EMPTY: +// CHECK-NEXT: _llgo_5: ; preds = %_llgo_0 +// CHECK-NEXT: br i1 %1, label %_llgo_1, label %_llgo_3 +// CHECK-EMPTY: +// CHECK-NEXT: _llgo_6: ; preds = %_llgo_8, %_llgo_2 +// CHECK-NEXT: store ptr blockaddress(@main.main, %_llgo_11), ptr %10, align 8 +// CHECK-NEXT: %37 = load i64, ptr %9, align 8 +// CHECK-NEXT: %38 = load ptr, ptr %12, align 8 +// CHECK-NEXT: %39 = icmp ne ptr %38, null +// CHECK-NEXT: br i1 %39, label %_llgo_12, label %_llgo_13 +// CHECK-EMPTY: +// CHECK-NEXT: _llgo_7: ; preds = %_llgo_8, %_llgo_19 +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.Rethrow"(ptr %2) +// CHECK-NEXT: br label %_llgo_4 +// CHECK-EMPTY: +// CHECK-NEXT: _llgo_8: ; preds = %_llgo_0 +// CHECK-NEXT: store ptr blockaddress(@main.main, %_llgo_7), ptr %11, align 8 +// CHECK-NEXT: %40 = load ptr, ptr %10, align 8 +// CHECK-NEXT: indirectbr ptr %40, [label %_llgo_7, label %_llgo_10, label %_llgo_11, label %_llgo_6] +// CHECK-EMPTY: +// CHECK-NEXT: _llgo_9: ; preds = %_llgo_19 +// CHECK-NEXT: ret void +// CHECK-EMPTY: +// CHECK-NEXT: _llgo_10: ; preds = %_llgo_8, %_llgo_15 +// CHECK-NEXT: store ptr blockaddress(@main.main, %_llgo_7), ptr %10, align 8 +// CHECK-NEXT: %41 = load i64, ptr %9, align 8 +// CHECK-NEXT: %42 = and i64 %41, 1 +// CHECK-NEXT: %43 = icmp ne i64 %42, 0 +// CHECK-NEXT: br i1 %43, label %_llgo_18, label %_llgo_19 +// CHECK-EMPTY: +// CHECK-NEXT: _llgo_11: ; preds = %_llgo_8, %_llgo_13 +// CHECK-NEXT: store ptr blockaddress(@main.main, %_llgo_10), ptr %10, align 8 +// CHECK-NEXT: %44 = load i64, ptr %9, align 8 +// CHECK-NEXT: %45 = and i64 %44, 2 +// CHECK-NEXT: %46 = icmp ne i64 %45, 0 +// CHECK-NEXT: br i1 %46, label %_llgo_14, label %_llgo_15 +// CHECK-EMPTY: +// CHECK-NEXT: _llgo_12: ; preds = %_llgo_6 +// CHECK-NEXT: %47 = load ptr, ptr %12, align 8 +// CHECK-NEXT: %48 = load { ptr, i64, ptr }, ptr %47, align 8 +// CHECK-NEXT: %49 = extractvalue { ptr, i64, ptr } %48, 0 +// CHECK-NEXT: store ptr %49, ptr %12, align 8 +// CHECK-NEXT: %50 = extractvalue { ptr, i64, ptr } %48, 2 +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.FreeDeferNode"(ptr %47) +// CHECK-NEXT: %51 = call i32 (ptr, ...) @printf(ptr %50) +// CHECK-NEXT: br label %_llgo_13 +// CHECK-EMPTY: +// CHECK-NEXT: _llgo_13: ; preds = %_llgo_12, %_llgo_6 +// CHECK-NEXT: br label %_llgo_11 +// CHECK-EMPTY: +// CHECK-NEXT: _llgo_14: ; preds = %_llgo_11 +// CHECK-NEXT: %52 = load ptr, ptr %12, align 8 +// CHECK-NEXT: %53 = icmp ne ptr %52, null +// CHECK-NEXT: br i1 %53, label %_llgo_16, label %_llgo_17 +// CHECK-EMPTY: +// CHECK-NEXT: _llgo_15: ; preds = %_llgo_17, %_llgo_11 +// CHECK-NEXT: br label %_llgo_10 +// CHECK-EMPTY: +// CHECK-NEXT: _llgo_16: ; preds = %_llgo_14 +// CHECK-NEXT: %54 = load ptr, ptr %12, align 8 +// CHECK-NEXT: %55 = load { ptr, i64, ptr }, ptr %54, align 8 +// CHECK-NEXT: %56 = extractvalue { ptr, i64, ptr } %55, 0 +// CHECK-NEXT: store ptr %56, ptr %12, align 8 +// CHECK-NEXT: %57 = extractvalue { ptr, i64, ptr } %55, 2 +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.FreeDeferNode"(ptr %54) +// CHECK-NEXT: %58 = call i32 (ptr, ...) @printf(ptr %57) +// CHECK-NEXT: br label %_llgo_17 +// CHECK-EMPTY: +// CHECK-NEXT: _llgo_17: ; preds = %_llgo_16, %_llgo_14 +// CHECK-NEXT: br label %_llgo_15 +// CHECK-EMPTY: +// CHECK-NEXT: _llgo_18: ; preds = %_llgo_10 +// CHECK-NEXT: %59 = load ptr, ptr %12, align 8 +// CHECK-NEXT: %60 = icmp ne ptr %59, null +// CHECK-NEXT: br i1 %60, label %_llgo_20, label %_llgo_21 +// CHECK-EMPTY: +// CHECK-NEXT: _llgo_19: ; preds = %_llgo_21, %_llgo_10 +// CHECK-NEXT: %61 = load %"{{.*}}/runtime/internal/runtime.Defer", ptr %4, align 8 +// CHECK-NEXT: %62 = extractvalue %"{{.*}}/runtime/internal/runtime.Defer" %61, 2 +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.SetThreadDefer"(ptr %62) +// CHECK-NEXT: %63 = load ptr, ptr %11, align 8 +// CHECK-NEXT: indirectbr ptr %63, [label %_llgo_7, label %_llgo_9] +// CHECK-EMPTY: +// CHECK-NEXT: _llgo_20: ; preds = %_llgo_18 +// CHECK-NEXT: %64 = load ptr, ptr %12, align 8 +// CHECK-NEXT: %65 = load { ptr, i64, ptr, ptr }, ptr %64, align 8 +// CHECK-NEXT: %66 = extractvalue { ptr, i64, ptr, ptr } %65, 0 +// CHECK-NEXT: store ptr %66, ptr %12, align 8 +// CHECK-NEXT: %67 = extractvalue { ptr, i64, ptr, ptr } %65, 2 +// CHECK-NEXT: %68 = extractvalue { ptr, i64, ptr, ptr } %65, 3 +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.FreeDeferNode"(ptr %64) +// CHECK-NEXT: %69 = call i32 (ptr, ...) @printf(ptr %67, ptr %68) +// CHECK-NEXT: br label %_llgo_21 +// CHECK-EMPTY: +// CHECK-NEXT: _llgo_21: ; preds = %_llgo_20, %_llgo_18 +// CHECK-NEXT: br label %_llgo_19 +// CHECK-NEXT: } diff --git a/cl/_testlibc/once/in.go b/cl/_testlibc/once/in.go index 61d9a02e91..e0323a7cb9 100644 --- a/cl/_testlibc/once/in.go +++ b/cl/_testlibc/once/in.go @@ -1,14 +1,15 @@ // LITTEST package main -// CHECK-DAG: call i32 @pthread_once({{.*}}) -// CHECK-DAG: define void @"main.f$1"(){{.*}} { - import ( "github.com/goplus/lib/c" "github.com/goplus/lib/c/pthread/sync" ) +// CHECK: {{^}}@{{[0-9]+}} = private unnamed_addr constant [9 x i8] c"Do once\0A\00", align 1{{$}} +// CHECK: {{^}}@{{[0-9]+}} = private unnamed_addr constant [16 x i8] c"sync.Once demo\0A\00", align 1{{$}} +// CHECK: {{^}}@{{[0-9]+}} = private unnamed_addr constant [16 x i8] c"sync.Once demo\0A\00", align 1{{$}} + var once sync.Once = sync.OnceInit func f() { @@ -23,3 +24,43 @@ func main() { f() f() } + +// CHECK-LABEL: define void @main.f(){{.*}} { +// CHECK-NEXT: _llgo_0: +// CHECK-NEXT: %0 = call i32 @pthread_once(ptr @main.once, ptr @"main.f$1") +// CHECK-NEXT: ret void +// CHECK-NEXT: } + +// CHECK-LABEL: define void @"main.f$1"(){{.*}} { +// CHECK-NEXT: _llgo_0: +// CHECK-NEXT: %0 = call i32 (ptr, ...) @printf(ptr @{{[0-9]+}}) +// CHECK-NEXT: ret void +// CHECK-NEXT: } + +// CHECK-LABEL: define void @main.init(){{.*}} { +// CHECK-NEXT: _llgo_0: +// CHECK-NEXT: %0 = load i1, ptr @"main.init$guard", align 1 +// CHECK-NEXT: br i1 %0, label %_llgo_2, label %_llgo_1 +// CHECK-EMPTY: +// CHECK-NEXT: _llgo_1: ; preds = %_llgo_0 +// CHECK-NEXT: store i1 true, ptr @"main.init$guard", align 1 +// CHECK-NEXT: %1 = load {{.*}}, ptr @llgoSyncOnceInitVal +// CHECK-NEXT: store {{.*}} %1, ptr @main.once +// CHECK-NEXT: br label %_llgo_2 +// CHECK-EMPTY: +// CHECK-NEXT: _llgo_2: ; preds = %_llgo_1, %_llgo_0 +// CHECK-NEXT: ret void +// CHECK-NEXT: } + +// CHECK-LABEL: define void @main.main(){{.*}} { +// CHECK-NEXT: _llgo_0: +// CHECK-NEXT: %0 = call %"{{.*}}/runtime/internal/runtime.String" @"{{.*}}/runtime/internal/runtime.StringFrom"(ptr @{{[0-9]+}}, i64 9) +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.PrintString"(%"{{.*}}/runtime/internal/runtime.String" %0) +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.PrintByte"(i8 10) +// CHECK-NEXT: %1 = call %"{{.*}}/runtime/internal/runtime.String" @"{{.*}}/runtime/internal/runtime.StringFromCStr"(ptr @{{[0-9]+}}) +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.PrintString"(%"{{.*}}/runtime/internal/runtime.String" %1) +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.PrintByte"(i8 10) +// CHECK-NEXT: call void @main.f() +// CHECK-NEXT: call void @main.f() +// CHECK-NEXT: ret void +// CHECK-NEXT: } diff --git a/cl/_testlibc/setjmp/in.go b/cl/_testlibc/setjmp/in.go index 4111e15483..136f26c76c 100644 --- a/cl/_testlibc/setjmp/in.go +++ b/cl/_testlibc/setjmp/in.go @@ -1,13 +1,14 @@ // LITTEST package main -// CHECK-DAG: call i32 @{{.*}}sigsetjmp(ptr %{{.*}}, i32 0) -// CHECK-DAG: call void @{{.*}}siglongjmp(ptr %{{.*}}, i32 1) - import ( "github.com/goplus/lib/c" ) +// CHECK: {{^}}@{{[0-9]+}} = private unnamed_addr constant [18 x i8] c"??Hello, setjmp!\0A\00", align 1{{$}} +// CHECK: {{^}}@{{[0-9]+}} = private unnamed_addr constant [3 x i8] c"%s\00", align 1{{$}} +// CHECK: {{^}}@{{[0-9]+}} = private unnamed_addr constant [10 x i8] c"exception:", align 1{{$}} + func main() { jb := c.AllocaSigjmpBuf() switch ret := c.Sigsetjmp(jb, 0); ret { @@ -19,3 +20,41 @@ func main() { println("exception:", ret) } } + +// CHECK-LABEL: define void @main.init(){{.*}} { +// CHECK-NEXT: _llgo_0: +// CHECK-NEXT: %0 = load i1, ptr @"main.init$guard", align 1 +// CHECK-NEXT: br i1 %0, label %_llgo_2, label %_llgo_1 +// CHECK-EMPTY: +// CHECK-NEXT: _llgo_1: ; preds = %_llgo_0 +// CHECK-NEXT: store i1 true, ptr @"main.init$guard", align 1 +// CHECK-NEXT: br label %_llgo_2 +// CHECK-EMPTY: +// CHECK-NEXT: _llgo_2: ; preds = %_llgo_1, %_llgo_0 +// CHECK-NEXT: ret void +// CHECK-NEXT: } + +// CHECK-LABEL: define void @main.main(){{.*}} { +// CHECK-NEXT: _llgo_0: +// CHECK-NEXT: %0 = alloca i8 +// CHECK-NEXT: %1 = call i32 @{{(__)?}}sigsetjmp(ptr %0, i32 0) +// CHECK-NEXT: %2 = icmp eq i32 %1, 0 +// CHECK-NEXT: br i1 %2, label %_llgo_2, label %_llgo_3 +// CHECK-EMPTY: +// CHECK-NEXT: _llgo_1: ; preds = %_llgo_3, %_llgo_2 +// CHECK-NEXT: ret void +// CHECK-EMPTY: +// CHECK-NEXT: _llgo_2: ; preds = %_llgo_0 +// CHECK-NEXT: %3 = load ptr, ptr @{{(__stderrp|stderr)}}, align 8 +// CHECK-NEXT: %4 = call i32 (ptr, ptr, ...) @fprintf(ptr %3, ptr @{{[0-9]+}}, ptr getelementptr (i8, ptr getelementptr (i8, ptr @{{[0-9]+}}, i64 1), i64 1)) +// CHECK-NEXT: call void @siglongjmp(ptr %0, i32 1) +// CHECK-NEXT: br label %_llgo_1 +// CHECK-EMPTY: +// CHECK-NEXT: _llgo_3: ; preds = %_llgo_0 +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.PrintString"(%"{{.*}}/runtime/internal/runtime.String" { ptr @{{[0-9]+}}, i64 10 }) +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.PrintByte"(i8 32) +// CHECK-NEXT: %5 = sext i32 %1 to i64 +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.PrintInt"(i64 %5) +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.PrintByte"(i8 10) +// CHECK-NEXT: br label %_llgo_1 +// CHECK-NEXT: } diff --git a/cl/_testlibgo/sync/in.go b/cl/_testlibgo/sync/in.go index 7365ac3f55..75b1e300c5 100644 --- a/cl/_testlibgo/sync/in.go +++ b/cl/_testlibgo/sync/in.go @@ -1,13 +1,13 @@ // LITTEST package main -// CHECK-DAG: call {{.*}}sync{{.*}}Once{{.*}}Do{{.*}} -// CHECK-DAG: define void @"main.f$1"(ptr {{((nest|swiftself) )?}}%{{.*}}){{.*}} { - import ( "sync" ) +// CHECK: {{^}}@{{[0-9]+}} = private unnamed_addr constant [7 x i8] c"Do once", align 1{{$}} +// CHECK: {{^}}@{{[0-9]+}} = private unnamed_addr constant [8 x i8] c"Do twice", align 1{{$}} + var once sync.Once func f(s string) { @@ -20,3 +20,46 @@ func main() { f("Do once") f("Do twice") } + +// CHECK-LABEL: define void @main.f(%"{{.*}}/runtime/internal/runtime.String" %0){{.*}} { +// CHECK-NEXT: _llgo_0: +// CHECK-NEXT: %1 = call ptr @"{{.*}}/runtime/internal/runtime.AllocZ"(i64 16) +// CHECK-NEXT: store %"{{.*}}/runtime/internal/runtime.String" %0, ptr %1, align 8 +// CHECK-NEXT: %2 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 8) +// CHECK-NEXT: %3 = getelementptr inbounds { ptr }, ptr %2, i32 0, i32 0 +// CHECK-NEXT: store ptr %1, ptr %3, align 8 +// CHECK-NEXT: %4 = insertvalue { ptr, ptr } { ptr @"main.f$1", ptr undef }, ptr %2, 1 +// CHECK-NEXT: call void @"sync.(*Once).Do"(ptr @main.once, { ptr, ptr } %4) +// CHECK-NEXT: ret void +// CHECK-NEXT: } + +// CHECK-LABEL: define void @"main.f$1"(ptr {{(nest|swiftself)}} %0){{.*}} { +// CHECK-NEXT: _llgo_0: +// CHECK-NEXT: %1 = load { ptr }, ptr %0, align 8 +// CHECK-NEXT: %2 = extractvalue { ptr } %1, 0 +// CHECK-NEXT: %3 = load %"{{.*}}/runtime/internal/runtime.String", ptr %2, align 8 +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.PrintString"(%"{{.*}}/runtime/internal/runtime.String" %3) +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.PrintByte"(i8 10) +// CHECK-NEXT: ret void +// CHECK-NEXT: } + +// CHECK-LABEL: define void @main.init(){{.*}} { +// CHECK-NEXT: _llgo_0: +// CHECK-NEXT: %0 = load i1, ptr @"main.init$guard", align 1 +// CHECK-NEXT: br i1 %0, label %_llgo_2, label %_llgo_1 +// CHECK-EMPTY: +// CHECK-NEXT: _llgo_1: ; preds = %_llgo_0 +// CHECK-NEXT: store i1 true, ptr @"main.init$guard", align 1 +// CHECK-NEXT: call void @sync.init() +// CHECK-NEXT: br label %_llgo_2 +// CHECK-EMPTY: +// CHECK-NEXT: _llgo_2: ; preds = %_llgo_1, %_llgo_0 +// CHECK-NEXT: ret void +// CHECK-NEXT: } + +// CHECK-LABEL: define void @main.main(){{.*}} { +// CHECK-NEXT: _llgo_0: +// CHECK-NEXT: call void @main.f(%"{{.*}}/runtime/internal/runtime.String" { ptr @{{[0-9]+}}, i64 7 }) +// CHECK-NEXT: call void @main.f(%"{{.*}}/runtime/internal/runtime.String" { ptr @{{[0-9]+}}, i64 8 }) +// CHECK-NEXT: ret void +// CHECK-NEXT: } diff --git a/cl/_testlibgo/waitgroup/in.go b/cl/_testlibgo/waitgroup/in.go index b0fb375a63..76cadc9ce7 100644 --- a/cl/_testlibgo/waitgroup/in.go +++ b/cl/_testlibgo/waitgroup/in.go @@ -1,15 +1,14 @@ // LITTEST package main -// CHECK-DAG: call {{.*}}sync{{.*}}WaitGroup{{.*}}Add{{.*}} -// CHECK-DAG: call void @"{{.*}}/runtime/internal/runtime.NewProc"({{.*}}) -// CHECK-DAG: call {{.*}}sync{{.*}}WaitGroup{{.*}}Done{{.*}} -// CHECK-DAG: call {{.*}}sync{{.*}}WaitGroup{{.*}}Wait{{.*}} - import ( "sync" ) +// CHECK: {{^}}@{{[0-9]+}} = private unnamed_addr constant [4 x i8] c"done", align 1{{$}} +// CHECK: {{^}}@{{[0-9]+}} = private unnamed_addr constant [6 x i8] c"work 1", align 1{{$}} +// CHECK: {{^}}@{{[0-9]+}} = private unnamed_addr constant [6 x i8] c"work 2", align 1{{$}} + func main() { var wg sync.WaitGroup wg.Add(2) @@ -24,3 +23,235 @@ func main() { wg.Wait() println("done") } + +// CHECK-LABEL: define void @main.init(){{.*}} { +// CHECK-NEXT: _llgo_0: +// CHECK-NEXT: %0 = load i1, ptr @"main.init$guard", align 1 +// CHECK-NEXT: br i1 %0, label %_llgo_2, label %_llgo_1 +// CHECK-EMPTY: +// CHECK-NEXT: _llgo_1: ; preds = %_llgo_0 +// CHECK-NEXT: store i1 true, ptr @"main.init$guard", align 1 +// CHECK-NEXT: call void @sync.init() +// CHECK-NEXT: br label %_llgo_2 +// CHECK-EMPTY: +// CHECK-NEXT: _llgo_2: ; preds = %_llgo_1, %_llgo_0 +// CHECK-NEXT: ret void +// CHECK-NEXT: } + +// CHECK-LABEL: define void @main.main(){{.*}} { +// CHECK-NEXT: _llgo_0: +// CHECK-NEXT: %0 = call ptr @"{{.*}}/runtime/internal/runtime.AllocZ"(i64 16) +// CHECK-NEXT: call void @"sync.(*WaitGroup).Add"(ptr %0, i64 2) +// CHECK-NEXT: %1 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 8) +// CHECK-NEXT: %2 = getelementptr inbounds { ptr }, ptr %1, i32 0, i32 0 +// CHECK-NEXT: store ptr %0, ptr %2, align 8 +// CHECK-NEXT: %3 = insertvalue { ptr, ptr } { ptr @"main.main$1", ptr undef }, ptr %1, 1 +// CHECK-NEXT: %4 = call ptr @"{{.*}}/runtime/internal/runtime.AllocRoot"(i64 16) +// CHECK-NEXT: %5 = getelementptr inbounds { { ptr, ptr } }, ptr %4, i32 0, i32 0 +// CHECK-NEXT: store { ptr, ptr } %3, ptr %5, align 8 +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.NewProc"(ptr @"main._llgo_routine$1", ptr %4, i64 0) +// CHECK-NEXT: %6 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 8) +// CHECK-NEXT: %7 = getelementptr inbounds { ptr }, ptr %6, i32 0, i32 0 +// CHECK-NEXT: store ptr %0, ptr %7, align 8 +// CHECK-NEXT: %8 = insertvalue { ptr, ptr } { ptr @"main.main$2", ptr undef }, ptr %6, 1 +// CHECK-NEXT: %9 = call ptr @"{{.*}}/runtime/internal/runtime.AllocRoot"(i64 16) +// CHECK-NEXT: %10 = getelementptr inbounds { { ptr, ptr } }, ptr %9, i32 0, i32 0 +// CHECK-NEXT: store { ptr, ptr } %8, ptr %10, align 8 +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.NewProc"(ptr @"main._llgo_routine$2", ptr %9, i64 0) +// CHECK-NEXT: call void @"sync.(*WaitGroup).Wait"(ptr %0) +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.PrintString"(%"{{.*}}/runtime/internal/runtime.String" { ptr @{{[0-9]+}}, i64 4 }) +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.PrintByte"(i8 10) +// CHECK-NEXT: ret void +// CHECK-NEXT: } + +// CHECK-LABEL: define void @"main.main$1"(ptr {{(nest|swiftself)}} %0){{.*}} { +// CHECK-NEXT: _llgo_0: +// CHECK-NEXT: %1 = load { ptr }, ptr %0, align 8 +// CHECK-NEXT: %2 = extractvalue { ptr } %1, 0 +// CHECK-NEXT: %3 = call ptr @"{{.*}}/runtime/internal/runtime.GetThreadDefer"() +// CHECK-NEXT: %4 = alloca i8 +// CHECK-NEXT: %5 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 48) +// CHECK-NEXT: %6 = getelementptr inbounds %"{{.*}}/runtime/internal/runtime.Defer", ptr %5, i32 0, i32 0 +// CHECK-NEXT: store ptr %4, ptr %6, align 8 +// CHECK-NEXT: %7 = getelementptr inbounds %"{{.*}}/runtime/internal/runtime.Defer", ptr %5, i32 0, i32 1 +// CHECK-NEXT: store i64 0, ptr %7, align 8 +// CHECK-NEXT: %8 = getelementptr inbounds %"{{.*}}/runtime/internal/runtime.Defer", ptr %5, i32 0, i32 2 +// CHECK-NEXT: store ptr %3, ptr %8, align 8 +// CHECK-NEXT: %9 = getelementptr inbounds %"{{.*}}/runtime/internal/runtime.Defer", ptr %5, i32 0, i32 3 +// CHECK-NEXT: store ptr blockaddress(@"main.main$1", %_llgo_2), ptr %9, align 8 +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.SetThreadDefer"(ptr %5) +// CHECK-NEXT: %10 = getelementptr inbounds %"{{.*}}/runtime/internal/runtime.Defer", ptr %5, i32 0, i32 1 +// CHECK-NEXT: %11 = getelementptr inbounds %"{{.*}}/runtime/internal/runtime.Defer", ptr %5, i32 0, i32 3 +// CHECK-NEXT: %12 = getelementptr inbounds %"{{.*}}/runtime/internal/runtime.Defer", ptr %5, i32 0, i32 4 +// CHECK-NEXT: %13 = getelementptr inbounds %"{{.*}}/runtime/internal/runtime.Defer", ptr %5, i32 0, i32 5 +// CHECK-NEXT: store ptr null, ptr %13, align 8 +// CHECK-NEXT: %14 = call i32 @{{(__)?}}sigsetjmp(ptr %4, i32 0) +// CHECK-NEXT: %15 = icmp eq i32 %14, 0 +// CHECK-NEXT: br i1 %15, label %_llgo_4, label %_llgo_5 +// CHECK-EMPTY: +// CHECK-NEXT: _llgo_1: ; preds = %_llgo_3 +// CHECK-NEXT: ret void +// CHECK-EMPTY: +// CHECK-NEXT: _llgo_2: ; preds = %_llgo_5, %_llgo_4 +// CHECK-NEXT: store ptr blockaddress(@"main.main$1", %_llgo_3), ptr %11, align 8 +// CHECK-NEXT: %16 = load i64, ptr %10, align 8 +// CHECK-NEXT: %17 = load ptr, ptr %13, align 8 +// CHECK-NEXT: %18 = icmp ne ptr %17, null +// CHECK-NEXT: br i1 %18, label %_llgo_7, label %_llgo_8 +// CHECK-EMPTY: +// CHECK-NEXT: _llgo_3: ; preds = %_llgo_5, %_llgo_8 +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.Rethrow"(ptr %3) +// CHECK-NEXT: br label %_llgo_1 +// CHECK-EMPTY: +// CHECK-NEXT: _llgo_4: ; preds = %_llgo_0 +// CHECK-NEXT: %19 = load ptr, ptr %13, align 8 +// CHECK-NEXT: %20 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 24) +// CHECK-NEXT: %21 = getelementptr inbounds { ptr, i64, ptr }, ptr %20, i32 0, i32 0 +// CHECK-NEXT: store ptr %19, ptr %21, align 8 +// CHECK-NEXT: %22 = getelementptr inbounds { ptr, i64, ptr }, ptr %20, i32 0, i32 1 +// CHECK-NEXT: store i64 0, ptr %22, align 8 +// CHECK-NEXT: %23 = getelementptr inbounds { ptr, i64, ptr }, ptr %20, i32 0, i32 2 +// CHECK-NEXT: store ptr %2, ptr %23, align 8 +// CHECK-NEXT: store ptr %20, ptr %13, align 8 +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.PrintString"(%"{{.*}}/runtime/internal/runtime.String" { ptr @{{[0-9]+}}, i64 6 }) +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.PrintByte"(i8 10) +// CHECK-NEXT: store ptr blockaddress(@"main.main$1", %_llgo_6), ptr %12, align 8 +// CHECK-NEXT: br label %_llgo_2 +// CHECK-EMPTY: +// CHECK-NEXT: _llgo_5: ; preds = %_llgo_0 +// CHECK-NEXT: store ptr blockaddress(@"main.main$1", %_llgo_3), ptr %12, align 8 +// CHECK-NEXT: %24 = load ptr, ptr %11, align 8 +// CHECK-NEXT: indirectbr ptr %24, [label %_llgo_3, label %_llgo_2] +// CHECK-EMPTY: +// CHECK-NEXT: _llgo_6: ; preds = %_llgo_8 +// CHECK-NEXT: ret void +// CHECK-EMPTY: +// CHECK-NEXT: _llgo_7: ; preds = %_llgo_2 +// CHECK-NEXT: %25 = load ptr, ptr %13, align 8 +// CHECK-NEXT: %26 = load { ptr, i64, ptr }, ptr %25, align 8 +// CHECK-NEXT: %27 = extractvalue { ptr, i64, ptr } %26, 0 +// CHECK-NEXT: store ptr %27, ptr %13, align 8 +// CHECK-NEXT: %28 = extractvalue { ptr, i64, ptr } %26, 2 +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.FreeDeferNode"(ptr %25) +// CHECK-NEXT: call void @"sync.(*WaitGroup).Done"(ptr %28) +// CHECK-NEXT: br label %_llgo_8 +// CHECK-EMPTY: +// CHECK-NEXT: _llgo_8: ; preds = %_llgo_7, %_llgo_2 +// CHECK-NEXT: %29 = load %"{{.*}}/runtime/internal/runtime.Defer", ptr %5, align 8 +// CHECK-NEXT: %30 = extractvalue %"{{.*}}/runtime/internal/runtime.Defer" %29, 2 +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.SetThreadDefer"(ptr %30) +// CHECK-NEXT: %31 = load ptr, ptr %12, align 8 +// CHECK-NEXT: indirectbr ptr %31, [label %_llgo_3, label %_llgo_6] +// CHECK-NEXT: } + +// CHECK-LABEL: define void @"main.main$2"(ptr {{(nest|swiftself)}} %0){{.*}} { +// CHECK-NEXT: _llgo_0: +// CHECK-NEXT: %1 = load { ptr }, ptr %0, align 8 +// CHECK-NEXT: %2 = extractvalue { ptr } %1, 0 +// CHECK-NEXT: %3 = call ptr @"{{.*}}/runtime/internal/runtime.GetThreadDefer"() +// CHECK-NEXT: %4 = alloca i8 +// CHECK-NEXT: %5 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 48) +// CHECK-NEXT: %6 = getelementptr inbounds %"{{.*}}/runtime/internal/runtime.Defer", ptr %5, i32 0, i32 0 +// CHECK-NEXT: store ptr %4, ptr %6, align 8 +// CHECK-NEXT: %7 = getelementptr inbounds %"{{.*}}/runtime/internal/runtime.Defer", ptr %5, i32 0, i32 1 +// CHECK-NEXT: store i64 0, ptr %7, align 8 +// CHECK-NEXT: %8 = getelementptr inbounds %"{{.*}}/runtime/internal/runtime.Defer", ptr %5, i32 0, i32 2 +// CHECK-NEXT: store ptr %3, ptr %8, align 8 +// CHECK-NEXT: %9 = getelementptr inbounds %"{{.*}}/runtime/internal/runtime.Defer", ptr %5, i32 0, i32 3 +// CHECK-NEXT: store ptr blockaddress(@"main.main$2", %_llgo_2), ptr %9, align 8 +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.SetThreadDefer"(ptr %5) +// CHECK-NEXT: %10 = getelementptr inbounds %"{{.*}}/runtime/internal/runtime.Defer", ptr %5, i32 0, i32 1 +// CHECK-NEXT: %11 = getelementptr inbounds %"{{.*}}/runtime/internal/runtime.Defer", ptr %5, i32 0, i32 3 +// CHECK-NEXT: %12 = getelementptr inbounds %"{{.*}}/runtime/internal/runtime.Defer", ptr %5, i32 0, i32 4 +// CHECK-NEXT: %13 = getelementptr inbounds %"{{.*}}/runtime/internal/runtime.Defer", ptr %5, i32 0, i32 5 +// CHECK-NEXT: store ptr null, ptr %13, align 8 +// CHECK-NEXT: %14 = call i32 @{{(__)?}}sigsetjmp(ptr %4, i32 0) +// CHECK-NEXT: %15 = icmp eq i32 %14, 0 +// CHECK-NEXT: br i1 %15, label %_llgo_4, label %_llgo_5 +// CHECK-EMPTY: +// CHECK-NEXT: _llgo_1: ; preds = %_llgo_3 +// CHECK-NEXT: ret void +// CHECK-EMPTY: +// CHECK-NEXT: _llgo_2: ; preds = %_llgo_5, %_llgo_4 +// CHECK-NEXT: store ptr blockaddress(@"main.main$2", %_llgo_3), ptr %11, align 8 +// CHECK-NEXT: %16 = load i64, ptr %10, align 8 +// CHECK-NEXT: %17 = load ptr, ptr %13, align 8 +// CHECK-NEXT: %18 = icmp ne ptr %17, null +// CHECK-NEXT: br i1 %18, label %_llgo_7, label %_llgo_8 +// CHECK-EMPTY: +// CHECK-NEXT: _llgo_3: ; preds = %_llgo_5, %_llgo_8 +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.Rethrow"(ptr %3) +// CHECK-NEXT: br label %_llgo_1 +// CHECK-EMPTY: +// CHECK-NEXT: _llgo_4: ; preds = %_llgo_0 +// CHECK-NEXT: %19 = load ptr, ptr %13, align 8 +// CHECK-NEXT: %20 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 24) +// CHECK-NEXT: %21 = getelementptr inbounds { ptr, i64, ptr }, ptr %20, i32 0, i32 0 +// CHECK-NEXT: store ptr %19, ptr %21, align 8 +// CHECK-NEXT: %22 = getelementptr inbounds { ptr, i64, ptr }, ptr %20, i32 0, i32 1 +// CHECK-NEXT: store i64 0, ptr %22, align 8 +// CHECK-NEXT: %23 = getelementptr inbounds { ptr, i64, ptr }, ptr %20, i32 0, i32 2 +// CHECK-NEXT: store ptr %2, ptr %23, align 8 +// CHECK-NEXT: store ptr %20, ptr %13, align 8 +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.PrintString"(%"{{.*}}/runtime/internal/runtime.String" { ptr @{{[0-9]+}}, i64 6 }) +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.PrintByte"(i8 10) +// CHECK-NEXT: store ptr blockaddress(@"main.main$2", %_llgo_6), ptr %12, align 8 +// CHECK-NEXT: br label %_llgo_2 +// CHECK-EMPTY: +// CHECK-NEXT: _llgo_5: ; preds = %_llgo_0 +// CHECK-NEXT: store ptr blockaddress(@"main.main$2", %_llgo_3), ptr %12, align 8 +// CHECK-NEXT: %24 = load ptr, ptr %11, align 8 +// CHECK-NEXT: indirectbr ptr %24, [label %_llgo_3, label %_llgo_2] +// CHECK-EMPTY: +// CHECK-NEXT: _llgo_6: ; preds = %_llgo_8 +// CHECK-NEXT: ret void +// CHECK-EMPTY: +// CHECK-NEXT: _llgo_7: ; preds = %_llgo_2 +// CHECK-NEXT: %25 = load ptr, ptr %13, align 8 +// CHECK-NEXT: %26 = load { ptr, i64, ptr }, ptr %25, align 8 +// CHECK-NEXT: %27 = extractvalue { ptr, i64, ptr } %26, 0 +// CHECK-NEXT: store ptr %27, ptr %13, align 8 +// CHECK-NEXT: %28 = extractvalue { ptr, i64, ptr } %26, 2 +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.FreeDeferNode"(ptr %25) +// CHECK-NEXT: call void @"sync.(*WaitGroup).Done"(ptr %28) +// CHECK-NEXT: br label %_llgo_8 +// CHECK-EMPTY: +// CHECK-NEXT: _llgo_8: ; preds = %_llgo_7, %_llgo_2 +// CHECK-NEXT: %29 = load %"{{.*}}/runtime/internal/runtime.Defer", ptr %5, align 8 +// CHECK-NEXT: %30 = extractvalue %"{{.*}}/runtime/internal/runtime.Defer" %29, 2 +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.SetThreadDefer"(ptr %30) +// CHECK-NEXT: %31 = load ptr, ptr %12, align 8 +// CHECK-NEXT: indirectbr ptr %31, [label %_llgo_3, label %_llgo_6] +// CHECK-NEXT: } + +// CHECK-LABEL: define ptr @"main._llgo_routine$1"(ptr %0){{.*}} { +// CHECK-NEXT: _llgo_0: +// CHECK-NEXT: %1 = alloca %"{{.*}}/runtime/internal/runtime.LocalContext", align 8 +// CHECK-NEXT: call void @llvm.memset.p0.i64(ptr %1, i8 0, i64 8, i1 false) +// CHECK-NEXT: %2 = call i64 @"{{.*}}/runtime/internal/runtime.EnterLocalContext"(ptr %1) +// CHECK-NEXT: %3 = load { { ptr, ptr } }, ptr %0, align 8 +// CHECK-NEXT: %4 = extractvalue { { ptr, ptr } } %3, 0 +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.FreeRoot"(ptr %0) +// CHECK-NEXT: %5 = extractvalue { ptr, ptr } %4, 1 +// CHECK-NEXT: %6 = extractvalue { ptr, ptr } %4, 0 +// CHECK-NEXT: %__llgo_funcval_code = call ptr asm "", "=r,0"(ptr %6) +// CHECK-NEXT: call void %__llgo_funcval_code(ptr {{(nest|swiftself)}} %5) +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.LeaveLocalContext"(ptr %1, i64 %2) +// CHECK-NEXT: ret ptr null +// CHECK-NEXT: } + +// CHECK-LABEL: define ptr @"main._llgo_routine$2"(ptr %0){{.*}} { +// CHECK-NEXT: _llgo_0: +// CHECK-NEXT: %1 = alloca %"{{.*}}/runtime/internal/runtime.LocalContext", align 8 +// CHECK-NEXT: call void @llvm.memset.p0.i64(ptr %1, i8 0, i64 8, i1 false) +// CHECK-NEXT: %2 = call i64 @"{{.*}}/runtime/internal/runtime.EnterLocalContext"(ptr %1) +// CHECK-NEXT: %3 = load { { ptr, ptr } }, ptr %0, align 8 +// CHECK-NEXT: %4 = extractvalue { { ptr, ptr } } %3, 0 +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.FreeRoot"(ptr %0) +// CHECK-NEXT: %5 = extractvalue { ptr, ptr } %4, 1 +// CHECK-NEXT: %6 = extractvalue { ptr, ptr } %4, 0 +// CHECK-NEXT: %__llgo_funcval_code = call ptr asm "", "=r,0"(ptr %6) +// CHECK-NEXT: call void %__llgo_funcval_code(ptr {{(nest|swiftself)}} %5) +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.LeaveLocalContext"(ptr %1, i64 %2) +// CHECK-NEXT: ret ptr null +// CHECK-NEXT: } diff --git a/cl/_testrt/nextblock/in.go b/cl/_testrt/nextblock/in.go index c2d2f973e7..3c5046175a 100644 --- a/cl/_testrt/nextblock/in.go +++ b/cl/_testrt/nextblock/in.go @@ -1,10 +1,7 @@ // LITTEST package main -// CHECK-DAG: define void @main.main(){{.*}} { -// CHECK-DAG: call ptr @"{{.*}}/runtime/internal/runtime.GetThreadDefer"() -// CHECK-DAG: call i32 @{{.*}}setjmp(ptr %{{.*}}{{.*}}) -// CHECK-DAG: call void @"{{.*}}/runtime/internal/runtime.Rethrow"(ptr %{{.*}}) +// CHECK: {{^}}@{{[0-9]+}} = private unnamed_addr constant [3 x i8] c"bye", align 1{{$}} func main() { syms := []int{} @@ -14,3 +11,128 @@ func main() { for range syms { } } + +// CHECK-LABEL: define void @main.init(){{.*}} { +// CHECK-NEXT: _llgo_0: +// CHECK-NEXT: %0 = load i1, ptr @"main.init$guard", align 1 +// CHECK-NEXT: br i1 %0, label %_llgo_2, label %_llgo_1 +// CHECK-EMPTY: +// CHECK-NEXT: _llgo_1: ; preds = %_llgo_0 +// CHECK-NEXT: store i1 true, ptr @"main.init$guard", align 1 +// CHECK-NEXT: br label %_llgo_2 +// CHECK-EMPTY: +// CHECK-NEXT: _llgo_2: ; preds = %_llgo_1, %_llgo_0 +// CHECK-NEXT: ret void +// CHECK-NEXT: } + +// CHECK-LABEL: define void @main.main(){{.*}} { +// CHECK-NEXT: _llgo_0: +// CHECK-NEXT: %0 = call ptr @"{{.*}}/runtime/internal/runtime.GetThreadDefer"() +// CHECK-NEXT: %1 = alloca i8 +// CHECK-NEXT: %2 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 48) +// CHECK-NEXT: %3 = getelementptr inbounds %"{{.*}}/runtime/internal/runtime.Defer", ptr %2, i32 0, i32 0 +// CHECK-NEXT: store ptr %1, ptr %3, align 8 +// CHECK-NEXT: %4 = getelementptr inbounds %"{{.*}}/runtime/internal/runtime.Defer", ptr %2, i32 0, i32 1 +// CHECK-NEXT: store i64 0, ptr %4, align 8 +// CHECK-NEXT: %5 = getelementptr inbounds %"{{.*}}/runtime/internal/runtime.Defer", ptr %2, i32 0, i32 2 +// CHECK-NEXT: store ptr %0, ptr %5, align 8 +// CHECK-NEXT: %6 = getelementptr inbounds %"{{.*}}/runtime/internal/runtime.Defer", ptr %2, i32 0, i32 3 +// CHECK-NEXT: store ptr blockaddress(@main.main, %_llgo_9), ptr %6, align 8 +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.SetThreadDefer"(ptr %2) +// CHECK-NEXT: %7 = getelementptr inbounds %"{{.*}}/runtime/internal/runtime.Defer", ptr %2, i32 0, i32 1 +// CHECK-NEXT: %8 = getelementptr inbounds %"{{.*}}/runtime/internal/runtime.Defer", ptr %2, i32 0, i32 3 +// CHECK-NEXT: %9 = getelementptr inbounds %"{{.*}}/runtime/internal/runtime.Defer", ptr %2, i32 0, i32 4 +// CHECK-NEXT: %10 = getelementptr inbounds %"{{.*}}/runtime/internal/runtime.Defer", ptr %2, i32 0, i32 5 +// CHECK-NEXT: store ptr null, ptr %10, align 8 +// CHECK-NEXT: %11 = call i32 @{{(__)?}}sigsetjmp(ptr %1, i32 0) +// CHECK-NEXT: %12 = icmp eq i32 %11, 0 +// CHECK-NEXT: br i1 %12, label %_llgo_8, label %_llgo_11 +// CHECK-EMPTY: +// CHECK-NEXT: _llgo_1: ; preds = %_llgo_2, %_llgo_8 +// CHECK-NEXT: %13 = phi i64 [ -1, %_llgo_8 ], [ %14, %_llgo_2 ] +// CHECK-NEXT: %14 = add i64 %13, 1 +// CHECK-NEXT: %15 = icmp slt i64 %14, 0 +// CHECK-NEXT: br i1 %15, label %_llgo_2, label %_llgo_3 +// CHECK-EMPTY: +// CHECK-NEXT: _llgo_2: ; preds = %_llgo_1 +// CHECK-NEXT: br label %_llgo_1 +// CHECK-EMPTY: +// CHECK-NEXT: _llgo_3: ; preds = %_llgo_1 +// CHECK-NEXT: %16 = load i64, ptr %7, align 8 +// CHECK-NEXT: %17 = or i64 %16, 1 +// CHECK-NEXT: store i64 %17, ptr %7, align 8 +// CHECK-NEXT: %18 = load ptr, ptr %10, align 8 +// CHECK-NEXT: %19 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 32) +// CHECK-NEXT: %20 = getelementptr inbounds { ptr, i64, %"{{.*}}/runtime/internal/runtime.String" }, ptr %19, i32 0, i32 0 +// CHECK-NEXT: store ptr %18, ptr %20, align 8 +// CHECK-NEXT: %21 = getelementptr inbounds { ptr, i64, %"{{.*}}/runtime/internal/runtime.String" }, ptr %19, i32 0, i32 1 +// CHECK-NEXT: store i64 0, ptr %21, align 8 +// CHECK-NEXT: %22 = getelementptr inbounds { ptr, i64, %"{{.*}}/runtime/internal/runtime.String" }, ptr %19, i32 0, i32 2 +// CHECK-NEXT: store %"{{.*}}/runtime/internal/runtime.String" { ptr @{{[0-9]+}}, i64 3 }, ptr %22, align 8 +// CHECK-NEXT: store ptr %19, ptr %10, align 8 +// CHECK-NEXT: br label %_llgo_5 +// CHECK-EMPTY: +// CHECK-NEXT: _llgo_4: ; preds = %_llgo_10 +// CHECK-NEXT: ret void +// CHECK-EMPTY: +// CHECK-NEXT: _llgo_5: ; preds = %_llgo_6, %_llgo_3 +// CHECK-NEXT: %23 = phi i64 [ -1, %_llgo_3 ], [ %24, %_llgo_6 ] +// CHECK-NEXT: %24 = add i64 %23, 1 +// CHECK-NEXT: %25 = icmp slt i64 %24, 0 +// CHECK-NEXT: br i1 %25, label %_llgo_6, label %_llgo_7 +// CHECK-EMPTY: +// CHECK-NEXT: _llgo_6: ; preds = %_llgo_5 +// CHECK-NEXT: br label %_llgo_5 +// CHECK-EMPTY: +// CHECK-NEXT: _llgo_7: ; preds = %_llgo_5 +// CHECK-NEXT: store ptr blockaddress(@main.main, %_llgo_12), ptr %9, align 8 +// CHECK-NEXT: br label %_llgo_9 +// CHECK-EMPTY: +// CHECK-NEXT: _llgo_8: ; preds = %_llgo_0 +// CHECK-NEXT: br label %_llgo_1 +// CHECK-EMPTY: +// CHECK-NEXT: _llgo_9: ; preds = %_llgo_11, %_llgo_7 +// CHECK-NEXT: store ptr blockaddress(@main.main, %_llgo_10), ptr %8, align 8 +// CHECK-NEXT: %26 = load i64, ptr %7, align 8 +// CHECK-NEXT: %27 = and i64 %26, 1 +// CHECK-NEXT: %28 = icmp ne i64 %27, 0 +// CHECK-NEXT: br i1 %28, label %_llgo_13, label %_llgo_14 +// CHECK-EMPTY: +// CHECK-NEXT: _llgo_10: ; preds = %_llgo_11, %_llgo_14 +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.Rethrow"(ptr %0) +// CHECK-NEXT: br label %_llgo_4 +// CHECK-EMPTY: +// CHECK-NEXT: _llgo_11: ; preds = %_llgo_0 +// CHECK-NEXT: store ptr blockaddress(@main.main, %_llgo_10), ptr %9, align 8 +// CHECK-NEXT: %29 = load ptr, ptr %8, align 8 +// CHECK-NEXT: indirectbr ptr %29, [label %_llgo_10, label %_llgo_9] +// CHECK-EMPTY: +// CHECK-NEXT: _llgo_12: ; preds = %_llgo_14 +// CHECK-NEXT: ret void +// CHECK-EMPTY: +// CHECK-NEXT: _llgo_13: ; preds = %_llgo_9 +// CHECK-NEXT: %30 = load ptr, ptr %10, align 8 +// CHECK-NEXT: %31 = icmp ne ptr %30, null +// CHECK-NEXT: br i1 %31, label %_llgo_15, label %_llgo_16 +// CHECK-EMPTY: +// CHECK-NEXT: _llgo_14: ; preds = %_llgo_16, %_llgo_9 +// CHECK-NEXT: %32 = load %"{{.*}}/runtime/internal/runtime.Defer", ptr %2, align 8 +// CHECK-NEXT: %33 = extractvalue %"{{.*}}/runtime/internal/runtime.Defer" %32, 2 +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.SetThreadDefer"(ptr %33) +// CHECK-NEXT: %34 = load ptr, ptr %9, align 8 +// CHECK-NEXT: indirectbr ptr %34, [label %_llgo_10, label %_llgo_12] +// CHECK-EMPTY: +// CHECK-NEXT: _llgo_15: ; preds = %_llgo_13 +// CHECK-NEXT: %35 = load ptr, ptr %10, align 8 +// CHECK-NEXT: %36 = load { ptr, i64, %"{{.*}}/runtime/internal/runtime.String" }, ptr %35, align 8 +// CHECK-NEXT: %37 = extractvalue { ptr, i64, %"{{.*}}/runtime/internal/runtime.String" } %36, 0 +// CHECK-NEXT: store ptr %37, ptr %10, align 8 +// CHECK-NEXT: %38 = extractvalue { ptr, i64, %"{{.*}}/runtime/internal/runtime.String" } %36, 2 +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.FreeDeferNode"(ptr %35) +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.PrintString"(%"{{.*}}/runtime/internal/runtime.String" %38) +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.PrintByte"(i8 10) +// CHECK-NEXT: br label %_llgo_16 +// CHECK-EMPTY: +// CHECK-NEXT: _llgo_16: ; preds = %_llgo_15, %_llgo_13 +// CHECK-NEXT: br label %_llgo_14 +// CHECK-NEXT: } From 022f3ed416e26aab5233bfd330446c8cb26b848c Mon Sep 17 00:00:00 2001 From: Li Jie Date: Sat, 1 Aug 2026 19:55:33 +0800 Subject: [PATCH 66/73] build: schedule package initialization in Go order --- cl/builtin_test.go | 6 ++ cl/import.go | 6 ++ cl/instr.go | 2 +- internal/build/build.go | 5 + internal/build/init_order.go | 123 +++++++++++++++++++++++ internal/build/main_module.go | 49 ++++++--- internal/build/main_module_test.go | 154 ++++++++++++++++++++++++++++- test/go/package_init_order_test.go | 119 ++++++++++++++++++++++ test/goroot/xfail.yaml | 33 ------- 9 files changed, 446 insertions(+), 51 deletions(-) create mode 100644 internal/build/init_order.go create mode 100644 test/go/package_init_order_test.go diff --git a/cl/builtin_test.go b/cl/builtin_test.go index 3fa2161aac..211becc7a4 100644 --- a/cl/builtin_test.go +++ b/cl/builtin_test.go @@ -652,6 +652,12 @@ func TestPkgKindOf(t *testing.T) { if v, _ := PkgKindOf(pkg); v != PkgNoInit { t.Fatal("PkgKindOf foo:", v) } + if PkgSkipsInit(PkgNormal) { + t.Fatal("normal package skips initialization") + } + if !PkgSkipsInit(PkgNoInit) || !PkgSkipsInit(PkgDeclOnly) { + t.Fatal("noinit/decl-only package does not skip initialization") + } } func TestIsAny(t *testing.T) { diff --git a/cl/import.go b/cl/import.go index 728d162049..00d39540db 100644 --- a/cl/import.go +++ b/cl/import.go @@ -96,6 +96,12 @@ func PkgKindOf(pkg *types.Package) (int, string) { return kind, param } +// PkgSkipsInit reports whether packages of kind are excluded from Go package +// initialization. +func PkgSkipsInit(kind int) bool { + return kind >= PkgNoInit +} + // decl: a package that only contains declarations // noinit: a package that does not need to be initialized func pkgKind(v string) (int, string) { diff --git a/cl/instr.go b/cl/instr.go index 4b52624f1b..9cd70333ef 100644 --- a/cl/instr.go +++ b/cl/instr.go @@ -708,7 +708,7 @@ func (p *context) funcKind(vfn ssa.Value) int { func (p *context) pkgNoInit(pkg *types.Package) bool { p.ensureLoaded(pkg) if i, ok := p.loaded[pkg]; ok { - return i.kind >= PkgNoInit + return PkgSkipsInit(i.kind) } return false } diff --git a/internal/build/build.go b/internal/build/build.go index 4e3ae2a499..9cc84fa4bf 100644 --- a/internal/build/build.go +++ b/internal/build/build.go @@ -1392,10 +1392,15 @@ func linkMainPkg(ctx *context, pkg *packages.Package, pkgs []*aPackage, outputPa funcInfo = prepareFuncInfoTableRecords(collectFuncInfo(linkedOrder), nil) pcLineInfo = collectPCLineInfo(linkedOrder) } + packageInits, err := linkedPackageInitNames(pkg, linkedOrder) + if err != nil { + return err + } entryPkg := genMainModule(ctx, llssa.PkgRuntime, pkg, &genConfig{ rtInit: needRuntime, pyInit: needPyInit, abiInit: needAbiInit, + packageInits: packageInits, methodByIndex: methodByIndex, methodByName: methodByName, abiSymbols: linkedModuleGlobals(linkedOrder), diff --git a/internal/build/init_order.go b/internal/build/init_order.go new file mode 100644 index 0000000000..cc28cc4d51 --- /dev/null +++ b/internal/build/init_order.go @@ -0,0 +1,123 @@ +//go:build !llgo +// +build !llgo + +/* + * Copyright (c) 2026 The XGo Authors (xgo.dev). All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package build + +import ( + "fmt" + "sort" + + "github.com/goplus/llgo/cl" + "github.com/goplus/llgo/internal/packages" + llssa "github.com/goplus/llgo/ssa" +) + +// packageInitOrder returns the packages reachable from root in the order in +// which Go initializes them: among packages whose imports are initialized, +// choose the one with the lexicographically first import path. +func packageInitOrder(root *packages.Package) ([]*packages.Package, error) { + if root == nil { + return nil, nil + } + + seen := make(map[*packages.Package]bool) + var all []*packages.Package + var collect func(*packages.Package) + collect = func(pkg *packages.Package) { + if pkg == nil || seen[pkg] { + return + } + seen[pkg] = true + all = append(all, pkg) + for _, imported := range pkg.Imports { + collect(imported) + } + } + collect(root) + sort.Slice(all, func(i, j int) bool { + if all[i].PkgPath != all[j].PkgPath { + return all[i].PkgPath < all[j].PkgPath + } + return all[i].ID < all[j].ID + }) + + remaining := make(map[*packages.Package]int, len(all)) + importers := make(map[*packages.Package][]*packages.Package, len(all)) + for _, pkg := range all { + imports := make(map[*packages.Package]bool, len(pkg.Imports)) + for _, imported := range pkg.Imports { + if imported == nil || !seen[imported] || imports[imported] { + continue + } + imports[imported] = true + remaining[pkg]++ + importers[imported] = append(importers[imported], pkg) + } + } + + order := make([]*packages.Package, 0, len(all)) + initialized := make(map[*packages.Package]bool, len(all)) + for len(order) != len(all) { + var next *packages.Package + for _, pkg := range all { + if !initialized[pkg] && remaining[pkg] == 0 { + next = pkg + break + } + } + if next == nil { + return nil, fmt.Errorf("package initialization graph rooted at %s contains a cycle", root.PkgPath) + } + initialized[next] = true + order = append(order, next) + for _, importer := range importers[next] { + remaining[importer]-- + } + } + return order, nil +} + +func linkedPackageInitNames(root *packages.Package, linked []Package) ([]string, error) { + order, err := packageInitOrder(root) + if err != nil { + return nil, err + } + builtByID := make(map[string]Package, len(linked)) + for _, pkg := range linked { + if pkg != nil && pkg.Package != nil { + builtByID[pkg.ID] = pkg + } + } + + names := make([]string, 0, len(order)) + for _, pkg := range order { + if pkg == root { + continue + } + built := builtByID[pkg.ID] + if built == nil || built.SSA == nil || built.SSA.Func("init") == nil || pkg.Types == nil { + continue + } + if kind, _ := cl.PkgKindOf(pkg.Types); cl.PkgSkipsInit(kind) { + continue + } + names = append(names, llssa.FullName(pkg.Types, "init")) + } + return names, nil +} diff --git a/internal/build/main_module.go b/internal/build/main_module.go index 2ff9d54d0a..2693cb8ed4 100644 --- a/internal/build/main_module.go +++ b/internal/build/main_module.go @@ -39,6 +39,7 @@ type genConfig struct { rtInit bool pyInit bool abiInit int + packageInits []string methodByIndex map[int]none methodByName map[string]none abiSymbols map[string]none @@ -110,6 +111,11 @@ func genMainModule(ctx *context, rtPkgPath string, pkg *packages.Package, cfg *g mainInit := declareNoArgFunc(mainPkg, pkgPath+".init") mainMain := declareNoArgFunc(mainPkg, pkgPath+".main") + packageInits := make([]llssa.Function, len(cfg.packageInits)) + for i, name := range cfg.packageInits { + packageInits[i] = declareNoArgFunc(mainPkg, name) + } + defineRootInitTask(mainPkg, pkgPath) if ctx.buildConf.BuildMode != BuildModeExe { initArraySection := "" @@ -120,6 +126,7 @@ func genMainModule(ctx *context, rtPkgPath string, pkg *packages.Package, cfg *g // The C test runner supplies argc/argv before calling the generated // test main package's init and main functions. if ctx.mode != ModeTest { + inits = append(inits, packageInits...) inits = append(inits, mainInit) } defineLibraryRuntimeInit(mainPkg, initArraySection, inits...) @@ -127,13 +134,14 @@ func genMainModule(ctx *context, rtPkgPath string, pkg *packages.Package, cfg *g } entryFn := defineEntryFunction(ctx, mainPkg, argcVar, argvVar, argvValueType, entryFunctions{ - runtimeStub: runtimeStub, - mainInit: mainInit, - mainMain: mainMain, - pyInit: pyInit, - pyFinalize: pyFinalize, - rtInit: rtInit, - abiInit: abiInit, + runtimeStub: runtimeStub, + mainInit: mainInit, + mainMain: mainMain, + pyInit: pyInit, + pyFinalize: pyFinalize, + rtInit: rtInit, + abiInit: abiInit, + packageInits: packageInits, }) if needStart(ctx) { @@ -221,13 +229,14 @@ func filterAbiSymbol(abiInit int, sym *llssa.AbiSymbol) bool { } type entryFunctions struct { - runtimeStub llssa.Function - mainInit llssa.Function - mainMain llssa.Function - pyInit llssa.Function - pyFinalize llssa.Function - rtInit llssa.Function - abiInit llssa.Function + runtimeStub llssa.Function + mainInit llssa.Function + mainMain llssa.Function + pyInit llssa.Function + pyFinalize llssa.Function + rtInit llssa.Function + abiInit llssa.Function + packageInits []llssa.Function } // defineEntryFunction creates the program's entry function. The name is @@ -271,6 +280,9 @@ func defineEntryFunction(ctx *context, pkg llssa.Package, argcVar, argvVar llssa b.Call(fns.abiInit.Expr) } b.Call(fns.runtimeStub.Expr) + for _, init := range fns.packageInits { + b.Call(init.Expr) + } b.Call(fns.mainInit.Expr) b.Call(fns.mainMain.Expr) if fns.pyFinalize != nil { @@ -296,6 +308,15 @@ func declareNoArgFunc(pkg llssa.Package, name string) llssa.Function { return pkg.NewFunc(name, llssa.NoArgsNoRet, llssa.InC) } +// defineRootInitTask exposes the header of the compiler-generated Go init task. +// LLGo runs package initialization through guarded package init functions, so +// there are no runtime-dispatched function entries in this compatibility task. +func defineRootInitTask(pkg llssa.Package, pkgPath string) { + prog := pkg.Prog + taskType := prog.Struct(prog.Uint32(), prog.Uint32()) + pkg.NewVarEx(pkgPath+"..inittask", prog.Pointer(taskType)).InitNil() +} + func defineWeakNoArgStub(pkg llssa.Package, name string) llssa.Function { fn := pkg.NewFunc(name, llssa.NoArgsNoRet, llssa.InC) pkg.Module().NamedFunction(name).SetLinkage(llvm.WeakAnyLinkage) diff --git a/internal/build/main_module_test.go b/internal/build/main_module_test.go index 4e0b16c907..a3e3bcf73d 100644 --- a/internal/build/main_module_test.go +++ b/internal/build/main_module_test.go @@ -4,8 +4,10 @@ package build import ( + "go/constant" "go/token" "go/types" + "slices" "strings" "testing" @@ -13,6 +15,7 @@ import ( "github.com/goplus/llgo/internal/packages" llssa "github.com/goplus/llgo/ssa" + "golang.org/x/tools/go/ssa" ) func init() { @@ -32,7 +35,7 @@ func TestGenMainModuleExecutable(t *testing.T) { } pkg := &packages.Package{PkgPath: "example.com/foo", ExportFile: "foo.a"} mod := genMainModule(ctx, llssa.PkgRuntime, pkg, - &genConfig{rtInit: true, pyInit: true}) + &genConfig{rtInit: true, pyInit: true, packageInits: []string{"example.com/b.init", "example.com/z.init", "example.com/a.init"}}) if mod.ExportFile != "foo.a-main" { t.Fatalf("unexpected export file: %s", mod.ExportFile) } @@ -42,6 +45,7 @@ func TestGenMainModuleExecutable(t *testing.T) { "call void @Py_Initialize()", "call void @Py_Finalize()", "call void @\"example.com/foo.init\"()", + `@"example.com/foo..inittask" = global { i32, i32 } zeroinitializer`, "define weak void @_start()", } for _, want := range checks { @@ -51,12 +55,146 @@ func TestGenMainModuleExecutable(t *testing.T) { } assertInOrder(t, ir, "call void @Py_Initialize()", + `call void @"example.com/b.init"()`, + `call void @"example.com/z.init"()`, + `call void @"example.com/a.init"()`, "call void @\"example.com/foo.init\"()", "call void @\"example.com/foo.main\"()", "call void @Py_Finalize()", ) } +func TestPackageInitOrderUsesLexicalReadyPackage(t *testing.T) { + newPackage := func(path string, imports ...*packages.Package) *packages.Package { + pkg := &packages.Package{ID: path, PkgPath: path, Imports: make(map[string]*packages.Package)} + for _, imported := range imports { + pkg.Imports[imported.PkgPath] = imported + } + return pkg + } + z := newPackage("example.com/z") + a := newPackage("example.com/a", z) + b := newPackage("example.com/b") + root := newPackage("example.com/main", a, b) + + order, err := packageInitOrder(root) + if err != nil { + t.Fatal(err) + } + got := make([]string, len(order)) + for i, pkg := range order { + got[i] = pkg.PkgPath + } + want := []string{"example.com/b", "example.com/z", "example.com/a", "example.com/main"} + if !slices.Equal(got, want) { + t.Fatalf("package init order = %v, want %v", got, want) + } +} + +func TestPackageInitOrderEdgeCases(t *testing.T) { + if order, err := packageInitOrder(nil); err != nil || order != nil { + t.Fatalf("nil root order = %v, %v, want nil, nil", order, err) + } + + first := &packages.Package{ID: "first", PkgPath: "example.com/same"} + second := &packages.Package{ID: "second", PkgPath: "example.com/same"} + root := &packages.Package{ + ID: "root", + PkgPath: "example.com/root", + Imports: map[string]*packages.Package{ + "alias/first": first, + "first": first, + "nil": nil, + "second": second, + }, + } + order, err := packageInitOrder(root) + if err != nil { + t.Fatal(err) + } + got := make([]string, len(order)) + for i, pkg := range order { + got[i] = pkg.ID + } + if want := []string{"first", "second", "root"}; !slices.Equal(got, want) { + t.Fatalf("package init order = %v, want %v", got, want) + } + + a := &packages.Package{ID: "a", PkgPath: "example.com/a", Imports: make(map[string]*packages.Package)} + b := &packages.Package{ID: "b", PkgPath: "example.com/b", Imports: map[string]*packages.Package{"a": a}} + a.Imports["b"] = b + if _, err := packageInitOrder(a); err == nil || !strings.Contains(err.Error(), "contains a cycle") { + t.Fatalf("cyclic package order error = %v, want cycle error", err) + } +} + +func TestLinkedPackageInitNamesFiltersUnavailablePackages(t *testing.T) { + newPackage := func(id string) *packages.Package { + path := "example.com/" + id + return &packages.Package{ID: id, PkgPath: path, Types: types.NewPackage(path, id)} + } + root := newPackage("root") + normal := newPackage("normal") + noinit := newPackage("noinit") + noinit.Types.Scope().Insert(types.NewConst(token.NoPos, noinit.Types, "LLGoPackage", types.Typ[types.String], constant.MakeString("noinit"))) + missingBuilt := newPackage("missing-built") + missingSSA := newPackage("missing-ssa") + missingInit := newPackage("missing-init") + missingTypes := &packages.Package{ID: "missing-types", PkgPath: "example.com/missing-types"} + root.Imports = map[string]*packages.Package{ + "normal": normal, + "noinit": noinit, + "missing-built": missingBuilt, + "missing-ssa": missingSSA, + "missing-init": missingInit, + "missing-types": missingTypes, + } + + ssaProg := ssa.NewProgram(token.NewFileSet(), 0) + normalSSA := ssaProg.CreatePackage(normal.Types, nil, nil, true) + noinitSSA := ssaProg.CreatePackage(noinit.Types, nil, nil, true) + if normalSSA.Func("init") == nil || noinitSSA.Func("init") == nil { + t.Fatal("test SSA packages are missing synthetic init functions") + } + missingInitSSA := &ssa.Package{Members: make(map[string]ssa.Member)} + + linked := []Package{ + nil, + &aPackage{}, + {Package: normal, SSA: normalSSA}, + {Package: noinit, SSA: noinitSSA}, + {Package: missingSSA}, + {Package: missingInit, SSA: missingInitSSA}, + {Package: missingTypes, SSA: normalSSA}, + } + names, err := linkedPackageInitNames(root, linked) + if err != nil { + t.Fatal(err) + } + if want := []string{"example.com/normal.init"}; !slices.Equal(names, want) { + t.Fatalf("linked init names = %v, want %v", names, want) + } + + cycle := &packages.Package{ID: "cycle", PkgPath: "example.com/cycle", Imports: make(map[string]*packages.Package)} + cycle.Imports["self"] = cycle + if _, err := linkedPackageInitNames(cycle, nil); err == nil { + t.Fatal("linkedPackageInitNames accepted an import cycle") + } +} + +func TestLinkMainPkgRejectsPackageInitCycle(t *testing.T) { + cycle := &packages.Package{ID: "cycle", PkgPath: "example.com/cycle", Imports: make(map[string]*packages.Package)} + cycle.Imports["self"] = cycle + ctx := &context{ + buildConf: &Config{}, + pkgs: make(map[*packages.Package]Package), + pkgByID: make(map[string]Package), + } + if err := linkMainPkg(ctx, cycle, nil, "", false); err == nil || !strings.Contains(err.Error(), "contains a cycle") { + t.Fatalf("linkMainPkg cycle error = %v, want cycle error", err) + } +} + func TestGenMainModuleLibrary(t *testing.T) { llvm.InitializeAllTargets() t.Setenv(llgoStdioNobuf, "") @@ -96,11 +234,15 @@ func TestGenMainModuleLibraryInitializesRuntime(t *testing.T) { }, } pkg := &packages.Package{PkgPath: "example.com/foo", ExportFile: "foo.a"} - mod := genMainModule(ctx, llssa.PkgRuntime, pkg, &genConfig{rtInit: true}) + mod := genMainModule(ctx, llssa.PkgRuntime, pkg, &genConfig{ + rtInit: true, + packageInits: []string{"example.com/dep.init"}, + }) ir := mod.LPkg.String() checks := []string{ "define internal void @__llgo_runtime_ctor()", "call void @\"github.com/goplus/llgo/runtime/internal/runtime.init\"()", + "call void @\"example.com/dep.init\"()", "call void @\"example.com/foo.init\"()", } if mode == BuildModeCShared { @@ -136,7 +278,10 @@ func TestGenMainModuleTestLibraryDefersMainInit(t *testing.T) { }, } pkg := &packages.Package{PkgPath: "example.com/foo", ExportFile: "foo.a"} - mod := genMainModule(ctx, llssa.PkgRuntime, pkg, &genConfig{rtInit: true}) + mod := genMainModule(ctx, llssa.PkgRuntime, pkg, &genConfig{ + rtInit: true, + packageInits: []string{"example.com/dep.init"}, + }) ir := mod.LPkg.String() if !strings.Contains(ir, "call void @\"github.com/goplus/llgo/runtime/internal/runtime.init\"()") { t.Fatalf("test library constructor missing runtime init:\n%s", ir) @@ -144,6 +289,9 @@ func TestGenMainModuleTestLibraryDefersMainInit(t *testing.T) { if strings.Contains(ir, "call void @\"example.com/foo.init\"()") { t.Fatalf("test library constructor initialized test main before the C runner supplied argc/argv:\n%s", ir) } + if strings.Contains(ir, "call void @\"example.com/dep.init\"()") { + t.Fatalf("test library constructor initialized a test dependency before the C runner supplied argc/argv:\n%s", ir) + } }) } } diff --git a/test/go/package_init_order_test.go b/test/go/package_init_order_test.go new file mode 100644 index 0000000000..0275fed500 --- /dev/null +++ b/test/go/package_init_order_test.go @@ -0,0 +1,119 @@ +/* + * Copyright (c) 2026 The XGo Authors (xgo.dev). All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package gotest + +import ( + "os" + "os/exec" + "path/filepath" + "sync" + "testing" +) + +var ( + packageInitLLGoOnce sync.Once + packageInitLLGoBin string + packageInitLLGoErr string +) + +func packageInitLLGo(t *testing.T) string { + t.Helper() + repoRoot := findStringConversionRepoRoot(t) + t.Setenv("LLGO_ROOT", repoRoot) + packageInitLLGoOnce.Do(func() { + dir, err := os.MkdirTemp("", "llgo-package-init-bin") + if err != nil { + packageInitLLGoErr = err.Error() + return + } + packageInitLLGoBin = filepath.Join(dir, "llgo") + cmd := exec.Command("go", "build", "-tags=dev", "-o", packageInitLLGoBin, "./cmd/llgo") + cmd.Dir = repoRoot + if out, err := cmd.CombinedOutput(); err != nil { + packageInitLLGoErr = err.Error() + "\n" + string(out) + } + }) + if packageInitLLGoErr != "" { + t.Fatalf("building llgo failed: %s", packageInitLLGoErr) + } + return packageInitLLGoBin +} + +func TestPackageInitializationUsesLexicalReadyOrder(t *testing.T) { + dir := t.TempDir() + files := map[string]string{ + "go.mod": "module initorder\n\ngo 1.21\n", + "tracker/tracker.go": `package tracker + +var Order []string + +func Add(name string) { Order = append(Order, name) } +`, + "z/z.go": `package z + +import "initorder/tracker" + +func init() { tracker.Add("z") } +`, + "a/a.go": `package a + +import ( + _ "initorder/z" + "initorder/tracker" +) + +func init() { tracker.Add("a") } +`, + "b/b.go": `package b + +import "initorder/tracker" + +func init() { tracker.Add("b") } +`, + "main.go": `package main + +import ( + _ "initorder/a" + _ "initorder/b" + "initorder/tracker" + "strings" +) + +func main() { + if got, want := strings.Join(tracker.Order, ","), "b,z,a"; got != want { + panic("package init order: got " + got + " want " + want) + } +} +`, + } + for name, contents := range files { + path := filepath.Join(dir, name) + if err := os.MkdirAll(filepath.Dir(path), 0o755); err != nil { + t.Fatal(err) + } + if err := os.WriteFile(path, []byte(contents), 0o644); err != nil { + t.Fatal(err) + } + } + + llgo := packageInitLLGo(t) + cmd := exec.Command(llgo, "run", ".") + cmd.Dir = dir + if out, err := cmd.CombinedOutput(); err != nil { + t.Fatalf("llgo package-init probe failed: %v\n%s", err, out) + } +} diff --git a/test/goroot/xfail.yaml b/test/goroot/xfail.yaml index 6183ce5d5e..a31dc1cc2b 100644 --- a/test/goroot/xfail.yaml +++ b/test/goroot/xfail.yaml @@ -1926,16 +1926,6 @@ xfails: directive: errorcheck case: syntax/vareq.go reason: llgo parser recovery emits additional diagnostics after the expected syntax error - - version: go1.24 - platform: darwin/arm64 - directive: run - case: init1.go - reason: current main goroot run failure on darwin/arm64 - - version: go1.25 - platform: darwin/arm64 - directive: run - case: init1.go - reason: current main goroot run failure on darwin/arm64 - version: go1.24 platform: darwin/arm64 directive: run @@ -2007,10 +1997,6 @@ xfails: directive: run case: convert5.go reason: out-of-range float-to-uint32 conversions wrap instead of producing zero on darwin/arm64 - - platform: darwin/arm64 - directive: run - case: noinit.go - reason: current main goroot run failure on darwin/arm64 - version: go1.24 platform: darwin/arm64 directive: run @@ -2089,11 +2075,6 @@ xfails: directive: run case: init1.go reason: go1.24 goroot run failure on linux/amd64 - - version: go1.24 - platform: linux/amd64 - directive: run - case: noinit.go - reason: go1.24 goroot run failure on linux/amd64 - version: go1.24 platform: linux/amd64 directive: run @@ -2159,11 +2140,6 @@ xfails: directive: run case: init1.go reason: go1.25 goroot run failure on linux/amd64 - - version: go1.25 - platform: linux/amd64 - directive: run - case: noinit.go - reason: go1.25 goroot run failure on linux/amd64 - version: go1.25 platform: linux/amd64 directive: run @@ -2214,11 +2190,6 @@ xfails: directive: run case: init1.go reason: go1.26 goroot run failure on linux/amd64 - - version: go1.26 - platform: linux/amd64 - directive: run - case: noinit.go - reason: go1.26 goroot run failure on linux/amd64 - version: go1.26 platform: linux/amd64 directive: run @@ -2954,10 +2925,6 @@ xfails: directive: rundir case: fixedbugs/issue29919.go reason: runtime CallersFrames reports llgo package names and initialization line metadata differently - - version: go1.26 - directive: rundir - case: fixedbugs/issue31636.go - reason: llgo initializes independent imported packages in reverse source order - version: go1.26 directive: rundir case: fixedbugs/issue24693.go From 7e4bcc6f751e5780cf9618b7fed273f0903af0b7 Mon Sep 17 00:00:00 2001 From: Li Jie Date: Tue, 4 Aug 2026 20:48:01 +0800 Subject: [PATCH 67/73] runtime: drain BDWGC finalizers during explicit GC --- runtime/internal/clite/bdwgc/bdwgc.go | 6 +++ runtime/internal/lib/runtime/runtime_gc.go | 16 ++++--- test/go/finalizer_llgo_test.go | 50 ++++++++++++++++++++++ 3 files changed, 67 insertions(+), 5 deletions(-) create mode 100644 test/go/finalizer_llgo_test.go diff --git a/runtime/internal/clite/bdwgc/bdwgc.go b/runtime/internal/clite/bdwgc/bdwgc.go index 9f0bec38e6..e4d9613862 100644 --- a/runtime/internal/clite/bdwgc/bdwgc.go +++ b/runtime/internal/clite/bdwgc/bdwgc.go @@ -88,6 +88,12 @@ func RegisterFinalizerUnreachable( fn FinalizerFunc, cd c.Pointer, oldFn *FinalizerFunc, oldCd *c.Pointer) +// InvokeFinalizers runs all finalizers that BDWGC has queued as ready. +// It returns the number of finalizers that were run. +// +//go:linkname InvokeFinalizers C.GC_invoke_finalizers +func InvokeFinalizers() c.Int + // ----------------------------------------------------------------------------- //go:linkname Enable C.GC_enable diff --git a/runtime/internal/lib/runtime/runtime_gc.go b/runtime/internal/lib/runtime/runtime_gc.go index d8656f93a4..7decf5579b 100644 --- a/runtime/internal/lib/runtime/runtime_gc.go +++ b/runtime/internal/lib/runtime/runtime_gc.go @@ -36,19 +36,25 @@ func ReadMemStats(m *runtime.MemStats) { } func GC() { - bdwgc.Gcollect() - runFinalizers() - // BDW finalizers are observed on a subsequent collection cycle. + collectAndRunFinalizers() // Run one extra cycle so weak-pointer cleanup hooks (unique/weak) see // finalized state before we trigger map cleanup callbacks. - bdwgc.Gcollect() - runFinalizers() + collectAndRunFinalizers() unique_runtime_notifyMapCleanup() if poolCleanup != nil { poolCleanup() } } +func collectAndRunFinalizers() { + bdwgc.Gcollect() + // GC_gcollect only discovers unreachable finalizable objects. Explicitly + // drain BDWGC's ready queue so runtime.GC does not depend on a later + // allocation to invoke the callbacks that feed runFinalizers. + bdwgc.InvokeFinalizers() + runFinalizers() +} + func saturatingSub(x, y uintptr) uintptr { if x < y { return 0 diff --git a/test/go/finalizer_llgo_test.go b/test/go/finalizer_llgo_test.go new file mode 100644 index 0000000000..611076ac3a --- /dev/null +++ b/test/go/finalizer_llgo_test.go @@ -0,0 +1,50 @@ +//go:build llgo && !baremetal && !nogc + +package gotest + +import ( + "runtime" + "testing" + _ "unsafe" +) + +//go:linkname getBDWGCFinalizeOnDemand C.GC_get_finalize_on_demand +func getBDWGCFinalizeOnDemand() int32 + +//go:linkname setBDWGCFinalizeOnDemand C.GC_set_finalize_on_demand +func setBDWGCFinalizeOnDemand(enabled int32) + +func TestRuntimeGCDrainsBDWGCFinalizersOnDemand(t *testing.T) { + // BDWGC normally may invoke ready finalizers during a later allocation. + // On-demand mode makes runtime.GC's explicit drain observable without + // relying on allocation timing. This setting is process-global, so this + // test and the neighboring finalizer tests must remain sequential. + old := getBDWGCFinalizeOnDemand() + setBDWGCFinalizeOnDemand(1) + t.Cleanup(func() { + setBDWGCFinalizeOnDemand(old) + }) + + const n = 32 + finalized := make(chan int32, n) + created := make(chan struct{}) + go func() { + makeFinalizerTinyObjects(n, finalized) + close(created) + }() + <-created + + // InvokeFinalizers runs synchronously once BDWGC has queued an object. + // The retries only let the producer goroutine exit so that conservative + // stack and register roots no longer keep the objects reachable. + for range 8 { + runtime.Gosched() + runGCWithTimeout(t) + if len(finalized) > n/2 { + return + } + } + if got := len(finalized); got <= n/2 { + t.Fatalf("runtime.GC ran only %d/%d on-demand finalizers", got, n) + } +} From 880b903088c1a41b2f17d540f22c82a6d1b5d209 Mon Sep 17 00:00:00 2001 From: ZhouGuangyuan Date: Tue, 4 Aug 2026 08:41:38 +0800 Subject: [PATCH 68/73] ssa: make recursive type conversion order-independent --- ssa/type_cvt.go | 172 ++++++++++++++++++++++++++++++++++---- ssa/type_cvt_test.go | 195 +++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 353 insertions(+), 14 deletions(-) create mode 100644 ssa/type_cvt_test.go diff --git a/ssa/type_cvt.go b/ssa/type_cvt.go index bd8ab36ed4..a5302a77b4 100644 --- a/ssa/type_cvt.go +++ b/ssa/type_cvt.go @@ -28,15 +28,27 @@ import ( // ----------------------------------------------------------------------------- type goTypes struct { - typs map[unsafe.Pointer]unsafe.Pointer - typbg sync.Map + // typs and cvtneed are owned by the single lowering goroutine for one + // Program. typbg is populated during concurrent package syntax preloading, + // before lowering starts, so it remains a sync.Map. + typs map[unsafe.Pointer]unsafe.Pointer + cvtneed map[*types.Named]conversionRequirement + typbg sync.Map } func newGoTypes() goTypes { typs := make(map[unsafe.Pointer]unsafe.Pointer) - return goTypes{typs: typs} + return goTypes{typs: typs, cvtneed: make(map[*types.Named]conversionRequirement)} } +type conversionRequirement uint8 + +const ( + conversionUnknown conversionRequirement = iota + conversionNotNeeded + conversionNeeded +) + type Background int const ( @@ -101,7 +113,7 @@ func (p goTypes) cvtType(typ types.Type) (raw types.Type, cvt bool) { } return p.cvtStruct(t) case *types.Named: - if v, ok := p.typbg.Load(namedLinkname(t)); ok && v.(Background) == InC { + if !p.shouldConvertNamed(t) { break } return p.cvtNamed(t) @@ -161,37 +173,169 @@ func namedLinkname(t *types.Named) string { return obj.Name() } +func (p goTypes) shouldConvertNamed(t *types.Named) bool { + v, ok := p.typbg.Load(namedLinkname(t)) + return !ok || v.(Background) != InC +} + func (p goTypes) cvtNamed(t *types.Named) (raw *types.Named, cvt bool) { if v, ok := p.typs[unsafe.Pointer(t)]; ok { raw = (*types.Named)(v) cvt = t != raw return } + // Decide whether the complete recursive type graph needs conversion before + // installing the recursion placeholder. Previously the placeholder was the + // original type. For mutually recursive named types, that made the result + // depend on which member of the cycle happened to be converted first: a + // closure reachable through a later member could leave an earlier member + // permanently cached in its unconverted form. + if !p.namedNeedsTypeConversion(t) { + p.typs[unsafe.Pointer(t)] = unsafe.Pointer(t) + return t, false + } n := t.NumMethods() methods := make([]*types.Func, n) for i := 0; i < n; i++ { m := t.Method(i) // don't need to convert method signature methods[i] = m } - named := types.NewNamed(t.Obj(), types.Typ[types.Int], methods) + origin := types.NewNamed(t.Obj(), types.Typ[types.Int], methods) if tp := t.TypeParams(); tp != nil { list := make([]*types.TypeParam, tp.Len()) for i := 0; i < tp.Len(); i++ { param := tp.At(i) list[i] = types.NewTypeParam(param.Obj(), param.Constraint()) } - named.SetTypeParams(list) + origin.SetTypeParams(list) } - p.typs[unsafe.Pointer(t)] = unsafe.Pointer(t) - if tund, cvt := p.cvtType(t.Underlying()); cvt { - named.SetUnderlying(tund) - if typ, ok := Instantiate(named, t); ok { - named = typ.(*types.Named) + named := origin + if typ, ok := Instantiate(origin, t); ok { + named = typ.(*types.Named) + } + // Publish the converted placeholder before descending so every back-edge in + // the cycle observes the same conversion decision. + p.typs[unsafe.Pointer(t)] = unsafe.Pointer(named) + tund, _ := p.cvtType(t.Underlying()) + // Generic instances derive their underlying type lazily from the origin. + // Fill the origin before any caller observes named.Underlying(), so a + // recursive My[T] back-edge resolves to the converted My[args] instance. + origin.SetUnderlying(tund) + return named, true +} + +type conversionNeedState struct { + visiting bool + seen bool +} + +type conversionNeedQuery map[*types.Named]conversionNeedState + +func (p goTypes) namedNeedsTypeConversion(t *types.Named) bool { + if requirement := p.cvtneed[t]; requirement != conversionUnknown { + return requirement == conversionNeeded + } + query := make(conversionNeedQuery) + needed := p.needsTypeConversion(t, query) + if !needed { + // A complete negative query proves that every named type it reached is + // also conversion-free. Negative results observed only on a cycle + // back-edge are never stored here. + for named, state := range query { + if state.seen { + p.cvtneed[named] = conversionNotNeeded + } } - p.typs[unsafe.Pointer(t)] = unsafe.Pointer(named) - return named, true } - return t, false + return needed +} + +// needsTypeConversion reports whether cvtType changes any part of typ. The +// recursion set deliberately belongs to one query: a cycle back-edge alone is +// not a conversion, but another member of that cycle may still require one. +// Keep its traversal and conversion predicates in lock-step with cvtType. +func (p goTypes) needsTypeConversion(typ types.Type, query conversionNeedQuery) bool { + if _, ok := cvtGoSSAOpaqueType(typ); ok { + return true + } + switch t := typ.(type) { + case *types.Basic: + return false + case *types.Pointer: + return p.needsTypeConversion(t.Elem(), query) + case *types.Interface: + for i := 0; i < t.NumExplicitMethods(); i++ { + sig := t.ExplicitMethod(i).Type().(*types.Signature) + if p.needsTypeConversion(sig.Params(), query) || p.needsTypeConversion(sig.Results(), query) { + return true + } + } + for i := 0; i < t.NumEmbeddeds(); i++ { + if p.needsTypeConversion(t.EmbeddedType(i), query) { + return true + } + } + return false + case *types.Slice: + return p.needsTypeConversion(t.Elem(), query) + case *types.Map: + return p.needsTypeConversion(t.Key(), query) || p.needsTypeConversion(t.Elem(), query) + case *types.Struct: + if IsClosure(t) { + return false + } + for i := 0; i < t.NumFields(); i++ { + if p.needsTypeConversion(t.Field(i).Type(), query) { + return true + } + } + return false + case *types.Named: + if !p.shouldConvertNamed(t) { + return false + } + if requirement := p.cvtneed[t]; requirement != conversionUnknown { + return requirement == conversionNeeded + } + state := query[t] + state.seen = true + if state.visiting { + query[t] = state + return false + } + state.visiting = true + query[t] = state + ret := p.needsTypeConversion(t.Underlying(), query) + state = query[t] + state.visiting = false + query[t] = state + if ret { + p.cvtneed[t] = conversionNeeded + } + return ret + case *types.Signature: + return true + case *types.Array: + return p.needsTypeConversion(t.Elem(), query) + case *types.Chan: + return p.needsTypeConversion(t.Elem(), query) + case *types.Tuple: + for i := 0; i < t.Len(); i++ { + if p.needsTypeConversion(t.At(i).Type(), query) { + return true + } + } + return false + case *types.TypeParam: + return false + case *types.Alias: + return p.needsTypeConversion(types.Unalias(t), query) + case *types.Union: + // cvtUnion currently always creates a raw union. + return true + default: + panic(fmt.Sprintf("needsTypeConversion: unexpected type - %T", typ)) + } } func Instantiate(orig types.Type, t *types.Named) (types.Type, bool) { diff --git a/ssa/type_cvt_test.go b/ssa/type_cvt_test.go new file mode 100644 index 0000000000..f599b024e2 --- /dev/null +++ b/ssa/type_cvt_test.go @@ -0,0 +1,195 @@ +/* + * Copyright (c) 2026 The XGo Authors (xgo.dev). All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package ssa + +import ( + "go/ast" + "go/parser" + "go/token" + "go/types" + "testing" +) + +func TestNamedTypeConversionIsIndependentOfTraversalOrder(t *testing.T) { + pkg := types.NewPackage("example.com/cycle", "cycle") + a := types.NewNamed(types.NewTypeName(token.NoPos, pkg, "A", nil), types.Typ[types.Int], nil) + b := types.NewNamed(types.NewTypeName(token.NoPos, pkg, "B", nil), types.Typ[types.Int], nil) + a.SetUnderlying(types.NewStruct([]*types.Var{ + types.NewField(token.NoPos, pkg, "B", types.NewPointer(b), false), + }, nil)) + b.SetUnderlying(types.NewStruct([]*types.Var{ + types.NewField(token.NoPos, pkg, "A", types.NewPointer(a), false), + types.NewField(token.NoPos, pkg, "F", types.NewSignatureType(nil, nil, nil, nil, nil, false), false), + }, nil)) + + convert := func(first, second *types.Named) (*types.Named, *types.Named) { + cvt := newGoTypes() + cvt.cvtNamed(first) + rawSecond, _ := cvt.cvtNamed(second) + rawFirst, _ := cvt.cvtNamed(first) + if first == a { + return rawFirst, rawSecond + } + return rawSecond, rawFirst + } + aFromA, bFromA := convert(a, b) + aFromB, bFromB := convert(b, a) + + for name, got := range map[string]*types.Named{ + "A after A-first conversion": aFromA, + "B after A-first conversion": bFromA, + "A after B-first conversion": aFromB, + "B after B-first conversion": bFromB, + } { + original := a + if name[0] == 'B' { + original = b + } + if got == original { + t.Errorf("%s retained the unconverted recursive type", name) + } + } + if got, want := types.TypeString(aFromA, nil), types.TypeString(aFromB, nil); got != want { + t.Errorf("A conversion depends on traversal order:\nA-first: %s\nB-first: %s", got, want) + } + if got, want := types.TypeString(bFromA, nil), types.TypeString(bFromB, nil); got != want { + t.Errorf("B conversion depends on traversal order:\nA-first: %s\nB-first: %s", got, want) + } + assertCycle := func(name string, rawA, rawB *types.Named) { + t.Helper() + aStruct := rawA.Underlying().(*types.Struct) + if got := aStruct.Field(0).Type().(*types.Pointer).Elem(); got != rawB { + t.Errorf("%s: converted A points to %v, want converted B", name, got) + } + bStruct := rawB.Underlying().(*types.Struct) + if got := bStruct.Field(0).Type().(*types.Pointer).Elem(); got != rawA { + t.Errorf("%s: converted B points to %v, want converted A", name, got) + } + if got, ok := bStruct.Field(1).Type().(*types.Struct); !ok || !IsClosure(got) { + t.Errorf("%s: converted B.F type = %v, want closure", name, got) + } + } + assertCycle("A-first", aFromA, bFromA) + assertCycle("B-first", aFromB, bFromB) +} + +func TestRecursiveGenericNamedTypeConversion(t *testing.T) { + fset := token.NewFileSet() + file, err := parser.ParseFile(fset, "generic.go", `package generic +type My[T any] struct { + F func(T) + Next *My[T] +} +`, 0) + if err != nil { + t.Fatal(err) + } + pkg, err := (&types.Config{}).Check("example.com/generic", fset, []*ast.File{file}, nil) + if err != nil { + t.Fatal(err) + } + origin := pkg.Scope().Lookup("My").Type() + instantiated, err := types.Instantiate(nil, origin, []types.Type{types.Typ[types.Int]}, false) + if err != nil { + t.Fatal(err) + } + original := instantiated.(*types.Named) + + cvt := newGoTypes() + raw, changed := cvt.cvtNamed(original) + if !changed || raw == original { + t.Fatal("recursive generic type was not converted") + } + underlying, ok := raw.Underlying().(*types.Struct) + if !ok { + t.Fatalf("converted generic underlying = %T, want *types.Struct", raw.Underlying()) + } + if closure, ok := underlying.Field(0).Type().(*types.Struct); !ok || !IsClosure(closure) { + t.Fatalf("converted generic F = %v, want closure", underlying.Field(0).Type()) + } + next := underlying.Field(1).Type().(*types.Pointer).Elem() + if next != raw { + t.Fatalf("converted generic Next points to %v, want converted instance %v", next, raw) + } +} + +func TestTypeConversionRequirementShapes(t *testing.T) { + sig := types.NewSignatureType(nil, nil, nil, nil, nil, false) + sigParam := types.NewSignatureType(nil, nil, nil, + types.NewTuple(types.NewVar(token.NoPos, nil, "f", sig)), nil, false) + method := types.NewFunc(token.NoPos, nil, "M", sigParam) + methodInterface := types.NewInterfaceType([]*types.Func{method}, nil) + methodInterface.Complete() + embeddedInterface := types.NewInterfaceType(nil, []types.Type{methodInterface}) + embeddedInterface.Complete() + typeParam := types.NewTypeParam( + types.NewTypeName(token.NoPos, nil, "T", nil), types.Universe.Lookup("any").Type()) + alias := types.NewAlias(types.NewTypeName(token.NoPos, nil, "Alias", nil), sig) + union := types.NewUnion([]*types.Term{types.NewTerm(false, types.Typ[types.Int])}) + + tests := []struct { + name string + typ types.Type + want bool + }{ + {name: "basic", typ: types.Typ[types.Int]}, + {name: "pointer", typ: types.NewPointer(sig), want: true}, + {name: "interface method", typ: methodInterface, want: true}, + {name: "embedded interface", typ: embeddedInterface, want: true}, + {name: "slice", typ: types.NewSlice(sig), want: true}, + {name: "map key", typ: types.NewMap(sig, types.Typ[types.Int]), want: true}, + {name: "map value", typ: types.NewMap(types.Typ[types.Int], sig), want: true}, + {name: "closure", typ: newGoTypes().cvtClosure(sig)}, + {name: "struct", typ: types.NewStruct([]*types.Var{types.NewField(token.NoPos, nil, "F", sig, false)}, nil), want: true}, + {name: "signature", typ: sig, want: true}, + {name: "array", typ: types.NewArray(sig, 1), want: true}, + {name: "channel", typ: types.NewChan(types.SendRecv, sig), want: true}, + {name: "tuple", typ: types.NewTuple(types.NewVar(token.NoPos, nil, "F", sig)), want: true}, + {name: "type parameter", typ: typeParam}, + {name: "alias", typ: alias, want: true}, + {name: "union", typ: union, want: true}, + } + for _, test := range tests { + t.Run(test.name, func(t *testing.T) { + cvt := newGoTypes() + query := make(conversionNeedQuery) + if got := cvt.needsTypeConversion(test.typ, query); got != test.want { + t.Fatalf("needsTypeConversion(%v) = %v, want %v", test.typ, got, test.want) + } + }) + } +} + +func TestRecursiveNamedTypesWithoutConversionKeepTheirIdentity(t *testing.T) { + pkg := types.NewPackage("example.com/plaincycle", "plaincycle") + a := types.NewNamed(types.NewTypeName(token.NoPos, pkg, "A", nil), types.Typ[types.Int], nil) + b := types.NewNamed(types.NewTypeName(token.NoPos, pkg, "B", nil), types.Typ[types.Int], nil) + a.SetUnderlying(types.NewStruct([]*types.Var{ + types.NewField(token.NoPos, pkg, "B", types.NewPointer(b), false), + }, nil)) + b.SetUnderlying(types.NewStruct([]*types.Var{ + types.NewField(token.NoPos, pkg, "A", types.NewPointer(a), false), + }, nil)) + + cvt := newGoTypes() + if got, changed := cvt.cvtNamed(a); changed || got != a { + t.Fatalf("plain recursive A conversion = (%v, %v), want original type", got, changed) + } + if got, changed := cvt.cvtNamed(b); changed || got != b { + t.Fatalf("plain recursive B conversion = (%v, %v), want original type", got, changed) + } +} From 06b5378478de95164e190b43102a96a5bd8887ac Mon Sep 17 00:00:00 2001 From: ZhouGuangyuan Date: Thu, 6 Aug 2026 00:08:56 +0800 Subject: [PATCH 69/73] test(ssa): keep conversion predicate in sync --- ssa/type_cvt_test.go | 3 +++ 1 file changed, 3 insertions(+) diff --git a/ssa/type_cvt_test.go b/ssa/type_cvt_test.go index f599b024e2..bd10a5a13d 100644 --- a/ssa/type_cvt_test.go +++ b/ssa/type_cvt_test.go @@ -170,6 +170,9 @@ func TestTypeConversionRequirementShapes(t *testing.T) { if got := cvt.needsTypeConversion(test.typ, query); got != test.want { t.Fatalf("needsTypeConversion(%v) = %v, want %v", test.typ, got, test.want) } + if _, got := newGoTypes().cvtType(test.typ); got != test.want { + t.Fatalf("cvtType(%v) changed = %v, want %v", test.typ, got, test.want) + } }) } } From c1728af80cbb41408b54cb1b1b94e4902edc36ff Mon Sep 17 00:00:00 2001 From: ZhouGuangyuan Date: Wed, 5 Aug 2026 21:29:27 +0800 Subject: [PATCH 70/73] build: prepare read-only package backend state --- cl/caller_tracking_precompute_test.go | 61 +++++++++++++++++ cl/compile.go | 9 ++- cl/import.go | 59 +++++++++++++++-- cl/instr.go | 24 ++++++- cl/preloaded_syntax_test.go | 82 +++++++++++++++++++++++ internal/build/backend_program_test.go | 48 ++++++++++++++ internal/build/build.go | 73 ++++++++++++++++++--- ssa/backend_program_test.go | 85 ++++++++++++++++++++++++ ssa/locality.go | 19 ++---- ssa/package.go | 79 +++++++++++++++------- ssa/package_syntax.go | 90 ++++++++++++++++++++++++++ ssa/type.go | 3 +- ssa/type_cvt.go | 27 +++++--- 13 files changed, 593 insertions(+), 66 deletions(-) create mode 100644 cl/caller_tracking_precompute_test.go create mode 100644 cl/preloaded_syntax_test.go create mode 100644 internal/build/backend_program_test.go create mode 100644 ssa/backend_program_test.go create mode 100644 ssa/package_syntax.go diff --git a/cl/caller_tracking_precompute_test.go b/cl/caller_tracking_precompute_test.go new file mode 100644 index 0000000000..f99428580b --- /dev/null +++ b/cl/caller_tracking_precompute_test.go @@ -0,0 +1,61 @@ +//go:build !llgo + +/* + * Copyright (c) 2026 The XGo Authors (xgo.dev). All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package cl + +import ( + "sync" + "testing" + + gossa "golang.org/x/tools/go/ssa" +) + +func TestCallerTrackingPrecomputeSupportsConcurrentReads(t *testing.T) { + var nilTracking *CallerTracking + nilTracking.Precompute(nil) + dep, root := buildCallerFrameSSAProgram(t, + "example.com/dep", `package dep +import "runtime" +func Where() { runtime.Caller(0) } +`, + "example.com/root", `package root +import "example.com/dep" +func Logs() { dep.Where() } +`) + tracking := NewCallerTracking() + tracking.Precompute([]*gossa.Package{dep, root}) + if !runtimeCallerBaseSet(tracking, dep)[dep.Func("Where")] { + t.Fatal("precomputed base set lost runtime caller function") + } + if !runtimeCallerFuncSet(tracking, root)[root.Func("Logs")] { + t.Fatal("precomputed extended set lost cross-package caller") + } + + var wg sync.WaitGroup + for range 32 { + wg.Add(1) + go func() { + defer wg.Done() + if !runtimeCallerBaseSet(tracking, dep)[dep.Func("Where")] || + !runtimeCallerFuncSet(tracking, root)[root.Func("Logs")] { + t.Error("concurrent read lost precomputed caller tracking data") + } + }() + } + wg.Wait() +} diff --git a/cl/compile.go b/cl/compile.go index c18ac435a9..909f89b939 100644 --- a/cl/compile.go +++ b/cl/compile.go @@ -74,6 +74,9 @@ type Options struct { Trace bool ExportRename bool ShadowStack bool + // PreloadedSyntax means all Program-side source metadata was collected + // before lowering and is now shared read-only by backend Programs. + PreloadedSyntax bool } func legacyOptions() Options { @@ -2231,8 +2234,10 @@ func newPackageEx(prog llssa.Program, ct *CallerTracking, patches Patches, rewri pkg.Pkg = pkgTypes patch.Alt.Pkg = pkgTypes } - if err = ParsePkgSyntax(prog, pkgProg.Fset, pkgTypes, files); err != nil { - return nil, nil, err + if !options.PreloadedSyntax { + if err = ParsePkgSyntaxWithOptions(prog, pkgProg.Fset, pkgTypes, files, options); err != nil { + return nil, nil, err + } } if err = prog.ValidateLocalitiesFor(pkgTypes); err != nil { return nil, nil, err diff --git a/cl/import.go b/cl/import.go index 728d162049..21eedd0818 100644 --- a/cl/import.go +++ b/cl/import.go @@ -146,6 +146,9 @@ func (p *context) importPkg(pkg *types.Package, i *pkgInfo) { } start: i.kind = kind + if p.frontendOptions().PreloadedSyntax { + return + } fset := p.fset names := scope.Names() syms := newPkgSymInfo() @@ -177,11 +180,18 @@ start: } func (p *context) initFiles(pkgPath string, files []*ast.File, cPkg bool) { + preloaded := p.frontendOptions().PreloadedSyntax for _, file := range files { for _, decl := range file.Decls { switch decl := decl.(type) { case *ast.FuncDecl: fullName, inPkgName := astFuncName(pkgPath, decl) + if preloaded { + if exportName, ok := p.prog.PackageExport(fullName); ok { + p.pkg.SetExport(fullName, exportName) + } + continue + } p.processNoInterfaceByDoc(decl.Doc, fullName) if !p.processLinknameByDoc(decl.Doc, fullName, inPkgName, false, true) && cPkg { // package C (https://github.com/goplus/llgo/issues/1165) @@ -197,7 +207,14 @@ func (p *context) initFiles(pkgPath string, files []*ast.File, cPkg bool) { if len(decl.Specs) == 1 { if names := decl.Specs[0].(*ast.ValueSpec).Names; len(names) == 1 { inPkgName := names[0].Name - p.processLinknameByDoc(decl.Doc, pkgPath+"."+inPkgName, inPkgName, true, true) + fullName := pkgPath + "." + inPkgName + if preloaded { + if exportName, ok := p.prog.PackageExport(fullName); ok { + p.pkg.SetExport(fullName, exportName) + } + } else { + p.processLinknameByDoc(decl.Doc, fullName, inPkgName, true, true) + } } } case token.CONST: @@ -279,6 +296,10 @@ func (p *context) collectSkip(line string, prefix int) { // collectDeclarationDirectives caches source metadata needed after the syntax // pass. funcPos is token.NoPos for non-function declarations. func collectDeclarationDirectives(prog llssa.Program, fset *token.FileSet, doc *ast.CommentGroup, fullName, inPkgName string, funcPos token.Pos) { + _, _ = collectDeclarationDirectivesWithOptions(prog, fset, doc, fullName, inPkgName, funcPos, legacyOptions()) +} + +func collectDeclarationDirectivesWithOptions(prog llssa.Program, fset *token.FileSet, doc *ast.CommentGroup, fullName, inPkgName string, funcPos token.Pos, options Options) (bool, error) { directives := directive.ParseGroup(doc) linkCollected := false hasClosureEnv := false @@ -294,6 +315,16 @@ func collectDeclarationDirectives(prog llssa.Program, fset *token.FileSet, doc * prog.SetLinkname(fullName, strings.Join(fields[1:], " ")) linkCollected = true } + case "export": + if linkCollected || item.Args == "" { + continue + } + if item.Args != inPkgName && !options.ExportRename { + return false, fmt.Errorf("export comment has wrong name %q", item.Args) + } + prog.SetLinkname(fullName, item.Args) + prog.SetPackageExport(fullName, item.Args) + linkCollected = true case "llgo:env": if funcPos.IsValid() { hasClosureEnv = true @@ -303,6 +334,7 @@ func collectDeclarationDirectives(prog llssa.Program, fset *token.FileSet, doc * if hasClosureEnv { prog.SetClosureEnvDirective(fset, fullName, funcPos) } + return linkCollected, nil } func (p *context) processLinknameByDoc(doc *ast.CommentGroup, fullName, inPkgName string, isVar, allowExport bool) bool { @@ -766,16 +798,21 @@ func (p *context) initPyModule() { } // ParsePkgSyntax collects declaration directives in one syntax pass before SSA -// creation. Directives that need an LLVM package (such as //export) are applied -// later by initFiles. +// creation using the legacy frontend options. func ParsePkgSyntax(prog llssa.Program, fset *token.FileSet, pkg *types.Package, files []*ast.File) error { + return ParsePkgSyntaxWithOptions(prog, fset, pkg, files, legacyOptions()) +} + +// ParsePkgSyntaxWithOptions collects all Program-side declaration metadata. +// LLVM Package effects such as preserving //export symbols are applied later. +func ParsePkgSyntaxWithOptions(prog llssa.Program, fset *token.FileSet, pkg *types.Package, files []*ast.File, options Options) error { if pkg == nil { return nil } if prog.PackageSyntaxParsed(pkg) { return nil } - ctx := &context{prog: prog} + ctx := &context{prog: prog, options: options, optionsSet: true} pkgPath := llssa.PathOf(pkg) for _, file := range files { for _, decl := range file.Decls { @@ -788,14 +825,24 @@ func ParsePkgSyntax(prog llssa.Program, fset *token.FileSet, pkg *types.Package, return err } fullName, inPkgName := astFuncName(pkgPath, decl) - collectDeclarationDirectives(prog, fset, decl.Doc, fullName, inPkgName, decl.Pos()) + hasLinkname, err := collectDeclarationDirectivesWithOptions(prog, fset, decl.Doc, fullName, inPkgName, decl.Pos(), options) + if err != nil { + return err + } + if !hasLinkname && pkg.Name() == "C" && decl.Recv == nil && token.IsExported(inPkgName) { + exportName := strings.TrimPrefix(inPkgName, "X") + prog.SetLinkname(fullName, exportName) + prog.SetPackageExport(fullName, exportName) + } ctx.processNoInterfaceByDoc(decl.Doc, fullName) case *ast.GenDecl: if decl.Tok == token.VAR { if len(decl.Specs) == 1 { if names := decl.Specs[0].(*ast.ValueSpec).Names; len(names) == 1 { inPkgName := names[0].Name - collectDeclarationDirectives(prog, fset, decl.Doc, pkgPath+"."+inPkgName, inPkgName, token.NoPos) + if _, err := collectDeclarationDirectivesWithOptions(prog, fset, decl.Doc, pkgPath+"."+inPkgName, inPkgName, token.NoPos, options); err != nil { + return err + } } } vars, err := locality.ScanPackageVar(fset, decl) diff --git a/cl/instr.go b/cl/instr.go index 4b52624f1b..230c21a94f 100644 --- a/cl/instr.go +++ b/cl/instr.go @@ -980,14 +980,32 @@ func runtimeCallerFuncSet(c *CallerTracking, pkg *ssa.Package) map[*ssa.Function // queries (criterion 2 below) hit the memoization. It must not outlive // the compilation — the maps are keyed by *ssa.Package with // *ssa.Function values, so anything longer-lived would pin every -// compiled package's go/types and go/ssa graphs. Plain maps are enough: -// packages of one compilation are compiled sequentially (the LLVM -// context is not thread-safe). +// compiled package's go/types and go/ssa graphs. Concurrent drivers call +// Precompute before workers start and then share the plain maps read-only. type CallerTracking struct { base map[*ssa.Package]map[*ssa.Function]bool extended map[*ssa.Package]map[*ssa.Function]bool } +// Precompute resolves caller-tracking data before package backends start. +// Once it returns, callers may share c for concurrent read-only lookups as long +// as pkgs contains every package that can be passed to this compilation. +func (c *CallerTracking) Precompute(pkgs []*ssa.Package) { + if c == nil { + return + } + for _, pkg := range pkgs { + if pkg != nil { + runtimeCallerBaseSet(c, pkg) + } + } + for _, pkg := range pkgs { + if pkg != nil { + runtimeCallerFuncSet(c, pkg) + } + } +} + // NewCallerTracking creates the caller-tracking memoization for one // compilation. func NewCallerTracking() *CallerTracking { diff --git a/cl/preloaded_syntax_test.go b/cl/preloaded_syntax_test.go new file mode 100644 index 0000000000..dc16fda600 --- /dev/null +++ b/cl/preloaded_syntax_test.go @@ -0,0 +1,82 @@ +//go:build !llgo + +/* + * Copyright (c) 2026 The XGo Authors (xgo.dev). All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package cl + +import ( + "go/ast" + "go/importer" + "go/parser" + "go/token" + "go/types" + "testing" + + "github.com/goplus/llgo/internal/goembed" + "github.com/goplus/llgo/ssa/ssatest" + "golang.org/x/tools/go/ssa" +) + +func TestPreloadedSyntaxFeedsBackendWithoutLateDiscovery(t *testing.T) { + const source = `package C + +//export callback +func Callback() {} + +func XDefault() {} +` + fset := token.NewFileSet() + file, err := parser.ParseFile(fset, "preloaded.go", source, parser.ParseComments) + if err != nil { + t.Fatal(err) + } + files := []*ast.File{file} + info := newLocalityTypeInfo() + imp := importer.Default() + pkg, err := (&types.Config{Importer: imp}).Check("example.com/C", fset, files, info) + if err != nil { + t.Fatal(err) + } + coordinator := ssatest.NewProgramEx(t, nil, imp) + if err := ParsePkgSyntaxWithOptions(coordinator, fset, pkg, files, Options{ExportRename: true}); err != nil { + t.Fatal(err) + } + backend := coordinator.NewBackendProgram() + defer backend.Dispose() + + goProg := ssa.NewProgram(fset, ssa.SanityCheckFunctions) + ssaPkg := goProg.CreatePackage(pkg, files, info, true) + ssaPkg.Build() + compiled, _, err := NewPackageExWithEmbedMetaOptions( + backend, nil, nil, nil, ssaPkg, files, goembed.VarMap{}, false, + Options{ExportRename: true, PreloadedSyntax: true}, + ) + if err != nil { + t.Fatal(err) + } + for fullName, want := range map[string]string{ + "example.com/C.Callback": "callback", + "example.com/C.XDefault": "Default", + } { + if link, ok := backend.Linkname(fullName); !ok || link != want { + t.Errorf("Linkname(%q) = (%q, %v), want (%q, true)", fullName, link, ok, want) + } + if export, ok := compiled.ExportFuncs()[fullName]; !ok || export != want { + t.Errorf("ExportFuncs()[%q] = (%q, %v), want (%q, true)", fullName, export, ok, want) + } + } +} diff --git a/internal/build/backend_program_test.go b/internal/build/backend_program_test.go new file mode 100644 index 0000000000..7af22f6416 --- /dev/null +++ b/internal/build/backend_program_test.go @@ -0,0 +1,48 @@ +/* + * Copyright (c) 2026 The XGo Authors (xgo.dev). All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package build + +import ( + "runtime" + "testing" + + llssa "github.com/goplus/llgo/ssa" +) + +func TestNewBackendSessionCreatesIndependentLLVMState(t *testing.T) { + coordinator := llssa.NewProgram(&llssa.Target{GOOS: runtime.GOOS, GOARCH: runtime.GOARCH}) + defer coordinator.Dispose() + ctx := &context{ + prog: coordinator, + buildConf: &Config{ + Goos: runtime.GOOS, + Goarch: runtime.GOARCH, + }, + } + first := ctx.newBackendSession() + defer first.prog.Dispose() + second := ctx.newBackendSession() + defer second.prog.Dispose() + if first.transformer == nil || second.transformer == nil { + t.Fatal("backend session missing C ABI transformer") + } + firstModule := first.prog.NewPackage("first", "example.com/first").Module() + secondModule := second.prog.NewPackage("second", "example.com/second").Module() + if firstModule.Context().C == secondModule.Context().C { + t.Fatal("backend sessions share an LLVM context") + } +} diff --git a/internal/build/build.go b/internal/build/build.go index 9af327bd3d..522a00cda6 100644 --- a/internal/build/build.go +++ b/internal/build/build.go @@ -448,6 +448,7 @@ func Build(inv Invocation) ([]Package, error) { ExportRename: conf.Target != "", ShadowStack: isEnvOn(llgoShadowStack, false), } + preloadOptions := frontendOptions llssaInitOnce.Do(func() { llssa.Initialize(llssa.InitAll) }) @@ -502,7 +503,7 @@ func Build(inv Invocation) ([]Package, error) { if llruntime.SkipToBuild(pkg.Path()) { return } - if err := cl.ParsePkgSyntax(prog, cfg.Fset, pkg, files); err != nil { + if err := cl.ParsePkgSyntaxWithOptions(prog, cfg.Fset, pkg, files, preloadOptions); err != nil { recordSyntaxErr(err) } }) @@ -579,15 +580,12 @@ func Build(inv Invocation) ([]Package, error) { return nil, err } - prog.SetRuntime(func() *types.Package { - return altPkgs[0].Types - }) - prog.SetPython(func() *types.Package { - return dedup.Check(llssa.PkgPython).Types - }) - if err := prepareLocalVariables(prog, initial, altPkgs); err != nil { - return nil, err + prog.SetRuntime(altPkgs[0].Types) + var pythonPackage *types.Package + if python := dedup.Check(llssa.PkgPython); python != nil { + pythonPackage = python.Types } + prog.SetPython(func() *types.Package { return pythonPackage }) buildMode := ssaBuildMode cabiOptimize := true @@ -603,6 +601,13 @@ func Build(inv Invocation) ([]Package, error) { progSSA := ssa.NewProgram(initial[0].Fset, buildMode) patches := make(cl.Patches, len(altPkgPaths)) altEntries := registerAltSSAPkgs(progSSA, patches, altPkgs[1:], conf, verbose) + if err := preloadPatchedPackageSyntax(prog, patches, dedup, preloadOptions); err != nil { + return nil, err + } + if err := prepareLocalVariables(prog, initial, altPkgs); err != nil { + return nil, err + } + frontendOptions.PreloadedSyntax = true output := conf.OutFile != "" ctx := &context{conf: cfg, progSSA: progSSA, prog: prog, dedup: dedup, @@ -634,6 +639,7 @@ func Build(inv Invocation) ([]Package, error) { return nil, err } buildSSAPkgs(ctx, append(append(altEntries, pkgEntries...), depEntries...)) + ctx.callerTracking.Precompute(ctx.progSSA.AllPackages()) allPkgs := append([]*aPackage{}, pkgs...) allPkgs = append(allPkgs, depPkgs...) @@ -913,6 +919,55 @@ func (c *context) closePackageMetas() { } } +// backendSession owns all LLVM state used to lower one package. The Program +// shares only the coordinator's already-prepared Go metadata. +type backendSession struct { + prog llssa.Program + transformer *cabi.Transformer +} + +func (c *context) newBackendSession() backendSession { + prog := c.prog.NewBackendProgram() + return backendSession{ + prog: prog, + transformer: cabi.NewTransformer( + prog, + c.crossCompile.LLVMTarget, + c.crossCompile.TargetABI, + c.buildConf.AbiMode, + !shouldEmitDebugInfo(c.buildConf, &c.crossCompile), + ), + } +} + +// preloadPatchedPackageSyntax prepares the effective types.Package used by +// patched lowering. Normal and alternate packages are already covered by the +// packages loader's preload callback, but patch.Types has a distinct identity. +func preloadPatchedPackageSyntax(prog llssa.Program, patches cl.Patches, dedup packages.Deduper, options cl.Options) error { + paths := make([]string, 0, len(patches)) + for pkgPath := range patches { + paths = append(paths, pkgPath) + } + slices.Sort(paths) + for _, pkgPath := range paths { + patch := patches[pkgPath] + alt := dedup.Check(altPkgPathPrefix + pkgPath) + if alt == nil || len(alt.Syntax) == 0 || patch.Types == nil { + continue + } + fset := alt.Fset + files := slices.Clone(alt.Syntax) + if original := dedup.Check(pkgPath); original != nil { + fset = original.Fset + files = append(slices.Clone(original.Syntax), files...) + } + if err := cl.ParsePkgSyntaxWithOptions(prog, fset, patch.Types, files, options); err != nil { + return err + } + } + return nil +} + func (c *context) compiler() *clang.Cmd { config := clang.NewConfig( c.crossCompile.CC, diff --git a/ssa/backend_program_test.go b/ssa/backend_program_test.go new file mode 100644 index 0000000000..06df50fdc3 --- /dev/null +++ b/ssa/backend_program_test.go @@ -0,0 +1,85 @@ +/* + * Copyright (c) 2026 The XGo Authors (xgo.dev). All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package ssa + +import ( + "go/token" + "go/types" + "testing" +) + +func TestNewBackendProgramSharesPreparedGoState(t *testing.T) { + coordinator := NewProgram(nil) + defer coordinator.Dispose() + coordinator.DisableBoundsChecks(true) + coordinator.EnableGoGlobalDCE(true) + coordinator.EnableDeadcodeDrop(true) + coordinator.SetPthreadStackSize(4096) + coordinator.EnableLTOPluginMarkers(true) + coordinator.EnableFuncInfoMetadata(true) + coordinator.EnableFuncInfoSites(true) + coordinator.SetDebugInfoOptimized(false) + + pkg := types.NewPackage("example.com/p", "p") + fset := token.NewFileSet() + coordinator.SetLinkname("example.com/p.Entry", "entry") + coordinator.SetPackageExport("example.com/p.Entry", "entry") + coordinator.SetNoInterfaceMethod("example.com/p.T.Hidden") + coordinator.SetTypeBackground("example.com/p.CType", InC) + coordinator.SetClosureEnvDirective(fset, "example.com/p.Entry", token.Pos(7)) + coordinator.MarkPackageSyntaxParsed(pkg) + coordinator.SetLocalityInfo("example.com/p.Value", LocalityInfo{Locality: ThreadLocal}) + coordinator.SetPython(func() *types.Package { return nil }) + + backend := coordinator.NewBackendProgram() + defer backend.Dispose() + if backend.ctx.C == coordinator.ctx.C { + t.Fatal("backend Program shares the coordinator LLVM context") + } + if backend.tm.C == coordinator.tm.C { + t.Fatal("backend Program shares the coordinator TargetMachine") + } + if backend.packageSyntax != coordinator.packageSyntax || backend.localities != coordinator.localities { + t.Fatal("backend Program did not share prepared Go metadata") + } + if backend.gocvt.typs == nil || len(backend.gocvt.typs) != 0 || backend.named == nil || backend.abiSymbol == nil { + t.Fatal("backend Program did not start with fresh lowering caches") + } + if link, ok := backend.Linkname("example.com/p.Entry"); !ok || link != "entry" { + t.Fatalf("Linkname = (%q, %v), want (entry, true)", link, ok) + } + if export, ok := backend.PackageExport("example.com/p.Entry"); !ok || export != "entry" { + t.Fatalf("PackageExport = (%q, %v), want (entry, true)", export, ok) + } + if !backend.HasClosureEnvDirective(fset, "example.com/p.Entry", token.Pos(7)) || !backend.PackageSyntaxParsed(pkg) { + t.Fatal("backend Program lost prepared syntax metadata") + } + if background, ok := backend.packageTypeBackground("example.com/p.CType"); !ok || background != InC { + t.Fatalf("type background = (%v, %v), want (InC, true)", background, ok) + } + if locality, ok := backend.VariableLocality("example.com/p.Value"); !ok || locality.Locality != ThreadLocal { + t.Fatalf("locality = (%+v, %v), want ThreadLocal", locality, ok) + } + if backend.python() != nil { + t.Fatal("backend Program changed the prepared optional Python package") + } + if !backend.disableBoundsChecks || !backend.enableGoGlobalDCE || !backend.enableDeadcodeDrop || + backend.pthreadStackSize != 4096 || !backend.enableLTOPluginMarker || + !backend.enableFuncInfoMetadata || !backend.enableFuncInfoSites || backend.debugInfoOptimized { + t.Fatal("backend Program did not preserve coordinator configuration") + } +} diff --git a/ssa/locality.go b/ssa/locality.go index 0e9b41e6cd..172a6b8cff 100644 --- a/ssa/locality.go +++ b/ssa/locality.go @@ -58,7 +58,6 @@ type localityInfos struct { ownerlessEntries map[string]VariableLocality declarationEntries map[string]map[string]VariableLocality activePackages map[string]struct{} - parsedPackages map[*types.Package]struct{} } func newLocalityInfos() *localityInfos { @@ -67,7 +66,6 @@ func newLocalityInfos() *localityInfos { ownerlessEntries: make(map[string]VariableLocality), declarationEntries: make(map[string]map[string]VariableLocality), activePackages: make(map[string]struct{}), - parsedPackages: make(map[*types.Package]struct{}), } } @@ -293,12 +291,12 @@ func (p Program) validateLocalities(pkgPath string, packageEntries map[string]Va if len(localNames) == 0 { return nil } - p.linknameMu.RLock() - links := make(map[string]string, len(p.linkname)) - for name, target := range p.linkname { + p.packageSyntax.mu.RLock() + links := make(map[string]string, len(p.packageSyntax.linknames)) + for name, target := range p.packageSyntax.linknames { links[name] = strings.TrimPrefix(target, "go:") } - p.linknameMu.RUnlock() + p.packageSyntax.mu.RUnlock() for name := range links { if strings.HasPrefix(name, prefix) && linknameReachesLocal(name, links, localNames) { nameSet[name] = true @@ -330,16 +328,11 @@ func linknameReachesLocal(name string, links map[string]string, localNames map[s } func (p Program) PackageSyntaxParsed(pkg *types.Package) bool { - p.localities.mu.RLock() - _, ok := p.localities.parsedPackages[pkg] - p.localities.mu.RUnlock() - return ok + return p.packageSyntaxParsed(pkg) } func (p Program) MarkPackageSyntaxParsed(pkg *types.Package) { - p.localities.mu.Lock() - p.localities.parsedPackages[pkg] = struct{}{} - p.localities.mu.Unlock() + p.markPackageSyntaxParsed(pkg) } // PackageLocalities returns the legacy canonical-only metadata view. Its diff --git a/ssa/package.go b/ssa/package.go index aaf91dbb25..dacee7f3b8 100644 --- a/ssa/package.go +++ b/ssa/package.go @@ -23,7 +23,6 @@ import ( "log" "runtime" "strconv" - "sync" "unsafe" "github.com/goplus/llgo/internal/env" @@ -221,13 +220,10 @@ type aProgram struct { printfTy *types.Signature - paramObjPtr_ *types.Var - linknameMu sync.RWMutex - linkname map[string]string // pkgPath.nameInPkg => linkname - closureEnvDirectives sync.Map // closureEnvDirectiveKey => none - localities *localityInfos - noInterface map[string]none // pkgPath.T.method or pkgPath.(*T).method - abiSymbol map[string]*AbiSymbol // abi symbol name => AbiSymbol + paramObjPtr_ *types.Var + packageSyntax *packageSyntaxData + localities *localityInfos + abiSymbol map[string]*AbiSymbol // abi symbol name => AbiSymbol ptrSize int @@ -312,18 +308,47 @@ func NewProgram(target *Target) Program { ctx.Finalize() */ is32Bits := (td.PointerSize() == 4 || is32Bits(target.GOARCH)) + packageSyntax := newPackageSyntaxData() prog := &aProgram{ - ctx: ctx, gocvt: newGoTypes(), + ctx: ctx, gocvt: newGoTypes(packageSyntax), target: target, td: td, tm: tm, is32Bits: is32Bits, ptrSize: td.PointerSize(), named: make(map[string]Type), fnnamed: make(map[string]int), - linkname: make(map[string]string), localities: newLocalityInfos(), - noInterface: make(map[string]none), abiSymbol: make(map[string]*AbiSymbol), + packageSyntax: packageSyntax, localities: newLocalityInfos(), + abiSymbol: make(map[string]*AbiSymbol), debugInfoOptimized: target.effectiveOptLevel() != optlevel.O0, } prog.abi.Init(uintptr(prog.ptrSize), (*goProgram)(unsafe.Pointer(prog))) return prog } +// NewBackendProgram creates a Program with fresh LLVM-owned state and the same +// build configuration as p. Go-side package syntax and locality metadata are +// shared directly; callers must finish preparing them before backend Programs +// are created and use them read-only afterwards. +func (p Program) NewBackendProgram() Program { + var target *Target + if p.target != nil { + targetCopy := *p.target + target = &targetCopy + } + backend := NewProgram(target) + backend.sizes = p.sizes + backend.rt, backend.rtget = p.rt, p.rtget + backend.py, backend.pyget = p.py, p.pyget + backend.packageSyntax = p.packageSyntax + backend.gocvt.packageSyntax = p.packageSyntax + backend.localities = p.localities + backend.enableGoGlobalDCE = p.enableGoGlobalDCE + backend.enableDeadcodeDrop = p.enableDeadcodeDrop + backend.disableBoundsChecks = p.disableBoundsChecks + backend.pthreadStackSize = p.pthreadStackSize + backend.enableLTOPluginMarker = p.enableLTOPluginMarker + backend.enableFuncInfoMetadata = p.enableFuncInfoMetadata + backend.enableFuncInfoSites = p.enableFuncInfoSites + backend.debugInfoOptimized = p.debugInfoOptimized + return backend +} + func (p Program) Target() *Target { return p.target } @@ -389,7 +414,9 @@ func (p Program) SetDebugInfoOptimized(enable bool) { } func (p Program) SetNoInterfaceMethod(fullName string) { - p.noInterface[fullName] = none{} + p.packageSyntax.mu.Lock() + p.packageSyntax.noInterface[fullName] = none{} + p.packageSyntax.mu.Unlock() } func (p Program) isNoInterfaceMethod(fn *types.Func) bool { @@ -400,7 +427,9 @@ func (p Program) isNoInterfaceMethod(fn *types.Func) bool { if !ok || sig.Recv() == nil { return false } - _, ok = p.noInterface[FuncName(fn.Pkg(), fn.Name(), sig.Recv(), true)] + p.packageSyntax.mu.RLock() + _, ok = p.packageSyntax.noInterface[FuncName(fn.Pkg(), fn.Name(), sig.Recv(), true)] + p.packageSyntax.mu.RUnlock() return ok } @@ -416,19 +445,21 @@ func (p Program) SetRuntime(runtime any) { } func (p Program) SetTypeBackground(fullName string, bg Background) { - p.gocvt.typbg.Store(fullName, bg) + p.packageSyntax.mu.Lock() + p.packageSyntax.typeBackgrounds[fullName] = bg + p.packageSyntax.mu.Unlock() } func (p Program) SetLinkname(name, link string) { - p.linknameMu.Lock() - p.linkname[name] = link - p.linknameMu.Unlock() + p.packageSyntax.mu.Lock() + p.packageSyntax.linknames[name] = link + p.packageSyntax.mu.Unlock() } func (p Program) Linkname(name string) (link string, ok bool) { - p.linknameMu.RLock() - link, ok = p.linkname[name] - p.linknameMu.RUnlock() + p.packageSyntax.mu.RLock() + link, ok = p.packageSyntax.linknames[name] + p.packageSyntax.mu.RUnlock() return } @@ -443,14 +474,18 @@ type closureEnvDirectiveKey struct { // than its resolved linker symbol, so aliases retain independent ABI metadata. func (p Program) SetClosureEnvDirective(fset *token.FileSet, name string, pos token.Pos) { key := closureEnvDirectiveKey{fset: fset, name: name, pos: pos} - p.closureEnvDirectives.Store(key, none{}) + p.packageSyntax.mu.Lock() + p.packageSyntax.closureEnvDirectives[key] = none{} + p.packageSyntax.mu.Unlock() } // HasClosureEnvDirective reports whether a source function declaration has the // cached llgo:env directive. func (p Program) HasClosureEnvDirective(fset *token.FileSet, name string, pos token.Pos) bool { key := closureEnvDirectiveKey{fset: fset, name: name, pos: pos} - _, ok := p.closureEnvDirectives.Load(key) + p.packageSyntax.mu.RLock() + _, ok := p.packageSyntax.closureEnvDirectives[key] + p.packageSyntax.mu.RUnlock() return ok } diff --git a/ssa/package_syntax.go b/ssa/package_syntax.go new file mode 100644 index 0000000000..6e3bdbe2b5 --- /dev/null +++ b/ssa/package_syntax.go @@ -0,0 +1,90 @@ +/* + * Copyright (c) 2026 The XGo Authors (xgo.dev). All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package ssa + +import ( + "go/types" + "sync" +) + +// packageSyntaxData is Go-owned metadata collected before LLVM package +// lowering. Build creates backend Programs only after this data is complete, +// so those Programs can share it directly for concurrent read-only access. +// One-shot compiler users keep the same Program-local mutation behavior. +type packageSyntaxData struct { + mu sync.RWMutex + linknames map[string]string + exports map[string]string + closureEnvDirectives map[closureEnvDirectiveKey]none + parsedPackages map[*types.Package]struct{} + noInterface map[string]none + typeBackgrounds map[string]Background +} + +func newPackageSyntaxData() *packageSyntaxData { + return &packageSyntaxData{ + linknames: make(map[string]string), + exports: make(map[string]string), + closureEnvDirectives: make(map[closureEnvDirectiveKey]none), + parsedPackages: make(map[*types.Package]struct{}), + noInterface: make(map[string]none), + typeBackgrounds: make(map[string]Background), + } +} + +// SetPackageExport records an export directive before the LLVM Package that +// will later preserve the symbol exists. +func (p Program) SetPackageExport(name, export string) { + p.packageSyntax.mu.Lock() + p.packageSyntax.exports[name] = export + p.packageSyntax.mu.Unlock() +} + +// PackageExport returns the preloaded export name for name. +func (p Program) PackageExport(name string) (string, bool) { + p.packageSyntax.mu.RLock() + export, ok := p.packageSyntax.exports[name] + p.packageSyntax.mu.RUnlock() + return export, ok +} + +func (p Program) packageSyntaxParsed(pkg *types.Package) bool { + p.packageSyntax.mu.RLock() + _, ok := p.packageSyntax.parsedPackages[pkg] + p.packageSyntax.mu.RUnlock() + return ok +} + +func (p Program) markPackageSyntaxParsed(pkg *types.Package) { + p.packageSyntax.mu.Lock() + p.packageSyntax.parsedPackages[pkg] = struct{}{} + p.packageSyntax.mu.Unlock() +} + +func (p Program) packageTypeBackground(name string) (Background, bool) { + p.packageSyntax.mu.RLock() + background, ok := p.packageSyntax.typeBackgrounds[name] + p.packageSyntax.mu.RUnlock() + return background, ok +} + +func (p *packageSyntaxData) typeBackground(name string) (Background, bool) { + p.mu.RLock() + background, ok := p.typeBackgrounds[name] + p.mu.RUnlock() + return background, ok +} diff --git a/ssa/type.go b/ssa/type.go index c635cf16e9..7a84e67737 100644 --- a/ssa/type.go +++ b/ssa/type.go @@ -130,7 +130,8 @@ func (p *goProgram) extraSize(typ types.Type, ptrSize int64) (ret int64) { retry: switch t := typ.(type) { case *types.Named: - if v, ok := p.gocvt.typbg.Load(namedLinkname(t)); ok && v.(Background) == InC { + prog := Program(unsafe.Pointer(p)) + if background, ok := prog.packageTypeBackground(namedLinkname(t)); ok && background == InC { return 0 } typ = t.Underlying() diff --git a/ssa/type_cvt.go b/ssa/type_cvt.go index a5302a77b4..f8d172fd87 100644 --- a/ssa/type_cvt.go +++ b/ssa/type_cvt.go @@ -21,7 +21,6 @@ import ( "go/token" "go/types" "reflect" - "sync" "unsafe" ) @@ -29,16 +28,24 @@ import ( type goTypes struct { // typs and cvtneed are owned by the single lowering goroutine for one - // Program. typbg is populated during concurrent package syntax preloading, - // before lowering starts, so it remains a sync.Map. - typs map[unsafe.Pointer]unsafe.Pointer - cvtneed map[*types.Named]conversionRequirement - typbg sync.Map + // Program. packageSyntax is prepared before backend lowering and shared + // read-only by Programs with independent LLVM contexts. + typs map[unsafe.Pointer]unsafe.Pointer + cvtneed map[*types.Named]conversionRequirement + packageSyntax *packageSyntaxData } -func newGoTypes() goTypes { +func newGoTypes(syntax ...*packageSyntaxData) goTypes { + packageSyntax := newPackageSyntaxData() + if len(syntax) != 0 && syntax[0] != nil { + packageSyntax = syntax[0] + } typs := make(map[unsafe.Pointer]unsafe.Pointer) - return goTypes{typs: typs, cvtneed: make(map[*types.Named]conversionRequirement)} + return goTypes{ + typs: typs, + cvtneed: make(map[*types.Named]conversionRequirement), + packageSyntax: packageSyntax, + } } type conversionRequirement uint8 @@ -174,8 +181,8 @@ func namedLinkname(t *types.Named) string { } func (p goTypes) shouldConvertNamed(t *types.Named) bool { - v, ok := p.typbg.Load(namedLinkname(t)) - return !ok || v.(Background) != InC + background, ok := p.packageSyntax.typeBackground(namedLinkname(t)) + return !ok || background != InC } func (p goTypes) cvtNamed(t *types.Named) (raw *types.Named, cvt bool) { From 7bc442f99e65e3a3ef08c46d6de4181c87104c97 Mon Sep 17 00:00:00 2001 From: Li Jie Date: Sun, 9 Aug 2026 15:18:00 +0800 Subject: [PATCH 71/73] test: use shared repository root helper --- test/go/package_init_order_test.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/go/package_init_order_test.go b/test/go/package_init_order_test.go index 0275fed500..9e3113327e 100644 --- a/test/go/package_init_order_test.go +++ b/test/go/package_init_order_test.go @@ -32,7 +32,7 @@ var ( func packageInitLLGo(t *testing.T) string { t.Helper() - repoRoot := findStringConversionRepoRoot(t) + repoRoot := findRepoRoot(t) t.Setenv("LLGO_ROOT", repoRoot) packageInitLLGoOnce.Do(func() { dir, err := os.MkdirTemp("", "llgo-package-init-bin") From d606bbab0b0490c3b285fedc35d7f0275cadb829 Mon Sep 17 00:00:00 2001 From: Li Jie Date: Sat, 1 Aug 2026 22:01:10 +0800 Subject: [PATCH 72/73] debug: let supported targets retain DWARF --- internal/build/build.go | 4 +- internal/build/collect_test.go | 4 +- internal/build/link_options.go | 22 ++-- internal/build/link_options_test.go | 113 +++++++++++++++++++-- internal/crosscompile/crosscompile.go | 48 +++++++-- internal/crosscompile/crosscompile_test.go | 43 ++++++-- 6 files changed, 201 insertions(+), 33 deletions(-) diff --git a/internal/build/build.go b/internal/build/build.go index 6db6ae9085..1c8588f89f 100644 --- a/internal/build/build.go +++ b/internal/build/build.go @@ -1609,9 +1609,7 @@ func linkObjFiles(ctx *context, app string, objFiles, linkArgs []string, verbose buildArgs = append(buildArgs, linuxExportDynamicArgs(ctx)...) } - if shouldEmitDebugInfo(ctx.buildConf, &ctx.crossCompile) { - buildArgs = append(buildArgs, "-gdwarf-4") - } + buildArgs = append(buildArgs, dwarfPreserveLinkerArgs(ctx.buildConf, &ctx.crossCompile)...) if ctx.buildConf.GenLL { var compiledObjFiles []string diff --git a/internal/build/collect_test.go b/internal/build/collect_test.go index cc9785518f..31cbf531aa 100644 --- a/internal/build/collect_test.go +++ b/internal/build/collect_test.go @@ -232,7 +232,7 @@ func TestCollectFingerprintIncludesEmitDWARF(t *testing.T) { } targetWithoutDWARF := newPkg() - if err := newContext(LinkOptions{}, crosscompile.DebugInfoPolicy{AlwaysOmit: true}).collectFingerprint(targetWithoutDWARF); err != nil { + if err := newContext(LinkOptions{}, crosscompile.DebugInfoPolicy{Capability: crosscompile.DebugInfoUnavailable}).collectFingerprint(targetWithoutDWARF); err != nil { t.Fatal(err) } if withDWARF.Fingerprint == targetWithoutDWARF.Fingerprint { @@ -243,7 +243,7 @@ func TestCollectFingerprintIncludesEmitDWARF(t *testing.T) { t.Fatal(err) } if targetData.Common != nil && targetData.Common.EmitDWARF { - t.Fatalf("always-omit target manifest unexpectedly contains EMIT_DWARF=true:\n%s", targetWithoutDWARF.Manifest) + t.Fatalf("target without DWARF support unexpectedly contains EMIT_DWARF=true:\n%s", targetWithoutDWARF.Manifest) } } diff --git a/internal/build/link_options.go b/internal/build/link_options.go index 1a7c0140d8..8d1370920a 100644 --- a/internal/build/link_options.go +++ b/internal/build/link_options.go @@ -76,10 +76,10 @@ func omitDWARFRequested(conf *Config) bool { } // effectiveOmitDWARF combines command intent with the selected toolchain's -// baseline behavior. Some fixed-target linkers always omit DWARF, so LLGo -// should avoid generating debug metadata that cannot reach the artifact. +// capability. LLGo avoids generating debug metadata when the linked output +// format cannot retain it. func effectiveOmitDWARF(conf *Config, target *crosscompile.Export) bool { - return omitDWARFRequested(conf) || target.DebugInfo.AlwaysOmit + return omitDWARFRequested(conf) || !target.DebugInfo.CanRetain() } // shouldEmitDebugInfo reports whether this compilation should produce DWARF. @@ -100,13 +100,13 @@ func validateLinkOptions(conf *Config, target *crosscompile.Export) error { if err := conf.LinkOptions.validate(); err != nil { return err } - if conf.LinkOptions.DWARF == DWARFPreserve && target.DebugInfo.AlwaysOmit { + if conf.LinkOptions.DWARF == DWARFPreserve && !target.DebugInfo.CanRetain() { return fmt.Errorf("preserving DWARF is not supported by the selected target linker") } if !omitDWARFRequested(conf) { return nil } - if target.DebugInfo.AlwaysOmit { + if !target.DebugInfo.CanRetain() { return nil } if len(target.DebugInfo.OmitLinkFlags) == 0 { @@ -120,7 +120,7 @@ func validateLinkOptions(conf *Config, target *crosscompile.Export) error { // earlier; this handles debug sections in native and prebuilt inputs without // rewriting the linked binary afterward. func dwarfLinkerArgs(conf *Config, target *crosscompile.Export) []string { - if target.DebugInfo.AlwaysOmit || !effectiveOmitDWARF(conf, target) { + if !target.DebugInfo.CanRetain() || !effectiveOmitDWARF(conf, target) { return nil } // c-archive has no final native link step. Omitting generated DWARF is @@ -130,3 +130,13 @@ func dwarfLinkerArgs(conf *Config, target *crosscompile.Export) []string { } return slices.Clone(target.DebugInfo.OmitLinkFlags) } + +// dwarfPreserveLinkerArgs returns compiler-driver options needed while linking +// a debug artifact. Direct linkers such as ld.lld retain input DWARF without a +// corresponding flag, while clang-compatible drivers accept -gdwarf-4. +func dwarfPreserveLinkerArgs(conf *Config, target *crosscompile.Export) []string { + if !shouldEmitDebugInfo(conf, target) { + return nil + } + return slices.Clone(target.DebugInfo.PreserveLinkFlags) +} diff --git a/internal/build/link_options_test.go b/internal/build/link_options_test.go index b903487dfe..d5ec1254b1 100644 --- a/internal/build/link_options_test.go +++ b/internal/build/link_options_test.go @@ -19,6 +19,7 @@ package build import ( + "bytes" "debug/elf" "os" "os/exec" @@ -29,6 +30,7 @@ import ( "testing" "github.com/goplus/llgo/internal/crosscompile" + "github.com/goplus/llgo/internal/firmware" "github.com/goplus/llgo/xtool/env/llvm" ) @@ -48,7 +50,9 @@ func TestDwarfLinkerArgs(t *testing.T) { {name: "w", conf: Config{LinkOptions: LinkOptions{DWARF: DWARFOmit}}, target: configurableDebugInfo(), want: []string{"-Wl,-S"}}, {name: "s implies w", conf: Config{LinkOptions: LinkOptions{OmitSymbolTable: true}}, target: configurableDebugInfo(), want: []string{"-Wl,-S"}}, {name: "explicit w false", conf: Config{LinkOptions: LinkOptions{OmitSymbolTable: true, DWARF: DWARFPreserve}}}, - {name: "target linker already suppresses DWARF", conf: Config{Target: "rp2040", LinkOptions: LinkOptions{DWARF: DWARFOmit}}, target: alwaysOmitDebugInfo()}, + {name: "fixed target w", conf: Config{Target: "rp2040", BuildMode: BuildModeExe, LinkOptions: LinkOptions{DWARF: DWARFOmit}}, target: targetDebugInfo(), want: []string{"-S"}}, + {name: "fixed target w false", conf: Config{Target: "rp2040", BuildMode: BuildModeExe, LinkOptions: LinkOptions{DWARF: DWARFPreserve}}, target: targetDebugInfo()}, + {name: "target without DWARF support", conf: Config{Target: "rp2040", LinkOptions: LinkOptions{DWARF: DWARFOmit}}, target: unavailableDebugInfo()}, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { @@ -59,6 +63,27 @@ func TestDwarfLinkerArgs(t *testing.T) { } } +func TestDwarfPreserveLinkerArgs(t *testing.T) { + tests := []struct { + name string + conf Config + target crosscompile.Export + want []string + }{ + {name: "native preserve", conf: Config{Mode: ModeBuild, LinkOptions: LinkOptions{DWARF: DWARFPreserve}}, target: configurableDebugInfo(), want: []string{"-gdwarf-4"}}, + {name: "native omit", conf: Config{Mode: ModeBuild, LinkOptions: LinkOptions{DWARF: DWARFOmit}}, target: configurableDebugInfo()}, + {name: "direct target preserve", conf: Config{Mode: ModeBuild, Target: "rp2040", LinkOptions: LinkOptions{DWARF: DWARFPreserve}}, target: targetDebugInfo()}, + {name: "unsupported target", conf: Config{Mode: ModeBuild, LinkOptions: LinkOptions{DWARF: DWARFPreserve}}, target: unavailableDebugInfo()}, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + if got := dwarfPreserveLinkerArgs(&tt.conf, &tt.target); !reflect.DeepEqual(got, tt.want) { + t.Fatalf("dwarfPreserveLinkerArgs() = %v, want %v", got, tt.want) + } + }) + } +} + func TestEffectiveOmitDWARF(t *testing.T) { tests := []struct { name string @@ -71,7 +96,7 @@ func TestEffectiveOmitDWARF(t *testing.T) { {name: "safe default c-shared", conf: Config{BuildMode: BuildModeCShared, OmitDWARFByDefault: true}, want: true}, {name: "safe default c-archive", conf: Config{BuildMode: BuildModeCArchive, OmitDWARFByDefault: true}, want: true}, {name: "requested", conf: Config{LinkOptions: LinkOptions{DWARF: DWARFOmit}}, want: true}, - {name: "target baseline", target: alwaysOmitDebugInfo(), want: true}, + {name: "target baseline", target: unavailableDebugInfo(), want: true}, {name: "explicit preserve", conf: Config{LinkOptions: LinkOptions{DWARF: DWARFPreserve}}}, {name: "explicit preserve overrides safe default", conf: Config{OmitDWARFByDefault: true, LinkOptions: LinkOptions{DWARF: DWARFPreserve}}}, } @@ -100,7 +125,7 @@ func TestShouldEmitDebugInfo(t *testing.T) { {name: "linked s w false", conf: Config{Mode: ModeBuild, LinkOptions: LinkOptions{OmitSymbolTable: true, DWARF: DWARFPreserve}}, want: true}, {name: "generation default", conf: Config{Mode: ModeGen}}, {name: "generation requested", conf: Config{Mode: ModeGen, LinkOptions: LinkOptions{DWARF: DWARFPreserve}}, want: true}, - {name: "target always omits", conf: Config{Mode: ModeBuild}, target: alwaysOmitDebugInfo()}, + {name: "target without DWARF support", conf: Config{Mode: ModeBuild}, target: unavailableDebugInfo()}, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { @@ -130,8 +155,10 @@ func TestValidateLinkOptions(t *testing.T) { {name: "c-archive omit", conf: Config{Goos: "linux", BuildMode: BuildModeCArchive, LinkOptions: w}, target: configurableDebugInfo()}, {name: "c-shared preserve", conf: Config{Goos: "linux", BuildMode: BuildModeCShared, LinkOptions: wFalse}, target: configurableDebugInfo()}, {name: "c-archive preserve", conf: Config{Goos: "linux", BuildMode: BuildModeCArchive, LinkOptions: wFalse}, target: configurableDebugInfo()}, - {name: "fixed target omit", conf: Config{Target: "rp2040", Goos: "linux", BuildMode: BuildModeExe, LinkOptions: w}, target: alwaysOmitDebugInfo()}, - {name: "fixed target explicit DWARF", conf: Config{Target: "rp2040", Goos: "linux", BuildMode: BuildModeExe, LinkOptions: wFalse}, target: alwaysOmitDebugInfo(), wantErr: true}, + {name: "target without DWARF support omit", conf: Config{Target: "custom", Goos: "linux", BuildMode: BuildModeExe, LinkOptions: w}, target: unavailableDebugInfo()}, + {name: "target without DWARF support preserve", conf: Config{Target: "custom", Goos: "linux", BuildMode: BuildModeExe, LinkOptions: wFalse}, target: unavailableDebugInfo(), wantErr: true}, + {name: "fixed target omit", conf: Config{Target: "rp2040", Goos: "linux", BuildMode: BuildModeExe, LinkOptions: w}, target: targetDebugInfo(), wantErr: false}, + {name: "fixed target preserve", conf: Config{Target: "rp2040", Goos: "linux", BuildMode: BuildModeExe, LinkOptions: wFalse}, target: targetDebugInfo()}, {name: "configurable WASI omit", conf: Config{Target: "wasi", Goos: "wasip1", BuildMode: BuildModeExe, LinkOptions: w}, target: configurableDebugInfo()}, {name: "configurable WASI preserve", conf: Config{Target: "wasi", Goos: "wasip1", BuildMode: BuildModeExe, LinkOptions: wFalse}, target: configurableDebugInfo()}, {name: "no omission", conf: Config{Goos: "windows", BuildMode: BuildModeExe, LinkOptions: wFalse}}, @@ -182,12 +209,82 @@ func TestDwarfLinkerArgsSuppressNativeInputDWARF(t *testing.T) { } } +func TestTargetDWARFDoesNotChangeLoadableELF(t *testing.T) { + dir := t.TempDir() + source := filepath.Join(dir, "main.c") + object := filepath.Join(dir, "main.o") + debugELF := filepath.Join(dir, "debug.elf") + strippedELF := filepath.Join(dir, "stripped.elf") + debugBin := filepath.Join(dir, "debug.bin") + strippedBin := filepath.Join(dir, "stripped.bin") + if err := os.WriteFile(source, []byte("volatile int value = 41; void Reset_Handler(void) { value++; for (;;) {} }\n"), 0o644); err != nil { + t.Fatal(err) + } + clang, err := exec.LookPath("clang") + if err != nil { + t.Fatal(err) + } + if out, err := exec.Command(clang, "--target=thumbv7em-none-unknown-eabi", "-g", "-ffreestanding", "-fno-unwind-tables", "-fno-asynchronous-unwind-tables", "-c", "-o", object, source).CombinedOutput(); err != nil { + t.Fatalf("compile Cortex-M DWARF fixture: %v\n%s", err, out) + } + linker, err := exec.LookPath("ld.lld") + if err != nil { + t.Fatal(err) + } + repoRoot, err := filepath.Abs(filepath.Join("..", "..")) + if err != nil { + t.Fatal(err) + } + linkerScript := filepath.Join(repoRoot, "targets", "lm3s6965.ld") + link := func(path string, opts LinkOptions) { + t.Helper() + conf := &Config{Target: "cortex-m", BuildMode: BuildModeExe, LinkOptions: opts} + target := targetDebugInfo() + args := append(dwarfLinkerArgs(conf, &target), "-T", linkerScript, "-L", repoRoot, "-o", path, object) + if out, err := exec.Command(linker, args...).CombinedOutput(); err != nil { + t.Fatalf("link Cortex-M fixture: %v\n%s", err, out) + } + } + link(debugELF, LinkOptions{DWARF: DWARFPreserve}) + link(strippedELF, LinkOptions{DWARF: DWARFOmit}) + if !elfHasDebugInfo(t, debugELF) { + t.Fatal("preserved Cortex-M ELF has no debug information") + } + if elfHasDebugInfo(t, strippedELF) { + t.Fatal("omitted Cortex-M ELF still has debug information") + } + if err := firmware.ConvertFormats("", "", map[string]string{"out": debugELF, "bin": debugBin}); err != nil { + t.Fatal(err) + } + if err := firmware.ConvertFormats("", "", map[string]string{"out": strippedELF, "bin": strippedBin}); err != nil { + t.Fatal(err) + } + debugImage, err := os.ReadFile(debugBin) + if err != nil { + t.Fatal(err) + } + strippedImage, err := os.ReadFile(strippedBin) + if err != nil { + t.Fatal(err) + } + if len(debugImage) == 0 || !bytes.Equal(debugImage, strippedImage) { + t.Fatal("DWARF changed Cortex-M flashed bytes") + } +} + func configurableDebugInfo() crosscompile.Export { - return crosscompile.Export{DebugInfo: crosscompile.DebugInfoPolicy{OmitLinkFlags: []string{"-Wl,-S"}}} + return crosscompile.Export{DebugInfo: crosscompile.DebugInfoPolicy{ + PreserveLinkFlags: []string{"-gdwarf-4"}, + OmitLinkFlags: []string{"-Wl,-S"}, + }} +} + +func targetDebugInfo() crosscompile.Export { + return crosscompile.Export{DebugInfo: crosscompile.DebugInfoPolicy{OmitLinkFlags: []string{"-S"}}} } -func alwaysOmitDebugInfo() crosscompile.Export { - return crosscompile.Export{DebugInfo: crosscompile.DebugInfoPolicy{AlwaysOmit: true}} +func unavailableDebugInfo() crosscompile.Export { + return crosscompile.Export{DebugInfo: crosscompile.DebugInfoPolicy{Capability: crosscompile.DebugInfoUnavailable}} } func elfHasDebugInfo(t *testing.T, path string) bool { diff --git a/internal/crosscompile/crosscompile.go b/internal/crosscompile/crosscompile.go index c017c7e5f4..46916a96dc 100644 --- a/internal/crosscompile/crosscompile.go +++ b/internal/crosscompile/crosscompile.go @@ -47,21 +47,50 @@ type Export struct { Device flash.Device // Device configuration for flashing/debugging } +// DebugInfoCapability describes whether the selected linker and its linked +// output format can retain DWARF. Deployment formats such as bin, hex, and uf2 +// are derived later and do not affect this capability. +type DebugInfoCapability uint8 + +const ( + DebugInfoRetainable DebugInfoCapability = iota + DebugInfoUnavailable +) + // DebugInfoPolicy describes how a selected linker handles debug information. // Build orchestration consumes this typed capability instead of inferring it // from a target name or linker executable. type DebugInfoPolicy struct { - AlwaysOmit bool - OmitLinkFlags []string + Capability DebugInfoCapability + PreserveLinkFlags []string + OmitLinkFlags []string +} + +func (p DebugInfoPolicy) CanRetain() bool { + return p.Capability == DebugInfoRetainable } func nativeDebugInfoPolicy(goos string) DebugInfoPolicy { + policy := DebugInfoPolicy{PreserveLinkFlags: []string{"-gdwarf-4"}} switch goos { case "darwin", "linux": - return DebugInfoPolicy{OmitLinkFlags: []string{"-Wl,-S"}} - default: - return DebugInfoPolicy{} + policy.OmitLinkFlags = []string{"-Wl,-S"} } + return policy +} + +func targetDebugInfoPolicy(linker, llvmTarget string) DebugInfoPolicy { + switch linker { + case "ld.lld": + if !strings.HasPrefix(llvmTarget, "wasm") { + return DebugInfoPolicy{OmitLinkFlags: []string{"-S"}} + } + case "wasm-ld": + if strings.HasPrefix(llvmTarget, "wasm") { + return DebugInfoPolicy{OmitLinkFlags: []string{"-S"}} + } + } + return DebugInfoPolicy{Capability: DebugInfoUnavailable} } // URLs and configuration that can be overridden for testing @@ -333,7 +362,10 @@ func use(goos, goarch string, wasiThreads, forceEspClang bool, level optlevel.Le if goarch != "wasm" { return } - export.DebugInfo.OmitLinkFlags = []string{"-Wl,-S"} + export.DebugInfo = DebugInfoPolicy{ + PreserveLinkFlags: []string{"-gdwarf-4"}, + OmitLinkFlags: []string{"-Wl,-S"}, + } // Configure based on GOOS switch goos { @@ -504,7 +536,7 @@ func UseTarget(targetName string, level optlevel.Level, ltoMode lto.Mode) (expor export.BinaryFormat = config.BinaryFormat export.FormatDetail = config.FormatDetail() export.Emulator = config.Emulator - export.DebugInfo.AlwaysOmit = true + export.DebugInfo = targetDebugInfoPolicy(config.Linker, config.LLVMTarget) // Set flashing/debugging configuration export.Device = flash.Device{ @@ -531,7 +563,7 @@ func UseTarget(targetName string, level optlevel.Level, ltoMode lto.Mode) (expor // Convert LLVMTarget, CPU, Features to CCFLAGS/LDFLAGS // ICF off for Go pc-identity semantics (see the non-cross flags above). - ldflags := []string{"-S", "--icf=none"} + ldflags := []string{"--icf=none"} ccflags := []string{level.Flag()} cflags := []string{"-Wno-override-module", "-Qunused-arguments", "-Wno-unused-command-line-argument"} if config.LLVMTarget != "" { diff --git a/internal/crosscompile/crosscompile_test.go b/internal/crosscompile/crosscompile_test.go index ea89a9596a..7bbe5c5628 100644 --- a/internal/crosscompile/crosscompile_test.go +++ b/internal/crosscompile/crosscompile_test.go @@ -248,11 +248,14 @@ func TestUseTarget(t *testing.T) { if err != nil { t.Fatalf("Unexpected error for target %s: %v", tc.targetName, err) } - if !export.DebugInfo.AlwaysOmit { - t.Fatalf("target %s debug-info policy = %+v, want AlwaysOmit", tc.targetName, export.DebugInfo) + if !export.DebugInfo.CanRetain() { + t.Fatalf("target %s debug-info policy = %+v, want retainable ELF DWARF", tc.targetName, export.DebugInfo) } - if !slices.Contains(export.LDFLAGS, "-S") { - t.Fatalf("target %s declares AlwaysOmit without linker -S: %v", tc.targetName, export.LDFLAGS) + if slices.Contains(export.LDFLAGS, "-S") { + t.Fatalf("target %s unconditionally strips DWARF: %v", tc.targetName, export.LDFLAGS) + } + if !slices.Equal(export.DebugInfo.OmitLinkFlags, []string{"-S"}) { + t.Fatalf("target %s debug omission flags = %v, want [-S]", tc.targetName, export.DebugInfo.OmitLinkFlags) } // Check if LLVM target is in CCFLAGS @@ -344,7 +347,9 @@ func TestUseWithTarget(t *testing.T) { t.Error("Expected LDFLAGS to be set for native build") } wantDebugInfo := nativeDebugInfoPolicy(runtime.GOOS) - if export.DebugInfo.AlwaysOmit != wantDebugInfo.AlwaysOmit || !slices.Equal(export.DebugInfo.OmitLinkFlags, wantDebugInfo.OmitLinkFlags) { + if export.DebugInfo.Capability != wantDebugInfo.Capability || + !slices.Equal(export.DebugInfo.PreserveLinkFlags, wantDebugInfo.PreserveLinkFlags) || + !slices.Equal(export.DebugInfo.OmitLinkFlags, wantDebugInfo.OmitLinkFlags) { t.Fatalf("native debug-info policy = %+v, want %+v", export.DebugInfo, wantDebugInfo) } } @@ -362,7 +367,9 @@ func TestNativeDebugInfoPolicy(t *testing.T) { for _, tt := range tests { t.Run(tt.goos, func(t *testing.T) { policy := nativeDebugInfoPolicy(tt.goos) - got := !policy.AlwaysOmit && slices.Equal(policy.OmitLinkFlags, []string{"-Wl,-S"}) + got := policy.CanRetain() && + slices.Equal(policy.PreserveLinkFlags, []string{"-gdwarf-4"}) && + slices.Equal(policy.OmitLinkFlags, []string{"-Wl,-S"}) if got != tt.supported { t.Fatalf("nativeDebugInfoPolicy(%q) = %+v, supported = %v", tt.goos, policy, got) } @@ -370,6 +377,30 @@ func TestNativeDebugInfoPolicy(t *testing.T) { } } +func TestTargetDebugInfoPolicy(t *testing.T) { + tests := []struct { + name string + linker string + target string + canRetain bool + omitFlags []string + }{ + {name: "ELF lld", linker: "ld.lld", target: "thumbv7em-none-unknown-eabi", canRetain: true, omitFlags: []string{"-S"}}, + {name: "Wasm lld", linker: "wasm-ld", target: "wasm32-unknown-unknown", canRetain: true, omitFlags: []string{"-S"}}, + {name: "mismatched ELF linker", linker: "ld.lld", target: "wasm32-unknown-unknown"}, + {name: "mismatched Wasm linker", linker: "wasm-ld", target: "thumbv7em-none-unknown-eabi"}, + {name: "unknown linker", linker: "custom-ld", target: "thumbv7em-none-unknown-eabi"}, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + got := targetDebugInfoPolicy(tt.linker, tt.target) + if got.CanRetain() != tt.canRetain || !slices.Equal(got.OmitLinkFlags, tt.omitFlags) { + t.Fatalf("targetDebugInfoPolicy(%q, %q) = %+v, want retain=%v flags=%v", tt.linker, tt.target, got, tt.canRetain, tt.omitFlags) + } + }) + } +} + func TestOptimizationFlagPlacement(t *testing.T) { export, err := UseTarget("rp2040", optlevel.Oz, lto.Off) if err != nil { From a16528cf86ec046c1e8773a177161d32078ea5de Mon Sep 17 00:00:00 2001 From: Li Jie Date: Mon, 10 Aug 2026 03:21:17 +0800 Subject: [PATCH 73/73] debug: clarify target DWARF policy paths --- internal/build/link_options.go | 7 ++++--- internal/crosscompile/crosscompile.go | 28 +++++++++++++++++++-------- 2 files changed, 24 insertions(+), 11 deletions(-) diff --git a/internal/build/link_options.go b/internal/build/link_options.go index 8d1370920a..dcc851eb18 100644 --- a/internal/build/link_options.go +++ b/internal/build/link_options.go @@ -131,9 +131,10 @@ func dwarfLinkerArgs(conf *Config, target *crosscompile.Export) []string { return slices.Clone(target.DebugInfo.OmitLinkFlags) } -// dwarfPreserveLinkerArgs returns compiler-driver options needed while linking -// a debug artifact. Direct linkers such as ld.lld retain input DWARF without a -// corresponding flag, while clang-compatible drivers accept -gdwarf-4. +// dwarfPreserveLinkerArgs returns options needed while linking a debug +// artifact. Direct linker invocations retain input DWARF without a preserve +// flag, while clang-driver invocations need -gdwarf-4; the invocation path, +// rather than the linker executable name, determines the option. func dwarfPreserveLinkerArgs(conf *Config, target *crosscompile.Export) []string { if !shouldEmitDebugInfo(conf, target) { return nil diff --git a/internal/crosscompile/crosscompile.go b/internal/crosscompile/crosscompile.go index 46916a96dc..7b25668995 100644 --- a/internal/crosscompile/crosscompile.go +++ b/internal/crosscompile/crosscompile.go @@ -70,11 +70,22 @@ func (p DebugInfoPolicy) CanRetain() bool { return p.Capability == DebugInfoRetainable } +// driverDebugInfoPolicy describes a link performed through a clang-compatible +// driver. The driver needs an explicit DWARF version while its linker flag +// spelling uses -Wl,-S. +func driverDebugInfoPolicy() DebugInfoPolicy { + return DebugInfoPolicy{ + PreserveLinkFlags: []string{"-gdwarf-4"}, + OmitLinkFlags: []string{"-Wl,-S"}, + } +} + func nativeDebugInfoPolicy(goos string) DebugInfoPolicy { - policy := DebugInfoPolicy{PreserveLinkFlags: []string{"-gdwarf-4"}} - switch goos { - case "darwin", "linux": - policy.OmitLinkFlags = []string{"-Wl,-S"} + policy := driverDebugInfoPolicy() + if goos != "darwin" && goos != "linux" { + // The driver still accepts the preserve flag, but these native targets + // do not have a supported omit-DWARF spelling. + policy.OmitLinkFlags = nil } return policy } @@ -86,10 +97,14 @@ func targetDebugInfoPolicy(linker, llvmTarget string) DebugInfoPolicy { return DebugInfoPolicy{OmitLinkFlags: []string{"-S"}} } case "wasm-ld": + // Use routes wasm/wasi names through the clang-driver path. Keep this + // direct wasm-ld policy for target-policy callers and tests. if strings.HasPrefix(llvmTarget, "wasm") { return DebugInfoPolicy{OmitLinkFlags: []string{"-S"}} } } + // Unknown linker/target pairs intentionally fail closed: without a known + // retention policy, generated DWARF must not be promised to callers. return DebugInfoPolicy{Capability: DebugInfoUnavailable} } @@ -362,10 +377,7 @@ func use(goos, goarch string, wasiThreads, forceEspClang bool, level optlevel.Le if goarch != "wasm" { return } - export.DebugInfo = DebugInfoPolicy{ - PreserveLinkFlags: []string{"-gdwarf-4"}, - OmitLinkFlags: []string{"-Wl,-S"}, - } + export.DebugInfo = driverDebugInfoPolicy() // Configure based on GOOS switch goos {