diff --git a/internal/abi/llgo_autogen.lla b/internal/abi/llgo_autogen.lla index fefd4872..f5f43eca 100644 Binary files a/internal/abi/llgo_autogen.lla and b/internal/abi/llgo_autogen.lla differ diff --git a/internal/build/build.go b/internal/build/build.go index e7da46b7..5e161979 100644 --- a/internal/build/build.go +++ b/internal/build/build.go @@ -88,15 +88,21 @@ 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, BuildFlags: flags, } + llssa.Initialize(llssa.InitAll) + if verbose { + llssa.SetDebug(llssa.DbgFlagAll) + cl.SetDebug(cl.DbgFlagAll) + } + + prog := llssa.NewProgram(nil) + sizes := prog.TypeSizes + if patterns == nil { patterns = []string{"."} } @@ -117,12 +123,6 @@ func Do(args []string, conf *Config) { return } - llssa.Initialize(llssa.InitAll) - if verbose { - llssa.SetDebug(llssa.DbgFlagAll) - cl.SetDebug(cl.DbgFlagAll) - } - var needRt bool var rt []*packages.Package load := func() []*packages.Package { diff --git a/internal/llgen/llgenf.go b/internal/llgen/llgenf.go index 34489f2d..cabbc234 100644 --- a/internal/llgen/llgenf.go +++ b/internal/llgen/llgenf.go @@ -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.LoadEx(prog.TypeSizes(), cfg, llssa.PkgRuntime, llssa.PkgPython) + pkgRtAndPy, err = packages.LoadEx(prog.TypeSizes, cfg, llssa.PkgRuntime, llssa.PkgPython) check(err) } return pkgRtAndPy @@ -65,7 +65,7 @@ func GenFrom(fileOrPkg string) string { cfg := &packages.Config{ Mode: loadSyntax | packages.NeedDeps, } - initial, err := packages.LoadEx(prog.TypeSizes(), cfg, fileOrPkg) + initial, err := packages.LoadEx(prog.TypeSizes, cfg, fileOrPkg) check(err) _, pkgs := ssautil.AllPackages(initial, ssa.SanityCheckFunctions) diff --git a/internal/packages/load.go b/internal/packages/load.go index 0797e099..18d49d63 100644 --- a/internal/packages/load.go +++ b/internal/packages/load.go @@ -101,17 +101,14 @@ func refine(ld *loader, response *packages.DriverResponse) ([]*Package, error) // 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) { +func LoadEx(sizes func(types.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 + ld.sizes = types.SizesFor(response.Compiler, response.Arch) if ld.sizes == nil && ld.Config.Mode&(NeedTypes|NeedTypesSizes|NeedTypesInfo) != 0 { // Type size information is needed but unavailable. if external { @@ -130,6 +127,9 @@ func LoadEx(sizes types.Sizes, cfg *Config, patterns ...string) ([]*Package, err } } + if sizes != nil { + ld.sizes = sizes(ld.sizes) + } return refine(ld, response) } diff --git a/internal/runtime/llgo_autogen.lla b/internal/runtime/llgo_autogen.lla index 5a32a2dc..d723b748 100644 Binary files a/internal/runtime/llgo_autogen.lla and b/internal/runtime/llgo_autogen.lla differ diff --git a/ssa/package.go b/ssa/package.go index b80d06e9..38fa3ae5 100644 --- a/ssa/package.go +++ b/ssa/package.go @@ -101,6 +101,7 @@ func Initialize(flags InitFlags) { type aProgram struct { ctx llvm.Context typs typeutil.Map // rawType -> Type + sizes types.Sizes // provided by Go compiler gocvt goTypes rt *types.Package diff --git a/ssa/type.go b/ssa/type.go index b112fdfb..36bbc089 100644 --- a/ssa/type.go +++ b/ssa/type.go @@ -74,6 +74,58 @@ func indexType(t types.Type) types.Type { // ----------------------------------------------------------------------------- +type goProgram aProgram + +// Alignof returns the alignment of a variable of type T. +// Alignof must implement the alignment guarantees required by the spec. +// The result must be >= 1. +func (p *goProgram) Alignof(T types.Type) int64 { + return p.sizes.Alignof(T) +} + +// Offsetsof returns the offsets of the given struct fields, in bytes. +// Offsetsof must implement the offset guarantees required by the spec. +// A negative entry in the result indicates that the struct is too large. +func (p *goProgram) Offsetsof(fields []*types.Var) (ret []int64) { + prog := Program(p) + ptrSize := int64(prog.PointerSize()) + extra := int64(0) + ret = p.sizes.Offsetsof(fields) + for i, f := range fields { + ret[i] += extra + extra += extraSize(f.Type(), ptrSize) + } + return +} + +// Sizeof returns the size of a variable of type T. +// Sizeof must implement the size guarantees required by the spec. +// A negative result indicates that T is too large. +func (p *goProgram) Sizeof(T types.Type) int64 { + prog := Program(p) + ptrSize := int64(prog.PointerSize()) + return prog.sizes.Sizeof(T) + extraSize(T, ptrSize) +} + +func extraSize(t types.Type, ptrSize int64) (ret int64) { + switch t := t.Underlying().(type) { + case *types.Signature: + return ptrSize + case *types.Struct: + n := t.NumFields() + for i := 0; i < n; i++ { + f := t.Field(i) + ret += extraSize(f.Type(), ptrSize) + } + return + case *types.Array: + return extraSize(t.Elem(), ptrSize) * t.Len() + } + return 0 +} + +// ----------------------------------------------------------------------------- + type rawType struct { Type types.Type } @@ -92,8 +144,9 @@ func (t Type) RawType() types.Type { } // TypeSizes returns the sizes of the types. -func (p Program) TypeSizes() types.Sizes { - return nil // TODO(xsw) +func (p Program) TypeSizes(sizes types.Sizes) types.Sizes { + p.sizes = sizes + return (*goProgram)(p) } // TODO(xsw): @@ -117,10 +170,12 @@ func SizeOf(prog Program, t Type, n ...int64) Expr { return prog.IntVal(size, prog.Uintptr()) } +/* func OffsetOf(prog Program, t Type, i int) Expr { offset := prog.OffsetOf(t, i) return prog.IntVal(offset, prog.Uintptr()) } +*/ func (p Program) PointerSize() int { return p.td.PointerSize()