compiler: implement unsafe.Alignof and unsafe.Sizeof for generic code
For some reason, these aren't lowered when a generic function is instantiated by the SSA package. I've left unsafe.Offsetof to be implemented later, it's a bit difficult to do correctly the way the code is currently structured.
Этот коммит содержится в:
родитель
70c52ef1b4
коммит
7b1e5f6f99
3 изменённых файлов: 26 добавлений и 0 удалений
|
@ -1585,6 +1585,20 @@ func (b *builder) createBuiltin(argTypes []types.Type, argValues []llvm.Value, c
|
|||
ptr := argValues[0]
|
||||
len := argValues[1]
|
||||
return b.CreateGEP(ptr, []llvm.Value{len}, ""), nil
|
||||
case "Alignof": // unsafe.Alignof
|
||||
align := b.targetData.ABITypeAlignment(argValues[0].Type())
|
||||
return llvm.ConstInt(b.uintptrType, uint64(align), false), nil
|
||||
case "Offsetof": // unsafe.Offsetof
|
||||
// This builtin is a bit harder to implement and may need a bit of
|
||||
// refactoring to work (it may be easier to implement if we have access
|
||||
// to the underlying Go SSA instruction). It is also rarely used: it
|
||||
// only applies in generic code and unsafe.Offsetof isn't very commonly
|
||||
// used anyway.
|
||||
// In other words, postpone it to some other day.
|
||||
return llvm.Value{}, b.makeError(pos, "todo: unsafe.Offsetof")
|
||||
case "Sizeof": // unsafe.Sizeof
|
||||
size := b.targetData.TypeAllocSize(argValues[0].Type())
|
||||
return llvm.ConstInt(b.uintptrType, size, false), nil
|
||||
case "Slice": // unsafe.Slice
|
||||
// This creates a slice from a pointer and a length.
|
||||
// Note that the exception mentioned in the documentation (if the
|
||||
|
|
6
compiler/testdata/generics.go
предоставленный
6
compiler/testdata/generics.go
предоставленный
|
@ -1,5 +1,7 @@
|
|||
package main
|
||||
|
||||
import "unsafe"
|
||||
|
||||
type Coord interface {
|
||||
int | float32
|
||||
}
|
||||
|
@ -9,6 +11,8 @@ type Point[T Coord] struct {
|
|||
}
|
||||
|
||||
func Add[T Coord](a, b Point[T]) Point[T] {
|
||||
checkSize(unsafe.Alignof(a))
|
||||
checkSize(unsafe.Sizeof(a))
|
||||
return Point[T]{
|
||||
X: a.X + b.X,
|
||||
Y: a.Y + b.Y,
|
||||
|
@ -22,3 +26,5 @@ func main() {
|
|||
var ai, bi Point[int]
|
||||
Add(ai, bi)
|
||||
}
|
||||
|
||||
func checkSize(uintptr)
|
||||
|
|
6
compiler/testdata/generics.ll
предоставленный
6
compiler/testdata/generics.ll
предоставленный
|
@ -94,6 +94,8 @@ entry:
|
|||
store float %b.X, float* %b.repack14, align 8
|
||||
%b.repack15 = getelementptr inbounds %"main.Point[float32]", %"main.Point[float32]"* %b, i32 0, i32 1
|
||||
store float %b.Y, float* %b.repack15, align 4
|
||||
call void @main.checkSize(i32 4, i8* undef) #2
|
||||
call void @main.checkSize(i32 8, i8* undef) #2
|
||||
%complit.repack = getelementptr inbounds %"main.Point[float32]", %"main.Point[float32]"* %complit, i32 0, i32 0
|
||||
store float 0.000000e+00, float* %complit.repack, align 8
|
||||
%complit.repack17 = getelementptr inbounds %"main.Point[float32]", %"main.Point[float32]"* %complit, i32 0, i32 1
|
||||
|
@ -157,6 +159,8 @@ store.throw7: ; preds = %store.next
|
|||
unreachable
|
||||
}
|
||||
|
||||
declare void @main.checkSize(i32, i8*) #0
|
||||
|
||||
declare void @runtime.nilPanic(i8*) #0
|
||||
|
||||
; Function Attrs: nounwind
|
||||
|
@ -185,6 +189,8 @@ entry:
|
|||
store i32 %b.X, i32* %b.repack14, align 8
|
||||
%b.repack15 = getelementptr inbounds %"main.Point[int]", %"main.Point[int]"* %b, i32 0, i32 1
|
||||
store i32 %b.Y, i32* %b.repack15, align 4
|
||||
call void @main.checkSize(i32 4, i8* undef) #2
|
||||
call void @main.checkSize(i32 8, i8* undef) #2
|
||||
%complit.repack = getelementptr inbounds %"main.Point[int]", %"main.Point[int]"* %complit, i32 0, i32 0
|
||||
store i32 0, i32* %complit.repack, align 8
|
||||
%complit.repack17 = getelementptr inbounds %"main.Point[int]", %"main.Point[int]"* %complit, i32 0, i32 1
|
||||
|
|
Загрузка…
Создание таблицы
Сослаться в новой задаче