compiler: fix stack overflow when creating recursive pointer types

There were two types that could result in a compiler stack overflow.
This is difficult to fix in LLVM 14, so I won't even bother. However,
this is trivial to fix with opaque pointers in LLVM 15. Therefore, this
fix is for LLVM 15 only.

Fixes: https://github.com/tinygo-org/tinygo/issues/3341
Этот коммит содержится в:
Ayke van Laethem 2022-12-22 00:48:12 +00:00 коммит произвёл Ron Evans
родитель 481aba6536
коммит 9fd0567fb5
4 изменённых файлов: 22 добавлений и 6 удалений

Просмотреть файл

@ -43,7 +43,7 @@ func (b *builder) createChanSend(instr *ssa.Send) {
}
// Allocate blockedlist buffer.
channelBlockedList := b.mod.GetTypeByName("runtime.channelBlockedList")
channelBlockedList := b.getLLVMRuntimeType("channelBlockedList")
channelBlockedListAlloca, channelBlockedListAllocaCast, channelBlockedListAllocaSize := b.createTemporaryAlloca(channelBlockedList, "chan.blockedList")
// Do the send.
@ -75,7 +75,7 @@ func (b *builder) createChanRecv(unop *ssa.UnOp) llvm.Value {
}
// Allocate blockedlist buffer.
channelBlockedList := b.mod.GetTypeByName("runtime.channelBlockedList")
channelBlockedList := b.getLLVMRuntimeType("channelBlockedList")
channelBlockedListAlloca, channelBlockedListAllocaCast, channelBlockedListAllocaSize := b.createTemporaryAlloca(channelBlockedList, "chan.blockedList")
// Do the receive.

Просмотреть файл

@ -76,6 +76,7 @@ type compilerContext struct {
i8ptrType llvm.Type // for convenience
rawVoidFuncType llvm.Type // for convenience
funcPtrAddrSpace int
hasTypedPointers bool // for LLVM 14 backwards compatibility
uintptrType llvm.Type
program *ssa.Program
diagnostics []error
@ -123,6 +124,7 @@ func newCompilerContext(moduleName string, machine llvm.TargetMachine, config *C
dummyFuncType := llvm.FunctionType(c.ctx.VoidType(), nil, false)
dummyFunc := llvm.AddFunction(c.mod, "tinygo.dummy", dummyFuncType)
c.funcPtrAddrSpace = dummyFunc.Type().PointerAddressSpace()
c.hasTypedPointers = c.i8ptrType != llvm.PointerType(c.ctx.Int16Type(), 0) // with opaque pointers, all pointers are the same type (LLVM 15+)
c.rawVoidFuncType = dummyFunc.Type()
dummyFunc.EraseFromParentAsFunction()
@ -422,14 +424,20 @@ func (c *compilerContext) makeLLVMType(goType types.Type) llvm.Type {
}
return c.getLLVMType(typ.Underlying())
case *types.Pointer:
ptrTo := c.getLLVMType(typ.Elem())
return llvm.PointerType(ptrTo, 0)
if c.hasTypedPointers {
ptrTo := c.getLLVMType(typ.Elem())
return llvm.PointerType(ptrTo, 0)
}
return c.i8ptrType // all pointers are the same
case *types.Signature: // function value
return c.getFuncType(typ)
case *types.Slice:
elemType := c.getLLVMType(typ.Elem())
ptrType := c.i8ptrType
if c.hasTypedPointers {
ptrType = llvm.PointerType(c.getLLVMType(typ.Elem()), 0)
}
members := []llvm.Type{
llvm.PointerType(elemType, 0),
ptrType,
c.uintptrType, // len
c.uintptrType, // cap
}

6
compiler/testdata/basic.go предоставленный
Просмотреть файл

@ -90,3 +90,9 @@ func foo() {
// Use this type.
func(b kv) {}(kv{})
}
type T1 []T1
type T2 [2]*T2
var a T1
var b T2

2
compiler/testdata/basic.ll предоставленный
Просмотреть файл

@ -7,6 +7,8 @@ target triple = "wasm32-unknown-wasi"
%main.kv.0 = type { i8, i32, i32, i32 }
@main.kvGlobal = hidden global %main.kv zeroinitializer, align 4
@main.a = hidden global { ptr, i32, i32 } zeroinitializer, align 4
@main.b = hidden global [2 x ptr] zeroinitializer, align 4
declare noalias nonnull ptr @runtime.alloc(i32, ptr, ptr) #0