@@ -31,6 +31,7 @@ import (
3131 "path/filepath"
3232 "runtime"
3333 "slices"
34+ "sort"
3435 "strings"
3536 "sync"
3637 "sync/atomic"
@@ -247,6 +248,9 @@ func Do(args []string, conf *Config) ([]Package, error) {
247248 verbose := conf .Verbose
248249 patterns := args
249250 tags := "llgo,math_big_pure_go,purego"
251+ if conf .AbiMode == cabi .ModeAllFunc {
252+ tags += ",llgo_abi_2"
253+ }
250254 if conf .Tags != "" {
251255 tags += "," + conf .Tags
252256 }
@@ -547,10 +551,9 @@ type context struct {
547551 // go list derived file lists (SFiles, etc.)
548552 sfilesCache map [string ][]string // pkg.ID -> absolute .s/.S file paths
549553
550- // plan9asm package allowlist parsed from env.
554+ // plan9asm package policy parsed from env.
551555 plan9asmOnce sync.Once
552- plan9asmAll bool
553- // when plan9asmAll=false: enabled set; when plan9asmAll=true: excluded set.
556+ plan9asmMode plan9asmPkgsEnvMode
554557 plan9asmPkgs map [string ]bool
555558}
556559
@@ -903,13 +906,24 @@ func linkMainPkg(ctx *context, pkg *packages.Package, pkgs []*aPackage, outputPa
903906 for _ , v := range pkgs {
904907 allPkgs = append (allPkgs , v .Package )
905908 }
906- // linkInputs contains .a archives from all packages and .o files from main module
907- var linkInputs []string
909+ visitRoots := allPkgs
910+ if ctx .mode == ModeTest {
911+ visitRoots = []* packages.Package {pkg }
912+ for _ , p := range allPkgs {
913+ if isRuntimePkg (p .PkgPath ) {
914+ visitRoots = append (visitRoots , p )
915+ }
916+ }
917+ }
918+ // archiveInputs contains package .a files. Object files are prepended later so
919+ // archive extraction can see their undefined references in a single linker pass.
920+ var archiveInputs []string
908921 var linkArgs []string
909922 var rtLinkInputs []string
910923 var rtLinkArgs []string
911924 linkedPkgs := make (map [string ]bool ) // Track linked packages by ID to avoid duplicates
912- packages .Visit (allPkgs , nil , func (p * packages.Package ) {
925+ var linkedOrder []Package
926+ packages .Visit (visitRoots , nil , func (p * packages.Package ) {
913927 // Skip if already linked this package (by ID)
914928 if linkedPkgs [p .ID ] {
915929 return
@@ -921,53 +935,62 @@ func linkMainPkg(ctx *context, pkg *packages.Package, pkgs []*aPackage, outputPa
921935 }
922936 if p .ExportFile != "" && aPkg != nil { // skip packages that only contain declarations
923937 linkedPkgs [p .ID ] = true
938+ linkedOrder = append (linkedOrder , aPkg )
939+ }
940+ })
924941
925- // Defer linking runtime packages unless we actually need the runtime.
926- if isRuntimePkg (p .PkgPath ) {
927- rtLinkArgs = append (rtLinkArgs , aPkg .LinkArgs ... )
928- if aPkg .ArchiveFile != "" {
929- rtLinkInputs = append (rtLinkInputs , aPkg .ArchiveFile )
930- }
931- return
932- } else {
933- // Only let non-runtime packages influence whether runtime is needed.
934- need1 , need2 := aPkg .isNeedRuntimeOrPyInit ()
935- needRuntime = needRuntime || need1
936- needPyInit = needPyInit || need2
937- }
938- if aPkg .LPkg .NeedAbiInit {
939- needAbiInit = true
940- }
941-
942- linkArgs = append (linkArgs , aPkg .LinkArgs ... )
942+ // packages.Visit with a post callback yields dependencies before importers.
943+ // Reverse that order so static archives are linked after the objects that use them.
944+ for i := len (linkedOrder ) - 1 ; i >= 0 ; i -- {
945+ aPkg := linkedOrder [i ]
946+ p := aPkg .Package
947+ // Defer linking runtime packages unless we actually need the runtime.
948+ if isRuntimePkg (p .PkgPath ) {
949+ rtLinkArgs = append (rtLinkArgs , aPkg .LinkArgs ... )
943950 if aPkg .ArchiveFile != "" {
944- linkInputs = append (linkInputs , aPkg .ArchiveFile )
951+ rtLinkInputs = append (rtLinkInputs , aPkg .ArchiveFile )
945952 }
953+ continue
946954 }
947- })
955+ // Only let non-runtime packages influence whether runtime is needed.
956+ need1 , need2 := aPkg .isNeedRuntimeOrPyInit ()
957+ needRuntime = needRuntime || need1
958+ needPyInit = needPyInit || need2
959+ if aPkg .LPkg .NeedAbiInit {
960+ needAbiInit = true
961+ }
962+
963+ linkArgs = append (linkArgs , aPkg .LinkArgs ... )
964+ if aPkg .ArchiveFile != "" {
965+ archiveInputs = append (archiveInputs , aPkg .ArchiveFile )
966+ }
967+ }
948968
949969 // Only link runtime objects when needed (or for host builds where runtime is always required).
950970 if needRuntime || needPyInit || ctx .buildConf .Target == "" {
951971 linkArgs = append (linkArgs , rtLinkArgs ... )
952- linkInputs = append (linkInputs , rtLinkInputs ... )
972+ archiveInputs = append (archiveInputs , rtLinkInputs ... )
953973 }
954974
975+ abiSymbols := linkedModuleGlobals (linkedOrder )
976+
955977 // Generate main module file (needed for global variables even in library modes)
956978 // This is compiled directly to .o and added to linkInputs (not cached)
957979 // Use a stable synthetic name to avoid confusing it with the real main package in traces/logs.
958- entryPkg := genMainModule (ctx , llssa .PkgRuntime , pkg , needRuntime , needPyInit , needAbiInit )
980+ entryPkg := genMainModule (ctx , llssa .PkgRuntime , pkg , needRuntime , needPyInit , needAbiInit , abiSymbols )
959981 entryObjFile , err := exportObject (ctx , "entry_main" , entryPkg .ExportFile , []byte (entryPkg .LPkg .String ()))
960982 if err != nil {
961983 return err
962984 }
963- linkInputs = append ( linkInputs , entryObjFile )
985+ linkInputs := [] string { entryObjFile }
964986
965987 // Compile extra files from target configuration
966988 extraObjFiles , err := compileExtraFiles (ctx , verbose )
967989 if err != nil {
968990 return err
969991 }
970992 linkInputs = append (linkInputs , extraObjFiles ... )
993+ linkInputs = append (linkInputs , archiveInputs ... )
971994
972995 if IsFullRpathEnabled () {
973996 // Treat every link-time library search path, specified by the -L parameter, as a runtime search path as well.
@@ -994,6 +1017,27 @@ func linkMainPkg(ctx *context, pkg *packages.Package, pkgs []*aPackage, outputPa
9941017 return nil
9951018}
9961019
1020+ func linkedModuleGlobals (pkgs []Package ) []string {
1021+ if len (pkgs ) == 0 {
1022+ return nil
1023+ }
1024+ seen := make (map [string ]struct {})
1025+ for _ , pkg := range pkgs {
1026+ if pkg == nil || pkg .LPkg == nil {
1027+ continue
1028+ }
1029+ for g := pkg .LPkg .Module ().FirstGlobal (); ! g .IsNil (); g = gllvm .NextGlobal (g ) {
1030+ seen [g .Name ()] = struct {}{}
1031+ }
1032+ }
1033+ names := make ([]string , 0 , len (seen ))
1034+ for name := range seen {
1035+ names = append (names , name )
1036+ }
1037+ sort .Strings (names )
1038+ return names
1039+ }
1040+
9971041// isRuntimePkg reports whether the package path belongs to the llgo runtime tree.
9981042func isRuntimePkg (pkgPath string ) bool {
9991043 rtRoot := env .LLGoRuntimePkg
0 commit comments