Skip to content

Commit 7b1e5f6

Browse files
aykevldeadprogram
authored andcommitted
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.
1 parent 70c52ef commit 7b1e5f6

File tree

3 files changed

+26
-0
lines changed

3 files changed

+26
-0
lines changed

compiler/compiler.go

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1585,6 +1585,20 @@ func (b *builder) createBuiltin(argTypes []types.Type, argValues []llvm.Value, c
15851585
ptr := argValues[0]
15861586
len := argValues[1]
15871587
return b.CreateGEP(ptr, []llvm.Value{len}, ""), nil
1588+
case "Alignof": // unsafe.Alignof
1589+
align := b.targetData.ABITypeAlignment(argValues[0].Type())
1590+
return llvm.ConstInt(b.uintptrType, uint64(align), false), nil
1591+
case "Offsetof": // unsafe.Offsetof
1592+
// This builtin is a bit harder to implement and may need a bit of
1593+
// refactoring to work (it may be easier to implement if we have access
1594+
// to the underlying Go SSA instruction). It is also rarely used: it
1595+
// only applies in generic code and unsafe.Offsetof isn't very commonly
1596+
// used anyway.
1597+
// In other words, postpone it to some other day.
1598+
return llvm.Value{}, b.makeError(pos, "todo: unsafe.Offsetof")
1599+
case "Sizeof": // unsafe.Sizeof
1600+
size := b.targetData.TypeAllocSize(argValues[0].Type())
1601+
return llvm.ConstInt(b.uintptrType, size, false), nil
15881602
case "Slice": // unsafe.Slice
15891603
// This creates a slice from a pointer and a length.
15901604
// Note that the exception mentioned in the documentation (if the

compiler/testdata/generics.go

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
package main
22

3+
import "unsafe"
4+
35
type Coord interface {
46
int | float32
57
}
@@ -9,6 +11,8 @@ type Point[T Coord] struct {
911
}
1012

1113
func Add[T Coord](a, b Point[T]) Point[T] {
14+
checkSize(unsafe.Alignof(a))
15+
checkSize(unsafe.Sizeof(a))
1216
return Point[T]{
1317
X: a.X + b.X,
1418
Y: a.Y + b.Y,
@@ -22,3 +26,5 @@ func main() {
2226
var ai, bi Point[int]
2327
Add(ai, bi)
2428
}
29+
30+
func checkSize(uintptr)

compiler/testdata/generics.ll

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -94,6 +94,8 @@ entry:
9494
store float %b.X, float* %b.repack14, align 8
9595
%b.repack15 = getelementptr inbounds %"main.Point[float32]", %"main.Point[float32]"* %b, i32 0, i32 1
9696
store float %b.Y, float* %b.repack15, align 4
97+
call void @main.checkSize(i32 4, i8* undef) #2
98+
call void @main.checkSize(i32 8, i8* undef) #2
9799
%complit.repack = getelementptr inbounds %"main.Point[float32]", %"main.Point[float32]"* %complit, i32 0, i32 0
98100
store float 0.000000e+00, float* %complit.repack, align 8
99101
%complit.repack17 = getelementptr inbounds %"main.Point[float32]", %"main.Point[float32]"* %complit, i32 0, i32 1
@@ -157,6 +159,8 @@ store.throw7: ; preds = %store.next
157159
unreachable
158160
}
159161

162+
declare void @main.checkSize(i32, i8*) #0
163+
160164
declare void @runtime.nilPanic(i8*) #0
161165

162166
; Function Attrs: nounwind
@@ -185,6 +189,8 @@ entry:
185189
store i32 %b.X, i32* %b.repack14, align 8
186190
%b.repack15 = getelementptr inbounds %"main.Point[int]", %"main.Point[int]"* %b, i32 0, i32 1
187191
store i32 %b.Y, i32* %b.repack15, align 4
192+
call void @main.checkSize(i32 4, i8* undef) #2
193+
call void @main.checkSize(i32 8, i8* undef) #2
188194
%complit.repack = getelementptr inbounds %"main.Point[int]", %"main.Point[int]"* %complit, i32 0, i32 0
189195
store i32 0, i32* %complit.repack, align 8
190196
%complit.repack17 = getelementptr inbounds %"main.Point[int]", %"main.Point[int]"* %complit, i32 0, i32 1

0 commit comments

Comments
 (0)