runtime: implement KeepAlive using inline assembly
Этот коммит содержится в:
родитель
361ecf9ea4
коммит
c02cc339c5
3 изменённых файлов: 38 добавлений и 6 удалений
|
@ -24,6 +24,8 @@ func (b *builder) defineIntrinsicFunction() {
|
|||
b.createMemoryCopyImpl()
|
||||
case name == "runtime.memzero":
|
||||
b.createMemoryZeroImpl()
|
||||
case name == "runtime.KeepAlive":
|
||||
b.createKeepAliveImpl()
|
||||
case strings.HasPrefix(name, "runtime/volatile.Load"):
|
||||
b.createVolatileLoad()
|
||||
case strings.HasPrefix(name, "runtime/volatile.Store"):
|
||||
|
@ -87,6 +89,29 @@ func (b *builder) createMemoryZeroImpl() {
|
|||
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{
|
||||
"math.Ceil": "llvm.ceil.f64",
|
||||
"math.Exp": "llvm.exp.f64",
|
||||
|
|
|
@ -88,12 +88,9 @@ func LockOSThread() {
|
|||
func UnlockOSThread() {
|
||||
}
|
||||
|
||||
func KeepAlive(x interface{}) {
|
||||
// Unimplemented.
|
||||
// TODO: This function needs to be implemented in a way that LLVM doesn't optimize away the x
|
||||
// parameter. This will likely need either a volatile operation or calling an assembly stub
|
||||
// that simply returns.
|
||||
}
|
||||
// KeepAlive makes sure the value in the interface is alive until at least the
|
||||
// point of the call.
|
||||
func KeepAlive(x interface{})
|
||||
|
||||
var godebugUpdate func(string, string)
|
||||
|
||||
|
|
10
testdata/gc.go
предоставленный
10
testdata/gc.go
предоставленный
|
@ -1,5 +1,7 @@
|
|||
package main
|
||||
|
||||
import "runtime"
|
||||
|
||||
var xorshift32State uint32 = 1
|
||||
|
||||
func xorshift32(x uint32) uint32 {
|
||||
|
@ -17,6 +19,7 @@ func randuint32() uint32 {
|
|||
|
||||
func main() {
|
||||
testNonPointerHeap()
|
||||
testKeepAlive()
|
||||
}
|
||||
|
||||
var scalarSlices [4][]byte
|
||||
|
@ -64,3 +67,10 @@ func testNonPointerHeap() {
|
|||
}
|
||||
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)
|
||||
}
|
||||
|
|
Загрузка…
Создание таблицы
Сослаться в новой задаче