compiler: really define runtime/volatile.* functions
This makes them available to deferred calls, among others.
Этот коммит содержится в:
родитель
e1052f921c
коммит
1ceb63d14c
5 изменённых файлов: 22 добавлений и 19 удалений
|
@ -1642,10 +1642,6 @@ func (b *builder) createFunctionCall(instr *ssa.CallCommon) (llvm.Value, error)
|
|||
return b.createSyscall(instr)
|
||||
case strings.HasPrefix(name, "syscall.rawSyscallNoError"):
|
||||
return b.createRawSyscallNoError(instr)
|
||||
case strings.HasPrefix(name, "runtime/volatile.Load"):
|
||||
return b.createVolatileLoad(instr)
|
||||
case strings.HasPrefix(name, "runtime/volatile.Store"):
|
||||
return b.createVolatileStore(instr)
|
||||
case name == "runtime.supportsRecover":
|
||||
supportsRecover := uint64(0)
|
||||
if b.supportsRecover() {
|
||||
|
|
|
@ -20,6 +20,10 @@ import (
|
|||
func (b *builder) defineIntrinsicFunction() {
|
||||
name := b.fn.RelString(nil)
|
||||
switch {
|
||||
case strings.HasPrefix(name, "runtime/volatile.Load"):
|
||||
b.createVolatileLoad()
|
||||
case strings.HasPrefix(name, "runtime/volatile.Store"):
|
||||
b.createVolatileStore()
|
||||
case strings.HasPrefix(name, "sync/atomic.") && token.IsExported(b.fn.Name()):
|
||||
b.createFunctionStart()
|
||||
returnValue := b.createAtomicOp(b.fn.Name())
|
||||
|
|
|
@ -3,28 +3,25 @@ package compiler
|
|||
// This file implements volatile loads/stores in runtime/volatile.LoadT and
|
||||
// runtime/volatile.StoreT as compiler builtins.
|
||||
|
||||
import (
|
||||
"golang.org/x/tools/go/ssa"
|
||||
"tinygo.org/x/go-llvm"
|
||||
)
|
||||
|
||||
// createVolatileLoad is the implementation of the intrinsic function
|
||||
// runtime/volatile.LoadT().
|
||||
func (b *builder) createVolatileLoad(instr *ssa.CallCommon) (llvm.Value, error) {
|
||||
addr := b.getValue(instr.Args[0])
|
||||
b.createNilCheck(instr.Args[0], addr, "deref")
|
||||
func (b *builder) createVolatileLoad() {
|
||||
b.createFunctionStart()
|
||||
addr := b.getValue(b.fn.Params[0])
|
||||
b.createNilCheck(b.fn.Params[0], addr, "deref")
|
||||
val := b.CreateLoad(addr, "")
|
||||
val.SetVolatile(true)
|
||||
return val, nil
|
||||
b.CreateRet(val)
|
||||
}
|
||||
|
||||
// createVolatileStore is the implementation of the intrinsic function
|
||||
// runtime/volatile.StoreT().
|
||||
func (b *builder) createVolatileStore(instr *ssa.CallCommon) (llvm.Value, error) {
|
||||
addr := b.getValue(instr.Args[0])
|
||||
val := b.getValue(instr.Args[1])
|
||||
b.createNilCheck(instr.Args[0], addr, "deref")
|
||||
func (b *builder) createVolatileStore() {
|
||||
b.createFunctionStart()
|
||||
addr := b.getValue(b.fn.Params[0])
|
||||
val := b.getValue(b.fn.Params[1])
|
||||
b.createNilCheck(b.fn.Params[0], addr, "deref")
|
||||
store := b.CreateStore(val, addr)
|
||||
store.SetVolatile(true)
|
||||
return llvm.Value{}, nil
|
||||
b.CreateRetVoid()
|
||||
}
|
||||
|
|
7
testdata/atomic.go
предоставленный
7
testdata/atomic.go
предоставленный
|
@ -3,6 +3,8 @@ package main
|
|||
import (
|
||||
"sync/atomic"
|
||||
"unsafe"
|
||||
|
||||
"runtime/volatile"
|
||||
)
|
||||
|
||||
func main() {
|
||||
|
@ -82,7 +84,7 @@ func main() {
|
|||
testValue(int(3), int(-2))
|
||||
testValue("", "foobar", "baz")
|
||||
|
||||
// Test atomic operations as deferred values.
|
||||
// Test atomic and volatile operations as deferred values.
|
||||
testDefer()
|
||||
}
|
||||
|
||||
|
@ -99,8 +101,11 @@ func testValue(values ...interface{}) {
|
|||
|
||||
func testDefer() {
|
||||
n1 := int32(5)
|
||||
n2 := uint32(6)
|
||||
defer func() {
|
||||
println("deferred atomic add:", n1)
|
||||
println("deferred volatile store:", n2)
|
||||
}()
|
||||
defer atomic.AddInt32(&n1, 3)
|
||||
defer volatile.StoreUint32(&n2, 22)
|
||||
}
|
||||
|
|
1
testdata/atomic.txt
предоставленный
1
testdata/atomic.txt
предоставленный
|
@ -34,3 +34,4 @@ StoreUint64: 20
|
|||
StoreUintptr: 20
|
||||
StorePointer: true
|
||||
deferred atomic add: 8
|
||||
deferred volatile store: 22
|
||||
|
|
Загрузка…
Создание таблицы
Сослаться в новой задаче