diff options
author | Ayke van Laethem <[email protected]> | 2022-07-28 14:14:23 +0200 |
---|---|---|
committer | Ron Evans <[email protected]> | 2022-07-28 15:43:51 +0200 |
commit | 7b1e5f6f99ac1cc9498e67738dcc421471391117 (patch) | |
tree | 2ed8063517d6c095cf583d81d6785807c362663c | |
parent | 70c52ef1b47fd6b0ed68e322cfcbbf3fd7005315 (diff) | |
download | tinygo-0.25.0-beta1.tar.gz tinygo-0.25.0-beta1.zip |
compiler: implement unsafe.Alignof and unsafe.Sizeof for generic codev0.25.0-beta1
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.
-rw-r--r-- | compiler/compiler.go | 14 | ||||
-rw-r--r-- | compiler/testdata/generics.go | 6 | ||||
-rw-r--r-- | compiler/testdata/generics.ll | 6 |
3 files changed, 26 insertions, 0 deletions
diff --git a/compiler/compiler.go b/compiler/compiler.go index 571ae710b..1b588d9c9 100644 --- a/compiler/compiler.go +++ b/compiler/compiler.go @@ -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 diff --git a/compiler/testdata/generics.go b/compiler/testdata/generics.go index 439de0ead..fc35538fe 100644 --- a/compiler/testdata/generics.go +++ b/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) diff --git a/compiler/testdata/generics.ll b/compiler/testdata/generics.ll index f861cb656..4aa304b07 100644 --- a/compiler/testdata/generics.ll +++ b/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 |