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).
Этот коммит содержится в:
Ayke van Laethem 2018-09-28 13:17:03 +02:00
родитель 0e813c4cb7
коммит 8d170d3bd2
Не найден ключ, соответствующий данной подписи
Идентификатор ключа GPG: E97FF5335DFDFDED
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

Просмотреть файл

@ -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