diff --git a/compiler/internal/build/build.go b/compiler/internal/build/build.go index f80d8daf..a8aa3f0b 100644 --- a/compiler/internal/build/build.go +++ b/compiler/internal/build/build.go @@ -46,6 +46,7 @@ import ( "github.com/goplus/llgo/xtool/env/llvm" llssa "github.com/goplus/llgo/compiler/ssa" + llruntime "github.com/goplus/llgo/runtime" clangCheck "github.com/goplus/llgo/xtool/clang/check" ) @@ -133,9 +134,9 @@ func Do(args []string, conf *Config) ([]Package, error) { cfg.Mode |= packages.NeedForTest } - if len(overlayFiles) > 0 { + if len(llruntime.OverlayFiles) > 0 { cfg.Overlay = make(map[string][]byte) - for file, src := range overlayFiles { + for file, src := range llruntime.OverlayFiles { overlay := unsafe.Slice(unsafe.StringData(src), len(src)) cfg.Overlay[filepath.Join(env.GOROOT(), "src", file)] = overlay } @@ -154,7 +155,7 @@ func Do(args []string, conf *Config) ([]Package, error) { sizes := prog.TypeSizes dedup := packages.NewDeduper() dedup.SetPreload(func(pkg *types.Package, files []*ast.File) { - if canSkipToBuild(pkg.Path()) { + if llruntime.SkipToBuild(pkg.Path()) { return } cl.ParsePkgSyntax(prog, pkg, files) @@ -580,7 +581,7 @@ func buildPkg(ctx *context, aPkg *aPackage, verbose bool) (cgoLdflags []string, if debugBuild || verbose { fmt.Fprintln(os.Stderr, pkgPath) } - if canSkipToBuild(pkgPath) { + if llruntime.SkipToBuild(pkgPath) { pkg.ExportFile = "" return } @@ -642,8 +643,8 @@ const ( func altPkgs(initial []*packages.Package, alts ...string) []string { packages.Visit(initial, nil, func(p *packages.Package) { if p.Types != nil && !p.IllTyped { - if _, ok := hasAltPkg[p.ID]; ok { - alts = append(alts, altPkgPathPrefix+p.ID) + if llruntime.HasAltPkg(p.PkgPath) { + alts = append(alts, altPkgPathPrefix+p.PkgPath) } } }) @@ -691,7 +692,7 @@ func allPkgs(ctx *context, initial []*packages.Package, verbose bool) (all []*aP } var altPkg *packages.Cached var ssaPkg = createSSAPkg(prog, p, verbose) - if _, ok := hasAltPkg[pkgPath]; ok { + if llruntime.HasAltPkg(pkgPath) { if altPkg = ctx.dedup.Check(altPkgPathPrefix + pkgPath); altPkg == nil { return } @@ -864,13 +865,6 @@ func pkgExists(initial []*packages.Package, pkg *packages.Package) bool { return false } -func canSkipToBuild(pkgPath string) bool { - if _, ok := hasAltPkg[pkgPath]; ok { - return false - } - return pkgPath == "unsafe" -} - // findDylibDep finds the dylib dependency in the executable. It returns empty // string if not found. func findDylibDep(exe, lib string) string { @@ -889,49 +883,6 @@ func findDylibDep(exe, lib string) string { type none struct{} -var hasAltPkg = map[string]none{ - "crypto/hmac": {}, - "crypto/md5": {}, - "crypto/rand": {}, - "crypto/sha1": {}, - "crypto/sha256": {}, - "crypto/sha512": {}, - "crypto/subtle": {}, - "go/parser": {}, - "hash/crc32": {}, - "internal/abi": {}, - "internal/bytealg": {}, - "internal/cpu": {}, - "internal/itoa": {}, - "internal/filepathlite": {}, - "internal/godebug": {}, - "internal/oserror": {}, - "internal/poll": {}, - "internal/race": {}, - "internal/reflectlite": {}, - "internal/stringslite": {}, - "internal/syscall/execenv": {}, - "internal/syscall/unix": {}, - "math": {}, - "math/big": {}, - "math/cmplx": {}, - "math/rand": {}, - "reflect": {}, - "sync": {}, - "sync/atomic": {}, - "syscall": {}, - "time": {}, - "os": {}, - "os/exec": {}, - "os/signal": {}, - "runtime": {}, - "runtime/debug": {}, - "runtime/pprof": {}, - "runtime/trace": {}, - "runtime/internal/syscall": {}, - "io": {}, -} - func check(err error) { if err != nil { panic(err) diff --git a/compiler/internal/build/_overlay/go/parser/resolver.go b/runtime/_overlay/go/parser/resolver.go similarity index 100% rename from compiler/internal/build/_overlay/go/parser/resolver.go rename to runtime/_overlay/go/parser/resolver.go diff --git a/compiler/internal/build/_overlay/net/textproto/textproto.go b/runtime/_overlay/net/textproto/textproto.go similarity index 100% rename from compiler/internal/build/_overlay/net/textproto/textproto.go rename to runtime/_overlay/net/textproto/textproto.go diff --git a/compiler/internal/build/_overlay/testing/testing.go b/runtime/_overlay/testing/testing.go similarity index 100% rename from compiler/internal/build/_overlay/testing/testing.go rename to runtime/_overlay/testing/testing.go diff --git a/runtime/build.go b/runtime/build.go new file mode 100644 index 00000000..dc6dfe67 --- /dev/null +++ b/runtime/build.go @@ -0,0 +1,75 @@ +package runtime + +import ( + "strings" +) + +func SkipToBuild(pkgPath string) bool { + if _, ok := hasAltPkg[pkgPath]; ok { + return false + } + if _, ok := supportedInternal[pkgPath]; ok { + return false + } + switch pkgPath { + case "unsafe": + return true + default: + return strings.HasPrefix(pkgPath, "internal/") || + strings.HasPrefix(pkgPath, "runtime/internal/") + } +} + +func HasAltPkg(path string) (b bool) { + _, b = hasAltPkg[path] + return +} + +type none struct{} + +var hasAltPkg = map[string]none{ + "crypto/hmac": {}, + "crypto/md5": {}, + "crypto/rand": {}, + "crypto/sha1": {}, + "crypto/sha256": {}, + "crypto/sha512": {}, + "crypto/subtle": {}, + "go/parser": {}, + "hash/crc32": {}, + "internal/abi": {}, + "internal/bytealg": {}, + "internal/cpu": {}, + "internal/itoa": {}, + "internal/godebug": {}, + "internal/oserror": {}, + "internal/poll": {}, + "internal/reflectlite": {}, + "internal/syscall/execenv": {}, + "internal/syscall/unix": {}, + "math": {}, + "math/big": {}, + "math/cmplx": {}, + "math/rand": {}, + "reflect": {}, + "sync": {}, + "sync/atomic": {}, + "syscall": {}, + "time": {}, + "os": {}, + "os/exec": {}, + "os/signal": {}, + "runtime": {}, + "runtime/debug": {}, + "runtime/pprof": {}, + "runtime/trace": {}, + "runtime/internal/syscall": {}, + "io": {}, +} + +var supportedInternal = map[string]none{ + "internal/race": {}, + "internal/stringslite": {}, + "internal/filepathlite": {}, + "internal/fmtsort": {}, +} diff --git a/runtime/internal/lib/internal/filepathlite/filepathlite.go b/runtime/internal/lib/internal/filepathlite/filepathlite.go deleted file mode 100644 index 34a3de68..00000000 --- a/runtime/internal/lib/internal/filepathlite/filepathlite.go +++ /dev/null @@ -1 +0,0 @@ -package filepathlite diff --git a/runtime/internal/lib/internal/fmtsort/sort.go b/runtime/internal/lib/internal/fmtsort/sort.go deleted file mode 100644 index 802f724d..00000000 --- a/runtime/internal/lib/internal/fmtsort/sort.go +++ /dev/null @@ -1,222 +0,0 @@ -// Copyright 2018 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -// Package fmtsort provides a general stable ordering mechanism -// for maps, on behalf of the fmt and text/template packages. -// It is not guaranteed to be efficient and works only for types -// that are valid map keys. -package fmtsort - -import ( - "reflect" - "sort" -) - -// llgo:skipall -type _fmtsort struct{} - -// Note: Throughout this package we avoid calling reflect.Value.Interface as -// it is not always legal to do so and it's easier to avoid the issue than to face it. - -// SortedMap represents a map's keys and values. The keys and values are -// aligned in index order: Value[i] is the value in the map corresponding to Key[i]. -type SortedMap struct { - Key []reflect.Value - Value []reflect.Value -} - -func (o *SortedMap) Len() int { return len(o.Key) } -func (o *SortedMap) Less(i, j int) bool { return compare(o.Key[i], o.Key[j]) < 0 } -func (o *SortedMap) Swap(i, j int) { - o.Key[i], o.Key[j] = o.Key[j], o.Key[i] - o.Value[i], o.Value[j] = o.Value[j], o.Value[i] -} - -// Sort accepts a map and returns a SortedMap that has the same keys and -// values but in a stable sorted order according to the keys, modulo issues -// raised by unorderable key values such as NaNs. -// -// The ordering rules are more general than with Go's < operator: -// -// - when applicable, nil compares low -// - ints, floats, and strings order by < -// - NaN compares less than non-NaN floats -// - bool compares false before true -// - complex compares real, then imag -// - pointers compare by machine address -// - channel values compare by machine address -// - structs compare each field in turn -// - arrays compare each element in turn. -// Otherwise identical arrays compare by length. -// - interface values compare first by reflect.Type describing the concrete type -// and then by concrete value as described in the previous rules. -func Sort(mapValue reflect.Value) *SortedMap { - if mapValue.Type().Kind() != reflect.Map { - return nil - } - // Note: this code is arranged to not panic even in the presence - // of a concurrent map update. The runtime is responsible for - // yelling loudly if that happens. See issue 33275. - n := mapValue.Len() - key := make([]reflect.Value, 0, n) - value := make([]reflect.Value, 0, n) - iter := mapValue.MapRange() - for iter.Next() { - key = append(key, iter.Key()) - value = append(value, iter.Value()) - } - sorted := &SortedMap{ - Key: key, - Value: value, - } - sort.Stable(sorted) - return sorted -} - -// compare compares two values of the same type. It returns -1, 0, 1 -// according to whether a > b (1), a == b (0), or a < b (-1). -// If the types differ, it returns -1. -// See the comment on Sort for the comparison rules. -func compare(aVal, bVal reflect.Value) int { - aType, bType := aVal.Type(), bVal.Type() - if aType != bType { - return -1 // No good answer possible, but don't return 0: they're not equal. - } - switch aVal.Kind() { - case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64: - a, b := aVal.Int(), bVal.Int() - switch { - case a < b: - return -1 - case a > b: - return 1 - default: - return 0 - } - case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr: - a, b := aVal.Uint(), bVal.Uint() - switch { - case a < b: - return -1 - case a > b: - return 1 - default: - return 0 - } - case reflect.String: - a, b := aVal.String(), bVal.String() - switch { - case a < b: - return -1 - case a > b: - return 1 - default: - return 0 - } - case reflect.Float32, reflect.Float64: - return floatCompare(aVal.Float(), bVal.Float()) - case reflect.Complex64, reflect.Complex128: - a, b := aVal.Complex(), bVal.Complex() - if c := floatCompare(real(a), real(b)); c != 0 { - return c - } - return floatCompare(imag(a), imag(b)) - case reflect.Bool: - a, b := aVal.Bool(), bVal.Bool() - switch { - case a == b: - return 0 - case a: - return 1 - default: - return -1 - } - case reflect.Pointer, reflect.UnsafePointer: - a, b := aVal.Pointer(), bVal.Pointer() - switch { - case a < b: - return -1 - case a > b: - return 1 - default: - return 0 - } - case reflect.Chan: - if c, ok := nilCompare(aVal, bVal); ok { - return c - } - ap, bp := aVal.Pointer(), bVal.Pointer() - switch { - case ap < bp: - return -1 - case ap > bp: - return 1 - default: - return 0 - } - case reflect.Struct: - for i := 0; i < aVal.NumField(); i++ { - if c := compare(aVal.Field(i), bVal.Field(i)); c != 0 { - return c - } - } - return 0 - case reflect.Array: - for i := 0; i < aVal.Len(); i++ { - if c := compare(aVal.Index(i), bVal.Index(i)); c != 0 { - return c - } - } - return 0 - case reflect.Interface: - if c, ok := nilCompare(aVal, bVal); ok { - return c - } - c := compare(reflect.ValueOf(aVal.Elem().Type()), reflect.ValueOf(bVal.Elem().Type())) - if c != 0 { - return c - } - return compare(aVal.Elem(), bVal.Elem()) - default: - // Certain types cannot appear as keys (maps, funcs, slices), but be explicit. - panic("bad type in compare: " + aType.String()) - } -} - -// nilCompare checks whether either value is nil. If not, the boolean is false. -// If either value is nil, the boolean is true and the integer is the comparison -// value. The comparison is defined to be 0 if both are nil, otherwise the one -// nil value compares low. Both arguments must represent a chan, func, -// interface, map, pointer, or slice. -func nilCompare(aVal, bVal reflect.Value) (int, bool) { - if aVal.IsNil() { - if bVal.IsNil() { - return 0, true - } - return -1, true - } - if bVal.IsNil() { - return 1, true - } - return 0, false -} - -// floatCompare compares two floating-point values. NaNs compare low. -func floatCompare(a, b float64) int { - switch { - case isNaN(a): - return -1 // No good answer if b is a NaN so don't bother checking. - case isNaN(b): - return 1 - case a < b: - return -1 - case a > b: - return 1 - } - return 0 -} - -func isNaN(a float64) bool { - return a != a -} diff --git a/runtime/internal/lib/internal/race/race.go b/runtime/internal/lib/internal/race/race.go deleted file mode 100644 index a6b23589..00000000 --- a/runtime/internal/lib/internal/race/race.go +++ /dev/null @@ -1 +0,0 @@ -package race diff --git a/runtime/internal/lib/internal/stringslite/strings.go b/runtime/internal/lib/internal/stringslite/strings.go deleted file mode 100644 index 66be1e34..00000000 --- a/runtime/internal/lib/internal/stringslite/strings.go +++ /dev/null @@ -1 +0,0 @@ -package stringslite diff --git a/compiler/internal/build/overlay.go b/runtime/overlay.go similarity index 88% rename from compiler/internal/build/overlay.go rename to runtime/overlay.go index fd8ff857..62bbea28 100644 --- a/compiler/internal/build/overlay.go +++ b/runtime/overlay.go @@ -1,4 +1,4 @@ -package build +package runtime import ( _ "embed" @@ -13,7 +13,7 @@ var testing_testing string //go:embed _overlay/net/textproto/textproto.go var net_textproto string -var overlayFiles = map[string]string{ +var OverlayFiles = map[string]string{ "math/exp_amd64.go": "package math;", "go/parser/resolver.go": go_parser_resolver, "testing/testing.go": testing_testing,