mirror of
https://github.com/tinygo-org/tinygo.git
synced 2026-08-20 04:19:04 +00:00
all: modernize (#5498)
* modernize string cut usage * modernize string cut prefix usage * modernize slices helper usage * modernize min and max usage * modernize loop variable copies * modernize integer range loops * modernize map copy loops * modernize go types iterator usage * modernize empty interface usage * modernize atomic type usage * modernize string builders * modernize string split iteration * modernize remaining loop variable copies * modernize usb cdc min usage * modernize src integer range loops * modernize example empty interface usage * modernize src min and max usage * modernize src integer range loops * modernize src empty interface usage * modernize src atomic type usage * modernize reflect type lookups * modernize review nits
This commit is contained in:
+3
-6
@@ -14,6 +14,7 @@ import (
|
|||||||
"fmt"
|
"fmt"
|
||||||
"go/types"
|
"go/types"
|
||||||
"hash/crc32"
|
"hash/crc32"
|
||||||
|
"maps"
|
||||||
"math/bits"
|
"math/bits"
|
||||||
"os"
|
"os"
|
||||||
"os/exec"
|
"os/exec"
|
||||||
@@ -137,9 +138,7 @@ func Build(pkgName, outpath, tmpdir string, config *compileopts.Config) (BuildRe
|
|||||||
if _, ok := globalValues[pkgPath]; !ok {
|
if _, ok := globalValues[pkgPath]; !ok {
|
||||||
globalValues[pkgPath] = map[string]string{}
|
globalValues[pkgPath] = map[string]string{}
|
||||||
}
|
}
|
||||||
for k, v := range vals {
|
maps.Copy(globalValues[pkgPath], vals)
|
||||||
globalValues[pkgPath][k] = v
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check for a libc dependency.
|
// Check for a libc dependency.
|
||||||
@@ -278,7 +277,6 @@ func Build(pkgName, outpath, tmpdir string, config *compileopts.Config) (BuildRe
|
|||||||
|
|
||||||
var embedFileObjects []*compileJob
|
var embedFileObjects []*compileJob
|
||||||
for _, pkg := range lprogram.Sorted() {
|
for _, pkg := range lprogram.Sorted() {
|
||||||
pkg := pkg // necessary to avoid a race condition
|
|
||||||
|
|
||||||
var undefinedGlobals []string
|
var undefinedGlobals []string
|
||||||
for name := range globalValues[pkg.Pkg.Path()] {
|
for name := range globalValues[pkg.Pkg.Path()] {
|
||||||
@@ -775,7 +773,6 @@ func Build(pkgName, outpath, tmpdir string, config *compileopts.Config) (BuildRe
|
|||||||
// TODO: do this as part of building the package to be able to link the
|
// TODO: do this as part of building the package to be able to link the
|
||||||
// bitcode files together.
|
// bitcode files together.
|
||||||
for _, pkg := range lprogram.Sorted() {
|
for _, pkg := range lprogram.Sorted() {
|
||||||
pkg := pkg
|
|
||||||
for _, filename := range pkg.CFiles {
|
for _, filename := range pkg.CFiles {
|
||||||
abspath := filepath.Join(pkg.OriginalDir(), filename)
|
abspath := filepath.Join(pkg.OriginalDir(), filename)
|
||||||
job := &compileJob{
|
job := &compileJob{
|
||||||
@@ -914,7 +911,7 @@ func Build(pkgName, outpath, tmpdir string, config *compileopts.Config) (BuildRe
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Run wasm-opt for wasm binaries
|
// Run wasm-opt for wasm binaries
|
||||||
if arch := strings.Split(config.Triple(), "-")[0]; arch == "wasm32" {
|
if arch, _, _ := strings.Cut(config.Triple(), "-"); arch == "wasm32" {
|
||||||
optLevel, _, _ := config.OptLevel()
|
optLevel, _, _ := config.OptLevel()
|
||||||
opt := "-" + optLevel
|
opt := "-" + optLevel
|
||||||
|
|
||||||
|
|||||||
@@ -47,7 +47,6 @@ func TestClangAttributes(t *testing.T) {
|
|||||||
targetNames = append(targetNames, "esp32", "esp8266")
|
targetNames = append(targetNames, "esp32", "esp8266")
|
||||||
}
|
}
|
||||||
for _, targetName := range targetNames {
|
for _, targetName := range targetNames {
|
||||||
targetName := targetName
|
|
||||||
t.Run(targetName, func(t *testing.T) {
|
t.Run(targetName, func(t *testing.T) {
|
||||||
testClangAttributes(t, &compileopts.Options{Target: targetName})
|
testClangAttributes(t, &compileopts.Options{Target: targetName})
|
||||||
})
|
})
|
||||||
|
|||||||
+1
-1
@@ -281,7 +281,7 @@ func parseDepFile(s string) ([]string, error) {
|
|||||||
s = strings.ReplaceAll(s, "\\\n", " ")
|
s = strings.ReplaceAll(s, "\\\n", " ")
|
||||||
|
|
||||||
// Only use the first line, which is expected to begin with "deps:".
|
// Only use the first line, which is expected to begin with "deps:".
|
||||||
line := strings.SplitN(s, "\n", 2)[0]
|
line, _, _ := strings.Cut(s, "\n")
|
||||||
if !strings.HasPrefix(line, "deps:") {
|
if !strings.HasPrefix(line, "deps:") {
|
||||||
return nil, errors.New("readDepFile: expected 'deps:' prefix")
|
return nil, errors.New("readDepFile: expected 'deps:' prefix")
|
||||||
}
|
}
|
||||||
|
|||||||
+1
-1
@@ -17,7 +17,7 @@ import (
|
|||||||
var commands = map[string][]string{}
|
var commands = map[string][]string{}
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
llvmMajor := strings.Split(llvm.Version, ".")[0]
|
llvmMajor, _, _ := strings.Cut(llvm.Version, ".")
|
||||||
commands["clang"] = []string{"clang-" + llvmMajor}
|
commands["clang"] = []string{"clang-" + llvmMajor}
|
||||||
commands["ld.lld"] = []string{"ld.lld-" + llvmMajor, "ld.lld"}
|
commands["ld.lld"] = []string{"ld.lld-" + llvmMajor, "ld.lld"}
|
||||||
commands["wasm-ld"] = []string{"wasm-ld-" + llvmMajor, "wasm-ld"}
|
commands["wasm-ld"] = []string{"wasm-ld-" + llvmMajor, "wasm-ld"}
|
||||||
|
|||||||
@@ -15,7 +15,7 @@ func makeDarwinLibSystemJob(config *compileopts.Config, tmpdir string) *compileJ
|
|||||||
return &compileJob{
|
return &compileJob{
|
||||||
description: "compile Darwin libSystem.dylib",
|
description: "compile Darwin libSystem.dylib",
|
||||||
run: func(job *compileJob) (err error) {
|
run: func(job *compileJob) (err error) {
|
||||||
arch := strings.Split(config.Triple(), "-")[0]
|
arch, _, _ := strings.Cut(config.Triple(), "-")
|
||||||
job.result = filepath.Join(tmpdir, "libSystem.dylib")
|
job.result = filepath.Join(tmpdir, "libSystem.dylib")
|
||||||
objpath := filepath.Join(tmpdir, "libSystem.o")
|
objpath := filepath.Join(tmpdir, "libSystem.o")
|
||||||
inpath := filepath.Join(goenv.Get("TINYGOROOT"), "lib/macos-minimal-sdk/src", arch, "libSystem.s")
|
inpath := filepath.Join(goenv.Get("TINYGOROOT"), "lib/macos-minimal-sdk/src", arch, "libSystem.s")
|
||||||
|
|||||||
+2
-2
@@ -195,11 +195,11 @@ type intHeap struct {
|
|||||||
sort.IntSlice
|
sort.IntSlice
|
||||||
}
|
}
|
||||||
|
|
||||||
func (h *intHeap) Push(x interface{}) {
|
func (h *intHeap) Push(x any) {
|
||||||
h.IntSlice = append(h.IntSlice, x.(int))
|
h.IntSlice = append(h.IntSlice, x.(int))
|
||||||
}
|
}
|
||||||
|
|
||||||
func (h *intHeap) Pop() interface{} {
|
func (h *intHeap) Pop() any {
|
||||||
x := h.IntSlice[len(h.IntSlice)-1]
|
x := h.IntSlice[len(h.IntSlice)-1]
|
||||||
h.IntSlice = h.IntSlice[:len(h.IntSlice)-1]
|
h.IntSlice = h.IntSlice[:len(h.IntSlice)-1]
|
||||||
return x
|
return x
|
||||||
|
|||||||
@@ -232,7 +232,6 @@ func (l *Library) load(config *compileopts.Config, tmpdir string) (job *compileJ
|
|||||||
}
|
}
|
||||||
for _, path := range paths {
|
for _, path := range paths {
|
||||||
// Strip leading "../" parts off the path.
|
// Strip leading "../" parts off the path.
|
||||||
path := path
|
|
||||||
cleanpath := path
|
cleanpath := path
|
||||||
for strings.HasPrefix(cleanpath, "../") {
|
for strings.HasPrefix(cleanpath, "../") {
|
||||||
cleanpath = cleanpath[3:]
|
cleanpath = cleanpath[3:]
|
||||||
|
|||||||
+2
-2
@@ -28,8 +28,8 @@ func buildMuslAllTypes(arch, muslDir, outputBitsDir string) error {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
lines := strings.Split(string(data), "\n")
|
lines := strings.SplitSeq(string(data), "\n")
|
||||||
for _, line := range lines {
|
for line := range lines {
|
||||||
if strings.HasPrefix(line, "TYPEDEF ") {
|
if strings.HasPrefix(line, "TYPEDEF ") {
|
||||||
matches := regexp.MustCompile(`TYPEDEF (.*) ([^ ]*);`).FindStringSubmatch(line)
|
matches := regexp.MustCompile(`TYPEDEF (.*) ([^ ]*);`).FindStringSubmatch(line)
|
||||||
value := matches[1]
|
value := matches[1]
|
||||||
|
|||||||
@@ -51,7 +51,6 @@ func TestBinarySize(t *testing.T) {
|
|||||||
// output varies by binaryen version.
|
// output varies by binaryen version.
|
||||||
}
|
}
|
||||||
for _, tc := range tests {
|
for _, tc := range tests {
|
||||||
tc := tc
|
|
||||||
t.Run(tc.target+"/"+tc.path, func(t *testing.T) {
|
t.Run(tc.target+"/"+tc.path, func(t *testing.T) {
|
||||||
t.Parallel()
|
t.Parallel()
|
||||||
|
|
||||||
@@ -85,7 +84,6 @@ func TestSizeFull(t *testing.T) {
|
|||||||
pkgMatch := regexp.MustCompile(`^[a-z/]+$`) // example: "internal/task"
|
pkgMatch := regexp.MustCompile(`^[a-z/]+$`) // example: "internal/task"
|
||||||
|
|
||||||
for _, target := range tests {
|
for _, target := range tests {
|
||||||
target := target
|
|
||||||
t.Run(target, func(t *testing.T) {
|
t.Run(target, func(t *testing.T) {
|
||||||
t.Parallel()
|
t.Parallel()
|
||||||
|
|
||||||
|
|||||||
+1
-1
@@ -116,7 +116,7 @@ func parseLLDErrors(text string) error {
|
|||||||
// This can happen in some cases like with CGo and //go:linkname tricker.
|
// This can happen in some cases like with CGo and //go:linkname tricker.
|
||||||
if matches := regexp.MustCompile(`^ld.lld(-[0-9]+)?: error: undefined symbol: (.*)\n`).FindStringSubmatch(message); matches != nil {
|
if matches := regexp.MustCompile(`^ld.lld(-[0-9]+)?: error: undefined symbol: (.*)\n`).FindStringSubmatch(message); matches != nil {
|
||||||
symbolName := matches[2]
|
symbolName := matches[2]
|
||||||
for _, line := range strings.Split(message, "\n") {
|
for line := range strings.SplitSeq(message, "\n") {
|
||||||
matches := regexp.MustCompile(`referenced by .* \(((.*):([0-9]+))\)`).FindStringSubmatch(line)
|
matches := regexp.MustCompile(`referenced by .* \(((.*):([0-9]+))\)`).FindStringSubmatch(line)
|
||||||
if matches != nil {
|
if matches != nil {
|
||||||
parsedError = true
|
parsedError = true
|
||||||
|
|||||||
+1
-1
@@ -40,7 +40,7 @@ func convertBinToUF2(input []byte, targetAddr uint32, uf2FamilyID string) ([]byt
|
|||||||
}
|
}
|
||||||
bl.SetNumBlocks(len(blocks))
|
bl.SetNumBlocks(len(blocks))
|
||||||
|
|
||||||
for i := 0; i < len(blocks); i++ {
|
for i := range blocks {
|
||||||
bl.SetBlockNo(i)
|
bl.SetBlockNo(i)
|
||||||
bl.SetData(blocks[i])
|
bl.SetData(blocks[i])
|
||||||
|
|
||||||
|
|||||||
+10
-8
@@ -40,7 +40,7 @@ type cgoPackage struct {
|
|||||||
tokenFiles map[string]*token.File
|
tokenFiles map[string]*token.File
|
||||||
definedGlobally map[string]ast.Node
|
definedGlobally map[string]ast.Node
|
||||||
noescapingFuncs map[string]*noescapingFunc // #cgo noescape lines
|
noescapingFuncs map[string]*noescapingFunc // #cgo noescape lines
|
||||||
anonDecls map[interface{}]string
|
anonDecls map[any]string
|
||||||
cflags []string // CFlags from #cgo lines
|
cflags []string // CFlags from #cgo lines
|
||||||
ldflags []string // LDFlags from #cgo lines
|
ldflags []string // LDFlags from #cgo lines
|
||||||
visitedFiles map[string][]byte
|
visitedFiles map[string][]byte
|
||||||
@@ -259,7 +259,7 @@ func Process(files []*ast.File, dir, importPath string, fset *token.FileSet, cfl
|
|||||||
tokenFiles: map[string]*token.File{},
|
tokenFiles: map[string]*token.File{},
|
||||||
definedGlobally: map[string]ast.Node{},
|
definedGlobally: map[string]ast.Node{},
|
||||||
noescapingFuncs: map[string]*noescapingFunc{},
|
noescapingFuncs: map[string]*noescapingFunc{},
|
||||||
anonDecls: map[interface{}]string{},
|
anonDecls: map[any]string{},
|
||||||
visitedFiles: map[string][]byte{},
|
visitedFiles: map[string][]byte{},
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -302,7 +302,7 @@ func Process(files []*ast.File, dir, importPath string, fset *token.FileSet, cfl
|
|||||||
// Find `import "C"` C fragments in the file.
|
// Find `import "C"` C fragments in the file.
|
||||||
p.cgoHeaders = make([]string, len(files)) // combined CGo header fragment for each file
|
p.cgoHeaders = make([]string, len(files)) // combined CGo header fragment for each file
|
||||||
for i, f := range files {
|
for i, f := range files {
|
||||||
var cgoHeader string
|
var cgoHeader strings.Builder
|
||||||
for i := 0; i < len(f.Decls); i++ {
|
for i := 0; i < len(f.Decls); i++ {
|
||||||
decl := f.Decls[i]
|
decl := f.Decls[i]
|
||||||
genDecl, ok := decl.(*ast.GenDecl)
|
genDecl, ok := decl.(*ast.GenDecl)
|
||||||
@@ -337,7 +337,8 @@ func Process(files []*ast.File, dir, importPath string, fset *token.FileSet, cfl
|
|||||||
// Iterate through all parts of the CGo header. Note that every //
|
// Iterate through all parts of the CGo header. Note that every //
|
||||||
// line is a new comment.
|
// line is a new comment.
|
||||||
position := fset.Position(genDecl.Doc.Pos())
|
position := fset.Position(genDecl.Doc.Pos())
|
||||||
fragment := fmt.Sprintf("# %d %#v\n", position.Line, position.Filename)
|
var fragment strings.Builder
|
||||||
|
fragment.WriteString(fmt.Sprintf("# %d %#v\n", position.Line, position.Filename))
|
||||||
for _, comment := range genDecl.Doc.List {
|
for _, comment := range genDecl.Doc.List {
|
||||||
// Find all #cgo lines, extract and use their contents, and
|
// Find all #cgo lines, extract and use their contents, and
|
||||||
// replace the lines with spaces (to preserve locations).
|
// replace the lines with spaces (to preserve locations).
|
||||||
@@ -354,12 +355,13 @@ func Process(files []*ast.File, dir, importPath string, fset *token.FileSet, cfl
|
|||||||
} else { // comment
|
} else { // comment
|
||||||
c = " " + c[2:len(c)-2]
|
c = " " + c[2:len(c)-2]
|
||||||
}
|
}
|
||||||
fragment += c + "\n"
|
fragment.WriteString(c)
|
||||||
|
fragment.WriteByte('\n')
|
||||||
}
|
}
|
||||||
cgoHeader += fragment
|
cgoHeader.WriteString(fragment.String())
|
||||||
}
|
}
|
||||||
|
|
||||||
p.cgoHeaders[i] = cgoHeader
|
p.cgoHeaders[i] = cgoHeader.String()
|
||||||
}
|
}
|
||||||
|
|
||||||
// Define CFlags that will be used while parsing the package.
|
// Define CFlags that will be used while parsing the package.
|
||||||
@@ -1217,7 +1219,7 @@ func getPos(node ast.Node) token.Pos {
|
|||||||
// getUnnamedDeclName creates a name (with the given prefix) for the given C
|
// getUnnamedDeclName creates a name (with the given prefix) for the given C
|
||||||
// declaration. This is used for structs, unions, and enums that are often
|
// declaration. This is used for structs, unions, and enums that are often
|
||||||
// defined without a name and used in a typedef.
|
// defined without a name and used in a typedef.
|
||||||
func (p *cgoPackage) getUnnamedDeclName(prefix string, itf interface{}) string {
|
func (p *cgoPackage) getUnnamedDeclName(prefix string, itf any) string {
|
||||||
if name, ok := p.anonDecls[itf]; ok {
|
if name, ok := p.anonDecls[itf]; ok {
|
||||||
return name
|
return name
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -45,7 +45,6 @@ func TestCGo(t *testing.T) {
|
|||||||
"flags",
|
"flags",
|
||||||
"const",
|
"const",
|
||||||
} {
|
} {
|
||||||
name := name // avoid a race condition
|
|
||||||
t.Run(name, func(t *testing.T) {
|
t.Run(name, func(t *testing.T) {
|
||||||
// Read the AST in memory.
|
// Read the AST in memory.
|
||||||
path := filepath.Join("testdata", name+".go")
|
path := filepath.Join("testdata", name+".go")
|
||||||
|
|||||||
+3
-3
@@ -160,7 +160,7 @@ func (f *cgoFile) readNames(fragment string, cflags []string, filename string, c
|
|||||||
pos := f.getClangLocationPosition(location, unit)
|
pos := f.getClangLocationPosition(location, unit)
|
||||||
f.addError(pos, severity+": "+spelling)
|
f.addError(pos, severity+": "+spelling)
|
||||||
}
|
}
|
||||||
for i := 0; i < numDiagnostics; i++ {
|
for i := range numDiagnostics {
|
||||||
diagnostic := C.clang_getDiagnostic(unit, C.uint(i))
|
diagnostic := C.clang_getDiagnostic(unit, C.uint(i))
|
||||||
addDiagnostic(diagnostic)
|
addDiagnostic(diagnostic)
|
||||||
|
|
||||||
@@ -278,7 +278,7 @@ func (f *cgoFile) createASTNode(name string, c clangCursor) (ast.Node, any) {
|
|||||||
Text: strings.Join(doc, "\n"),
|
Text: strings.Join(doc, "\n"),
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
for i := 0; i < numArgs; i++ {
|
for i := range numArgs {
|
||||||
arg := C.tinygo_clang_Cursor_getArgument(c, C.uint(i))
|
arg := C.tinygo_clang_Cursor_getArgument(c, C.uint(i))
|
||||||
argName := getString(C.tinygo_clang_getCursorSpelling(arg))
|
argName := getString(C.tinygo_clang_getCursorSpelling(arg))
|
||||||
argType := C.clang_getArgType(cursorType, C.uint(i))
|
argType := C.clang_getArgType(cursorType, C.uint(i))
|
||||||
@@ -534,7 +534,7 @@ func tinygo_clang_globals_visitor(c, parent C.GoCXCursor, client_data C.CXClient
|
|||||||
|
|
||||||
// Get the precise location in the source code. Used for uniquely identifying
|
// Get the precise location in the source code. Used for uniquely identifying
|
||||||
// source locations.
|
// source locations.
|
||||||
func (f *cgoFile) getUniqueLocationID(pos token.Pos, cursor C.GoCXCursor) interface{} {
|
func (f *cgoFile) getUniqueLocationID(pos token.Pos, cursor C.GoCXCursor) any {
|
||||||
clangLocation := C.tinygo_clang_getCursorLocation(cursor)
|
clangLocation := C.tinygo_clang_getCursorLocation(cursor)
|
||||||
var file C.CXFile
|
var file C.CXFile
|
||||||
var line C.unsigned
|
var line C.unsigned
|
||||||
|
|||||||
+4
-4
@@ -12,17 +12,17 @@ import "C"
|
|||||||
// C. It is useful if an API uses function pointers and you cannot pass a Go
|
// C. It is useful if an API uses function pointers and you cannot pass a Go
|
||||||
// pointer but only a C pointer.
|
// pointer but only a C pointer.
|
||||||
type refMap struct {
|
type refMap struct {
|
||||||
refs map[unsafe.Pointer]interface{}
|
refs map[unsafe.Pointer]any
|
||||||
lock sync.Mutex
|
lock sync.Mutex
|
||||||
}
|
}
|
||||||
|
|
||||||
// Put stores a value in the map. It can later be retrieved using Get. It must
|
// Put stores a value in the map. It can later be retrieved using Get. It must
|
||||||
// be removed using Remove to avoid memory leaks.
|
// be removed using Remove to avoid memory leaks.
|
||||||
func (m *refMap) Put(v interface{}) unsafe.Pointer {
|
func (m *refMap) Put(v any) unsafe.Pointer {
|
||||||
m.lock.Lock()
|
m.lock.Lock()
|
||||||
defer m.lock.Unlock()
|
defer m.lock.Unlock()
|
||||||
if m.refs == nil {
|
if m.refs == nil {
|
||||||
m.refs = make(map[unsafe.Pointer]interface{}, 1)
|
m.refs = make(map[unsafe.Pointer]any, 1)
|
||||||
}
|
}
|
||||||
ref := C.malloc(1)
|
ref := C.malloc(1)
|
||||||
m.refs[ref] = v
|
m.refs[ref] = v
|
||||||
@@ -31,7 +31,7 @@ func (m *refMap) Put(v interface{}) unsafe.Pointer {
|
|||||||
|
|
||||||
// Get returns a stored value previously inserted with Put. Use the same
|
// Get returns a stored value previously inserted with Put. Use the same
|
||||||
// reference as you got from Put.
|
// reference as you got from Put.
|
||||||
func (m *refMap) Get(ref unsafe.Pointer) interface{} {
|
func (m *refMap) Get(ref unsafe.Pointer) any {
|
||||||
m.lock.Lock()
|
m.lock.Lock()
|
||||||
defer m.lock.Unlock()
|
defer m.lock.Unlock()
|
||||||
return m.refs[ref]
|
return m.refs[ref]
|
||||||
|
|||||||
@@ -8,6 +8,7 @@ import (
|
|||||||
"os"
|
"os"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
"regexp"
|
"regexp"
|
||||||
|
"slices"
|
||||||
"strconv"
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
@@ -140,13 +141,7 @@ func (c *Config) GC() string {
|
|||||||
func (c *Config) NeedsStackObjects() bool {
|
func (c *Config) NeedsStackObjects() bool {
|
||||||
switch c.GC() {
|
switch c.GC() {
|
||||||
case "conservative", "custom", "precise", "boehm":
|
case "conservative", "custom", "precise", "boehm":
|
||||||
for _, tag := range c.BuildTags() {
|
return slices.Contains(c.BuildTags(), "tinygo.wasm")
|
||||||
if tag == "tinygo.wasm" {
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return false
|
|
||||||
default:
|
default:
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
@@ -245,7 +240,7 @@ func (c *Config) RP2040BootPatch() bool {
|
|||||||
// Return a canonicalized architecture name, so we don't have to deal with arm*
|
// Return a canonicalized architecture name, so we don't have to deal with arm*
|
||||||
// vs thumb* vs arm64.
|
// vs thumb* vs arm64.
|
||||||
func CanonicalArchName(triple string) string {
|
func CanonicalArchName(triple string) string {
|
||||||
arch := strings.Split(triple, "-")[0]
|
arch, _, _ := strings.Cut(triple, "-")
|
||||||
if arch == "arm64" {
|
if arch == "arm64" {
|
||||||
return "aarch64"
|
return "aarch64"
|
||||||
}
|
}
|
||||||
|
|||||||
+8
-16
@@ -3,6 +3,7 @@ package compileopts
|
|||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"regexp"
|
"regexp"
|
||||||
|
"slices"
|
||||||
"strings"
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
)
|
)
|
||||||
@@ -67,7 +68,7 @@ type Options struct {
|
|||||||
// Verify performs a validation on the given options, raising an error if options are not valid.
|
// Verify performs a validation on the given options, raising an error if options are not valid.
|
||||||
func (o *Options) Verify() error {
|
func (o *Options) Verify() error {
|
||||||
if o.BuildMode != "" {
|
if o.BuildMode != "" {
|
||||||
valid := isInArray(validBuildModeOptions, o.BuildMode)
|
valid := slices.Contains(validBuildModeOptions, o.BuildMode)
|
||||||
if !valid {
|
if !valid {
|
||||||
return fmt.Errorf(`invalid buildmode option '%s': valid values are %s`,
|
return fmt.Errorf(`invalid buildmode option '%s': valid values are %s`,
|
||||||
o.BuildMode,
|
o.BuildMode,
|
||||||
@@ -75,7 +76,7 @@ func (o *Options) Verify() error {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
if o.GC != "" {
|
if o.GC != "" {
|
||||||
valid := isInArray(validGCOptions, o.GC)
|
valid := slices.Contains(validGCOptions, o.GC)
|
||||||
if !valid {
|
if !valid {
|
||||||
return fmt.Errorf(`invalid gc option '%s': valid values are %s`,
|
return fmt.Errorf(`invalid gc option '%s': valid values are %s`,
|
||||||
o.GC,
|
o.GC,
|
||||||
@@ -84,7 +85,7 @@ func (o *Options) Verify() error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if o.Scheduler != "" {
|
if o.Scheduler != "" {
|
||||||
valid := isInArray(validSchedulerOptions, o.Scheduler)
|
valid := slices.Contains(validSchedulerOptions, o.Scheduler)
|
||||||
if !valid {
|
if !valid {
|
||||||
return fmt.Errorf(`invalid scheduler option '%s': valid values are %s`,
|
return fmt.Errorf(`invalid scheduler option '%s': valid values are %s`,
|
||||||
o.Scheduler,
|
o.Scheduler,
|
||||||
@@ -93,7 +94,7 @@ func (o *Options) Verify() error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if o.Serial != "" {
|
if o.Serial != "" {
|
||||||
valid := isInArray(validSerialOptions, o.Serial)
|
valid := slices.Contains(validSerialOptions, o.Serial)
|
||||||
if !valid {
|
if !valid {
|
||||||
return fmt.Errorf(`invalid serial option '%s': valid values are %s`,
|
return fmt.Errorf(`invalid serial option '%s': valid values are %s`,
|
||||||
o.Serial,
|
o.Serial,
|
||||||
@@ -102,7 +103,7 @@ func (o *Options) Verify() error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if o.PrintSizes != "" {
|
if o.PrintSizes != "" {
|
||||||
valid := isInArray(validPrintSizeOptions, o.PrintSizes)
|
valid := slices.Contains(validPrintSizeOptions, o.PrintSizes)
|
||||||
if !valid {
|
if !valid {
|
||||||
return fmt.Errorf(`invalid size option '%s': valid values are %s`,
|
return fmt.Errorf(`invalid size option '%s': valid values are %s`,
|
||||||
o.PrintSizes,
|
o.PrintSizes,
|
||||||
@@ -111,7 +112,7 @@ func (o *Options) Verify() error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if o.PanicStrategy != "" {
|
if o.PanicStrategy != "" {
|
||||||
valid := isInArray(validPanicStrategyOptions, o.PanicStrategy)
|
valid := slices.Contains(validPanicStrategyOptions, o.PanicStrategy)
|
||||||
if !valid {
|
if !valid {
|
||||||
return fmt.Errorf(`invalid panic option '%s': valid values are %s`,
|
return fmt.Errorf(`invalid panic option '%s': valid values are %s`,
|
||||||
o.PanicStrategy,
|
o.PanicStrategy,
|
||||||
@@ -120,19 +121,10 @@ func (o *Options) Verify() error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if o.Opt != "" {
|
if o.Opt != "" {
|
||||||
if !isInArray(validOptOptions, o.Opt) {
|
if !slices.Contains(validOptOptions, o.Opt) {
|
||||||
return fmt.Errorf("invalid -opt=%s: valid values are %s", o.Opt, strings.Join(validOptOptions, ", "))
|
return fmt.Errorf("invalid -opt=%s: valid values are %s", o.Opt, strings.Join(validOptOptions, ", "))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func isInArray(arr []string, item string) bool {
|
|
||||||
for _, i := range arr {
|
|
||||||
if i == item {
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -168,7 +168,7 @@ type builder struct {
|
|||||||
dilocals map[*types.Var]llvm.Metadata
|
dilocals map[*types.Var]llvm.Metadata
|
||||||
initInlinedAt llvm.Metadata // fake inlinedAt position
|
initInlinedAt llvm.Metadata // fake inlinedAt position
|
||||||
initPseudoFuncs map[string]llvm.Metadata // fake "inlined" functions for proper init debug locations
|
initPseudoFuncs map[string]llvm.Metadata // fake "inlined" functions for proper init debug locations
|
||||||
allDeferFuncs []interface{}
|
allDeferFuncs []any
|
||||||
deferFuncs map[*ssa.Function]int
|
deferFuncs map[*ssa.Function]int
|
||||||
deferInvokeFuncs map[string]int
|
deferInvokeFuncs map[string]int
|
||||||
deferClosureFuncs map[*ssa.Function]int
|
deferClosureFuncs map[*ssa.Function]int
|
||||||
@@ -2154,13 +2154,10 @@ func (c *compilerContext) maxSliceSize(elementType llvm.Type) uint64 {
|
|||||||
if elementSize == 0 {
|
if elementSize == 0 {
|
||||||
elementSize = 1
|
elementSize = 1
|
||||||
}
|
}
|
||||||
maxSize := maxPointerValue / elementSize
|
maxSize := min(
|
||||||
|
// len(slice) is an int. Make sure the length remains small enough to fit in
|
||||||
// len(slice) is an int. Make sure the length remains small enough to fit in
|
// an int.
|
||||||
// an int.
|
maxPointerValue/elementSize, maxIntegerValue)
|
||||||
if maxSize > maxIntegerValue {
|
|
||||||
maxSize = maxIntegerValue
|
|
||||||
}
|
|
||||||
|
|
||||||
return maxSize
|
return maxSize
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -188,9 +188,9 @@ func TestCompilerErrors(t *testing.T) {
|
|||||||
t.Error(err)
|
t.Error(err)
|
||||||
}
|
}
|
||||||
errorsFileString := strings.ReplaceAll(string(errorsFile), "\r\n", "\n")
|
errorsFileString := strings.ReplaceAll(string(errorsFile), "\r\n", "\n")
|
||||||
for _, line := range strings.Split(errorsFileString, "\n") {
|
for line := range strings.SplitSeq(errorsFileString, "\n") {
|
||||||
if strings.HasPrefix(line, "// ERROR: ") {
|
if after, ok := strings.CutPrefix(line, "// ERROR: "); ok {
|
||||||
expectedErrors = append(expectedErrors, strings.TrimPrefix(line, "// ERROR: "))
|
expectedErrors = append(expectedErrors, after)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+4
-4
@@ -669,8 +669,8 @@ func (b *builder) createRunDefers() {
|
|||||||
fn := callback.Fn.(*ssa.Function)
|
fn := callback.Fn.(*ssa.Function)
|
||||||
valueTypes := []llvm.Type{b.uintptrType, b.dataPtrType}
|
valueTypes := []llvm.Type{b.uintptrType, b.dataPtrType}
|
||||||
params := fn.Signature.Params()
|
params := fn.Signature.Params()
|
||||||
for i := 0; i < params.Len(); i++ {
|
for v := range params.Variables() {
|
||||||
valueTypes = append(valueTypes, b.getLLVMType(params.At(i).Type()))
|
valueTypes = append(valueTypes, b.getLLVMType(v.Type()))
|
||||||
}
|
}
|
||||||
valueTypes = append(valueTypes, b.dataPtrType) // closure
|
valueTypes = append(valueTypes, b.dataPtrType) // closure
|
||||||
deferredCallType := b.ctx.StructType(valueTypes, false)
|
deferredCallType := b.ctx.StructType(valueTypes, false)
|
||||||
@@ -695,8 +695,8 @@ func (b *builder) createRunDefers() {
|
|||||||
|
|
||||||
//Get signature from call results
|
//Get signature from call results
|
||||||
params := callback.Type().Underlying().(*types.Signature).Params()
|
params := callback.Type().Underlying().(*types.Signature).Params()
|
||||||
for i := 0; i < params.Len(); i++ {
|
for v := range params.Variables() {
|
||||||
valueTypes = append(valueTypes, b.getLLVMType(params.At(i).Type()))
|
valueTypes = append(valueTypes, b.getLLVMType(v.Type()))
|
||||||
}
|
}
|
||||||
|
|
||||||
deferredCallType := b.ctx.StructType(valueTypes, false)
|
deferredCallType := b.ctx.StructType(valueTypes, false)
|
||||||
|
|||||||
+2
-2
@@ -81,8 +81,8 @@ func (c *compilerContext) getLLVMFunctionType(typ *types.Signature) llvm.Type {
|
|||||||
paramTypes = append(paramTypes, info.llvmType)
|
paramTypes = append(paramTypes, info.llvmType)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
for i := 0; i < typ.Params().Len(); i++ {
|
for v := range typ.Params().Variables() {
|
||||||
subType := c.getLLVMType(typ.Params().At(i).Type())
|
subType := c.getLLVMType(v.Type())
|
||||||
for _, info := range c.expandFormalParamType(subType, "", nil) {
|
for _, info := range c.expandFormalParamType(subType, "", nil) {
|
||||||
paramTypes = append(paramTypes, info.llvmType)
|
paramTypes = append(paramTypes, info.llvmType)
|
||||||
}
|
}
|
||||||
|
|||||||
+4
-8
@@ -5,6 +5,7 @@ package compiler
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"go/token"
|
"go/token"
|
||||||
|
"slices"
|
||||||
|
|
||||||
"golang.org/x/tools/go/ssa"
|
"golang.org/x/tools/go/ssa"
|
||||||
"tinygo.org/x/go-llvm"
|
"tinygo.org/x/go-llvm"
|
||||||
@@ -88,7 +89,7 @@ func (b *builder) trackValue(value llvm.Value) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
numElements := typ.StructElementTypesCount()
|
numElements := typ.StructElementTypesCount()
|
||||||
for i := 0; i < numElements; i++ {
|
for i := range numElements {
|
||||||
subValue := b.CreateExtractValue(value, i, "")
|
subValue := b.CreateExtractValue(value, i, "")
|
||||||
b.trackValue(subValue)
|
b.trackValue(subValue)
|
||||||
}
|
}
|
||||||
@@ -97,7 +98,7 @@ func (b *builder) trackValue(value llvm.Value) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
numElements := typ.ArrayLength()
|
numElements := typ.ArrayLength()
|
||||||
for i := 0; i < numElements; i++ {
|
for i := range numElements {
|
||||||
subValue := b.CreateExtractValue(value, i, "")
|
subValue := b.CreateExtractValue(value, i, "")
|
||||||
b.trackValue(subValue)
|
b.trackValue(subValue)
|
||||||
}
|
}
|
||||||
@@ -118,12 +119,7 @@ func typeHasPointers(t llvm.Type) bool {
|
|||||||
case llvm.PointerTypeKind:
|
case llvm.PointerTypeKind:
|
||||||
return true
|
return true
|
||||||
case llvm.StructTypeKind:
|
case llvm.StructTypeKind:
|
||||||
for _, subType := range t.StructElementTypes() {
|
return slices.ContainsFunc(t.StructElementTypes(), typeHasPointers)
|
||||||
if typeHasPointers(subType) {
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return false
|
|
||||||
case llvm.ArrayTypeKind:
|
case llvm.ArrayTypeKind:
|
||||||
if t.ArrayLength() == 0 {
|
if t.ArrayLength() == 0 {
|
||||||
return false
|
return false
|
||||||
|
|||||||
@@ -414,7 +414,7 @@ func (c *compilerContext) createGoroutineStartWrapper(fnType llvm.Type, fn llvm.
|
|||||||
// Extract parameters from the state object, and call the function
|
// Extract parameters from the state object, and call the function
|
||||||
// that's being wrapped.
|
// that's being wrapped.
|
||||||
var callParams []llvm.Value
|
var callParams []llvm.Value
|
||||||
for i := 0; i < numParams; i++ {
|
for i := range numParams {
|
||||||
gep := b.CreateInBoundsGEP(stateStruct, statePtr, []llvm.Value{
|
gep := b.CreateInBoundsGEP(stateStruct, statePtr, []llvm.Value{
|
||||||
llvm.ConstInt(b.ctx.Int32Type(), 0, false),
|
llvm.ConstInt(b.ctx.Int32Type(), 0, false),
|
||||||
llvm.ConstInt(b.ctx.Int32Type(), uint64(i), false),
|
llvm.ConstInt(b.ctx.Int32Type(), uint64(i), false),
|
||||||
|
|||||||
+12
-10
@@ -146,13 +146,14 @@ func (b *builder) emitSVCall(args []ssa.Value, pos token.Pos) (llvm.Value, error
|
|||||||
llvmArgs := []llvm.Value{}
|
llvmArgs := []llvm.Value{}
|
||||||
argTypes := []llvm.Type{}
|
argTypes := []llvm.Type{}
|
||||||
asm := "svc #" + strconv.FormatUint(num, 10)
|
asm := "svc #" + strconv.FormatUint(num, 10)
|
||||||
constraints := "={r0}"
|
var constraints strings.Builder
|
||||||
|
constraints.WriteString("={r0}")
|
||||||
for i, arg := range args[1:] {
|
for i, arg := range args[1:] {
|
||||||
arg = arg.(*ssa.MakeInterface).X
|
arg = arg.(*ssa.MakeInterface).X
|
||||||
if i == 0 {
|
if i == 0 {
|
||||||
constraints += ",0"
|
constraints.WriteString(",0")
|
||||||
} else {
|
} else {
|
||||||
constraints += ",{r" + strconv.Itoa(i) + "}"
|
constraints.WriteString(",{r" + strconv.Itoa(i) + "}")
|
||||||
}
|
}
|
||||||
llvmValue := b.getValue(arg, pos)
|
llvmValue := b.getValue(arg, pos)
|
||||||
llvmArgs = append(llvmArgs, llvmValue)
|
llvmArgs = append(llvmArgs, llvmValue)
|
||||||
@@ -161,9 +162,9 @@ func (b *builder) emitSVCall(args []ssa.Value, pos token.Pos) (llvm.Value, error
|
|||||||
// Implement the ARM calling convention by marking r1-r3 as
|
// Implement the ARM calling convention by marking r1-r3 as
|
||||||
// clobbered. r0 is used as an output register so doesn't have to be
|
// clobbered. r0 is used as an output register so doesn't have to be
|
||||||
// marked as clobbered.
|
// marked as clobbered.
|
||||||
constraints += ",~{r1},~{r2},~{r3}"
|
constraints.WriteString(",~{r1},~{r2},~{r3}")
|
||||||
fnType := llvm.FunctionType(b.uintptrType, argTypes, false)
|
fnType := llvm.FunctionType(b.uintptrType, argTypes, false)
|
||||||
target := llvm.InlineAsm(fnType, asm, constraints, true, false, 0, false)
|
target := llvm.InlineAsm(fnType, asm, constraints.String(), true, false, 0, false)
|
||||||
return b.CreateCall(fnType, target, llvmArgs, ""), nil
|
return b.CreateCall(fnType, target, llvmArgs, ""), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -184,13 +185,14 @@ func (b *builder) emitSV64Call(args []ssa.Value, pos token.Pos) (llvm.Value, err
|
|||||||
llvmArgs := []llvm.Value{}
|
llvmArgs := []llvm.Value{}
|
||||||
argTypes := []llvm.Type{}
|
argTypes := []llvm.Type{}
|
||||||
asm := "svc #" + strconv.FormatUint(num, 10)
|
asm := "svc #" + strconv.FormatUint(num, 10)
|
||||||
constraints := "={x0}"
|
var constraints strings.Builder
|
||||||
|
constraints.WriteString("={x0}")
|
||||||
for i, arg := range args[1:] {
|
for i, arg := range args[1:] {
|
||||||
arg = arg.(*ssa.MakeInterface).X
|
arg = arg.(*ssa.MakeInterface).X
|
||||||
if i == 0 {
|
if i == 0 {
|
||||||
constraints += ",0"
|
constraints.WriteString(",0")
|
||||||
} else {
|
} else {
|
||||||
constraints += ",{x" + strconv.Itoa(i) + "}"
|
constraints.WriteString(",{x" + strconv.Itoa(i) + "}")
|
||||||
}
|
}
|
||||||
llvmValue := b.getValue(arg, pos)
|
llvmValue := b.getValue(arg, pos)
|
||||||
llvmArgs = append(llvmArgs, llvmValue)
|
llvmArgs = append(llvmArgs, llvmValue)
|
||||||
@@ -199,9 +201,9 @@ func (b *builder) emitSV64Call(args []ssa.Value, pos token.Pos) (llvm.Value, err
|
|||||||
// Implement the ARM64 calling convention by marking x1-x7 as
|
// Implement the ARM64 calling convention by marking x1-x7 as
|
||||||
// clobbered. x0 is used as an output register so doesn't have to be
|
// clobbered. x0 is used as an output register so doesn't have to be
|
||||||
// marked as clobbered.
|
// marked as clobbered.
|
||||||
constraints += ",~{x1},~{x2},~{x3},~{x4},~{x5},~{x6},~{x7}"
|
constraints.WriteString(",~{x1},~{x2},~{x3},~{x4},~{x5},~{x6},~{x7}")
|
||||||
fnType := llvm.FunctionType(b.uintptrType, argTypes, false)
|
fnType := llvm.FunctionType(b.uintptrType, argTypes, false)
|
||||||
target := llvm.InlineAsm(fnType, asm, constraints, true, false, 0, false)
|
target := llvm.InlineAsm(fnType, asm, constraints.String(), true, false, 0, false)
|
||||||
return b.CreateCall(fnType, target, llvmArgs, ""), nil
|
return b.CreateCall(fnType, target, llvmArgs, ""), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+42
-42
@@ -145,8 +145,8 @@ func (c *compilerContext) getTypeCode(typ types.Type) llvm.Value {
|
|||||||
// For a non-interface type, it returns the number of exported methods.
|
// For a non-interface type, it returns the number of exported methods.
|
||||||
// For an interface type, it returns the number of exported and unexported methods.
|
// For an interface type, it returns the number of exported and unexported methods.
|
||||||
var numMethods int
|
var numMethods int
|
||||||
for i := 0; i < ms.Len(); i++ {
|
for method := range ms.Methods() {
|
||||||
if isInterface || ms.At(i).Obj().Exported() {
|
if isInterface || method.Obj().Exported() {
|
||||||
numMethods++
|
numMethods++
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -193,8 +193,8 @@ func (c *compilerContext) getTypeCode(typ types.Type) llvm.Value {
|
|||||||
}
|
}
|
||||||
// Compute the method set value for types that support methods.
|
// Compute the method set value for types that support methods.
|
||||||
var methods []*types.Func
|
var methods []*types.Func
|
||||||
for i := 0; i < ms.Len(); i++ {
|
for method := range ms.Methods() {
|
||||||
methods = append(methods, ms.At(i).Obj().(*types.Func))
|
methods = append(methods, method.Obj().(*types.Func))
|
||||||
}
|
}
|
||||||
methodSetType := types.NewStruct([]*types.Var{
|
methodSetType := types.NewStruct([]*types.Var{
|
||||||
types.NewVar(token.NoPos, nil, "length", types.Typ[types.Uintptr]),
|
types.NewVar(token.NoPos, nil, "length", types.Typ[types.Uintptr]),
|
||||||
@@ -490,10 +490,7 @@ func (c *compilerContext) getTypeCode(typ types.Type) llvm.Value {
|
|||||||
c.getTypeMethodSet(typ),
|
c.getTypeMethodSet(typ),
|
||||||
}, typeFields...)
|
}, typeFields...)
|
||||||
}
|
}
|
||||||
alignment := c.targetData.TypeAllocSize(c.dataPtrType)
|
alignment := max(c.targetData.TypeAllocSize(c.dataPtrType), 4)
|
||||||
if alignment < 4 {
|
|
||||||
alignment = 4
|
|
||||||
}
|
|
||||||
globalValue := c.ctx.ConstStruct(typeFields, false)
|
globalValue := c.ctx.ConstStruct(typeFields, false)
|
||||||
global.SetInitializer(globalValue)
|
global.SetInitializer(globalValue)
|
||||||
if isLocal {
|
if isLocal {
|
||||||
@@ -783,12 +780,12 @@ func (c *compilerContext) scanLocalTypes(ssaPkg *ssa.Package) {
|
|||||||
walk(m, false)
|
walk(m, false)
|
||||||
case *ssa.Type:
|
case *ssa.Type:
|
||||||
mset := c.program.MethodSets.MethodSet(m.Type())
|
mset := c.program.MethodSets.MethodSet(m.Type())
|
||||||
for i := 0; i < mset.Len(); i++ {
|
for method := range mset.Methods() {
|
||||||
walk(c.program.MethodValue(mset.At(i)), false)
|
walk(c.program.MethodValue(method), false)
|
||||||
}
|
}
|
||||||
pmset := c.program.MethodSets.MethodSet(types.NewPointer(m.Type()))
|
pmset := c.program.MethodSets.MethodSet(types.NewPointer(m.Type()))
|
||||||
for i := 0; i < pmset.Len(); i++ {
|
for method := range pmset.Methods() {
|
||||||
walk(c.program.MethodValue(pmset.At(i)), false)
|
walk(c.program.MethodValue(method), false)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -846,8 +843,8 @@ func (c *compilerContext) registerSyntheticLocalTypes(fn *ssa.Function) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
targs := t.TypeArgs()
|
targs := t.TypeArgs()
|
||||||
for i := 0; i < targs.Len(); i++ {
|
for t := range targs.Types() {
|
||||||
visit(targs.At(i))
|
visit(t)
|
||||||
}
|
}
|
||||||
visit(t.Underlying())
|
visit(t.Underlying())
|
||||||
case *types.Pointer:
|
case *types.Pointer:
|
||||||
@@ -862,23 +859,23 @@ func (c *compilerContext) registerSyntheticLocalTypes(fn *ssa.Function) {
|
|||||||
visit(t.Key())
|
visit(t.Key())
|
||||||
visit(t.Elem())
|
visit(t.Elem())
|
||||||
case *types.Struct:
|
case *types.Struct:
|
||||||
for i := 0; i < t.NumFields(); i++ {
|
for field := range t.Fields() {
|
||||||
visit(t.Field(i).Type())
|
visit(field.Type())
|
||||||
}
|
}
|
||||||
case *types.Signature:
|
case *types.Signature:
|
||||||
if p := t.Params(); p != nil {
|
if p := t.Params(); p != nil {
|
||||||
for i := 0; i < p.Len(); i++ {
|
for v := range p.Variables() {
|
||||||
visit(p.At(i).Type())
|
visit(v.Type())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if r := t.Results(); r != nil {
|
if r := t.Results(); r != nil {
|
||||||
for i := 0; i < r.Len(); i++ {
|
for v := range r.Variables() {
|
||||||
visit(r.At(i).Type())
|
visit(v.Type())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
case *types.Tuple:
|
case *types.Tuple:
|
||||||
for i := 0; i < t.Len(); i++ {
|
for v := range t.Variables() {
|
||||||
visit(t.At(i).Type())
|
visit(v.Type())
|
||||||
}
|
}
|
||||||
case *types.Interface:
|
case *types.Interface:
|
||||||
// A synthetic local type can be reachable only through a
|
// A synthetic local type can be reachable only through a
|
||||||
@@ -887,8 +884,8 @@ func (c *compilerContext) registerSyntheticLocalTypes(fn *ssa.Function) {
|
|||||||
// the interface's identifier, and the seen map breaks
|
// the interface's identifier, and the seen map breaks
|
||||||
// cycles formed by methods that mention the interface
|
// cycles formed by methods that mention the interface
|
||||||
// itself.
|
// itself.
|
||||||
for i := 0; i < t.NumMethods(); i++ {
|
for method := range t.Methods() {
|
||||||
visit(t.Method(i).Type())
|
visit(method.Type())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -939,8 +936,7 @@ func (c *compilerContext) getTypeMethodSet(typ types.Type) llvm.Value {
|
|||||||
|
|
||||||
// Create method set.
|
// Create method set.
|
||||||
var signatures, wrappers []llvm.Value
|
var signatures, wrappers []llvm.Value
|
||||||
for i := 0; i < ms.Len(); i++ {
|
for method := range ms.Methods() {
|
||||||
method := ms.At(i)
|
|
||||||
signatureGlobal := c.getMethodSignature(method.Obj().(*types.Func))
|
signatureGlobal := c.getMethodSignature(method.Obj().(*types.Func))
|
||||||
signatures = append(signatures, signatureGlobal)
|
signatures = append(signatures, signatureGlobal)
|
||||||
fn := c.program.MethodValue(method)
|
fn := c.program.MethodValue(method)
|
||||||
@@ -1189,8 +1185,8 @@ func (c *compilerContext) getInvokeFunction(instr *ssa.CallCommon) llvm.Value {
|
|||||||
if llvmFn.IsNil() {
|
if llvmFn.IsNil() {
|
||||||
sig := instr.Method.Type().(*types.Signature)
|
sig := instr.Method.Type().(*types.Signature)
|
||||||
var paramTuple []*types.Var
|
var paramTuple []*types.Var
|
||||||
for i := 0; i < sig.Params().Len(); i++ {
|
for v := range sig.Params().Variables() {
|
||||||
paramTuple = append(paramTuple, sig.Params().At(i))
|
paramTuple = append(paramTuple, v)
|
||||||
}
|
}
|
||||||
paramTuple = append(paramTuple, types.NewVar(token.NoPos, nil, "$typecode", types.Typ[types.UnsafePointer]))
|
paramTuple = append(paramTuple, types.NewVar(token.NoPos, nil, "$typecode", types.Typ[types.UnsafePointer]))
|
||||||
llvmFnType := c.getLLVMFunctionType(types.NewSignature(sig.Recv(), types.NewTuple(paramTuple...), sig.Results(), false))
|
llvmFnType := c.getLLVMFunctionType(types.NewSignature(sig.Recv(), types.NewTuple(paramTuple...), sig.Results(), false))
|
||||||
@@ -1307,34 +1303,38 @@ func methodSignature(method *types.Func) string {
|
|||||||
// () string
|
// () string
|
||||||
// (string, int) (int, error)
|
// (string, int) (int, error)
|
||||||
func signature(sig *types.Signature) string {
|
func signature(sig *types.Signature) string {
|
||||||
s := ""
|
var s strings.Builder
|
||||||
if sig.Params().Len() == 0 {
|
if sig.Params().Len() == 0 {
|
||||||
s += "()"
|
s.WriteString("()")
|
||||||
} else {
|
} else {
|
||||||
s += "("
|
s.WriteString("(")
|
||||||
for i := 0; i < sig.Params().Len(); i++ {
|
i := 0
|
||||||
|
for v := range sig.Params().Variables() {
|
||||||
if i > 0 {
|
if i > 0 {
|
||||||
s += ", "
|
s.WriteString(", ")
|
||||||
}
|
}
|
||||||
s += typestring(sig.Params().At(i).Type())
|
s.WriteString(typestring(v.Type()))
|
||||||
|
i++
|
||||||
}
|
}
|
||||||
s += ")"
|
s.WriteString(")")
|
||||||
}
|
}
|
||||||
if sig.Results().Len() == 0 {
|
if sig.Results().Len() == 0 {
|
||||||
// keep as-is
|
// keep as-is
|
||||||
} else if sig.Results().Len() == 1 {
|
} else if sig.Results().Len() == 1 {
|
||||||
s += " " + typestring(sig.Results().At(0).Type())
|
s.WriteString(" " + typestring(sig.Results().At(0).Type()))
|
||||||
} else {
|
} else {
|
||||||
s += " ("
|
s.WriteString(" (")
|
||||||
for i := 0; i < sig.Results().Len(); i++ {
|
i := 0
|
||||||
|
for v := range sig.Results().Variables() {
|
||||||
if i > 0 {
|
if i > 0 {
|
||||||
s += ", "
|
s.WriteString(", ")
|
||||||
}
|
}
|
||||||
s += typestring(sig.Results().At(i).Type())
|
s.WriteString(typestring(v.Type()))
|
||||||
|
i++
|
||||||
}
|
}
|
||||||
s += ")"
|
s.WriteString(")")
|
||||||
}
|
}
|
||||||
return s
|
return s.String()
|
||||||
}
|
}
|
||||||
|
|
||||||
// typestring returns a stable (human-readable) type string for the given type
|
// typestring returns a stable (human-readable) type string for the given type
|
||||||
|
|||||||
+3
-3
@@ -206,7 +206,7 @@ func (c *compilerContext) makeGlobalArray(buf []byte, name string, elementType l
|
|||||||
globalType := llvm.ArrayType(elementType, len(buf))
|
globalType := llvm.ArrayType(elementType, len(buf))
|
||||||
global := llvm.AddGlobal(c.mod, globalType, name)
|
global := llvm.AddGlobal(c.mod, globalType, name)
|
||||||
value := llvm.Undef(globalType)
|
value := llvm.Undef(globalType)
|
||||||
for i := 0; i < len(buf); i++ {
|
for i := range buf {
|
||||||
ch := uint64(buf[i])
|
ch := uint64(buf[i])
|
||||||
value = c.builder.CreateInsertValue(value, llvm.ConstInt(elementType, ch, false), i, "")
|
value = c.builder.CreateInsertValue(value, llvm.ConstInt(elementType, ch, false), i, "")
|
||||||
}
|
}
|
||||||
@@ -390,7 +390,7 @@ func (c *compilerContext) buildPointerBitmap(
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
elementSize /= ptrAlign
|
elementSize /= ptrAlign
|
||||||
for i := 0; i < len; i++ {
|
for i := range len {
|
||||||
c.buildPointerBitmap(
|
c.buildPointerBitmap(
|
||||||
dst,
|
dst,
|
||||||
ptrAlign,
|
ptrAlign,
|
||||||
@@ -417,7 +417,7 @@ func (c *compilerContext) archFamily() string {
|
|||||||
// features string is not one for an ARM architecture.
|
// features string is not one for an ARM architecture.
|
||||||
func (c *compilerContext) isThumb() bool {
|
func (c *compilerContext) isThumb() bool {
|
||||||
var isThumb, isNotThumb bool
|
var isThumb, isNotThumb bool
|
||||||
for _, feature := range strings.Split(c.Features, ",") {
|
for feature := range strings.SplitSeq(c.Features, ",") {
|
||||||
if feature == "+thumb-mode" {
|
if feature == "+thumb-mode" {
|
||||||
isThumb = true
|
isThumb = true
|
||||||
}
|
}
|
||||||
|
|||||||
+6
-4
@@ -7,6 +7,7 @@ import (
|
|||||||
"go/token"
|
"go/token"
|
||||||
"go/types"
|
"go/types"
|
||||||
"golang.org/x/tools/go/ssa"
|
"golang.org/x/tools/go/ssa"
|
||||||
|
"strings"
|
||||||
"tinygo.org/x/go-llvm"
|
"tinygo.org/x/go-llvm"
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -293,14 +294,15 @@ func hashmapCanonicalTypeName(t types.Type) string {
|
|||||||
}
|
}
|
||||||
return t.String()
|
return t.String()
|
||||||
case *types.Struct:
|
case *types.Struct:
|
||||||
s := "struct{"
|
var s strings.Builder
|
||||||
|
s.WriteString("struct{")
|
||||||
for i := 0; i < t.NumFields(); i++ {
|
for i := 0; i < t.NumFields(); i++ {
|
||||||
if i > 0 {
|
if i > 0 {
|
||||||
s += "; "
|
s.WriteString("; ")
|
||||||
}
|
}
|
||||||
s += hashmapCanonicalTypeName(t.Field(i).Type())
|
s.WriteString(hashmapCanonicalTypeName(t.Field(i).Type()))
|
||||||
}
|
}
|
||||||
return s + "}"
|
return s.String() + "}"
|
||||||
case *types.Array:
|
case *types.Array:
|
||||||
return fmt.Sprintf("[%d]%s", t.Len(), hashmapCanonicalTypeName(t.Elem()))
|
return fmt.Sprintf("[%d]%s", t.Len(), hashmapCanonicalTypeName(t.Elem()))
|
||||||
}
|
}
|
||||||
|
|||||||
+1
-2
@@ -29,8 +29,7 @@ func (s *stdSizes) Alignof(T types.Type) int64 {
|
|||||||
// is the largest of the values unsafe.Alignof(x.f) for each
|
// is the largest of the values unsafe.Alignof(x.f) for each
|
||||||
// field f of x, but at least 1."
|
// field f of x, but at least 1."
|
||||||
max := int64(1)
|
max := int64(1)
|
||||||
for i := 0; i < t.NumFields(); i++ {
|
for f := range t.Fields() {
|
||||||
f := t.Field(i)
|
|
||||||
if a := s.Alignof(f.Type()); a > max {
|
if a := s.Alignof(f.Type()); a > max {
|
||||||
max = a
|
max = a
|
||||||
}
|
}
|
||||||
|
|||||||
+13
-25
@@ -8,6 +8,7 @@ import (
|
|||||||
"go/ast"
|
"go/ast"
|
||||||
"go/token"
|
"go/token"
|
||||||
"go/types"
|
"go/types"
|
||||||
|
"slices"
|
||||||
"strconv"
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
@@ -85,8 +86,8 @@ func (c *compilerContext) getFunction(fn *ssa.Function) (llvm.Type, llvm.Value)
|
|||||||
retType = c.getLLVMType(fn.Signature.Results().At(0).Type())
|
retType = c.getLLVMType(fn.Signature.Results().At(0).Type())
|
||||||
} else {
|
} else {
|
||||||
results := make([]llvm.Type, 0, fn.Signature.Results().Len())
|
results := make([]llvm.Type, 0, fn.Signature.Results().Len())
|
||||||
for i := 0; i < fn.Signature.Results().Len(); i++ {
|
for v := range fn.Signature.Results().Variables() {
|
||||||
results = append(results, c.getLLVMType(fn.Signature.Results().At(i).Type()))
|
results = append(results, c.getLLVMType(v.Type()))
|
||||||
}
|
}
|
||||||
retType = c.ctx.StructType(results, false)
|
retType = c.ctx.StructType(results, false)
|
||||||
}
|
}
|
||||||
@@ -389,7 +390,7 @@ func (c *compilerContext) parsePragmas(info *functionInfo, f *ssa.Function) {
|
|||||||
info.wasmName = info.linkName
|
info.wasmName = info.linkName
|
||||||
info.exported = true
|
info.exported = true
|
||||||
case "//go:interrupt":
|
case "//go:interrupt":
|
||||||
if hasUnsafeImport(f.Pkg.Pkg) {
|
if slices.Contains(f.Pkg.Pkg.Imports(), types.Unsafe) {
|
||||||
info.interrupt = true
|
info.interrupt = true
|
||||||
}
|
}
|
||||||
case "//go:wasm-module":
|
case "//go:wasm-module":
|
||||||
@@ -451,14 +452,14 @@ func (c *compilerContext) parsePragmas(info *functionInfo, f *ssa.Function) {
|
|||||||
// This is a slightly looser requirement than what gc uses: gc
|
// This is a slightly looser requirement than what gc uses: gc
|
||||||
// requires the file to import "unsafe", not the package as a
|
// requires the file to import "unsafe", not the package as a
|
||||||
// whole.
|
// whole.
|
||||||
if hasUnsafeImport(f.Pkg.Pkg) {
|
if slices.Contains(f.Pkg.Pkg.Imports(), types.Unsafe) {
|
||||||
info.linkName = parts[2]
|
info.linkName = parts[2]
|
||||||
}
|
}
|
||||||
case "//go:section":
|
case "//go:section":
|
||||||
// Only enable go:section when the package imports "unsafe".
|
// Only enable go:section when the package imports "unsafe".
|
||||||
// go:section also implies go:noinline since inlining could
|
// go:section also implies go:noinline since inlining could
|
||||||
// move the code to a different section than that requested.
|
// move the code to a different section than that requested.
|
||||||
if len(parts) == 2 && hasUnsafeImport(f.Pkg.Pkg) {
|
if len(parts) == 2 && slices.Contains(f.Pkg.Pkg.Imports(), types.Unsafe) {
|
||||||
info.section = parts[1]
|
info.section = parts[1]
|
||||||
info.inline = inlineNone
|
info.inline = inlineNone
|
||||||
}
|
}
|
||||||
@@ -467,7 +468,7 @@ func (c *compilerContext) parsePragmas(info *functionInfo, f *ssa.Function) {
|
|||||||
// runtime functions.
|
// runtime functions.
|
||||||
// This is somewhat dangerous and thus only imported in packages
|
// This is somewhat dangerous and thus only imported in packages
|
||||||
// that import unsafe.
|
// that import unsafe.
|
||||||
if hasUnsafeImport(f.Pkg.Pkg) {
|
if slices.Contains(f.Pkg.Pkg.Imports(), types.Unsafe) {
|
||||||
info.nobounds = true
|
info.nobounds = true
|
||||||
}
|
}
|
||||||
case "//go:noescape":
|
case "//go:noescape":
|
||||||
@@ -567,8 +568,8 @@ func (c *compilerContext) isValidWasmType(typ types.Type, site wasmSite) bool {
|
|||||||
hasHostLayout = false // package structs added in go1.23
|
hasHostLayout = false // package structs added in go1.23
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
for i := 0; i < typ.NumFields(); i++ {
|
for field := range typ.Fields() {
|
||||||
ftyp := typ.Field(i).Type()
|
ftyp := field.Type()
|
||||||
if types.Unalias(ftyp).String() == "structs.HostLayout" {
|
if types.Unalias(ftyp).String() == "structs.HostLayout" {
|
||||||
hasHostLayout = true
|
hasHostLayout = true
|
||||||
continue
|
continue
|
||||||
@@ -600,8 +601,8 @@ func getParams(sig *types.Signature) []*types.Var {
|
|||||||
if sig.Recv() != nil {
|
if sig.Recv() != nil {
|
||||||
params = append(params, sig.Recv())
|
params = append(params, sig.Recv())
|
||||||
}
|
}
|
||||||
for i := 0; i < sig.Params().Len(); i++ {
|
for v := range sig.Params().Variables() {
|
||||||
params = append(params, sig.Params().At(i))
|
params = append(params, v)
|
||||||
}
|
}
|
||||||
return params
|
return params
|
||||||
}
|
}
|
||||||
@@ -704,10 +705,7 @@ func (c *compilerContext) getGlobal(g *ssa.Global) llvm.Value {
|
|||||||
llvmGlobal = llvm.AddGlobal(c.mod, llvmType, info.linkName)
|
llvmGlobal = llvm.AddGlobal(c.mod, llvmType, info.linkName)
|
||||||
|
|
||||||
// Set alignment from the //go:align comment.
|
// Set alignment from the //go:align comment.
|
||||||
alignment := c.targetData.ABITypeAlignment(llvmType)
|
alignment := max(info.align, c.targetData.ABITypeAlignment(llvmType))
|
||||||
if info.align > alignment {
|
|
||||||
alignment = info.align
|
|
||||||
}
|
|
||||||
if alignment <= 0 || alignment&(alignment-1) != 0 {
|
if alignment <= 0 || alignment&(alignment-1) != 0 {
|
||||||
// Check for power-of-two (or 0).
|
// Check for power-of-two (or 0).
|
||||||
// See: https://stackoverflow.com/a/108360
|
// See: https://stackoverflow.com/a/108360
|
||||||
@@ -781,7 +779,7 @@ func (info *globalInfo) parsePragmas(doc *ast.CommentGroup, c *compilerContext,
|
|||||||
// This is a slightly looser requirement than what gc uses: gc
|
// This is a slightly looser requirement than what gc uses: gc
|
||||||
// requires the file to import "unsafe", not the package as a
|
// requires the file to import "unsafe", not the package as a
|
||||||
// whole.
|
// whole.
|
||||||
if hasUnsafeImport(g.Pkg.Pkg) {
|
if slices.Contains(g.Pkg.Pkg.Imports(), types.Unsafe) {
|
||||||
info.linkName = parts[2]
|
info.linkName = parts[2]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -797,13 +795,3 @@ func getAllMethods(prog *ssa.Program, typ types.Type) []*types.Selection {
|
|||||||
}
|
}
|
||||||
return methods
|
return methods
|
||||||
}
|
}
|
||||||
|
|
||||||
// Return true if this package imports "unsafe", false otherwise.
|
|
||||||
func hasUnsafeImport(pkg *types.Package) bool {
|
|
||||||
for _, imp := range pkg.Imports() {
|
|
||||||
if imp == types.Unsafe {
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|||||||
+32
-27
@@ -26,24 +26,25 @@ func (b *builder) createRawSyscall(call *ssa.CallCommon) (llvm.Value, error) {
|
|||||||
argTypes := []llvm.Type{b.uintptrType}
|
argTypes := []llvm.Type{b.uintptrType}
|
||||||
// Constraints will look something like:
|
// Constraints will look something like:
|
||||||
// "={rax},0,{rdi},{rsi},{rdx},{r10},{r8},{r9},~{rcx},~{r11}"
|
// "={rax},0,{rdi},{rsi},{rdx},{r10},{r8},{r9},~{rcx},~{r11}"
|
||||||
constraints := "={rax},0"
|
var constraints strings.Builder
|
||||||
|
constraints.WriteString("={rax},0")
|
||||||
for i, arg := range call.Args[1:] {
|
for i, arg := range call.Args[1:] {
|
||||||
constraints += "," + [...]string{
|
constraints.WriteString("," + [...]string{
|
||||||
"{rdi}",
|
"{rdi}",
|
||||||
"{rsi}",
|
"{rsi}",
|
||||||
"{rdx}",
|
"{rdx}",
|
||||||
"{r10}",
|
"{r10}",
|
||||||
"{r8}",
|
"{r8}",
|
||||||
"{r9}",
|
"{r9}",
|
||||||
}[i]
|
}[i])
|
||||||
llvmValue := b.getValue(arg, getPos(call))
|
llvmValue := b.getValue(arg, getPos(call))
|
||||||
args = append(args, llvmValue)
|
args = append(args, llvmValue)
|
||||||
argTypes = append(argTypes, llvmValue.Type())
|
argTypes = append(argTypes, llvmValue.Type())
|
||||||
}
|
}
|
||||||
// rcx and r11 are clobbered by the syscall, so make sure they are not used
|
// rcx and r11 are clobbered by the syscall, so make sure they are not used
|
||||||
constraints += ",~{rcx},~{r11}"
|
constraints.WriteString(",~{rcx},~{r11}")
|
||||||
fnType := llvm.FunctionType(b.uintptrType, argTypes, false)
|
fnType := llvm.FunctionType(b.uintptrType, argTypes, false)
|
||||||
target := llvm.InlineAsm(fnType, "syscall", constraints, true, false, llvm.InlineAsmDialectIntel, false)
|
target := llvm.InlineAsm(fnType, "syscall", constraints.String(), true, false, llvm.InlineAsmDialectIntel, false)
|
||||||
return b.CreateCall(fnType, target, args, ""), nil
|
return b.CreateCall(fnType, target, args, ""), nil
|
||||||
|
|
||||||
case b.GOARCH == "386" && b.GOOS == "linux":
|
case b.GOARCH == "386" && b.GOOS == "linux":
|
||||||
@@ -55,22 +56,23 @@ func (b *builder) createRawSyscall(call *ssa.CallCommon) (llvm.Value, error) {
|
|||||||
argTypes := []llvm.Type{b.uintptrType}
|
argTypes := []llvm.Type{b.uintptrType}
|
||||||
// Constraints will look something like:
|
// Constraints will look something like:
|
||||||
// "={eax},0,{ebx},{ecx},{edx},{esi},{edi},{ebp}"
|
// "={eax},0,{ebx},{ecx},{edx},{esi},{edi},{ebp}"
|
||||||
constraints := "={eax},0"
|
var constraints strings.Builder
|
||||||
|
constraints.WriteString("={eax},0")
|
||||||
for i, arg := range call.Args[1:] {
|
for i, arg := range call.Args[1:] {
|
||||||
constraints += "," + [...]string{
|
constraints.WriteString("," + [...]string{
|
||||||
"{ebx}",
|
"{ebx}",
|
||||||
"{ecx}",
|
"{ecx}",
|
||||||
"{edx}",
|
"{edx}",
|
||||||
"{esi}",
|
"{esi}",
|
||||||
"{edi}",
|
"{edi}",
|
||||||
"{ebp}",
|
"{ebp}",
|
||||||
}[i]
|
}[i])
|
||||||
llvmValue := b.getValue(arg, getPos(call))
|
llvmValue := b.getValue(arg, getPos(call))
|
||||||
args = append(args, llvmValue)
|
args = append(args, llvmValue)
|
||||||
argTypes = append(argTypes, llvmValue.Type())
|
argTypes = append(argTypes, llvmValue.Type())
|
||||||
}
|
}
|
||||||
fnType := llvm.FunctionType(b.uintptrType, argTypes, false)
|
fnType := llvm.FunctionType(b.uintptrType, argTypes, false)
|
||||||
target := llvm.InlineAsm(fnType, "int 0x80", constraints, true, false, llvm.InlineAsmDialectIntel, false)
|
target := llvm.InlineAsm(fnType, "int 0x80", constraints.String(), true, false, llvm.InlineAsmDialectIntel, false)
|
||||||
return b.CreateCall(fnType, target, args, ""), nil
|
return b.CreateCall(fnType, target, args, ""), nil
|
||||||
|
|
||||||
case b.GOARCH == "arm" && b.GOOS == "linux":
|
case b.GOARCH == "arm" && b.GOOS == "linux":
|
||||||
@@ -88,9 +90,10 @@ func (b *builder) createRawSyscall(call *ssa.CallCommon) (llvm.Value, error) {
|
|||||||
argTypes := []llvm.Type{}
|
argTypes := []llvm.Type{}
|
||||||
// Constraints will look something like:
|
// Constraints will look something like:
|
||||||
// ={r0},0,{r1},{r2},{r7},~{r3}
|
// ={r0},0,{r1},{r2},{r7},~{r3}
|
||||||
constraints := "={r0}"
|
var constraints strings.Builder
|
||||||
|
constraints.WriteString("={r0}")
|
||||||
for i, arg := range call.Args[1:] {
|
for i, arg := range call.Args[1:] {
|
||||||
constraints += "," + [...]string{
|
constraints.WriteString("," + [...]string{
|
||||||
"0", // tie to output
|
"0", // tie to output
|
||||||
"{r1}",
|
"{r1}",
|
||||||
"{r2}",
|
"{r2}",
|
||||||
@@ -98,20 +101,20 @@ func (b *builder) createRawSyscall(call *ssa.CallCommon) (llvm.Value, error) {
|
|||||||
"{r4}",
|
"{r4}",
|
||||||
"{r5}",
|
"{r5}",
|
||||||
"{r6}",
|
"{r6}",
|
||||||
}[i]
|
}[i])
|
||||||
llvmValue := b.getValue(arg, getPos(call))
|
llvmValue := b.getValue(arg, getPos(call))
|
||||||
args = append(args, llvmValue)
|
args = append(args, llvmValue)
|
||||||
argTypes = append(argTypes, llvmValue.Type())
|
argTypes = append(argTypes, llvmValue.Type())
|
||||||
}
|
}
|
||||||
args = append(args, num)
|
args = append(args, num)
|
||||||
argTypes = append(argTypes, b.uintptrType)
|
argTypes = append(argTypes, b.uintptrType)
|
||||||
constraints += ",{r7}" // syscall number
|
constraints.WriteString(",{r7}") // syscall number
|
||||||
for i := len(call.Args) - 1; i < 4; i++ {
|
for i := len(call.Args) - 1; i < 4; i++ {
|
||||||
// r0-r3 get clobbered after the syscall returns
|
// r0-r3 get clobbered after the syscall returns
|
||||||
constraints += ",~{r" + strconv.Itoa(i) + "}"
|
constraints.WriteString(",~{r" + strconv.Itoa(i) + "}")
|
||||||
}
|
}
|
||||||
fnType := llvm.FunctionType(b.uintptrType, argTypes, false)
|
fnType := llvm.FunctionType(b.uintptrType, argTypes, false)
|
||||||
target := llvm.InlineAsm(fnType, "svc #0", constraints, true, false, 0, false)
|
target := llvm.InlineAsm(fnType, "svc #0", constraints.String(), true, false, 0, false)
|
||||||
return b.CreateCall(fnType, target, args, ""), nil
|
return b.CreateCall(fnType, target, args, ""), nil
|
||||||
|
|
||||||
case b.GOARCH == "arm64" && b.GOOS == "linux":
|
case b.GOARCH == "arm64" && b.GOOS == "linux":
|
||||||
@@ -120,31 +123,32 @@ func (b *builder) createRawSyscall(call *ssa.CallCommon) (llvm.Value, error) {
|
|||||||
argTypes := []llvm.Type{}
|
argTypes := []llvm.Type{}
|
||||||
// Constraints will look something like:
|
// Constraints will look something like:
|
||||||
// ={x0},0,{x1},{x2},{x8},~{x3},~{x4},~{x5},~{x6},~{x7},~{x16},~{x17}
|
// ={x0},0,{x1},{x2},{x8},~{x3},~{x4},~{x5},~{x6},~{x7},~{x16},~{x17}
|
||||||
constraints := "={x0}"
|
var constraints strings.Builder
|
||||||
|
constraints.WriteString("={x0}")
|
||||||
for i, arg := range call.Args[1:] {
|
for i, arg := range call.Args[1:] {
|
||||||
constraints += "," + [...]string{
|
constraints.WriteString("," + [...]string{
|
||||||
"0", // tie to output
|
"0", // tie to output
|
||||||
"{x1}",
|
"{x1}",
|
||||||
"{x2}",
|
"{x2}",
|
||||||
"{x3}",
|
"{x3}",
|
||||||
"{x4}",
|
"{x4}",
|
||||||
"{x5}",
|
"{x5}",
|
||||||
}[i]
|
}[i])
|
||||||
llvmValue := b.getValue(arg, getPos(call))
|
llvmValue := b.getValue(arg, getPos(call))
|
||||||
args = append(args, llvmValue)
|
args = append(args, llvmValue)
|
||||||
argTypes = append(argTypes, llvmValue.Type())
|
argTypes = append(argTypes, llvmValue.Type())
|
||||||
}
|
}
|
||||||
args = append(args, num)
|
args = append(args, num)
|
||||||
argTypes = append(argTypes, b.uintptrType)
|
argTypes = append(argTypes, b.uintptrType)
|
||||||
constraints += ",{x8}" // syscall number
|
constraints.WriteString(",{x8}") // syscall number
|
||||||
for i := len(call.Args) - 1; i < 8; i++ {
|
for i := len(call.Args) - 1; i < 8; i++ {
|
||||||
// x0-x7 may get clobbered during the syscall following the aarch64
|
// x0-x7 may get clobbered during the syscall following the aarch64
|
||||||
// calling convention.
|
// calling convention.
|
||||||
constraints += ",~{x" + strconv.Itoa(i) + "}"
|
constraints.WriteString(",~{x" + strconv.Itoa(i) + "}")
|
||||||
}
|
}
|
||||||
constraints += ",~{x16},~{x17}" // scratch registers
|
constraints.WriteString(",~{x16},~{x17}") // scratch registers
|
||||||
fnType := llvm.FunctionType(b.uintptrType, argTypes, false)
|
fnType := llvm.FunctionType(b.uintptrType, argTypes, false)
|
||||||
target := llvm.InlineAsm(fnType, "svc #0", constraints, true, false, 0, false)
|
target := llvm.InlineAsm(fnType, "svc #0", constraints.String(), true, false, 0, false)
|
||||||
return b.CreateCall(fnType, target, args, ""), nil
|
return b.CreateCall(fnType, target, args, ""), nil
|
||||||
|
|
||||||
case (b.GOARCH == "mips" || b.GOARCH == "mipsle") && b.GOOS == "linux":
|
case (b.GOARCH == "mips" || b.GOARCH == "mipsle") && b.GOOS == "linux":
|
||||||
@@ -163,7 +167,8 @@ func (b *builder) createRawSyscall(call *ssa.CallCommon) (llvm.Value, error) {
|
|||||||
// faster and smaller code.
|
// faster and smaller code.
|
||||||
args := []llvm.Value{num}
|
args := []llvm.Value{num}
|
||||||
argTypes := []llvm.Type{b.uintptrType}
|
argTypes := []llvm.Type{b.uintptrType}
|
||||||
constraints := "={$2},={$7},0"
|
var constraints strings.Builder
|
||||||
|
constraints.WriteString("={$2},={$7},0")
|
||||||
syscallParams := call.Args[1:]
|
syscallParams := call.Args[1:]
|
||||||
if len(syscallParams) > 7 {
|
if len(syscallParams) > 7 {
|
||||||
// There is one syscall that uses 7 parameters: sync_file_range.
|
// There is one syscall that uses 7 parameters: sync_file_range.
|
||||||
@@ -172,7 +177,7 @@ func (b *builder) createRawSyscall(call *ssa.CallCommon) (llvm.Value, error) {
|
|||||||
syscallParams = syscallParams[:7]
|
syscallParams = syscallParams[:7]
|
||||||
}
|
}
|
||||||
for i, arg := range syscallParams {
|
for i, arg := range syscallParams {
|
||||||
constraints += "," + [...]string{
|
constraints.WriteString("," + [...]string{
|
||||||
"{$4}", // arg1
|
"{$4}", // arg1
|
||||||
"{$5}", // arg2
|
"{$5}", // arg2
|
||||||
"{$6}", // arg3
|
"{$6}", // arg3
|
||||||
@@ -180,7 +185,7 @@ func (b *builder) createRawSyscall(call *ssa.CallCommon) (llvm.Value, error) {
|
|||||||
"r", // arg5 on the stack
|
"r", // arg5 on the stack
|
||||||
"r", // arg6 on the stack
|
"r", // arg6 on the stack
|
||||||
"r", // arg7 on the stack
|
"r", // arg7 on the stack
|
||||||
}[i]
|
}[i])
|
||||||
llvmValue := b.getValue(arg, getPos(call))
|
llvmValue := b.getValue(arg, getPos(call))
|
||||||
args = append(args, llvmValue)
|
args = append(args, llvmValue)
|
||||||
argTypes = append(argTypes, llvmValue.Type())
|
argTypes = append(argTypes, llvmValue.Type())
|
||||||
@@ -221,10 +226,10 @@ func (b *builder) createRawSyscall(call *ssa.CallCommon) (llvm.Value, error) {
|
|||||||
"addu $$sp, $$sp, 32\n" +
|
"addu $$sp, $$sp, 32\n" +
|
||||||
".set at\n"
|
".set at\n"
|
||||||
}
|
}
|
||||||
constraints += ",~{$3},~{$4},~{$5},~{$6},~{$8},~{$9},~{$10},~{$11},~{$12},~{$13},~{$14},~{$15},~{$24},~{$25},~{hi},~{lo},~{memory}"
|
constraints.WriteString(",~{$3},~{$4},~{$5},~{$6},~{$8},~{$9},~{$10},~{$11},~{$12},~{$13},~{$14},~{$15},~{$24},~{$25},~{hi},~{lo},~{memory}")
|
||||||
returnType := b.ctx.StructType([]llvm.Type{b.uintptrType, b.uintptrType}, false)
|
returnType := b.ctx.StructType([]llvm.Type{b.uintptrType, b.uintptrType}, false)
|
||||||
fnType := llvm.FunctionType(returnType, argTypes, false)
|
fnType := llvm.FunctionType(returnType, argTypes, false)
|
||||||
target := llvm.InlineAsm(fnType, asm, constraints, true, true, 0, false)
|
target := llvm.InlineAsm(fnType, asm, constraints.String(), true, true, 0, false)
|
||||||
call := b.CreateCall(fnType, target, args, "")
|
call := b.CreateCall(fnType, target, args, "")
|
||||||
resultCode := b.CreateExtractValue(call, 0, "") // r2
|
resultCode := b.CreateExtractValue(call, 0, "") // r2
|
||||||
errorFlag := b.CreateExtractValue(call, 1, "") // r7
|
errorFlag := b.CreateExtractValue(call, 1, "") // r7
|
||||||
|
|||||||
@@ -59,7 +59,6 @@ func TestCorpus(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
for _, repo := range repos {
|
for _, repo := range repos {
|
||||||
repo := repo
|
|
||||||
name := repo.Repo
|
name := repo.Repo
|
||||||
if repo.Tags != "" {
|
if repo.Tags != "" {
|
||||||
name += "(" + strings.ReplaceAll(repo.Tags, " ", "-") + ")"
|
name += "(" + strings.ReplaceAll(repo.Tags, " ", "-") + ")"
|
||||||
@@ -132,7 +131,6 @@ func TestCorpus(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
for _, dir := range repo.Subdirs {
|
for _, dir := range repo.Subdirs {
|
||||||
dir := dir
|
|
||||||
t.Run(dir.Pkg, func(t *testing.T) {
|
t.Run(dir.Pkg, func(t *testing.T) {
|
||||||
t.Parallel()
|
t.Parallel()
|
||||||
|
|
||||||
|
|||||||
@@ -116,10 +116,7 @@ func Diff(oldName string, old []byte, newName string, new []byte) []byte {
|
|||||||
|
|
||||||
// End chunk with common lines for context.
|
// End chunk with common lines for context.
|
||||||
if len(ctext) > 0 {
|
if len(ctext) > 0 {
|
||||||
n := end.x - start.x
|
n := min(end.x-start.x, C)
|
||||||
if n > C {
|
|
||||||
n = C
|
|
||||||
}
|
|
||||||
for _, s := range x[start.x : start.x+n] {
|
for _, s := range x[start.x : start.x+n] {
|
||||||
ctext = append(ctext, " "+s)
|
ctext = append(ctext, " "+s)
|
||||||
count.x++
|
count.x++
|
||||||
@@ -234,7 +231,7 @@ func tgs(x, y []string) []pair {
|
|||||||
for i := range T {
|
for i := range T {
|
||||||
T[i] = n + 1
|
T[i] = n + 1
|
||||||
}
|
}
|
||||||
for i := 0; i < n; i++ {
|
for i := range n {
|
||||||
k := sort.Search(n, func(k int) bool {
|
k := sort.Search(n, func(k int) bool {
|
||||||
return T[k] >= J[i]
|
return T[k] >= J[i]
|
||||||
})
|
})
|
||||||
|
|||||||
+1
-1
@@ -136,7 +136,7 @@ func readErrorMessages(t *testing.T, file string) string {
|
|||||||
}
|
}
|
||||||
|
|
||||||
var errors []string
|
var errors []string
|
||||||
for _, line := range strings.Split(string(data), "\n") {
|
for line := range strings.SplitSeq(string(data), "\n") {
|
||||||
if strings.HasPrefix(line, "// ERROR: ") {
|
if strings.HasPrefix(line, "// ERROR: ") {
|
||||||
errors = append(errors, strings.TrimRight(line[len("// ERROR: "):], "\r\n"))
|
errors = append(errors, strings.TrimRight(line[len("// ERROR: "):], "\r\n"))
|
||||||
}
|
}
|
||||||
|
|||||||
+1
-1
@@ -151,7 +151,7 @@ func (r *runner) compileFunction(llvmFn llvm.Value) *function {
|
|||||||
case llvm.PHI:
|
case llvm.PHI:
|
||||||
inst.name = llvmInst.Name()
|
inst.name = llvmInst.Name()
|
||||||
incomingCount := inst.llvmInst.IncomingCount()
|
incomingCount := inst.llvmInst.IncomingCount()
|
||||||
for i := 0; i < incomingCount; i++ {
|
for i := range incomingCount {
|
||||||
incomingBB := inst.llvmInst.IncomingBlock(i)
|
incomingBB := inst.llvmInst.IncomingBlock(i)
|
||||||
incomingValue := inst.llvmInst.IncomingValue(i)
|
incomingValue := inst.llvmInst.IncomingValue(i)
|
||||||
inst.operands = append(inst.operands,
|
inst.operands = append(inst.operands,
|
||||||
|
|||||||
@@ -22,7 +22,6 @@ func TestInterp(t *testing.T) {
|
|||||||
"alloc",
|
"alloc",
|
||||||
"slicedata",
|
"slicedata",
|
||||||
} {
|
} {
|
||||||
name := name // make local to this closure
|
|
||||||
t.Run(name, func(t *testing.T) {
|
t.Run(name, func(t *testing.T) {
|
||||||
t.Parallel()
|
t.Parallel()
|
||||||
runTest(t, "testdata/"+name)
|
runTest(t, "testdata/"+name)
|
||||||
|
|||||||
@@ -5,6 +5,7 @@ import (
|
|||||||
"fmt"
|
"fmt"
|
||||||
"math"
|
"math"
|
||||||
"os"
|
"os"
|
||||||
|
"slices"
|
||||||
"strconv"
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
@@ -470,7 +471,7 @@ func (r *runner) run(fn *function, params []value, parentMem *memoryView, indent
|
|||||||
// should be returned.
|
// should be returned.
|
||||||
numMethods := int(r.builder.CreateExtractValue(methodSet, 0, "").ZExtValue())
|
numMethods := int(r.builder.CreateExtractValue(methodSet, 0, "").ZExtValue())
|
||||||
var method llvm.Value
|
var method llvm.Value
|
||||||
for i := 0; i < numMethods; i++ {
|
for i := range numMethods {
|
||||||
methodSignatureAgg := r.builder.CreateExtractValue(methodSet, 1, "")
|
methodSignatureAgg := r.builder.CreateExtractValue(methodSet, 1, "")
|
||||||
methodSignature := r.builder.CreateExtractValue(methodSignatureAgg, i, "")
|
methodSignature := r.builder.CreateExtractValue(methodSignatureAgg, i, "")
|
||||||
if methodSignature == signature {
|
if methodSignature == signature {
|
||||||
@@ -907,7 +908,7 @@ func (r *runner) interpretICmp(lhs, rhs value, predicate llvm.IntPredicate) bool
|
|||||||
func (r *runner) runAtRuntime(fn *function, inst instruction, locals []value, mem *memoryView, indent string) *Error {
|
func (r *runner) runAtRuntime(fn *function, inst instruction, locals []value, mem *memoryView, indent string) *Error {
|
||||||
numOperands := inst.llvmInst.OperandsCount()
|
numOperands := inst.llvmInst.OperandsCount()
|
||||||
operands := make([]llvm.Value, numOperands)
|
operands := make([]llvm.Value, numOperands)
|
||||||
for i := 0; i < numOperands; i++ {
|
for i := range numOperands {
|
||||||
operand := inst.llvmInst.Operand(i)
|
operand := inst.llvmInst.Operand(i)
|
||||||
if !operand.IsAInstruction().IsNil() || !operand.IsAArgument().IsNil() {
|
if !operand.IsAInstruction().IsNil() || !operand.IsAArgument().IsNil() {
|
||||||
var err error
|
var err error
|
||||||
@@ -985,9 +986,9 @@ func (r *runner) runAtRuntime(fn *function, inst instruction, locals []value, me
|
|||||||
mem.instructions = append(mem.instructions, agg)
|
mem.instructions = append(mem.instructions, agg)
|
||||||
}
|
}
|
||||||
result = operands[1]
|
result = operands[1]
|
||||||
for i := len(indices) - 1; i >= 0; i-- {
|
for i, indice := range slices.Backward(indices) {
|
||||||
agg := aggregates[i]
|
agg := aggregates[i]
|
||||||
result = r.builder.CreateInsertValue(agg, result, int(indices[i]), inst.name+".insertvalue"+strconv.Itoa(i))
|
result = r.builder.CreateInsertValue(agg, result, int(indice), inst.name+".insertvalue"+strconv.Itoa(i))
|
||||||
if i != 0 { // don't add last result to mem.instructions as it will be done at the end already
|
if i != 0 { // don't add last result to mem.instructions as it will be done at the end already
|
||||||
mem.instructions = append(mem.instructions, result)
|
mem.instructions = append(mem.instructions, result)
|
||||||
}
|
}
|
||||||
|
|||||||
+14
-14
@@ -18,8 +18,10 @@ import (
|
|||||||
"encoding/binary"
|
"encoding/binary"
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"maps"
|
||||||
"math"
|
"math"
|
||||||
"math/big"
|
"math/big"
|
||||||
|
"slices"
|
||||||
"strconv"
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
@@ -80,9 +82,7 @@ func (mv *memoryView) extend(sub memoryView) {
|
|||||||
if mv.objects == nil && len(sub.objects) != 0 {
|
if mv.objects == nil && len(sub.objects) != 0 {
|
||||||
mv.objects = make(map[uint32]object)
|
mv.objects = make(map[uint32]object)
|
||||||
}
|
}
|
||||||
for key, value := range sub.objects {
|
maps.Copy(mv.objects, sub.objects)
|
||||||
mv.objects[key] = value
|
|
||||||
}
|
|
||||||
mv.instructions = append(mv.instructions, sub.instructions...)
|
mv.instructions = append(mv.instructions, sub.instructions...)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -90,8 +90,8 @@ func (mv *memoryView) extend(sub memoryView) {
|
|||||||
// created in this memoryView. Do not reuse this memoryView.
|
// created in this memoryView. Do not reuse this memoryView.
|
||||||
func (mv *memoryView) revert() {
|
func (mv *memoryView) revert() {
|
||||||
// Erase instructions in reverse order.
|
// Erase instructions in reverse order.
|
||||||
for i := len(mv.instructions) - 1; i >= 0; i-- {
|
for _, llvmInst := range slices.Backward(mv.instructions) {
|
||||||
llvmInst := mv.instructions[i]
|
|
||||||
if llvmInst.IsAInstruction().IsNil() {
|
if llvmInst.IsAInstruction().IsNil() {
|
||||||
// The IR builder will try to create constant versions of
|
// The IR builder will try to create constant versions of
|
||||||
// instructions whenever possible. If it does this, it's not an
|
// instructions whenever possible. If it does this, it's not an
|
||||||
@@ -172,7 +172,7 @@ func (mv *memoryView) markExternal(llvmValue llvm.Value, mark uint8) error {
|
|||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
numOperands := inst.OperandsCount()
|
numOperands := inst.OperandsCount()
|
||||||
for i := 0; i < numOperands; i++ {
|
for i := range numOperands {
|
||||||
// Using mark '2' (which means read/write access)
|
// Using mark '2' (which means read/write access)
|
||||||
// because this might be a store instruction.
|
// because this might be a store instruction.
|
||||||
err := mv.markExternal(inst.Operand(i), 2)
|
err := mv.markExternal(inst.Operand(i), 2)
|
||||||
@@ -215,7 +215,7 @@ func (mv *memoryView) markExternal(llvmValue llvm.Value, mark uint8) error {
|
|||||||
// need any marking.
|
// need any marking.
|
||||||
case llvm.StructTypeKind:
|
case llvm.StructTypeKind:
|
||||||
numElements := llvmType.StructElementTypesCount()
|
numElements := llvmType.StructElementTypesCount()
|
||||||
for i := 0; i < numElements; i++ {
|
for i := range numElements {
|
||||||
element := mv.r.builder.CreateExtractValue(llvmValue, i, "")
|
element := mv.r.builder.CreateExtractValue(llvmValue, i, "")
|
||||||
err := mv.markExternal(element, mark)
|
err := mv.markExternal(element, mark)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -224,7 +224,7 @@ func (mv *memoryView) markExternal(llvmValue llvm.Value, mark uint8) error {
|
|||||||
}
|
}
|
||||||
case llvm.ArrayTypeKind:
|
case llvm.ArrayTypeKind:
|
||||||
numElements := llvmType.ArrayLength()
|
numElements := llvmType.ArrayLength()
|
||||||
for i := 0; i < numElements; i++ {
|
for i := range numElements {
|
||||||
element := mv.r.builder.CreateExtractValue(llvmValue, i, "")
|
element := mv.r.builder.CreateExtractValue(llvmValue, i, "")
|
||||||
err := mv.markExternal(element, mark)
|
err := mv.markExternal(element, mark)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -366,7 +366,7 @@ func (mv *memoryView) store(v value, p pointerValue) bool {
|
|||||||
buffer := obj.buffer.asRawValue(mv.r)
|
buffer := obj.buffer.asRawValue(mv.r)
|
||||||
obj.buffer = buffer
|
obj.buffer = buffer
|
||||||
v := v.asRawValue(mv.r)
|
v := v.asRawValue(mv.r)
|
||||||
for i := uint32(0); i < valueLen; i++ {
|
for i := range valueLen {
|
||||||
buffer.buf[p.offset()+i] = v.buf[i]
|
buffer.buf[p.offset()+i] = v.buf[i]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -392,7 +392,7 @@ type value interface {
|
|||||||
// literalValue contains simple integer values that don't need to be stored in a
|
// literalValue contains simple integer values that don't need to be stored in a
|
||||||
// buffer.
|
// buffer.
|
||||||
type literalValue struct {
|
type literalValue struct {
|
||||||
value interface{}
|
value any
|
||||||
}
|
}
|
||||||
|
|
||||||
// Make a literalValue given the number of bits.
|
// Make a literalValue given the number of bits.
|
||||||
@@ -1015,7 +1015,7 @@ func (v *rawValue) set(llvmValue llvm.Value, r *runner) {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
panic(err)
|
panic(err)
|
||||||
}
|
}
|
||||||
for i := uint32(0); i < ptrSize; i++ {
|
for i := range ptrSize {
|
||||||
v.buf[i] = ptr.pointer
|
v.buf[i] = ptr.pointer
|
||||||
}
|
}
|
||||||
} else if !llvmValue.IsAConstantExpr().IsNil() {
|
} else if !llvmValue.IsAConstantExpr().IsNil() {
|
||||||
@@ -1056,7 +1056,7 @@ func (v *rawValue) set(llvmValue llvm.Value, r *runner) {
|
|||||||
panic(err)
|
panic(err)
|
||||||
}
|
}
|
||||||
ptrValue.pointer += totalOffset
|
ptrValue.pointer += totalOffset
|
||||||
for i := uint32(0); i < ptrSize; i++ {
|
for i := range ptrSize {
|
||||||
v.buf[i] = ptrValue.pointer
|
v.buf[i] = ptrValue.pointer
|
||||||
}
|
}
|
||||||
case llvm.ICmp:
|
case llvm.ICmp:
|
||||||
@@ -1113,7 +1113,7 @@ func (v *rawValue) set(llvmValue llvm.Value, r *runner) {
|
|||||||
}
|
}
|
||||||
case llvm.StructTypeKind:
|
case llvm.StructTypeKind:
|
||||||
numElements := llvmType.StructElementTypesCount()
|
numElements := llvmType.StructElementTypesCount()
|
||||||
for i := 0; i < numElements; i++ {
|
for i := range numElements {
|
||||||
offset := r.targetData.ElementOffset(llvmType, i)
|
offset := r.targetData.ElementOffset(llvmType, i)
|
||||||
field := rawValue{
|
field := rawValue{
|
||||||
buf: v.buf[offset:],
|
buf: v.buf[offset:],
|
||||||
@@ -1124,7 +1124,7 @@ func (v *rawValue) set(llvmValue llvm.Value, r *runner) {
|
|||||||
numElements := llvmType.ArrayLength()
|
numElements := llvmType.ArrayLength()
|
||||||
childType := llvmType.ElementType()
|
childType := llvmType.ElementType()
|
||||||
childTypeSize := r.targetData.TypeAllocSize(childType)
|
childTypeSize := r.targetData.TypeAllocSize(childType)
|
||||||
for i := 0; i < numElements; i++ {
|
for i := range numElements {
|
||||||
offset := i * int(childTypeSize)
|
offset := i * int(childTypeSize)
|
||||||
field := rawValue{
|
field := rawValue{
|
||||||
buf: v.buf[offset:],
|
buf: v.buf[offset:],
|
||||||
|
|||||||
@@ -786,15 +786,15 @@ func Debug(debugger, pkgName string, ocdOutput bool, options *compileopts.Option
|
|||||||
}
|
}
|
||||||
defer func() {
|
defer func() {
|
||||||
daemon.Process.Signal(os.Interrupt)
|
daemon.Process.Signal(os.Interrupt)
|
||||||
var stopped uint32
|
var stopped atomic.Uint32
|
||||||
go func() {
|
go func() {
|
||||||
time.Sleep(time.Millisecond * 100)
|
time.Sleep(time.Millisecond * 100)
|
||||||
if atomic.LoadUint32(&stopped) == 0 {
|
if stopped.Load() == 0 {
|
||||||
daemon.Process.Kill()
|
daemon.Process.Kill()
|
||||||
}
|
}
|
||||||
}()
|
}()
|
||||||
daemon.Wait()
|
daemon.Wait()
|
||||||
atomic.StoreUint32(&stopped, 1)
|
stopped.Store(1)
|
||||||
}()
|
}()
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1046,7 +1046,7 @@ func buildAndRun(pkgName string, config *compileopts.Config, stdout io.Writer, c
|
|||||||
|
|
||||||
func touchSerialPortAt1200bps(port string) (err error) {
|
func touchSerialPortAt1200bps(port string) (err error) {
|
||||||
retryCount := 3
|
retryCount := 3
|
||||||
for i := 0; i < retryCount; i++ {
|
for range retryCount {
|
||||||
// Open port
|
// Open port
|
||||||
p, e := serial.Open(port, &serial.Mode{BaudRate: 1200})
|
p, e := serial.Open(port, &serial.Mode{BaudRate: 1200})
|
||||||
if e != nil {
|
if e != nil {
|
||||||
@@ -1244,7 +1244,7 @@ func findFATMounts(options *compileopts.Options) ([]mountPoint, error) {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("could not list mount points: %w", err)
|
return nil, fmt.Errorf("could not list mount points: %w", err)
|
||||||
}
|
}
|
||||||
for _, line := range strings.Split(string(tab), "\n") {
|
for line := range strings.SplitSeq(string(tab), "\n") {
|
||||||
fields := strings.Fields(line)
|
fields := strings.Fields(line)
|
||||||
if len(fields) <= 2 {
|
if len(fields) <= 2 {
|
||||||
continue
|
continue
|
||||||
@@ -1273,7 +1273,7 @@ func findFATMounts(options *compileopts.Options) ([]mountPoint, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Extract data to convert to a []mountPoint slice.
|
// Extract data to convert to a []mountPoint slice.
|
||||||
for _, line := range strings.Split(out.String(), "\n") {
|
for line := range strings.SplitSeq(out.String(), "\n") {
|
||||||
words := strings.Fields(line)
|
words := strings.Fields(line)
|
||||||
if len(words) < 3 {
|
if len(words) < 3 {
|
||||||
continue
|
continue
|
||||||
@@ -1685,18 +1685,18 @@ func (m globalValuesFlag) String() string {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (m globalValuesFlag) Set(value string) error {
|
func (m globalValuesFlag) Set(value string) error {
|
||||||
equalsIndex := strings.IndexByte(value, '=')
|
before, after, ok := strings.Cut(value, "=")
|
||||||
if equalsIndex < 0 {
|
if !ok {
|
||||||
return errors.New("expected format pkgpath.Var=value")
|
return errors.New("expected format pkgpath.Var=value")
|
||||||
}
|
}
|
||||||
pathAndName := value[:equalsIndex]
|
pathAndName := before
|
||||||
pointIndex := strings.LastIndexByte(pathAndName, '.')
|
pointIndex := strings.LastIndexByte(pathAndName, '.')
|
||||||
if pointIndex < 0 {
|
if pointIndex < 0 {
|
||||||
return errors.New("expected format pkgpath.Var=value")
|
return errors.New("expected format pkgpath.Var=value")
|
||||||
}
|
}
|
||||||
path := pathAndName[:pointIndex]
|
path := pathAndName[:pointIndex]
|
||||||
name := pathAndName[pointIndex+1:]
|
name := pathAndName[pointIndex+1:]
|
||||||
stringValue := value[equalsIndex+1:]
|
stringValue := after
|
||||||
if m[path] == nil {
|
if m[path] == nil {
|
||||||
m[path] = make(map[string]string)
|
m[path] = make(map[string]string)
|
||||||
}
|
}
|
||||||
@@ -2054,7 +2054,6 @@ func main() {
|
|||||||
// This uses an additional semaphore to reduce the memory usage.
|
// This uses an additional semaphore to reduce the memory usage.
|
||||||
testSema := make(chan struct{}, cap(options.Semaphore))
|
testSema := make(chan struct{}, cap(options.Semaphore))
|
||||||
for i, pkgName := range explicitPkgNames {
|
for i, pkgName := range explicitPkgNames {
|
||||||
pkgName := pkgName
|
|
||||||
buf := &bufs[i]
|
buf := &bufs[i]
|
||||||
testSema <- struct{}{}
|
testSema <- struct{}{}
|
||||||
wg.Add(1)
|
wg.Add(1)
|
||||||
|
|||||||
+2
-7
@@ -398,7 +398,7 @@ func emuCheck(t *testing.T, options compileopts.Options) {
|
|||||||
t.Fatal("failed to load target spec:", err)
|
t.Fatal("failed to load target spec:", err)
|
||||||
}
|
}
|
||||||
if spec.Emulator != "" {
|
if spec.Emulator != "" {
|
||||||
emulatorCommand := strings.SplitN(spec.Emulator, " ", 2)[0]
|
emulatorCommand, _, _ := strings.Cut(spec.Emulator, " ")
|
||||||
_, err := exec.LookPath(emulatorCommand)
|
_, err := exec.LookPath(emulatorCommand)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
if errors.Is(err, exec.ErrNotFound) {
|
if errors.Is(err, exec.ErrNotFound) {
|
||||||
@@ -493,7 +493,7 @@ func runTestWithConfig(name string, t *testing.T, options compileopts.Options, c
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
w := &bytes.Buffer{}
|
w := &bytes.Buffer{}
|
||||||
diagnostics.CreateDiagnostics(err).WriteTo(w, "")
|
diagnostics.CreateDiagnostics(err).WriteTo(w, "")
|
||||||
for _, line := range strings.Split(strings.TrimRight(w.String(), "\n"), "\n") {
|
for line := range strings.SplitSeq(strings.TrimRight(w.String(), "\n"), "\n") {
|
||||||
t.Log(line)
|
t.Log(line)
|
||||||
}
|
}
|
||||||
if stdout.Len() != 0 {
|
if stdout.Len() != 0 {
|
||||||
@@ -569,7 +569,6 @@ func TestWebAssembly(t *testing.T) {
|
|||||||
{name: "panic-default", target: "wasip1", imports: []string{"wasi_snapshot_preview1.fd_write", "wasi_snapshot_preview1.random_get"}},
|
{name: "panic-default", target: "wasip1", imports: []string{"wasi_snapshot_preview1.fd_write", "wasi_snapshot_preview1.random_get"}},
|
||||||
{name: "panic-trap", target: "wasm-unknown", panicStrategy: "trap", imports: []string{}},
|
{name: "panic-trap", target: "wasm-unknown", panicStrategy: "trap", imports: []string{}},
|
||||||
} {
|
} {
|
||||||
tc := tc
|
|
||||||
t.Run(tc.name, func(t *testing.T) {
|
t.Run(tc.name, func(t *testing.T) {
|
||||||
t.Parallel()
|
t.Parallel()
|
||||||
tmpdir := t.TempDir()
|
tmpdir := t.TempDir()
|
||||||
@@ -691,7 +690,6 @@ func TestWasmExport(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
for _, tc := range tests {
|
for _, tc := range tests {
|
||||||
tc := tc
|
|
||||||
t.Run(tc.name, func(t *testing.T) {
|
t.Run(tc.name, func(t *testing.T) {
|
||||||
t.Parallel()
|
t.Parallel()
|
||||||
|
|
||||||
@@ -861,7 +859,6 @@ func TestWasmExportJS(t *testing.T) {
|
|||||||
{name: "c-shared", buildMode: "c-shared"},
|
{name: "c-shared", buildMode: "c-shared"},
|
||||||
}
|
}
|
||||||
for _, tc := range tests {
|
for _, tc := range tests {
|
||||||
tc := tc
|
|
||||||
t.Run(tc.name, func(t *testing.T) {
|
t.Run(tc.name, func(t *testing.T) {
|
||||||
t.Parallel()
|
t.Parallel()
|
||||||
// Build the wasm binary.
|
// Build the wasm binary.
|
||||||
@@ -909,7 +906,6 @@ func TestWasmExit(t *testing.T) {
|
|||||||
{name: "exit-1-sleep", output: "slept\nexit code: 1\n"},
|
{name: "exit-1-sleep", output: "slept\nexit code: 1\n"},
|
||||||
}
|
}
|
||||||
for _, tc := range tests {
|
for _, tc := range tests {
|
||||||
tc := tc
|
|
||||||
t.Run(tc.name, func(t *testing.T) {
|
t.Run(tc.name, func(t *testing.T) {
|
||||||
t.Parallel()
|
t.Parallel()
|
||||||
options := optionsFromTarget("wasm", sema)
|
options := optionsFromTarget("wasm", sema)
|
||||||
@@ -984,7 +980,6 @@ func TestTest(t *testing.T) {
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
for _, targ := range targs {
|
for _, targ := range targs {
|
||||||
targ := targ
|
|
||||||
t.Run(targ.name, func(t *testing.T) {
|
t.Run(targ.name, func(t *testing.T) {
|
||||||
t.Parallel()
|
t.Parallel()
|
||||||
|
|
||||||
|
|||||||
@@ -25,7 +25,7 @@ func main() {
|
|||||||
func escapesToHeap() {
|
func escapesToHeap() {
|
||||||
n := rand.Intn(100)
|
n := rand.Intn(100)
|
||||||
println("Doing ", n, " iterations")
|
println("Doing ", n, " iterations")
|
||||||
for i := 0; i < n; i++ {
|
for i := range n {
|
||||||
s := make([]byte, i)
|
s := make([]byte, i)
|
||||||
_ = append(s, 42)
|
_ = append(s, 42)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -70,7 +70,7 @@ func main() {
|
|||||||
printItf(Number(3))
|
printItf(Number(3))
|
||||||
s := Stringer(thing)
|
s := Stringer(thing)
|
||||||
println("Stringer.String():", s.String())
|
println("Stringer.String():", s.String())
|
||||||
var itf interface{} = s
|
var itf any = s
|
||||||
println("Stringer.(*Thing).String():", itf.(Stringer).String())
|
println("Stringer.(*Thing).String():", itf.(Stringer).String())
|
||||||
|
|
||||||
// unusual calls
|
// unusual calls
|
||||||
@@ -124,7 +124,7 @@ func strlen(s string) int {
|
|||||||
return len(s)
|
return len(s)
|
||||||
}
|
}
|
||||||
|
|
||||||
func printItf(val interface{}) {
|
func printItf(val any) {
|
||||||
switch val := val.(type) {
|
switch val := val.(type) {
|
||||||
case Doubler:
|
case Doubler:
|
||||||
println("is Doubler:", val.Double())
|
println("is Doubler:", val.Double())
|
||||||
|
|||||||
@@ -45,11 +45,8 @@ func Compare(a, b []byte) int {
|
|||||||
// This function was copied from the Go 1.23 source tree (with runtime_cmpstring
|
// This function was copied from the Go 1.23 source tree (with runtime_cmpstring
|
||||||
// manually inlined).
|
// manually inlined).
|
||||||
func CompareString(a, b string) int {
|
func CompareString(a, b string) int {
|
||||||
l := len(a)
|
l := min(len(b), len(a))
|
||||||
if len(b) < l {
|
for i := range l {
|
||||||
l = len(b)
|
|
||||||
}
|
|
||||||
for i := 0; i < l; i++ {
|
|
||||||
c1, c2 := a[i], b[i]
|
c1, c2 := a[i], b[i]
|
||||||
if c1 < c2 {
|
if c1 < c2 {
|
||||||
return -1
|
return -1
|
||||||
@@ -170,7 +167,7 @@ const PrimeRK = 16777619
|
|||||||
// This function was removed in Go 1.22.
|
// This function was removed in Go 1.22.
|
||||||
func HashStrBytes(sep []byte) (uint32, uint32) {
|
func HashStrBytes(sep []byte) (uint32, uint32) {
|
||||||
hash := uint32(0)
|
hash := uint32(0)
|
||||||
for i := 0; i < len(sep); i++ {
|
for i := range sep {
|
||||||
hash = hash*PrimeRK + uint32(sep[i])
|
hash = hash*PrimeRK + uint32(sep[i])
|
||||||
}
|
}
|
||||||
var pow, sq uint32 = 1, PrimeRK
|
var pow, sq uint32 = 1, PrimeRK
|
||||||
@@ -249,7 +246,7 @@ func IndexRabinKarpBytes(s, sep []byte) int {
|
|||||||
hashsep, pow := HashStrBytes(sep)
|
hashsep, pow := HashStrBytes(sep)
|
||||||
n := len(sep)
|
n := len(sep)
|
||||||
var h uint32
|
var h uint32
|
||||||
for i := 0; i < n; i++ {
|
for i := range n {
|
||||||
h = h*PrimeRK + uint32(s[i])
|
h = h*PrimeRK + uint32(s[i])
|
||||||
}
|
}
|
||||||
if h == hashsep && Equal(s[:n], sep) {
|
if h == hashsep && Equal(s[:n], sep) {
|
||||||
@@ -276,7 +273,7 @@ func IndexRabinKarp[T string | []byte](s, sep T) int {
|
|||||||
hashss, pow := HashStr(sep)
|
hashss, pow := HashStr(sep)
|
||||||
n := len(sep)
|
n := len(sep)
|
||||||
var h uint32
|
var h uint32
|
||||||
for i := 0; i < n; i++ {
|
for i := range n {
|
||||||
h = h*PrimeRK + uint32(s[i])
|
h = h*PrimeRK + uint32(s[i])
|
||||||
}
|
}
|
||||||
if h == hashss && string(s[:n]) == string(sep) {
|
if h == hashss && string(s[:n]) == string(sep) {
|
||||||
|
|||||||
@@ -12,8 +12,8 @@ func CaseUnmarshaler[T ~uint8 | ~uint16 | ~uint32](cases []string) func(v *T, te
|
|||||||
return &emptyTextError{}
|
return &emptyTextError{}
|
||||||
}
|
}
|
||||||
s := string(text)
|
s := string(text)
|
||||||
for i := 0; i < len(cases); i++ {
|
for i, c := range cases {
|
||||||
if cases[i] == s {
|
if c == s {
|
||||||
*v = T(i)
|
*v = T(i)
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -268,7 +268,7 @@ func TestRing512_PutOversize(t *testing.T) {
|
|||||||
|
|
||||||
func TestRing512_MultiplePutPeekDiscard(t *testing.T) {
|
func TestRing512_MultiplePutPeekDiscard(t *testing.T) {
|
||||||
var r ring512
|
var r ring512
|
||||||
for i := 0; i < 2000; i++ {
|
for i := range 2000 {
|
||||||
msg := []byte(fmt.Sprintf("msg%04d", i))
|
msg := []byte(fmt.Sprintf("msg%04d", i))
|
||||||
if !r.Put(msg) {
|
if !r.Put(msg) {
|
||||||
t.Fatalf("Put failed at iteration %d, Free=%d, Used=%d", i, r.Free(), r.Used())
|
t.Fatalf("Put failed at iteration %d, Free=%d, Used=%d", i, r.Free(), r.Used())
|
||||||
@@ -290,7 +290,7 @@ func TestRing512_HeadTailOverflow(t *testing.T) {
|
|||||||
t.Fatalf("Used=%d Free=%d, want 0/512", r.Used(), r.Free())
|
t.Fatalf("Used=%d Free=%d, want 0/512", r.Used(), r.Free())
|
||||||
}
|
}
|
||||||
|
|
||||||
for i := 0; i < 300; i++ {
|
for i := range 300 {
|
||||||
data := []byte{byte(i), byte(i + 1), byte(i + 2)}
|
data := []byte{byte(i), byte(i + 1), byte(i + 2)}
|
||||||
if !r.Put(data) {
|
if !r.Put(data) {
|
||||||
t.Fatalf("Put failed at iter %d (head=%d tail=%d)", i, r.head.Load(), r.tail.Load())
|
t.Fatalf("Put failed at iter %d (head=%d tail=%d)", i, r.head.Load(), r.tail.Load())
|
||||||
@@ -370,7 +370,7 @@ func TestRing512_PeekTotalEqualsUsed(t *testing.T) {
|
|||||||
// --- Concurrent SPSC Test ---
|
// --- Concurrent SPSC Test ---
|
||||||
|
|
||||||
func TestRing512_SPSC(t *testing.T) {
|
func TestRing512_SPSC(t *testing.T) {
|
||||||
for trial := 0; trial < 20; trial++ {
|
for trial := range 20 {
|
||||||
var r ring512
|
var r ring512
|
||||||
const totalBytes = 1 << 18
|
const totalBytes = 1 << 18
|
||||||
produced := make([]byte, totalBytes)
|
produced := make([]byte, totalBytes)
|
||||||
@@ -431,7 +431,7 @@ func TestRing512_SPSCSmallChunks(t *testing.T) {
|
|||||||
|
|
||||||
go func() {
|
go func() {
|
||||||
defer wg.Done()
|
defer wg.Done()
|
||||||
for i := 0; i < totalBytes; i++ {
|
for i := range totalBytes {
|
||||||
for !r.Put([]byte{byte(i)}) {
|
for !r.Put([]byte{byte(i)}) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -494,10 +494,7 @@ func FuzzRing512(f *testing.F) {
|
|||||||
|
|
||||||
switch op {
|
switch op {
|
||||||
case 0: // Put
|
case 0: // Put
|
||||||
size := int(arg)
|
size := min(int(arg), 512)
|
||||||
if size > 512 {
|
|
||||||
size = 512
|
|
||||||
}
|
|
||||||
data := make([]byte, size)
|
data := make([]byte, size)
|
||||||
for j := range data {
|
for j := range data {
|
||||||
data[j] = byte(j)
|
data[j] = byte(j)
|
||||||
|
|||||||
@@ -15,21 +15,21 @@ func TestCondSignal(t *testing.T) {
|
|||||||
cond.L.Lock()
|
cond.L.Lock()
|
||||||
|
|
||||||
// Start a goroutine to signal us once we wait.
|
// Start a goroutine to signal us once we wait.
|
||||||
var signaled uint32
|
var signaled atomic.Uint32
|
||||||
go func() {
|
go func() {
|
||||||
// Wait for the test goroutine to wait.
|
// Wait for the test goroutine to wait.
|
||||||
cond.L.Lock()
|
cond.L.Lock()
|
||||||
defer cond.L.Unlock()
|
defer cond.L.Unlock()
|
||||||
|
|
||||||
// Send a signal to the test goroutine.
|
// Send a signal to the test goroutine.
|
||||||
atomic.StoreUint32(&signaled, 1)
|
signaled.Store(1)
|
||||||
cond.Signal()
|
cond.Signal()
|
||||||
}()
|
}()
|
||||||
|
|
||||||
// Wait for a signal.
|
// Wait for a signal.
|
||||||
// This will unlock the mutex, and allow the spawned goroutine to run.
|
// This will unlock the mutex, and allow the spawned goroutine to run.
|
||||||
cond.Wait()
|
cond.Wait()
|
||||||
if atomic.LoadUint32(&signaled) == 0 {
|
if signaled.Load() == 0 {
|
||||||
t.Error("wait returned before a signal was sent")
|
t.Error("wait returned before a signal was sent")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -44,7 +44,7 @@ func TestCondBroadcast(t *testing.T) {
|
|||||||
// Start goroutines to wait for the broadcast.
|
// Start goroutines to wait for the broadcast.
|
||||||
var wg sync.WaitGroup
|
var wg sync.WaitGroup
|
||||||
const n = 5
|
const n = 5
|
||||||
for i := 0; i < n; i++ {
|
for range n {
|
||||||
wg.Add(1)
|
wg.Add(1)
|
||||||
mu.RLock()
|
mu.RLock()
|
||||||
go func() {
|
go func() {
|
||||||
|
|||||||
+22
-22
@@ -14,7 +14,7 @@ type mutex interface {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func HammerMutex(m mutex, loops int, cdone chan bool) {
|
func HammerMutex(m mutex, loops int, cdone chan bool) {
|
||||||
for i := 0; i < loops; i++ {
|
for i := range loops {
|
||||||
if i%3 == 0 {
|
if i%3 == 0 {
|
||||||
if m.TryLock() {
|
if m.TryLock() {
|
||||||
m.Unlock()
|
m.Unlock()
|
||||||
@@ -41,10 +41,10 @@ func TestMutex(t *testing.T) {
|
|||||||
m.Unlock()
|
m.Unlock()
|
||||||
|
|
||||||
c := make(chan bool)
|
c := make(chan bool)
|
||||||
for i := 0; i < 10; i++ {
|
for range 10 {
|
||||||
go HammerMutex(m, 1000, c)
|
go HammerMutex(m, 1000, c)
|
||||||
}
|
}
|
||||||
for i := 0; i < 10; i++ {
|
for range 10 {
|
||||||
<-c
|
<-c
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -54,7 +54,7 @@ func TestMutexUncontended(t *testing.T) {
|
|||||||
var mu sync.Mutex
|
var mu sync.Mutex
|
||||||
|
|
||||||
// Lock and unlock the mutex a few times.
|
// Lock and unlock the mutex a few times.
|
||||||
for i := 0; i < 3; i++ {
|
for range 3 {
|
||||||
mu.Lock()
|
mu.Lock()
|
||||||
mu.Unlock()
|
mu.Unlock()
|
||||||
}
|
}
|
||||||
@@ -69,7 +69,7 @@ func TestMutexConcurrent(t *testing.T) {
|
|||||||
var fail atomic.Uint32
|
var fail atomic.Uint32
|
||||||
|
|
||||||
const n = 10
|
const n = 10
|
||||||
for i := 0; i < n; i++ {
|
for i := range n {
|
||||||
j := i
|
j := i
|
||||||
go func() {
|
go func() {
|
||||||
// Delay a bit.
|
// Delay a bit.
|
||||||
@@ -129,12 +129,12 @@ func TestRWMutexUncontended(t *testing.T) {
|
|||||||
|
|
||||||
// Acquire several read locks.
|
// Acquire several read locks.
|
||||||
const n = 5
|
const n = 5
|
||||||
for i := 0; i < n; i++ {
|
for range n {
|
||||||
mu.RLock()
|
mu.RLock()
|
||||||
}
|
}
|
||||||
|
|
||||||
// Release all of the read locks.
|
// Release all of the read locks.
|
||||||
for i := 0; i < n; i++ {
|
for range n {
|
||||||
mu.RUnlock()
|
mu.RUnlock()
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -150,31 +150,31 @@ func TestRWMutexWriteToRead(t *testing.T) {
|
|||||||
mu.Lock()
|
mu.Lock()
|
||||||
|
|
||||||
const n = 3
|
const n = 3
|
||||||
var readAcquires uint32
|
var readAcquires atomic.Uint32
|
||||||
var completed uint32
|
var completed atomic.Uint32
|
||||||
var unlocked uint32
|
var unlocked atomic.Uint32
|
||||||
var bad uint32
|
var bad uint32
|
||||||
for i := 0; i < n; i++ {
|
for range n {
|
||||||
go func() {
|
go func() {
|
||||||
// Acquire a read lock.
|
// Acquire a read lock.
|
||||||
mu.RLock()
|
mu.RLock()
|
||||||
|
|
||||||
// Verify that the write lock is supposed to be released by now.
|
// Verify that the write lock is supposed to be released by now.
|
||||||
if atomic.LoadUint32(&unlocked) == 0 {
|
if unlocked.Load() == 0 {
|
||||||
// The write lock is still being held.
|
// The write lock is still being held.
|
||||||
atomic.AddUint32(&bad, 1)
|
atomic.AddUint32(&bad, 1)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Add ourselves to the read lock counter.
|
// Add ourselves to the read lock counter.
|
||||||
atomic.AddUint32(&readAcquires, 1)
|
readAcquires.Add(1)
|
||||||
|
|
||||||
// Wait for everything to hold the read lock simultaneously.
|
// Wait for everything to hold the read lock simultaneously.
|
||||||
for atomic.LoadUint32(&readAcquires) < n {
|
for readAcquires.Load() < n {
|
||||||
runtime.Gosched()
|
runtime.Gosched()
|
||||||
}
|
}
|
||||||
|
|
||||||
// Notify of completion.
|
// Notify of completion.
|
||||||
atomic.AddUint32(&completed, 1)
|
completed.Add(1)
|
||||||
|
|
||||||
// Release the read lock.
|
// Release the read lock.
|
||||||
mu.RUnlock()
|
mu.RUnlock()
|
||||||
@@ -182,16 +182,16 @@ func TestRWMutexWriteToRead(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Wait a bit for the goroutines to block.
|
// Wait a bit for the goroutines to block.
|
||||||
for i := 0; i < 3*n; i++ {
|
for range 3 * n {
|
||||||
runtime.Gosched()
|
runtime.Gosched()
|
||||||
}
|
}
|
||||||
|
|
||||||
// Release the write lock so that the goroutines acquire read locks.
|
// Release the write lock so that the goroutines acquire read locks.
|
||||||
atomic.StoreUint32(&unlocked, 1)
|
unlocked.Store(1)
|
||||||
mu.Unlock()
|
mu.Unlock()
|
||||||
|
|
||||||
// Wait for everything to complete.
|
// Wait for everything to complete.
|
||||||
for atomic.LoadUint32(&completed) < n {
|
for completed.Load() < n {
|
||||||
runtime.Gosched()
|
runtime.Gosched()
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -209,7 +209,7 @@ func TestRWMutexReadToWrite(t *testing.T) {
|
|||||||
const n = 3
|
const n = 3
|
||||||
var mu sync.RWMutex
|
var mu sync.RWMutex
|
||||||
var readers uint32
|
var readers uint32
|
||||||
for i := 0; i < n; i++ {
|
for range n {
|
||||||
mu.RLock()
|
mu.RLock()
|
||||||
readers++
|
readers++
|
||||||
}
|
}
|
||||||
@@ -230,7 +230,7 @@ func TestRWMutexReadToWrite(t *testing.T) {
|
|||||||
}()
|
}()
|
||||||
|
|
||||||
// Release the read locks.
|
// Release the read locks.
|
||||||
for i := 0; i < n; i++ {
|
for range n {
|
||||||
runtime.Gosched()
|
runtime.Gosched()
|
||||||
atomic.AddUint32(&readers, ^uint32(0))
|
atomic.AddUint32(&readers, ^uint32(0))
|
||||||
mu.RUnlock()
|
mu.RUnlock()
|
||||||
@@ -261,10 +261,10 @@ func TestRWMutex(t *testing.T) {
|
|||||||
m.Unlock()
|
m.Unlock()
|
||||||
|
|
||||||
c := make(chan bool)
|
c := make(chan bool)
|
||||||
for i := 0; i < 10; i++ {
|
for range 10 {
|
||||||
go HammerMutex(m, 1000, c)
|
go HammerMutex(m, 1000, c)
|
||||||
}
|
}
|
||||||
for i := 0; i < 10; i++ {
|
for range 10 {
|
||||||
<-c
|
<-c
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -11,7 +11,7 @@ type testItem struct {
|
|||||||
|
|
||||||
func TestPool(t *testing.T) {
|
func TestPool(t *testing.T) {
|
||||||
p := sync.Pool{
|
p := sync.Pool{
|
||||||
New: func() interface{} {
|
New: func() any {
|
||||||
return &testItem{}
|
return &testItem{}
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -27,7 +27,7 @@ func TestWaitGroup(t *testing.T) {
|
|||||||
const n = 5
|
const n = 5
|
||||||
var wg sync.WaitGroup
|
var wg sync.WaitGroup
|
||||||
wg.Add(n)
|
wg.Add(n)
|
||||||
for i := 0; i < n; i++ {
|
for range n {
|
||||||
go wg.Done()
|
go wg.Done()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -170,20 +170,6 @@ func (b *B) runN(n int) {
|
|||||||
b.StopTimer()
|
b.StopTimer()
|
||||||
}
|
}
|
||||||
|
|
||||||
func min(x, y int64) int64 {
|
|
||||||
if x > y {
|
|
||||||
return y
|
|
||||||
}
|
|
||||||
return x
|
|
||||||
}
|
|
||||||
|
|
||||||
func max(x, y int64) int64 {
|
|
||||||
if x < y {
|
|
||||||
return y
|
|
||||||
}
|
|
||||||
return x
|
|
||||||
}
|
|
||||||
|
|
||||||
// run1 runs the first iteration of benchFunc. It reports whether more
|
// run1 runs the first iteration of benchFunc. It reports whether more
|
||||||
// iterations of this benchmarks should be run.
|
// iterations of this benchmarks should be run.
|
||||||
func (b *B) run1() bool {
|
func (b *B) run1() bool {
|
||||||
|
|||||||
+20
-20
@@ -53,7 +53,7 @@ type corpusEntry = struct {
|
|||||||
Parent string
|
Parent string
|
||||||
Path string
|
Path string
|
||||||
Data []byte
|
Data []byte
|
||||||
Values []interface{}
|
Values []any
|
||||||
Generation int
|
Generation int
|
||||||
IsSeed bool
|
IsSeed bool
|
||||||
}
|
}
|
||||||
@@ -61,8 +61,8 @@ type corpusEntry = struct {
|
|||||||
// Add will add the arguments to the seed corpus for the fuzz test. This will be
|
// Add will add the arguments to the seed corpus for the fuzz test. This will be
|
||||||
// a no-op if called after or within the fuzz target, and args must match the
|
// a no-op if called after or within the fuzz target, and args must match the
|
||||||
// arguments for the fuzz target.
|
// arguments for the fuzz target.
|
||||||
func (f *F) Add(args ...interface{}) {
|
func (f *F) Add(args ...any) {
|
||||||
var values []interface{}
|
var values []any
|
||||||
for i := range args {
|
for i := range args {
|
||||||
if t := reflect.TypeOf(args[i]); !supportedTypes[t] {
|
if t := reflect.TypeOf(args[i]); !supportedTypes[t] {
|
||||||
panic(fmt.Sprintf("testing: unsupported type to Add %v", t))
|
panic(fmt.Sprintf("testing: unsupported type to Add %v", t))
|
||||||
@@ -74,23 +74,23 @@ func (f *F) Add(args ...interface{}) {
|
|||||||
|
|
||||||
// supportedTypes represents all of the supported types which can be fuzzed.
|
// supportedTypes represents all of the supported types which can be fuzzed.
|
||||||
var supportedTypes = map[reflect.Type]bool{
|
var supportedTypes = map[reflect.Type]bool{
|
||||||
reflect.TypeOf(([]byte)("")): true,
|
reflect.TypeFor[[]byte](): true,
|
||||||
reflect.TypeOf((string)("")): true,
|
reflect.TypeFor[string](): true,
|
||||||
reflect.TypeOf((bool)(false)): true,
|
reflect.TypeOf((bool)(false)): true,
|
||||||
reflect.TypeOf((byte)(0)): true,
|
reflect.TypeFor[byte](): true,
|
||||||
reflect.TypeOf((rune)(0)): true,
|
reflect.TypeFor[rune](): true,
|
||||||
reflect.TypeOf((float32)(0)): true,
|
reflect.TypeFor[float32](): true,
|
||||||
reflect.TypeOf((float64)(0)): true,
|
reflect.TypeFor[float64](): true,
|
||||||
reflect.TypeOf((int)(0)): true,
|
reflect.TypeFor[int](): true,
|
||||||
reflect.TypeOf((int8)(0)): true,
|
reflect.TypeFor[int8](): true,
|
||||||
reflect.TypeOf((int16)(0)): true,
|
reflect.TypeFor[int16](): true,
|
||||||
reflect.TypeOf((int32)(0)): true,
|
reflect.TypeFor[int32](): true,
|
||||||
reflect.TypeOf((int64)(0)): true,
|
reflect.TypeFor[int64](): true,
|
||||||
reflect.TypeOf((uint)(0)): true,
|
reflect.TypeFor[uint](): true,
|
||||||
reflect.TypeOf((uint8)(0)): true,
|
reflect.TypeFor[uint8](): true,
|
||||||
reflect.TypeOf((uint16)(0)): true,
|
reflect.TypeFor[uint16](): true,
|
||||||
reflect.TypeOf((uint32)(0)): true,
|
reflect.TypeFor[uint32](): true,
|
||||||
reflect.TypeOf((uint64)(0)): true,
|
reflect.TypeFor[uint64](): true,
|
||||||
}
|
}
|
||||||
|
|
||||||
// Fuzz runs the fuzz function, ff, for fuzz testing. If ff fails for a set of
|
// Fuzz runs the fuzz function, ff, for fuzz testing. If ff fails for a set of
|
||||||
@@ -119,7 +119,7 @@ var supportedTypes = map[reflect.Type]bool{
|
|||||||
// When fuzzing, F.Fuzz does not return until a problem is found, time runs out
|
// When fuzzing, F.Fuzz does not return until a problem is found, time runs out
|
||||||
// (set with -fuzztime), or the test process is interrupted by a signal. F.Fuzz
|
// (set with -fuzztime), or the test process is interrupted by a signal. F.Fuzz
|
||||||
// should be called exactly once, unless F.Skip or F.Fail is called beforehand.
|
// should be called exactly once, unless F.Skip or F.Fail is called beforehand.
|
||||||
func (f *F) Fuzz(ff interface{}) {
|
func (f *F) Fuzz(ff any) {
|
||||||
f.failed = true
|
f.failed = true
|
||||||
f.result.N = 0
|
f.result.N = 0
|
||||||
f.result.T = 0
|
f.result.T = 0
|
||||||
|
|||||||
+19
-19
@@ -137,7 +137,7 @@ func Testing() bool {
|
|||||||
|
|
||||||
// flushToParent writes c.output to the parent after first writing the header
|
// flushToParent writes c.output to the parent after first writing the header
|
||||||
// with the given format and arguments.
|
// with the given format and arguments.
|
||||||
func (c *common) flushToParent(testName, format string, args ...interface{}) {
|
func (c *common) flushToParent(testName, format string, args ...any) {
|
||||||
if c.parent == nil {
|
if c.parent == nil {
|
||||||
// The fake top-level test doesn't want a FAIL or PASS banner.
|
// The fake top-level test doesn't want a FAIL or PASS banner.
|
||||||
// Not quite sure how this works upstream.
|
// Not quite sure how this works upstream.
|
||||||
@@ -157,21 +157,21 @@ func fmtDuration(d time.Duration) string {
|
|||||||
type TB interface {
|
type TB interface {
|
||||||
Cleanup(func())
|
Cleanup(func())
|
||||||
Context() context.Context
|
Context() context.Context
|
||||||
Error(args ...interface{})
|
Error(args ...any)
|
||||||
Errorf(format string, args ...interface{})
|
Errorf(format string, args ...any)
|
||||||
Fail()
|
Fail()
|
||||||
FailNow()
|
FailNow()
|
||||||
Failed() bool
|
Failed() bool
|
||||||
Fatal(args ...interface{})
|
Fatal(args ...any)
|
||||||
Fatalf(format string, args ...interface{})
|
Fatalf(format string, args ...any)
|
||||||
Helper()
|
Helper()
|
||||||
Log(args ...interface{})
|
Log(args ...any)
|
||||||
Logf(format string, args ...interface{})
|
Logf(format string, args ...any)
|
||||||
Name() string
|
Name() string
|
||||||
Setenv(key, value string)
|
Setenv(key, value string)
|
||||||
Skip(args ...interface{})
|
Skip(args ...any)
|
||||||
SkipNow()
|
SkipNow()
|
||||||
Skipf(format string, args ...interface{})
|
Skipf(format string, args ...any)
|
||||||
Skipped() bool
|
Skipped() bool
|
||||||
TempDir() string
|
TempDir() string
|
||||||
}
|
}
|
||||||
@@ -238,47 +238,47 @@ func (c *common) log(s string) {
|
|||||||
// and records the text in the error log. For tests, the text will be printed only if
|
// and records the text in the error log. For tests, the text will be printed only if
|
||||||
// the test fails or the -test.v flag is set. For benchmarks, the text is always
|
// the test fails or the -test.v flag is set. For benchmarks, the text is always
|
||||||
// printed to avoid having performance depend on the value of the -test.v flag.
|
// printed to avoid having performance depend on the value of the -test.v flag.
|
||||||
func (c *common) Log(args ...interface{}) { c.log(fmt.Sprintln(args...)) }
|
func (c *common) Log(args ...any) { c.log(fmt.Sprintln(args...)) }
|
||||||
|
|
||||||
// Logf formats its arguments according to the format, analogous to Printf, and
|
// Logf formats its arguments according to the format, analogous to Printf, and
|
||||||
// records the text in the error log. A final newline is added if not provided. For
|
// records the text in the error log. A final newline is added if not provided. For
|
||||||
// tests, the text will be printed only if the test fails or the -test.v flag is
|
// tests, the text will be printed only if the test fails or the -test.v flag is
|
||||||
// set. For benchmarks, the text is always printed to avoid having performance
|
// set. For benchmarks, the text is always printed to avoid having performance
|
||||||
// depend on the value of the -test.v flag.
|
// depend on the value of the -test.v flag.
|
||||||
func (c *common) Logf(format string, args ...interface{}) { c.log(fmt.Sprintf(format, args...)) }
|
func (c *common) Logf(format string, args ...any) { c.log(fmt.Sprintf(format, args...)) }
|
||||||
|
|
||||||
// Error is equivalent to Log followed by Fail.
|
// Error is equivalent to Log followed by Fail.
|
||||||
func (c *common) Error(args ...interface{}) {
|
func (c *common) Error(args ...any) {
|
||||||
c.log(fmt.Sprintln(args...))
|
c.log(fmt.Sprintln(args...))
|
||||||
c.Fail()
|
c.Fail()
|
||||||
}
|
}
|
||||||
|
|
||||||
// Errorf is equivalent to Logf followed by Fail.
|
// Errorf is equivalent to Logf followed by Fail.
|
||||||
func (c *common) Errorf(format string, args ...interface{}) {
|
func (c *common) Errorf(format string, args ...any) {
|
||||||
c.log(fmt.Sprintf(format, args...))
|
c.log(fmt.Sprintf(format, args...))
|
||||||
c.Fail()
|
c.Fail()
|
||||||
}
|
}
|
||||||
|
|
||||||
// Fatal is equivalent to Log followed by FailNow.
|
// Fatal is equivalent to Log followed by FailNow.
|
||||||
func (c *common) Fatal(args ...interface{}) {
|
func (c *common) Fatal(args ...any) {
|
||||||
c.log(fmt.Sprintln(args...))
|
c.log(fmt.Sprintln(args...))
|
||||||
c.FailNow()
|
c.FailNow()
|
||||||
}
|
}
|
||||||
|
|
||||||
// Fatalf is equivalent to Logf followed by FailNow.
|
// Fatalf is equivalent to Logf followed by FailNow.
|
||||||
func (c *common) Fatalf(format string, args ...interface{}) {
|
func (c *common) Fatalf(format string, args ...any) {
|
||||||
c.log(fmt.Sprintf(format, args...))
|
c.log(fmt.Sprintf(format, args...))
|
||||||
c.FailNow()
|
c.FailNow()
|
||||||
}
|
}
|
||||||
|
|
||||||
// Skip is equivalent to Log followed by SkipNow.
|
// Skip is equivalent to Log followed by SkipNow.
|
||||||
func (c *common) Skip(args ...interface{}) {
|
func (c *common) Skip(args ...any) {
|
||||||
c.log(fmt.Sprintln(args...))
|
c.log(fmt.Sprintln(args...))
|
||||||
c.SkipNow()
|
c.SkipNow()
|
||||||
}
|
}
|
||||||
|
|
||||||
// Skipf is equivalent to Logf followed by SkipNow.
|
// Skipf is equivalent to Logf followed by SkipNow.
|
||||||
func (c *common) Skipf(format string, args ...interface{}) {
|
func (c *common) Skipf(format string, args ...any) {
|
||||||
c.log(fmt.Sprintf(format, args...))
|
c.log(fmt.Sprintf(format, args...))
|
||||||
c.SkipNow()
|
c.SkipNow()
|
||||||
}
|
}
|
||||||
@@ -672,7 +672,7 @@ func (t *T) report() {
|
|||||||
// Not implemented.
|
// Not implemented.
|
||||||
func AllocsPerRun(runs int, f func()) (avg float64) {
|
func AllocsPerRun(runs int, f func()) (avg float64) {
|
||||||
f()
|
f()
|
||||||
for i := 0; i < runs; i++ {
|
for range runs {
|
||||||
f()
|
f()
|
||||||
}
|
}
|
||||||
return 0
|
return 0
|
||||||
@@ -688,7 +688,7 @@ type InternalExample struct {
|
|||||||
// MainStart is meant for use by tests generated by 'go test'.
|
// MainStart is meant for use by tests generated by 'go test'.
|
||||||
// It is not meant to be called directly and is not subject to the Go 1 compatibility document.
|
// It is not meant to be called directly and is not subject to the Go 1 compatibility document.
|
||||||
// It may change signature from release to release.
|
// It may change signature from release to release.
|
||||||
func MainStart(deps interface{}, tests []InternalTest, benchmarks []InternalBenchmark, fuzzTargets []InternalFuzzTarget, examples []InternalExample) *M {
|
func MainStart(deps any, tests []InternalTest, benchmarks []InternalBenchmark, fuzzTargets []InternalFuzzTarget, examples []InternalExample) *M {
|
||||||
Init()
|
Init()
|
||||||
return &M{
|
return &M{
|
||||||
Tests: tests,
|
Tests: tests,
|
||||||
|
|||||||
@@ -71,4 +71,4 @@ func Make[T comparable](value T) Handle[T] {
|
|||||||
}
|
}
|
||||||
|
|
||||||
//go:linkname decomposeInterface runtime.decomposeInterface
|
//go:linkname decomposeInterface runtime.decomposeInterface
|
||||||
func decomposeInterface(i interface{}) (unsafe.Pointer, unsafe.Pointer)
|
func decomposeInterface(i any) (unsafe.Pointer, unsafe.Pointer)
|
||||||
|
|||||||
@@ -150,11 +150,11 @@ func (p *lowerInterfacesPass) run() error {
|
|||||||
|
|
||||||
// Collect all type codes.
|
// Collect all type codes.
|
||||||
for global := p.mod.FirstGlobal(); !global.IsNil(); global = llvm.NextGlobal(global) {
|
for global := p.mod.FirstGlobal(); !global.IsNil(); global = llvm.NextGlobal(global) {
|
||||||
if strings.HasPrefix(global.Name(), "reflect/types.type:") {
|
if after, ok := strings.CutPrefix(global.Name(), "reflect/types.type:"); ok {
|
||||||
// Retrieve Go type information based on an opaque global variable.
|
// Retrieve Go type information based on an opaque global variable.
|
||||||
// Only the name of the global is relevant, the object itself is
|
// Only the name of the global is relevant, the object itself is
|
||||||
// discarded afterwards.
|
// discarded afterwards.
|
||||||
name := strings.TrimPrefix(global.Name(), "reflect/types.type:")
|
name := after
|
||||||
if _, ok := p.types[name]; !ok {
|
if _, ok := p.types[name]; !ok {
|
||||||
t := &typeInfo{
|
t := &typeInfo{
|
||||||
name: name,
|
name: name,
|
||||||
@@ -463,7 +463,7 @@ func (p *lowerInterfacesPass) addTypeMethods(t *typeInfo, methodSet llvm.Value)
|
|||||||
signatures := p.builder.CreateExtractValue(set, 1, "")
|
signatures := p.builder.CreateExtractValue(set, 1, "")
|
||||||
wrappers := p.builder.CreateExtractValue(set, 2, "")
|
wrappers := p.builder.CreateExtractValue(set, 2, "")
|
||||||
numMethods := signatures.Type().ArrayLength()
|
numMethods := signatures.Type().ArrayLength()
|
||||||
for i := 0; i < numMethods; i++ {
|
for i := range numMethods {
|
||||||
signatureGlobal := p.builder.CreateExtractValue(signatures, i, "")
|
signatureGlobal := p.builder.CreateExtractValue(signatures, i, "")
|
||||||
function := p.builder.CreateExtractValue(wrappers, i, "")
|
function := p.builder.CreateExtractValue(wrappers, i, "")
|
||||||
function = stripPointerCasts(function) // strip bitcasts
|
function = stripPointerCasts(function) // strip bitcasts
|
||||||
@@ -489,7 +489,7 @@ func (p *lowerInterfacesPass) addInterface(methodsString string) {
|
|||||||
signatures: make(map[string]*signatureInfo),
|
signatures: make(map[string]*signatureInfo),
|
||||||
}
|
}
|
||||||
p.interfaces[methodsString] = t
|
p.interfaces[methodsString] = t
|
||||||
for _, method := range strings.Split(methodsString, "; ") {
|
for method := range strings.SplitSeq(methodsString, "; ") {
|
||||||
signature := p.getSignature(method)
|
signature := p.getSignature(method)
|
||||||
signature.interfaces = append(signature.interfaces, t)
|
signature.interfaces = append(signature.interfaces, t)
|
||||||
t.signatures[method] = signature
|
t.signatures[method] = signature
|
||||||
@@ -683,7 +683,7 @@ func (p *lowerInterfacesPass) extractMethodSigs(field llvm.Value) []string {
|
|||||||
methodArray := p.builder.CreateExtractValue(field, 1, "")
|
methodArray := p.builder.CreateExtractValue(field, 1, "")
|
||||||
n := methodArray.Type().ArrayLength()
|
n := methodArray.Type().ArrayLength()
|
||||||
sigs := make([]string, 0, n)
|
sigs := make([]string, 0, n)
|
||||||
for j := 0; j < n; j++ {
|
for j := range n {
|
||||||
sig := p.builder.CreateExtractValue(methodArray, j, "")
|
sig := p.builder.CreateExtractValue(methodArray, j, "")
|
||||||
sig = stripPointerCasts(sig)
|
sig = stripPointerCasts(sig)
|
||||||
sigs = append(sigs, sig.Name())
|
sigs = append(sigs, sig.Name())
|
||||||
@@ -727,7 +727,7 @@ func (p *lowerInterfacesPass) filterMethodSet(field llvm.Value, keepSigs map[str
|
|||||||
}
|
}
|
||||||
entries := make([]methodEntry, numMethods)
|
entries := make([]methodEntry, numMethods)
|
||||||
nameSet := make(map[string]struct{}, numMethods)
|
nameSet := make(map[string]struct{}, numMethods)
|
||||||
for j := 0; j < numMethods; j++ {
|
for j := range numMethods {
|
||||||
sig := p.builder.CreateExtractValue(methodArray, j, "")
|
sig := p.builder.CreateExtractValue(methodArray, j, "")
|
||||||
stripped := stripPointerCasts(sig)
|
stripped := stripPointerCasts(sig)
|
||||||
name := stripped.Name()
|
name := stripped.Name()
|
||||||
|
|||||||
+2
-2
@@ -34,7 +34,7 @@ func hasUses(value llvm.Value) bool {
|
|||||||
// contents, and returns the global and initializer type.
|
// contents, and returns the global and initializer type.
|
||||||
// Note that it is left with the default linkage etc., you should set
|
// Note that it is left with the default linkage etc., you should set
|
||||||
// linkage/constant/etc properties yourself.
|
// linkage/constant/etc properties yourself.
|
||||||
func makeGlobalArray(mod llvm.Module, bufItf interface{}, name string, elementType llvm.Type) (llvm.Type, llvm.Value) {
|
func makeGlobalArray(mod llvm.Module, bufItf any, name string, elementType llvm.Type) (llvm.Type, llvm.Value) {
|
||||||
buf := reflect.ValueOf(bufItf)
|
buf := reflect.ValueOf(bufItf)
|
||||||
var values []llvm.Value
|
var values []llvm.Value
|
||||||
for i := 0; i < buf.Len(); i++ {
|
for i := 0; i < buf.Len(); i++ {
|
||||||
@@ -64,7 +64,7 @@ func getGlobalBytes(global llvm.Value, builder llvm.Builder) []byte {
|
|||||||
// replaceGlobalByteWithArray replaces a global integer type in the module with
|
// replaceGlobalByteWithArray replaces a global integer type in the module with
|
||||||
// an integer array, using a GEP to make the types match. It is a convenience
|
// an integer array, using a GEP to make the types match. It is a convenience
|
||||||
// function used for creating reflection sidetables, for example.
|
// function used for creating reflection sidetables, for example.
|
||||||
func replaceGlobalIntWithArray(mod llvm.Module, name string, buf interface{}) llvm.Value {
|
func replaceGlobalIntWithArray(mod llvm.Module, name string, buf any) llvm.Value {
|
||||||
oldGlobal := mod.NamedGlobal(name)
|
oldGlobal := mod.NamedGlobal(name)
|
||||||
globalType, global := makeGlobalArray(mod, buf, name+".tmp", oldGlobal.GlobalValueType())
|
globalType, global := makeGlobalArray(mod, buf, name+".tmp", oldGlobal.GlobalValueType())
|
||||||
gep := llvm.ConstGEP(globalType, global, []llvm.Value{
|
gep := llvm.ConstGEP(globalType, global, []llvm.Value{
|
||||||
|
|||||||
Reference in New Issue
Block a user