Skip to content

Commit

Permalink
Merge pull request #243 from xushiwei/q
Browse files Browse the repository at this point in the history
github.com/goplus/llgo/internal/packages; prog.TypeSizes: todo
  • Loading branch information
xushiwei authored May 28, 2024
2 parents 0a0d72e + 3da1aa3 commit 90c76bb
Show file tree
Hide file tree
Showing 5 changed files with 162 additions and 10 deletions.
10 changes: 6 additions & 4 deletions internal/build/build.go
Original file line number Diff line number Diff line change
Expand Up @@ -29,10 +29,10 @@ import (
"runtime"
"strings"

"golang.org/x/tools/go/packages"
"golang.org/x/tools/go/ssa"

"github.com/goplus/llgo/cl"
"github.com/goplus/llgo/internal/packages"
"github.com/goplus/llgo/xtool/clang"

llssa "github.com/goplus/llgo/ssa"
Expand Down Expand Up @@ -88,6 +88,9 @@ const (
)

func Do(args []string, conf *Config) {
prog := llssa.NewProgram(nil)
sizes := prog.TypeSizes()

flags, patterns, verbose := ParseArgs(args, buildFlags)
cfg := &packages.Config{
Mode: loadSyntax | packages.NeedDeps | packages.NeedModule | packages.NeedExportFile,
Expand All @@ -97,7 +100,7 @@ func Do(args []string, conf *Config) {
if patterns == nil {
patterns = []string{"."}
}
initial, err := packages.Load(cfg, patterns...)
initial, err := packages.LoadEx(sizes, cfg, patterns...)
check(err)

mode := conf.Mode
Expand All @@ -122,11 +125,10 @@ func Do(args []string, conf *Config) {

var needRt bool
var rt []*packages.Package
prog := llssa.NewProgram(nil)
load := func() []*packages.Package {
if rt == nil {
var err error
rt, err = packages.Load(cfg, llssa.PkgRuntime, llssa.PkgPython)
rt, err = packages.LoadEx(sizes, cfg, llssa.PkgRuntime, llssa.PkgPython)
check(err)
}
return rt
Expand Down
4 changes: 2 additions & 2 deletions internal/build/clean.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ import (
"path"
"path/filepath"

"golang.org/x/tools/go/packages"
"github.com/goplus/llgo/internal/packages"
)

var (
Expand All @@ -42,7 +42,7 @@ func Clean(args []string, conf *Config) {
if patterns == nil {
patterns = []string{"."}
}
initial, err := packages.Load(cfg, patterns...)
initial, err := packages.LoadEx(nil, cfg, patterns...)
check(err)

cleanPkgs(initial, verbose)
Expand Down
9 changes: 5 additions & 4 deletions internal/llgen/llgenf.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ import (
"strings"

"github.com/goplus/llgo/cl"
"golang.org/x/tools/go/packages"
"github.com/goplus/llgo/internal/packages"
"golang.org/x/tools/go/ssa"
"golang.org/x/tools/go/ssa/ssautil"

Expand All @@ -43,7 +43,7 @@ func initRtAndPy(prog llssa.Program, cfg *packages.Config) {
load := func() []*packages.Package {
if pkgRtAndPy == nil {
var err error
pkgRtAndPy, err = packages.Load(cfg, llssa.PkgRuntime, llssa.PkgPython)
pkgRtAndPy, err = packages.LoadEx(prog.TypeSizes(), cfg, llssa.PkgRuntime, llssa.PkgPython)
check(err)
}
return pkgRtAndPy
Expand All @@ -60,10 +60,12 @@ func initRtAndPy(prog llssa.Program, cfg *packages.Config) {
}

func GenFrom(fileOrPkg string) string {
prog := llssa.NewProgram(nil)

cfg := &packages.Config{
Mode: loadSyntax | packages.NeedDeps,
}
initial, err := packages.Load(cfg, fileOrPkg)
initial, err := packages.LoadEx(prog.TypeSizes(), cfg, fileOrPkg)
check(err)

_, pkgs := ssautil.AllPackages(initial, ssa.SanityCheckFunctions)
Expand All @@ -72,7 +74,6 @@ func GenFrom(fileOrPkg string) string {
ssaPkg := pkgs[0]
ssaPkg.Build()

prog := llssa.NewProgram(nil)
initRtAndPy(prog, cfg)

if Verbose {
Expand Down
144 changes: 144 additions & 0 deletions internal/packages/load.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,144 @@
/*
* Copyright (c) 2024 The GoPlus Authors (goplus.org). All rights reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

package packages

import (
"fmt"
"go/types"
"runtime"
"sync"
"unsafe"

"golang.org/x/tools/go/packages"
)

// A LoadMode controls the amount of detail to return when loading.
// The bits below can be combined to specify which fields should be
// filled in the result packages.
// The zero value is a special case, equivalent to combining
// the NeedName, NeedFiles, and NeedCompiledGoFiles bits.
// ID and Errors (if present) will always be filled.
// Load may return more information than requested.
type LoadMode = packages.LoadMode

const (
NeedName = packages.NeedName
NeedFiles = packages.NeedFiles

NeedSyntax = packages.NeedSyntax
NeedImports = packages.NeedImports
NeedDeps = packages.NeedDeps
NeedModule = packages.NeedModule
NeedExportFile = packages.NeedExportFile

NeedCompiledGoFiles = packages.NeedCompiledGoFiles

NeedTypes = packages.NeedTypes
NeedTypesSizes = packages.NeedTypesSizes
NeedTypesInfo = packages.NeedTypesInfo
)

// A Config specifies details about how packages should be loaded.
// The zero value is a valid configuration.
// Calls to Load do not modify this struct.
type Config = packages.Config

// A Package describes a loaded Go package.
type Package = packages.Package

// loader holds the working state of a single call to load.
type loader struct {
pkgs map[string]unsafe.Pointer
Config
sizes types.Sizes // non-nil if needed by mode
parseCache map[string]unsafe.Pointer
parseCacheMu sync.Mutex
exportMu sync.Mutex // enforces mutual exclusion of exportdata operations

// Config.Mode contains the implied mode (see impliedLoadMode).
// Implied mode contains all the fields we need the data for.
// In requestedMode there are the actually requested fields.
// We'll zero them out before returning packages to the user.
// This makes it easier for us to get the conditions where
// we need certain modes right.
requestedMode LoadMode
}

//go:linkname newLoader golang.org/x/tools/go/packages.newLoader
func newLoader(cfg *Config) *loader

//go:linkname defaultDriver golang.org/x/tools/go/packages.defaultDriver
func defaultDriver(cfg *Config, patterns ...string) (*packages.DriverResponse, bool, error)

//go:linkname refine golang.org/x/tools/go/packages.(*loader).refine
func refine(ld *loader, response *packages.DriverResponse) ([]*Package, error)

// LoadEx loads and returns the Go packages named by the given patterns.
//
// Config specifies loading options;
// nil behaves the same as an empty Config.
//
// If any of the patterns was invalid as defined by the
// underlying build system, Load returns an error.
// It may return an empty list of packages without an error,
// for instance for an empty expansion of a valid wildcard.
// Errors associated with a particular package are recorded in the
// corresponding Package's Errors list, and do not cause Load to
// return an error. Clients may need to handle such errors before
// proceeding with further analysis. The PrintErrors function is
// provided for convenient display of all errors.
func LoadEx(sizes types.Sizes, cfg *Config, patterns ...string) ([]*Package, error) {
ld := newLoader(cfg)
response, external, err := defaultDriver(&ld.Config, patterns...)
if err != nil {
return nil, err
}

if sizes == nil {
sizes = types.SizesFor(response.Compiler, response.Arch)
}
ld.sizes = sizes
if ld.sizes == nil && ld.Config.Mode&(NeedTypes|NeedTypesSizes|NeedTypesInfo) != 0 {
// Type size information is needed but unavailable.
if external {
// An external driver may fail to populate the Compiler/GOARCH fields,
// especially since they are relatively new (see #63700).
// Provide a sensible fallback in this case.
ld.sizes = types.SizesFor("gc", runtime.GOARCH)
if ld.sizes == nil { // gccgo-only arch
ld.sizes = types.SizesFor("gc", "amd64")
}
} else {
// Go list should never fail to deliver accurate size information.
// Reject the whole Load since the error is the same for every package.
return nil, fmt.Errorf("can't determine type sizes for compiler %q on GOARCH %q",
response.Compiler, response.Arch)
}
}

return refine(ld, response)
}

// Visit visits all the packages in the import graph whose roots are
// pkgs, calling the optional pre function the first time each package
// is encountered (preorder), and the optional post function after a
// package's dependencies have been visited (postorder).
// The boolean result of pre(pkg) determines whether
// the imports of package pkg are visited.
//
//go:linkname Visit golang.org/x/tools/go/packages.Visit
func Visit(pkgs []*Package, pre func(*Package) bool, post func(*Package))
5 changes: 5 additions & 0 deletions ssa/type.go
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,11 @@ func (t Type) RawType() types.Type {
return t.raw.Type
}

// TypeSizes returns the sizes of the types.
func (p Program) TypeSizes() types.Sizes {
return nil // TODO(xsw)
}

// TODO(xsw):
// how to generate platform independent code?
func (p Program) SizeOf(typ Type, n ...int64) uint64 {
Expand Down

0 comments on commit 90c76bb

Please sign in to comment.