runtime: implement KeepAlive using inline assembly
Этот коммит содержится в:
родитель
361ecf9ea4
коммит
c02cc339c5
3 изменённых файлов: 38 добавлений и 6 удалений
|
@ -24,6 +24,8 @@ func (b *builder) defineIntrinsicFunction() {
|
||||||
b.createMemoryCopyImpl()
|
b.createMemoryCopyImpl()
|
||||||
case name == "runtime.memzero":
|
case name == "runtime.memzero":
|
||||||
b.createMemoryZeroImpl()
|
b.createMemoryZeroImpl()
|
||||||
|
case name == "runtime.KeepAlive":
|
||||||
|
b.createKeepAliveImpl()
|
||||||
case strings.HasPrefix(name, "runtime/volatile.Load"):
|
case strings.HasPrefix(name, "runtime/volatile.Load"):
|
||||||
b.createVolatileLoad()
|
b.createVolatileLoad()
|
||||||
case strings.HasPrefix(name, "runtime/volatile.Store"):
|
case strings.HasPrefix(name, "runtime/volatile.Store"):
|
||||||
|
@ -87,6 +89,29 @@ func (b *builder) createMemoryZeroImpl() {
|
||||||
b.CreateRetVoid()
|
b.CreateRetVoid()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// createKeepAlive creates the runtime.KeepAlive function. It is implemented
|
||||||
|
// using inline assembly.
|
||||||
|
func (b *builder) createKeepAliveImpl() {
|
||||||
|
b.createFunctionStart(true)
|
||||||
|
|
||||||
|
// Get the underlying value of the interface value.
|
||||||
|
interfaceValue := b.getValue(b.fn.Params[0])
|
||||||
|
pointerValue := b.CreateExtractValue(interfaceValue, 1, "")
|
||||||
|
|
||||||
|
// Create an equivalent of the following C code, which is basically just a
|
||||||
|
// nop but ensures the pointerValue is kept alive:
|
||||||
|
//
|
||||||
|
// __asm__ __volatile__("" : : "r"(pointerValue))
|
||||||
|
//
|
||||||
|
// It should be portable to basically everything as the "r" register type
|
||||||
|
// exists basically everywhere.
|
||||||
|
asmType := llvm.FunctionType(b.ctx.VoidType(), []llvm.Type{b.i8ptrType}, false)
|
||||||
|
asmFn := llvm.InlineAsm(asmType, "", "r", true, false, 0, false)
|
||||||
|
b.createCall(asmType, asmFn, []llvm.Value{pointerValue}, "")
|
||||||
|
|
||||||
|
b.CreateRetVoid()
|
||||||
|
}
|
||||||
|
|
||||||
var mathToLLVMMapping = map[string]string{
|
var mathToLLVMMapping = map[string]string{
|
||||||
"math.Ceil": "llvm.ceil.f64",
|
"math.Ceil": "llvm.ceil.f64",
|
||||||
"math.Exp": "llvm.exp.f64",
|
"math.Exp": "llvm.exp.f64",
|
||||||
|
|
|
@ -88,12 +88,9 @@ func LockOSThread() {
|
||||||
func UnlockOSThread() {
|
func UnlockOSThread() {
|
||||||
}
|
}
|
||||||
|
|
||||||
func KeepAlive(x interface{}) {
|
// KeepAlive makes sure the value in the interface is alive until at least the
|
||||||
// Unimplemented.
|
// point of the call.
|
||||||
// TODO: This function needs to be implemented in a way that LLVM doesn't optimize away the x
|
func KeepAlive(x interface{})
|
||||||
// parameter. This will likely need either a volatile operation or calling an assembly stub
|
|
||||||
// that simply returns.
|
|
||||||
}
|
|
||||||
|
|
||||||
var godebugUpdate func(string, string)
|
var godebugUpdate func(string, string)
|
||||||
|
|
||||||
|
|
10
testdata/gc.go
предоставленный
10
testdata/gc.go
предоставленный
|
@ -1,5 +1,7 @@
|
||||||
package main
|
package main
|
||||||
|
|
||||||
|
import "runtime"
|
||||||
|
|
||||||
var xorshift32State uint32 = 1
|
var xorshift32State uint32 = 1
|
||||||
|
|
||||||
func xorshift32(x uint32) uint32 {
|
func xorshift32(x uint32) uint32 {
|
||||||
|
@ -17,6 +19,7 @@ func randuint32() uint32 {
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
testNonPointerHeap()
|
testNonPointerHeap()
|
||||||
|
testKeepAlive()
|
||||||
}
|
}
|
||||||
|
|
||||||
var scalarSlices [4][]byte
|
var scalarSlices [4][]byte
|
||||||
|
@ -64,3 +67,10 @@ func testNonPointerHeap() {
|
||||||
}
|
}
|
||||||
println("ok")
|
println("ok")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func testKeepAlive() {
|
||||||
|
// There isn't much we can test, but at least we can test that
|
||||||
|
// runtime.KeepAlive compiles correctly.
|
||||||
|
var x int
|
||||||
|
runtime.KeepAlive(&x)
|
||||||
|
}
|
||||||
|
|
Загрузка…
Создание таблицы
Сослаться в новой задаче