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 }