all: change special type __volatile to pragma //go:volatile
This is one step towards removing unnecessary special casts in most cases. It is also part of removing as much magic as possible from the compiler (the pragma is explicit, the special name is not).
Этот коммит содержится в:
родитель
0e813c4cb7
коммит
8d170d3bd2
6 изменённых файлов: 52 добавлений и 30 удалений
|
@ -1528,9 +1528,8 @@ func (c *Compiler) parseInstr(frame *Frame, instr ssa.Instruction) error {
|
|||
}
|
||||
store := c.builder.CreateStore(llvmVal, llvmAddr)
|
||||
valType := instr.Addr.Type().(*types.Pointer).Elem()
|
||||
if valType, ok := valType.(*types.Named); ok && valType.Obj().Name() == "__volatile" {
|
||||
// Magic type name to make this store volatile, for memory-mapped
|
||||
// registers.
|
||||
if c.ir.IsVolatile(valType) {
|
||||
// Volatile store, for memory-mapped registers.
|
||||
store.SetVolatile(true)
|
||||
}
|
||||
return nil
|
||||
|
@ -3040,9 +3039,8 @@ func (c *Compiler) parseUnOp(frame *Frame, unop *ssa.UnOp) (llvm.Value, error) {
|
|||
case token.MUL: // *x, dereference pointer
|
||||
valType := unop.X.Type().(*types.Pointer).Elem()
|
||||
load := c.builder.CreateLoad(x, "")
|
||||
if valType, ok := valType.(*types.Named); ok && valType.Obj().Name() == "__volatile" {
|
||||
// Magic type name to make this load volatile, for memory-mapped
|
||||
// registers.
|
||||
if c.ir.IsVolatile(valType) {
|
||||
// Volatile load, for memory-mapped registers.
|
||||
load.SetVolatile(true)
|
||||
}
|
||||
return load, nil
|
||||
|
|
33
ir/ir.go
33
ir/ir.go
|
@ -90,15 +90,20 @@ func NewProgram(lprogram *loader.Program, mainPath string) *Program {
|
|||
switch decl := decl.(type) {
|
||||
case *ast.GenDecl:
|
||||
switch decl.Tok {
|
||||
case token.VAR:
|
||||
case token.TYPE, 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
|
||||
switch spec := spec.(type) {
|
||||
case *ast.TypeSpec: // decl.Tok == token.TYPE
|
||||
id := pkgInfo.Pkg.Path() + "." + spec.Name.Name
|
||||
comments[id] = decl.Doc
|
||||
case *ast.ValueSpec: // decl.Tok == token.VAR
|
||||
for _, name := range spec.Names {
|
||||
id := pkgInfo.Pkg.Path() + "." + name.Name
|
||||
comments[id] = decl.Doc
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -414,6 +419,26 @@ func (g *Global) Initializer() Value {
|
|||
return g.initializer
|
||||
}
|
||||
|
||||
// Return true if this named type is annotated with the //go:volatile pragma,
|
||||
// for volatile loads and stores.
|
||||
func (p *Program) IsVolatile(t types.Type) bool {
|
||||
if t, ok := t.(*types.Named); !ok {
|
||||
return false
|
||||
} else {
|
||||
id := t.Obj().Pkg().Path() + "." + t.Obj().Name()
|
||||
doc := p.comments[id]
|
||||
if doc == nil {
|
||||
return false
|
||||
}
|
||||
for _, line := range doc.List {
|
||||
if strings.TrimSpace(line.Text) == "//go:volatile" {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
// Wrapper type to implement sort.Interface for []*types.Selection.
|
||||
type methodList struct {
|
||||
methods []*types.Selection
|
||||
|
|
|
@ -33,8 +33,8 @@ import (
|
|||
"unsafe"
|
||||
)
|
||||
|
||||
type __volatile uint32
|
||||
type RegValue = __volatile
|
||||
//go:volatile
|
||||
type RegValue uint32
|
||||
|
||||
type __asm string
|
||||
|
||||
|
@ -47,7 +47,7 @@ const (
|
|||
|
||||
// Nested Vectored Interrupt Controller (NVIC).
|
||||
type NVIC_Type struct {
|
||||
ISER [8]__volatile
|
||||
ISER [8]RegValue
|
||||
}
|
||||
|
||||
var NVIC = (*NVIC_Type)(unsafe.Pointer(uintptr(NVIC_BASE)))
|
||||
|
|
|
@ -81,9 +81,10 @@ func ticks() timeUnit {
|
|||
return timestamp
|
||||
}
|
||||
|
||||
type __volatile bool
|
||||
//go:volatile
|
||||
type isrFlag bool
|
||||
|
||||
var rtc_wakeup __volatile
|
||||
var rtc_wakeup isrFlag
|
||||
|
||||
func rtc_sleep(ticks uint32) {
|
||||
nrf.RTC0.INTENSET = nrf.RTC_INTENSET_COMPARE0
|
||||
|
|
|
@ -142,11 +142,10 @@ package {pkgName}
|
|||
|
||||
import "unsafe"
|
||||
|
||||
// Magic type name for the compiler.
|
||||
type __volatile uint8
|
||||
|
||||
// Export this magic type name.
|
||||
type RegValue = __volatile
|
||||
// Special type that causes loads/stores to be volatile (necessary for
|
||||
// memory-mapped registers).
|
||||
//go:volatile
|
||||
type RegValue uint8
|
||||
|
||||
// Some information about this device.
|
||||
const (
|
||||
|
@ -169,7 +168,7 @@ const (
|
|||
out.write('\n\t// {description}\n'.format(**peripheral))
|
||||
for register in peripheral['registers']:
|
||||
for variant in register['variants']:
|
||||
out.write('\t{name} = (*__volatile)(unsafe.Pointer(uintptr(0x{address:x})))\n'.format(**variant))
|
||||
out.write('\t{name} = (*RegValue)(unsafe.Pointer(uintptr(0x{address:x})))\n'.format(**variant))
|
||||
out.write(')\n')
|
||||
|
||||
for peripheral in device.peripherals:
|
||||
|
|
|
@ -216,11 +216,10 @@ package {pkgName}
|
|||
|
||||
import "unsafe"
|
||||
|
||||
// Magic type name for the compiler.
|
||||
type __volatile uint32
|
||||
|
||||
// Export this magic type name.
|
||||
type RegValue = __volatile
|
||||
// Special type that causes loads/stores to be volatile (necessary for
|
||||
// memory-mapped registers).
|
||||
//go:volatile
|
||||
type RegValue uint32
|
||||
|
||||
// Some information about this device.
|
||||
const (
|
||||
|
@ -255,14 +254,14 @@ const (
|
|||
if address < register['address']:
|
||||
numSkip = (register['address'] - address) // 4
|
||||
if numSkip == 1:
|
||||
out.write('\t_padding{padNumber} __volatile\n'.format(padNumber=padNumber))
|
||||
out.write('\t_padding{padNumber} RegValue\n'.format(padNumber=padNumber))
|
||||
else:
|
||||
out.write('\t_padding{padNumber} [{num}]__volatile\n'.format(padNumber=padNumber, num=numSkip))
|
||||
out.write('\t_padding{padNumber} [{num}]RegValue\n'.format(padNumber=padNumber, num=numSkip))
|
||||
padNumber += 1
|
||||
|
||||
regType = '__volatile'
|
||||
regType = 'RegValue'
|
||||
if register['array'] is not None:
|
||||
regType = '[{}]__volatile'.format(register['array'])
|
||||
regType = '[{}]RegValue'.format(register['array'])
|
||||
out.write('\t{name} {regType}\n'.format(**register, regType=regType))
|
||||
|
||||
# next address
|
||||
|
|
Загрузка…
Создание таблицы
Сослаться в новой задаче