compiler: really define runtime.mem* as LLVM intrinsic wrappers
This makes it possible to //go:linkname them from other places, like in the reflect package. And is in my opinion a much cleaner solution.
Этот коммит содержится в:
родитель
1ceb63d14c
коммит
4262f0ff1f
4 изменённых файлов: 23 добавлений и 22 удалений
|
@ -1619,10 +1619,6 @@ func (b *builder) createFunctionCall(instr *ssa.CallCommon) (llvm.Value, error)
|
||||||
// applied) function call. If it is anonymous, it may be a closure.
|
// applied) function call. If it is anonymous, it may be a closure.
|
||||||
name := fn.RelString(nil)
|
name := fn.RelString(nil)
|
||||||
switch {
|
switch {
|
||||||
case name == "runtime.memcpy" || name == "runtime.memmove" || name == "reflect.memcpy":
|
|
||||||
return b.createMemoryCopyCall(fn, instr.Args)
|
|
||||||
case name == "runtime.memzero":
|
|
||||||
return b.createMemoryZeroCall(instr.Args)
|
|
||||||
case name == "math.Ceil" || name == "math.Floor" || name == "math.Sqrt" || name == "math.Trunc":
|
case name == "math.Ceil" || name == "math.Floor" || name == "math.Sqrt" || name == "math.Trunc":
|
||||||
result, ok := b.createMathOp(instr)
|
result, ok := b.createMathOp(instr)
|
||||||
if ok {
|
if ok {
|
||||||
|
|
|
@ -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 name == "runtime.memcpy" || name == "runtime.memmove":
|
||||||
|
b.createMemoryCopyImpl()
|
||||||
|
case name == "runtime.memzero":
|
||||||
|
b.createMemoryZeroImpl()
|
||||||
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"):
|
||||||
|
@ -35,30 +39,32 @@ func (b *builder) defineIntrinsicFunction() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// createMemoryCopyCall creates a call to a builtin LLVM memcpy or memmove
|
// createMemoryCopyImpl creates a call to a builtin LLVM memcpy or memmove
|
||||||
// function, declaring this function if needed. These calls are treated
|
// function, declaring this function if needed. These calls are treated
|
||||||
// specially by optimization passes possibly resulting in better generated code,
|
// specially by optimization passes possibly resulting in better generated code,
|
||||||
// and will otherwise be lowered to regular libc memcpy/memmove calls.
|
// and will otherwise be lowered to regular libc memcpy/memmove calls.
|
||||||
func (b *builder) createMemoryCopyCall(fn *ssa.Function, args []ssa.Value) (llvm.Value, error) {
|
func (b *builder) createMemoryCopyImpl() {
|
||||||
fnName := "llvm." + fn.Name() + ".p0i8.p0i8.i" + strconv.Itoa(b.uintptrType.IntTypeWidth())
|
b.createFunctionStart()
|
||||||
|
fnName := "llvm." + b.fn.Name() + ".p0i8.p0i8.i" + strconv.Itoa(b.uintptrType.IntTypeWidth())
|
||||||
llvmFn := b.mod.NamedFunction(fnName)
|
llvmFn := b.mod.NamedFunction(fnName)
|
||||||
if llvmFn.IsNil() {
|
if llvmFn.IsNil() {
|
||||||
fnType := llvm.FunctionType(b.ctx.VoidType(), []llvm.Type{b.i8ptrType, b.i8ptrType, b.uintptrType, b.ctx.Int1Type()}, false)
|
fnType := llvm.FunctionType(b.ctx.VoidType(), []llvm.Type{b.i8ptrType, b.i8ptrType, b.uintptrType, b.ctx.Int1Type()}, false)
|
||||||
llvmFn = llvm.AddFunction(b.mod, fnName, fnType)
|
llvmFn = llvm.AddFunction(b.mod, fnName, fnType)
|
||||||
}
|
}
|
||||||
var params []llvm.Value
|
var params []llvm.Value
|
||||||
for _, param := range args {
|
for _, param := range b.fn.Params {
|
||||||
params = append(params, b.getValue(param))
|
params = append(params, b.getValue(param))
|
||||||
}
|
}
|
||||||
params = append(params, llvm.ConstInt(b.ctx.Int1Type(), 0, false))
|
params = append(params, llvm.ConstInt(b.ctx.Int1Type(), 0, false))
|
||||||
b.CreateCall(llvmFn, params, "")
|
b.CreateCall(llvmFn, params, "")
|
||||||
return llvm.Value{}, nil
|
b.CreateRetVoid()
|
||||||
}
|
}
|
||||||
|
|
||||||
// createMemoryZeroCall creates calls to llvm.memset.* to zero a block of
|
// createMemoryZeroImpl creates calls to llvm.memset.* to zero a block of
|
||||||
// memory, declaring the function if needed. These calls will be lowered to
|
// memory, declaring the function if needed. These calls will be lowered to
|
||||||
// regular libc memset calls if they aren't optimized out in a different way.
|
// regular libc memset calls if they aren't optimized out in a different way.
|
||||||
func (b *builder) createMemoryZeroCall(args []ssa.Value) (llvm.Value, error) {
|
func (b *builder) createMemoryZeroImpl() {
|
||||||
|
b.createFunctionStart()
|
||||||
fnName := "llvm.memset.p0i8.i" + strconv.Itoa(b.uintptrType.IntTypeWidth())
|
fnName := "llvm.memset.p0i8.i" + strconv.Itoa(b.uintptrType.IntTypeWidth())
|
||||||
llvmFn := b.mod.NamedFunction(fnName)
|
llvmFn := b.mod.NamedFunction(fnName)
|
||||||
if llvmFn.IsNil() {
|
if llvmFn.IsNil() {
|
||||||
|
@ -66,13 +72,13 @@ func (b *builder) createMemoryZeroCall(args []ssa.Value) (llvm.Value, error) {
|
||||||
llvmFn = llvm.AddFunction(b.mod, fnName, fnType)
|
llvmFn = llvm.AddFunction(b.mod, fnName, fnType)
|
||||||
}
|
}
|
||||||
params := []llvm.Value{
|
params := []llvm.Value{
|
||||||
b.getValue(args[0]),
|
b.getValue(b.fn.Params[0]),
|
||||||
llvm.ConstInt(b.ctx.Int8Type(), 0, false),
|
llvm.ConstInt(b.ctx.Int8Type(), 0, false),
|
||||||
b.getValue(args[1]),
|
b.getValue(b.fn.Params[1]),
|
||||||
llvm.ConstInt(b.ctx.Int1Type(), 0, false),
|
llvm.ConstInt(b.ctx.Int1Type(), 0, false),
|
||||||
}
|
}
|
||||||
b.CreateCall(llvmFn, params, "")
|
b.CreateCall(llvmFn, params, "")
|
||||||
return llvm.Value{}, nil
|
b.CreateRetVoid()
|
||||||
}
|
}
|
||||||
|
|
||||||
var mathToLLVMMapping = map[string]string{
|
var mathToLLVMMapping = map[string]string{
|
||||||
|
|
|
@ -808,8 +808,7 @@ func (e *ValueError) Error() string {
|
||||||
return "reflect: call of " + e.Method + " on " + e.Kind.String() + " Value"
|
return "reflect: call of " + e.Method + " on " + e.Kind.String() + " Value"
|
||||||
}
|
}
|
||||||
|
|
||||||
// Calls to this function are converted to LLVM intrinsic calls such as
|
//go:linkname memcpy runtime.memcpy
|
||||||
// llvm.memcpy.p0i8.p0i8.i32().
|
|
||||||
func memcpy(dst, src unsafe.Pointer, size uintptr)
|
func memcpy(dst, src unsafe.Pointer, size uintptr)
|
||||||
|
|
||||||
//go:linkname alloc runtime.alloc
|
//go:linkname alloc runtime.alloc
|
||||||
|
|
|
@ -26,19 +26,19 @@ func GOROOT() string {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Copy size bytes from src to dst. The memory areas must not overlap.
|
// Copy size bytes from src to dst. The memory areas must not overlap.
|
||||||
// Calls to this function are converted to LLVM intrinsic calls such as
|
// This function is implemented by the compiler as a call to a LLVM intrinsic
|
||||||
// llvm.memcpy.p0i8.p0i8.i32(dst, src, size, false).
|
// like llvm.memcpy.p0i8.p0i8.i32(dst, src, size, false).
|
||||||
func memcpy(dst, src unsafe.Pointer, size uintptr)
|
func memcpy(dst, src unsafe.Pointer, size uintptr)
|
||||||
|
|
||||||
// Copy size bytes from src to dst. The memory areas may overlap and will do the
|
// Copy size bytes from src to dst. The memory areas may overlap and will do the
|
||||||
// correct thing.
|
// correct thing.
|
||||||
// Calls to this function are converted to LLVM intrinsic calls such as
|
// This function is implemented by the compiler as a call to a LLVM intrinsic
|
||||||
// llvm.memmove.p0i8.p0i8.i32(dst, src, size, false).
|
// like llvm.memmove.p0i8.p0i8.i32(dst, src, size, false).
|
||||||
func memmove(dst, src unsafe.Pointer, size uintptr)
|
func memmove(dst, src unsafe.Pointer, size uintptr)
|
||||||
|
|
||||||
// Set the given number of bytes to zero.
|
// Set the given number of bytes to zero.
|
||||||
// Calls to this function are converted to LLVM intrinsic calls such as
|
// This function is implemented by the compiler as a call to a LLVM intrinsic
|
||||||
// llvm.memset.p0i8.i32(ptr, 0, size, false).
|
// like llvm.memset.p0i8.i32(ptr, 0, size, false).
|
||||||
func memzero(ptr unsafe.Pointer, size uintptr)
|
func memzero(ptr unsafe.Pointer, size uintptr)
|
||||||
|
|
||||||
// This intrinsic returns the current stack pointer.
|
// This intrinsic returns the current stack pointer.
|
||||||
|
|
Загрузка…
Создание таблицы
Сослаться в новой задаче