all: replace _extern_* workaround with //go:extern pragma
Этот коммит содержится в:
родитель
2ca2220e44
коммит
3c22f5731c
3 изменённых файлов: 69 добавлений и 18 удалений
66
ir.go
66
ir.go
|
@ -2,6 +2,7 @@ package main
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"go/ast"
|
"go/ast"
|
||||||
|
"go/token"
|
||||||
"go/types"
|
"go/types"
|
||||||
"sort"
|
"sort"
|
||||||
"strings"
|
"strings"
|
||||||
|
@ -24,6 +25,7 @@ type Program struct {
|
||||||
functionMap map[*ssa.Function]*Function
|
functionMap map[*ssa.Function]*Function
|
||||||
Globals []*Global
|
Globals []*Global
|
||||||
globalMap map[*ssa.Global]*Global
|
globalMap map[*ssa.Global]*Global
|
||||||
|
comments map[string]*ast.CommentGroup
|
||||||
NamedTypes []*NamedType
|
NamedTypes []*NamedType
|
||||||
needsScheduler bool
|
needsScheduler bool
|
||||||
goCalls []*ssa.Go
|
goCalls []*ssa.Go
|
||||||
|
@ -50,8 +52,11 @@ type Function struct {
|
||||||
|
|
||||||
// Global variable, possibly constant.
|
// Global variable, possibly constant.
|
||||||
type Global struct {
|
type Global struct {
|
||||||
|
program *Program
|
||||||
g *ssa.Global
|
g *ssa.Global
|
||||||
llvmGlobal llvm.Value
|
llvmGlobal llvm.Value
|
||||||
|
linkName string // go:extern
|
||||||
|
extern bool // go:extern
|
||||||
initializer Value
|
initializer Value
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -77,6 +82,30 @@ type Interface struct {
|
||||||
|
|
||||||
// Create and intialize a new *Program from a *ssa.Program.
|
// Create and intialize a new *Program from a *ssa.Program.
|
||||||
func NewProgram(lprogram *loader.Program, mainPath string) *Program {
|
func NewProgram(lprogram *loader.Program, mainPath string) *Program {
|
||||||
|
comments := map[string]*ast.CommentGroup{}
|
||||||
|
for _, pkgInfo := range lprogram.AllPackages {
|
||||||
|
for _, file := range pkgInfo.Files {
|
||||||
|
for _, decl := range file.Decls {
|
||||||
|
switch decl := decl.(type) {
|
||||||
|
case *ast.GenDecl:
|
||||||
|
switch decl.Tok {
|
||||||
|
case token.VAR:
|
||||||
|
if len(decl.Specs) != 1 {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
for _, spec := range decl.Specs {
|
||||||
|
valueSpec := spec.(*ast.ValueSpec)
|
||||||
|
for _, valueName := range valueSpec.Names {
|
||||||
|
id := pkgInfo.Pkg.Path() + "." + valueName.Name
|
||||||
|
comments[id] = decl.Doc
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
program := ssautil.CreateProgram(lprogram, ssa.SanityCheckFunctions|ssa.BareInits|ssa.GlobalDebug)
|
program := ssautil.CreateProgram(lprogram, ssa.SanityCheckFunctions|ssa.BareInits|ssa.GlobalDebug)
|
||||||
program.Build()
|
program.Build()
|
||||||
|
|
||||||
|
@ -87,6 +116,7 @@ func NewProgram(lprogram *loader.Program, mainPath string) *Program {
|
||||||
globalMap: make(map[*ssa.Global]*Global),
|
globalMap: make(map[*ssa.Global]*Global),
|
||||||
methodSignatureNames: make(map[string]int),
|
methodSignatureNames: make(map[string]int),
|
||||||
interfaces: make(map[string]*Interface),
|
interfaces: make(map[string]*Interface),
|
||||||
|
comments: comments,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -121,7 +151,11 @@ func (p *Program) AddPackage(pkg *ssa.Package) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
case *ssa.Global:
|
case *ssa.Global:
|
||||||
g := &Global{g: member}
|
g := &Global{program: p, g: member}
|
||||||
|
doc := p.comments[g.g.RelString(nil)]
|
||||||
|
if doc != nil {
|
||||||
|
g.parsePragmas(doc)
|
||||||
|
}
|
||||||
p.Globals = append(p.Globals, g)
|
p.Globals = append(p.Globals, g)
|
||||||
p.globalMap[member] = g
|
p.globalMap[member] = g
|
||||||
case *ssa.NamedConst:
|
case *ssa.NamedConst:
|
||||||
|
@ -249,17 +283,33 @@ func (f *Function) CName() string {
|
||||||
return ""
|
return ""
|
||||||
}
|
}
|
||||||
|
|
||||||
// Return the link name for this global.
|
// Parse //go: pragma comments from the source.
|
||||||
func (g *Global) LinkName() string {
|
func (g *Global) parsePragmas(doc *ast.CommentGroup) {
|
||||||
if strings.HasPrefix(g.g.Name(), "_extern_") {
|
for _, comment := range doc.List {
|
||||||
return g.g.Name()[len("_extern_"):]
|
if !strings.HasPrefix(comment.Text, "//go:") {
|
||||||
} else {
|
continue
|
||||||
return g.g.RelString(nil)
|
}
|
||||||
|
parts := strings.Fields(comment.Text)
|
||||||
|
switch parts[0] {
|
||||||
|
case "//go:extern":
|
||||||
|
g.extern = true
|
||||||
|
if len(parts) == 2 {
|
||||||
|
g.linkName = parts[1]
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Return the link name for this global.
|
||||||
|
func (g *Global) LinkName() string {
|
||||||
|
if g.linkName != "" {
|
||||||
|
return g.linkName
|
||||||
|
}
|
||||||
|
return g.g.RelString(nil)
|
||||||
|
}
|
||||||
|
|
||||||
func (g *Global) IsExtern() bool {
|
func (g *Global) IsExtern() bool {
|
||||||
return strings.HasPrefix(g.g.Name(), "_extern_")
|
return g.extern
|
||||||
}
|
}
|
||||||
|
|
||||||
// Wrapper type to implement sort.Interface for []*types.Selection.
|
// Wrapper type to implement sort.Interface for []*types.Selection.
|
||||||
|
|
|
@ -6,10 +6,10 @@ import (
|
||||||
"unsafe"
|
"unsafe"
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
//go:extern _heap_start
|
||||||
_extern__heap_start unsafe.Pointer // defined by the linker
|
var heapStart unsafe.Pointer
|
||||||
heapptr = uintptr(unsafe.Pointer(&_extern__heap_start))
|
|
||||||
)
|
var heapptr = uintptr(unsafe.Pointer(&heapStart))
|
||||||
|
|
||||||
func alloc(size uintptr) unsafe.Pointer {
|
func alloc(size uintptr) unsafe.Pointer {
|
||||||
// TODO: this can be optimized by not casting between pointers and ints so
|
// TODO: this can be optimized by not casting between pointers and ints so
|
||||||
|
|
|
@ -29,15 +29,16 @@ const (
|
||||||
WDT_PERIOD_2S
|
WDT_PERIOD_2S
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
//go:extern _sbss
|
||||||
_extern__sbss unsafe.Pointer // defined by the linker
|
var _sbss unsafe.Pointer
|
||||||
_extern__ebss unsafe.Pointer // defined by the linker
|
|
||||||
)
|
//go:extern _ebss
|
||||||
|
var _ebss unsafe.Pointer
|
||||||
|
|
||||||
func preinit() {
|
func preinit() {
|
||||||
// Initialize .bss: zero-initialized global variables.
|
// Initialize .bss: zero-initialized global variables.
|
||||||
ptr := uintptr(unsafe.Pointer(&_extern__sbss))
|
ptr := uintptr(unsafe.Pointer(&_sbss))
|
||||||
for ptr != uintptr(unsafe.Pointer(&_extern__ebss)) {
|
for ptr != uintptr(unsafe.Pointer(&_ebss)) {
|
||||||
*(*uint8)(unsafe.Pointer(ptr)) = 0
|
*(*uint8)(unsafe.Pointer(ptr)) = 0
|
||||||
ptr += 1
|
ptr += 1
|
||||||
}
|
}
|
||||||
|
|
Загрузка…
Создание таблицы
Сослаться в новой задаче