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)
|
store := c.builder.CreateStore(llvmVal, llvmAddr)
|
||||||
valType := instr.Addr.Type().(*types.Pointer).Elem()
|
valType := instr.Addr.Type().(*types.Pointer).Elem()
|
||||||
if valType, ok := valType.(*types.Named); ok && valType.Obj().Name() == "__volatile" {
|
if c.ir.IsVolatile(valType) {
|
||||||
// Magic type name to make this store volatile, for memory-mapped
|
// Volatile store, for memory-mapped registers.
|
||||||
// registers.
|
|
||||||
store.SetVolatile(true)
|
store.SetVolatile(true)
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
|
@ -3040,9 +3039,8 @@ func (c *Compiler) parseUnOp(frame *Frame, unop *ssa.UnOp) (llvm.Value, error) {
|
||||||
case token.MUL: // *x, dereference pointer
|
case token.MUL: // *x, dereference pointer
|
||||||
valType := unop.X.Type().(*types.Pointer).Elem()
|
valType := unop.X.Type().(*types.Pointer).Elem()
|
||||||
load := c.builder.CreateLoad(x, "")
|
load := c.builder.CreateLoad(x, "")
|
||||||
if valType, ok := valType.(*types.Named); ok && valType.Obj().Name() == "__volatile" {
|
if c.ir.IsVolatile(valType) {
|
||||||
// Magic type name to make this load volatile, for memory-mapped
|
// Volatile load, for memory-mapped registers.
|
||||||
// registers.
|
|
||||||
load.SetVolatile(true)
|
load.SetVolatile(true)
|
||||||
}
|
}
|
||||||
return load, nil
|
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) {
|
switch decl := decl.(type) {
|
||||||
case *ast.GenDecl:
|
case *ast.GenDecl:
|
||||||
switch decl.Tok {
|
switch decl.Tok {
|
||||||
case token.VAR:
|
case token.TYPE, token.VAR:
|
||||||
if len(decl.Specs) != 1 {
|
if len(decl.Specs) != 1 {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
for _, spec := range decl.Specs {
|
for _, spec := range decl.Specs {
|
||||||
valueSpec := spec.(*ast.ValueSpec)
|
switch spec := spec.(type) {
|
||||||
for _, valueName := range valueSpec.Names {
|
case *ast.TypeSpec: // decl.Tok == token.TYPE
|
||||||
id := pkgInfo.Pkg.Path() + "." + valueName.Name
|
id := pkgInfo.Pkg.Path() + "." + spec.Name.Name
|
||||||
comments[id] = decl.Doc
|
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 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.
|
// Wrapper type to implement sort.Interface for []*types.Selection.
|
||||||
type methodList struct {
|
type methodList struct {
|
||||||
methods []*types.Selection
|
methods []*types.Selection
|
||||||
|
|
|
@ -33,8 +33,8 @@ import (
|
||||||
"unsafe"
|
"unsafe"
|
||||||
)
|
)
|
||||||
|
|
||||||
type __volatile uint32
|
//go:volatile
|
||||||
type RegValue = __volatile
|
type RegValue uint32
|
||||||
|
|
||||||
type __asm string
|
type __asm string
|
||||||
|
|
||||||
|
@ -47,7 +47,7 @@ const (
|
||||||
|
|
||||||
// Nested Vectored Interrupt Controller (NVIC).
|
// Nested Vectored Interrupt Controller (NVIC).
|
||||||
type NVIC_Type struct {
|
type NVIC_Type struct {
|
||||||
ISER [8]__volatile
|
ISER [8]RegValue
|
||||||
}
|
}
|
||||||
|
|
||||||
var NVIC = (*NVIC_Type)(unsafe.Pointer(uintptr(NVIC_BASE)))
|
var NVIC = (*NVIC_Type)(unsafe.Pointer(uintptr(NVIC_BASE)))
|
||||||
|
|
|
@ -81,9 +81,10 @@ func ticks() timeUnit {
|
||||||
return timestamp
|
return timestamp
|
||||||
}
|
}
|
||||||
|
|
||||||
type __volatile bool
|
//go:volatile
|
||||||
|
type isrFlag bool
|
||||||
|
|
||||||
var rtc_wakeup __volatile
|
var rtc_wakeup isrFlag
|
||||||
|
|
||||||
func rtc_sleep(ticks uint32) {
|
func rtc_sleep(ticks uint32) {
|
||||||
nrf.RTC0.INTENSET = nrf.RTC_INTENSET_COMPARE0
|
nrf.RTC0.INTENSET = nrf.RTC_INTENSET_COMPARE0
|
||||||
|
|
|
@ -142,11 +142,10 @@ package {pkgName}
|
||||||
|
|
||||||
import "unsafe"
|
import "unsafe"
|
||||||
|
|
||||||
// Magic type name for the compiler.
|
// Special type that causes loads/stores to be volatile (necessary for
|
||||||
type __volatile uint8
|
// memory-mapped registers).
|
||||||
|
//go:volatile
|
||||||
// Export this magic type name.
|
type RegValue uint8
|
||||||
type RegValue = __volatile
|
|
||||||
|
|
||||||
// Some information about this device.
|
// Some information about this device.
|
||||||
const (
|
const (
|
||||||
|
@ -169,7 +168,7 @@ const (
|
||||||
out.write('\n\t// {description}\n'.format(**peripheral))
|
out.write('\n\t// {description}\n'.format(**peripheral))
|
||||||
for register in peripheral['registers']:
|
for register in peripheral['registers']:
|
||||||
for variant in register['variants']:
|
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')
|
out.write(')\n')
|
||||||
|
|
||||||
for peripheral in device.peripherals:
|
for peripheral in device.peripherals:
|
||||||
|
|
|
@ -216,11 +216,10 @@ package {pkgName}
|
||||||
|
|
||||||
import "unsafe"
|
import "unsafe"
|
||||||
|
|
||||||
// Magic type name for the compiler.
|
// Special type that causes loads/stores to be volatile (necessary for
|
||||||
type __volatile uint32
|
// memory-mapped registers).
|
||||||
|
//go:volatile
|
||||||
// Export this magic type name.
|
type RegValue uint32
|
||||||
type RegValue = __volatile
|
|
||||||
|
|
||||||
// Some information about this device.
|
// Some information about this device.
|
||||||
const (
|
const (
|
||||||
|
@ -255,14 +254,14 @@ const (
|
||||||
if address < register['address']:
|
if address < register['address']:
|
||||||
numSkip = (register['address'] - address) // 4
|
numSkip = (register['address'] - address) // 4
|
||||||
if numSkip == 1:
|
if numSkip == 1:
|
||||||
out.write('\t_padding{padNumber} __volatile\n'.format(padNumber=padNumber))
|
out.write('\t_padding{padNumber} RegValue\n'.format(padNumber=padNumber))
|
||||||
else:
|
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
|
padNumber += 1
|
||||||
|
|
||||||
regType = '__volatile'
|
regType = 'RegValue'
|
||||||
if register['array'] is not None:
|
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))
|
out.write('\t{name} {regType}\n'.format(**register, regType=regType))
|
||||||
|
|
||||||
# next address
|
# next address
|
||||||
|
|
Загрузка…
Создание таблицы
Сослаться в новой задаче