diff --git a/cl/_testlibgo/_errors/in.go b/cl/_testlibgo/errors/in.go similarity index 100% rename from cl/_testlibgo/_errors/in.go rename to cl/_testlibgo/errors/in.go diff --git a/cl/_testlibgo/errors/out.ll b/cl/_testlibgo/errors/out.ll new file mode 100644 index 000000000..ffce31e6c --- /dev/null +++ b/cl/_testlibgo/errors/out.ll @@ -0,0 +1,60 @@ +; ModuleID = 'main' +source_filename = "main" + +%"github.com/goplus/llgo/internal/runtime.String" = type { ptr, i64 } +%"github.com/goplus/llgo/internal/runtime.iface" = type { ptr, ptr } +%"github.com/goplus/llgo/internal/runtime.eface" = type { ptr, ptr } + +@"main.init$guard" = global i1 false, align 1 +@__llgo_argc = global i32 0, align 4 +@__llgo_argv = global ptr null, align 8 +@0 = private unnamed_addr constant [5 x i8] c"error", align 1 + +define void @main.init() { +_llgo_0: + %0 = load i1, ptr @"main.init$guard", align 1 + br i1 %0, label %_llgo_2, label %_llgo_1 + +_llgo_1: ; preds = %_llgo_0 + store i1 true, ptr @"main.init$guard", align 1 + call void @errors.init() + br label %_llgo_2 + +_llgo_2: ; preds = %_llgo_1, %_llgo_0 + ret void +} + +define i32 @main(i32 %0, ptr %1) { +_llgo_0: + store i32 %0, ptr @__llgo_argc, align 4 + store ptr %1, ptr @__llgo_argv, align 8 + call void @"github.com/goplus/llgo/internal/runtime.init"() + call void @main.init() + %2 = alloca %"github.com/goplus/llgo/internal/runtime.String", align 8 + %3 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.String", ptr %2, i32 0, i32 0 + store ptr @0, ptr %3, align 8 + %4 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.String", ptr %2, i32 0, i32 1 + store i64 5, ptr %4, align 4 + %5 = load %"github.com/goplus/llgo/internal/runtime.String", ptr %2, align 8 + %6 = call %"github.com/goplus/llgo/internal/runtime.iface" @errors.New(%"github.com/goplus/llgo/internal/runtime.String" %5) + %7 = call ptr @"github.com/goplus/llgo/internal/runtime.IfaceType"(%"github.com/goplus/llgo/internal/runtime.iface" %6) + %8 = extractvalue %"github.com/goplus/llgo/internal/runtime.iface" %6, 1 + %9 = alloca %"github.com/goplus/llgo/internal/runtime.eface", align 8 + %10 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.eface", ptr %9, i32 0, i32 0 + store ptr %7, ptr %10, align 8 + %11 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.eface", ptr %9, i32 0, i32 1 + store ptr %8, ptr %11, align 8 + %12 = load %"github.com/goplus/llgo/internal/runtime.eface", ptr %9, align 8 + call void @"github.com/goplus/llgo/internal/runtime.Panic"(%"github.com/goplus/llgo/internal/runtime.eface" %12) + unreachable +} + +declare void @errors.init() + +declare void @"github.com/goplus/llgo/internal/runtime.init"() + +declare %"github.com/goplus/llgo/internal/runtime.iface" @errors.New(%"github.com/goplus/llgo/internal/runtime.String") + +declare ptr @"github.com/goplus/llgo/internal/runtime.IfaceType"(%"github.com/goplus/llgo/internal/runtime.iface") + +declare void @"github.com/goplus/llgo/internal/runtime.Panic"(%"github.com/goplus/llgo/internal/runtime.eface") diff --git a/internal/build/build.go b/internal/build/build.go index fb591d896..e7174e3ed 100644 --- a/internal/build/build.go +++ b/internal/build/build.go @@ -35,6 +35,7 @@ import ( "github.com/goplus/llgo/cl" "github.com/goplus/llgo/internal/packages" + "github.com/goplus/llgo/ssa/abi" "github.com/goplus/llgo/xtool/clang" "github.com/goplus/llgo/xtool/env" @@ -400,7 +401,7 @@ func buildPkg(ctx *context, aPkg *aPackage) { } const ( - altPkgPathPrefix = "github.com/goplus/llgo/internal/lib/" + altPkgPathPrefix = abi.PatchPathPrefix ) func altPkgs(initial []*packages.Package, alts ...string) []string { diff --git a/internal/lib/errors/errors.go b/internal/lib/errors/errors.go index 465fac108..5f95bdef3 100644 --- a/internal/lib/errors/errors.go +++ b/internal/lib/errors/errors.go @@ -15,3 +15,54 @@ */ package errors + +// llgo:skipall +import ( + _ "unsafe" +) + +// Unwrap returns the result of calling the Unwrap method on err, if err's +// type contains an Unwrap method returning error. +// Otherwise, Unwrap returns nil. +// +// Unwrap only calls a method of the form "Unwrap() error". +// In particular Unwrap does not unwrap errors returned by [Join]. +func Unwrap(err error) error { + u, ok := err.(interface { + Unwrap() error + }) + if !ok { + return nil + } + return u.Unwrap() +} + +// New returns an error that formats as the given text. +// Each call to New returns a distinct error value even if the text is identical. +func New(text string) error { + return &errorString{text} +} + +// errorString is a trivial implementation of error. +type errorString struct { + s string +} + +func (e *errorString) Error() string { + return e.s +} + +// ErrUnsupported indicates that a requested operation cannot be performed, +// because it is unsupported. For example, a call to [os.Link] when using a +// file system that does not support hard links. +// +// Functions and methods should not return this error but should instead +// return an error including appropriate context that satisfies +// +// errors.Is(err, errors.ErrUnsupported) +// +// either by directly wrapping ErrUnsupported or by implementing an Is method. +// +// Functions and methods should document the cases in which an error +// wrapping this will be returned. +var ErrUnsupported = New("unsupported operation") diff --git a/internal/typepatch/patch.go b/internal/typepatch/patch.go index 48feb73b9..e6f42e9af 100644 --- a/internal/typepatch/patch.go +++ b/internal/typepatch/patch.go @@ -43,6 +43,7 @@ type typesScope struct { isFunc bool } +/* type object struct { parent *types.Scope pos token.Pos @@ -54,6 +55,7 @@ type iface struct { tab unsafe.Pointer data unsafe.Pointer } +*/ const ( tagPatched = 0x17 @@ -77,11 +79,24 @@ func setScope(pkg *types.Package, scope *types.Scope) { p.scope = scope } +/* +func setPath(pkg *types.Package, path string) { + p := (*typesPackage)(unsafe.Pointer(pkg)) + p.path = path +} + +/* +func setPkg(o types.Object, pkg *types.Package) { + data := (*iface)(unsafe.Pointer(&o)).data + (*object)(data).pkg = pkg +} + func setPkgAndParent(o types.Object, pkg *types.Package, parent *types.Scope) { data := (*iface)(unsafe.Pointer(&o)).data (*object)(data).pkg = pkg (*object)(data).parent = parent } +*/ func getElems(scope *types.Scope) map[string]types.Object { s := (*typesScope)(unsafe.Pointer(scope)) @@ -105,11 +120,23 @@ func Pkg(pkg, alt *types.Package) *types.Package { altScope := alt.Scope() for name, o := range getElems(altScope) { - setPkgAndParent(o, &ret, &scope) + /* + switch o := o.(type) { + case *types.TypeName: + if t, ok := o.Type().(*types.Named); ok { + for i, n := 0, t.NumMethods(); i < n; i++ { + m := t.Method(i) + setPkg(m, &ret) + } + } + } + setPkgAndParent(o, &ret, &scope) + */ elems[name] = o } setElems(&scope, elems) setScope(&ret, &scope) setPatched(pkg) + // setPath(alt, ret.Path()) return &ret } diff --git a/ssa/abi/abi.go b/ssa/abi/abi.go index 28e065b3a..25298272f 100644 --- a/ssa/abi/abi.go +++ b/ssa/abi/abi.go @@ -23,6 +23,7 @@ import ( "go/types" "hash" "log" + "strings" "github.com/goplus/llgo/internal/abi" ) @@ -168,6 +169,10 @@ func (b *Builder) TypeName(t types.Type) (ret string, pub bool) { return } +const ( + PatchPathPrefix = "github.com/goplus/llgo/internal/lib/" +) + // PathOf returns the package path of the specified package. func PathOf(pkg *types.Package) string { if pkg == nil { @@ -176,7 +181,7 @@ func PathOf(pkg *types.Package) string { if pkg.Name() == "main" { return "main" } - return pkg.Path() + return strings.TrimPrefix(pkg.Path(), PatchPathPrefix) } // FullName returns the full name of a package member.