From 8d170d3bd291f110a9bc72cd462d6c86557897e0 Mon Sep 17 00:00:00 2001 From: Ayke van Laethem Date: Fri, 28 Sep 2018 13:17:03 +0200 Subject: [PATCH] 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). --- compiler/compiler.go | 10 ++++------ ir/ir.go | 33 +++++++++++++++++++++++++++++---- src/device/arm/arm.go | 6 +++--- src/runtime/runtime_nrf.go | 5 +++-- tools/gen-device-avr.py | 11 +++++------ tools/gen-device-svd.py | 17 ++++++++--------- 6 files changed, 52 insertions(+), 30 deletions(-) diff --git a/compiler/compiler.go b/compiler/compiler.go index ba8d77ac..0da00b40 100644 --- a/compiler/compiler.go +++ b/compiler/compiler.go @@ -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 diff --git a/ir/ir.go b/ir/ir.go index 76dce610..684d94a4 100644 --- a/ir/ir.go +++ b/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 diff --git a/src/device/arm/arm.go b/src/device/arm/arm.go index e0c4a070..7f6858fb 100644 --- a/src/device/arm/arm.go +++ b/src/device/arm/arm.go @@ -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))) diff --git a/src/runtime/runtime_nrf.go b/src/runtime/runtime_nrf.go index 40ecd098..1cccce97 100644 --- a/src/runtime/runtime_nrf.go +++ b/src/runtime/runtime_nrf.go @@ -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 diff --git a/tools/gen-device-avr.py b/tools/gen-device-avr.py index f2592c1f..1b7efe3f 100755 --- a/tools/gen-device-avr.py +++ b/tools/gen-device-avr.py @@ -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: diff --git a/tools/gen-device-svd.py b/tools/gen-device-svd.py index fb8c077c..97acee6f 100755 --- a/tools/gen-device-svd.py +++ b/tools/gen-device-svd.py @@ -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