runtime: implement KeepAlive using inline assembly

Этот коммит содержится в:
Ayke van Laethem 2023-02-17 01:19:53 +01:00 коммит произвёл Ron Evans
родитель 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 предоставленный
Просмотреть файл

@ -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)
}