Skip to content

Commit

Permalink
compiler: implement unsafe.Alignof and unsafe.Sizeof for generic code
Browse files Browse the repository at this point in the history
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.
  • Loading branch information
aykevl authored and deadprogram committed Jul 28, 2022
1 parent 70c52ef commit 7b1e5f6
Show file tree
Hide file tree
Showing 3 changed files with 26 additions and 0 deletions.
14 changes: 14 additions & 0 deletions compiler/compiler.go
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
6 changes: 6 additions & 0 deletions compiler/testdata/generics.go
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
package main

import "unsafe"

type Coord interface {
int | float32
}
Expand All @@ -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,
Expand All @@ -22,3 +26,5 @@ func main() {
var ai, bi Point[int]
Add(ai, bi)
}

func checkSize(uintptr)
6 changes: 6 additions & 0 deletions compiler/testdata/generics.ll
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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
Expand Down

0 comments on commit 7b1e5f6

Please sign in to comment.