github.com/tardisgo/tardisgo@v0.0.0-20161119180838-e0dd9a7e46b5/pogo/globals.go (about)

     1  // Copyright 2014 Elliott Stoneham and The TARDIS Go Authors
     2  // Use of this source code is governed by an MIT-style
     3  // license that can be found in the LICENSE file.
     4  
     5  package pogo
     6  
     7  import (
     8  	"fmt"
     9  	"go/token"
    10  	"go/types"
    11  	"sort"
    12  	"unicode"
    13  
    14  	"golang.org/x/tools/go/ssa"
    15  )
    16  
    17  /* THIS SECTION ONLY REQUIRED IF GLOBALS ARE ADDRESSABLE USING OFFSETS RATTHER THAN PSEUDO-POINTERS
    18  // TODO review adding this method of addressing global values as an option
    19  
    20  // everything we need to remember about globals
    21  type GlobalInfo struct {
    22  	Typ             types.Type
    23  	TypDesc         string
    24  	Package, Member string
    25  	Location, Size  uint
    26  }
    27  
    28  var GlobalsMap = make(map[*ssa.Global]GlobalInfo)
    29  var GoGlobalsSize uint = 0
    30  
    31  // Get the location and size of all of the globals
    32  func scanGlobals() {
    33  	var address uint = 0
    34  	for pName, pack := range rootProgram.PackagesByPath {
    35  		for mName, member := range pack.Members {
    36  			switch member.(type) {
    37  			case *ssa.Global:
    38  				var g GlobalInfo
    39  				glob := member.(*ssa.Global)
    40  				g.Package = pName
    41  				g.Member = mName
    42  				g.Typ = glob.Type().(*types.Pointer).Elem() // all globals are pointers
    43  				g.Size = uint(types.DefaultSizeof(g.Typ))
    44  				// do not error on g.Size == 0 as it is in some library code, for example:
    45  				// "var zero [0]byte" in /src/pkg/io/pipe.go
    46  				g.TypDesc = g.Typ.String()
    47  				// make sure the next address is on a correct byte boundary for the type
    48  				boundary := uint(types.DefaultAlignof(g.Typ))
    49  				for address%boundary != 0 {
    50  					address++ // increase the address until we are on the correct byte boundary
    51  				}
    52  				g.Location = address
    53  				address += g.Size
    54  				GlobalsMap[glob] = g
    55  			default:
    56  				// do nothing if it is not a global declaration
    57  			}
    58  		}
    59  	}
    60  	GoGlobalsSize = address
    61  }
    62  
    63   END ADDRESSABLE GLOBALS SECTION */
    64  
    65  // Emit the Global declarations, run inside the Go class declaration output.
    66  func (comp *Compilation) emitGlobals() {
    67  	allPack := comp.rootProgram.AllPackages()
    68  	sort.Sort(PackageSorter(allPack))
    69  	for pkgIdx := range allPack {
    70  		pkg := allPack[pkgIdx]
    71  		allMem := MemberNamesSorted(pkg)
    72  		for _, mName := range allMem {
    73  			mem := pkg.Members[mName]
    74  			if mem.Token() == token.VAR {
    75  				glob := mem.(*ssa.Global)
    76  				pName := glob.Pkg.Pkg.Path() // was .Name()
    77  				//println("DEBUG processing global:", pName, mName)
    78  				posStr := comp.CodePosition(glob.Pos())
    79  				comp.MakePosHash(glob.Pos()) // mark that we are dealing with this global
    80  				if comp.IsValidInPogo(
    81  					glob.Type().(*types.Pointer).Elem(), // globals are always pointers to a global
    82  					"Global:"+pName+"."+mName+":"+posStr) {
    83  					if !comp.hadErrors { // no point emitting code if we have already encounderd an error
    84  						isPublic := unicode.IsUpper(rune(mName[0])) // Object value sometimes not available
    85  						l := comp.TargetLang
    86  						fmt.Fprintln(&LanguageList[l].buffer,
    87  							LanguageList[l].Global(pName, mName, *glob, posStr, isPublic))
    88  					}
    89  				}
    90  			}
    91  		}
    92  	}
    93  }
    94  
    95  // GlobalInfo holds the description of an individual global declaration
    96  type GlobalInfo struct {
    97  	Package string
    98  	Member  string
    99  	Global  *ssa.Global
   100  	Public  bool
   101  }
   102  
   103  // GlobalList returns all of the globals in the Compilation
   104  func (comp *Compilation) GlobalList() []GlobalInfo {
   105  	var gi = make([]GlobalInfo, 0)
   106  	allPack := comp.rootProgram.AllPackages()
   107  	sort.Sort(PackageSorter(allPack))
   108  	for pkgIdx := range allPack {
   109  		pkg := allPack[pkgIdx]
   110  		allMem := MemberNamesSorted(pkg)
   111  		for _, mName := range allMem {
   112  			mem := pkg.Members[mName]
   113  			if mem.Token() == token.VAR {
   114  				glob := mem.(*ssa.Global)
   115  				pName := glob.Pkg.Pkg.Path()                // was .Name()
   116  				isPublic := unicode.IsUpper(rune(mName[0])) // Object value sometimes not available
   117  				gi = append(gi, GlobalInfo{pName, mName, glob, isPublic})
   118  			}
   119  		}
   120  	}
   121  	return gi
   122  }