@@ -276,19 +276,33 @@ func (p *context) collectSkip(line string, prefix int) {
276276 }
277277}
278278
279- func collectLinknameByDoc (prog llssa.Program , doc * ast.CommentGroup , fullName , inPkgName string ) {
279+ // collectDeclarationDirectives caches source metadata needed after the syntax
280+ // pass. funcPos is token.NoPos for non-function declarations.
281+ func collectDeclarationDirectives (prog llssa.Program , fset * token.FileSet , doc * ast.CommentGroup , fullName , inPkgName string , funcPos token.Pos ) {
280282 directives := directive .ParseGroup (doc )
283+ linkCollected := false
284+ hasClosureEnv := false
281285 for n := len (directives ) - 1 ; n >= 0 ; n -- {
282- directive := directives [n ]
283- if directive .Name != "go:linkname" && directive .Name != "llgo:link" {
284- continue
285- }
286- fields := strings .Fields (directive .Args )
287- if len (fields ) >= 2 && fields [0 ] == inPkgName {
288- prog .SetLinkname (fullName , strings .Join (fields [1 :], " " ))
289- return
286+ item := directives [n ]
287+ switch item .Name {
288+ case "go:linkname" , "llgo:link" :
289+ if linkCollected {
290+ continue
291+ }
292+ fields := strings .Fields (item .Args )
293+ if len (fields ) >= 2 && fields [0 ] == inPkgName {
294+ prog .SetLinkname (fullName , strings .Join (fields [1 :], " " ))
295+ linkCollected = true
296+ }
297+ case "llgo:env" :
298+ if funcPos .IsValid () {
299+ hasClosureEnv = true
300+ }
290301 }
291302 }
303+ if funcPos .IsValid () {
304+ prog .SetClosureEnvDirective (fset , fullName , funcPos , hasClosureEnv )
305+ }
292306}
293307
294308func (p * context ) processLinknameByDoc (doc * ast.CommentGroup , fullName , inPkgName string , isVar , allowExport bool ) bool {
@@ -563,8 +577,7 @@ const (
563577 llgoAtomicCmpXchgOK = llgoInstrBase + 0x45
564578 llgoAtomicAddReturnNew = llgoInstrBase + 0x46
565579 llgoBoolToUint8 = llgoInstrBase + 0x47
566- // 0x48 is reserved for llgoCoroPark in the coroutine backend.
567- llgoClosureEnv = llgoInstrBase + 0x49
580+ llgoClosureEnv = llgoInstrBase + 0x48
568581
569582 llgoAtomicOpLast = llgoAtomicOpBase + int (llssa .OpUMin )
570583)
@@ -775,14 +788,14 @@ func ParsePkgSyntax(prog llssa.Program, fset *token.FileSet, pkg *types.Package,
775788 return err
776789 }
777790 fullName , inPkgName := astFuncName (pkgPath , decl )
778- collectLinknameByDoc (prog , decl .Doc , fullName , inPkgName )
791+ collectDeclarationDirectives (prog , fset , decl .Doc , fullName , inPkgName , decl . Pos () )
779792 ctx .processNoInterfaceByDoc (decl .Doc , fullName )
780793 case * ast.GenDecl :
781794 if decl .Tok == token .VAR {
782795 if len (decl .Specs ) == 1 {
783796 if names := decl .Specs [0 ].(* ast.ValueSpec ).Names ; len (names ) == 1 {
784797 inPkgName := names [0 ].Name
785- collectLinknameByDoc (prog , decl .Doc , pkgPath + "." + inPkgName , inPkgName )
798+ collectDeclarationDirectives (prog , fset , decl .Doc , pkgPath + "." + inPkgName , inPkgName , token . NoPos )
786799 }
787800 }
788801 vars , err := locality .ScanPackageVar (fset , decl )
0 commit comments