mirror of
https://github.com/tinygo-org/tinygo.git
synced 2026-08-09 05:23:40 +00:00
reflect: add support for linked lists
Linked lists are usually implemented as follows:
type linkedList struct {
next *linkedList
data int // whatever
}
This caused a stack overflow while writing out the reflect run-time type
information. This has now been fixed by splitting the allocation of a
named type number from setting the underlying type in the sidetable.
This commit is contained in:
committed by
Ron Evans
parent
0818a125c0
commit
ea8e4079bc
+17
-13
@@ -1,6 +1,8 @@
|
||||
package compiler
|
||||
|
||||
import (
|
||||
"reflect"
|
||||
|
||||
"tinygo.org/x/go-llvm"
|
||||
)
|
||||
|
||||
@@ -153,24 +155,26 @@ func (c *Compiler) splitBasicBlock(afterInst llvm.Value, insertAfter llvm.BasicB
|
||||
return newBlock
|
||||
}
|
||||
|
||||
// makeGlobalBytes creates a new LLVM global with the given name and bytes as
|
||||
// makeGlobalArray creates a new LLVM global with the given name and integers as
|
||||
// contents, and returns the global.
|
||||
// Note that it is left with the default linkage etc., you should set
|
||||
// linkage/constant/etc properties yourself.
|
||||
func (c *Compiler) makeGlobalBytes(buf []byte, name string) llvm.Value {
|
||||
globalType := llvm.ArrayType(c.ctx.Int8Type(), len(buf))
|
||||
func (c *Compiler) makeGlobalArray(bufItf interface{}, name string, elementType llvm.Type) llvm.Value {
|
||||
buf := reflect.ValueOf(bufItf)
|
||||
globalType := llvm.ArrayType(elementType, buf.Len())
|
||||
global := llvm.AddGlobal(c.mod, globalType, name)
|
||||
value := llvm.Undef(globalType)
|
||||
for i, ch := range buf {
|
||||
value = llvm.ConstInsertValue(value, llvm.ConstInt(c.ctx.Int8Type(), uint64(ch), false), []uint32{uint32(i)})
|
||||
for i := 0; i < buf.Len(); i++ {
|
||||
ch := buf.Index(i).Uint()
|
||||
value = llvm.ConstInsertValue(value, llvm.ConstInt(elementType, ch, false), []uint32{uint32(i)})
|
||||
}
|
||||
global.SetInitializer(value)
|
||||
return global
|
||||
}
|
||||
|
||||
// getGlobalBytes returns the byte slice contained in the i8 array of the
|
||||
// provided global. It can recover the bytes originally created using
|
||||
// makeGlobalBytes.
|
||||
// getGlobalBytes returns the slice contained in the array of the provided
|
||||
// global. It can recover the bytes originally created using makeGlobalArray, if
|
||||
// makeGlobalArray was given a byte slice.
|
||||
func getGlobalBytes(global llvm.Value) []byte {
|
||||
value := global.Initializer()
|
||||
buf := make([]byte, value.Type().ArrayLength())
|
||||
@@ -180,12 +184,12 @@ func getGlobalBytes(global llvm.Value) []byte {
|
||||
return buf
|
||||
}
|
||||
|
||||
// replaceGlobalByteWithArray replaces a global i8 in the module with a byte
|
||||
// array, using a GEP to make the types match. It is a convenience function used
|
||||
// for creating reflection sidetables, for example.
|
||||
func (c *Compiler) replaceGlobalByteWithArray(name string, buf []byte) llvm.Value {
|
||||
global := c.makeGlobalBytes(buf, name+".tmp")
|
||||
// replaceGlobalByteWithArray replaces a global integer type in the module with
|
||||
// an integer array, using a GEP to make the types match. It is a convenience
|
||||
// function used for creating reflection sidetables, for example.
|
||||
func (c *Compiler) replaceGlobalIntWithArray(name string, buf interface{}) llvm.Value {
|
||||
oldGlobal := c.mod.NamedGlobal(name)
|
||||
global := c.makeGlobalArray(buf, name+".tmp", oldGlobal.Type().ElementType())
|
||||
gep := llvm.ConstGEP(global, []llvm.Value{
|
||||
llvm.ConstInt(c.ctx.Int32Type(), 0, false),
|
||||
llvm.ConstInt(c.ctx.Int32Type(), 0, false),
|
||||
|
||||
Reference in New Issue
Block a user