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).
This commit is contained in:
Ayke van Laethem
2018-09-28 13:17:03 +02:00
parent 0e813c4cb7
commit 8d170d3bd2
6 changed files with 52 additions and 30 deletions
+4 -6
View File
@@ -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
+29 -4
View File
@@ -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
+3 -3
View File
@@ -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)))
+3 -2
View File
@@ -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
+5 -6
View File
@@ -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:
+8 -9
View File
@@ -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