diff options
author | Ayke van Laethem <[email protected]> | 2019-08-08 14:41:52 +0200 |
---|---|---|
committer | Ron Evans <[email protected]> | 2019-08-08 15:23:47 +0200 |
commit | e2c8654237bd2893c256e1a268ce350952d4fb4c (patch) | |
tree | 835ab0118b2cf5f2b8433fea4ed674e49b1557c9 /compiler/llvm.go | |
parent | 5012be337f59c45833e4c9dc55feeaf0d86f52bf (diff) | |
download | tinygo-e2c8654237bd2893c256e1a268ce350952d4fb4c.tar.gz tinygo-e2c8654237bd2893c256e1a268ce350952d4fb4c.zip |
reflect: add support for struct types
Diffstat (limited to 'compiler/llvm.go')
-rw-r--r-- | compiler/llvm.go | 43 |
1 files changed, 43 insertions, 0 deletions
diff --git a/compiler/llvm.go b/compiler/llvm.go index fb52b0069..79dbbfd12 100644 --- a/compiler/llvm.go +++ b/compiler/llvm.go @@ -152,3 +152,46 @@ 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 +// 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)) + 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)}) + } + 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. +func getGlobalBytes(global llvm.Value) []byte { + value := global.Initializer() + buf := make([]byte, value.Type().ArrayLength()) + for i := range buf { + buf[i] = byte(llvm.ConstExtractValue(value, []uint32{uint32(i)}).ZExtValue()) + } + 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") + oldGlobal := c.mod.NamedGlobal(name) + gep := llvm.ConstGEP(global, []llvm.Value{ + llvm.ConstInt(c.ctx.Int32Type(), 0, false), + llvm.ConstInt(c.ctx.Int32Type(), 0, false), + }) + oldGlobal.ReplaceAllUsesWith(gep) + oldGlobal.EraseFromParentAsGlobal() + global.SetName(name) + return global +} |