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