aboutsummaryrefslogtreecommitdiffhomepage
path: root/compiler/llvm.go
diff options
context:
space:
mode:
authorAyke van Laethem <[email protected]>2019-08-08 14:41:52 +0200
committerRon Evans <[email protected]>2019-08-08 15:23:47 +0200
commite2c8654237bd2893c256e1a268ce350952d4fb4c (patch)
tree835ab0118b2cf5f2b8433fea4ed674e49b1557c9 /compiler/llvm.go
parent5012be337f59c45833e4c9dc55feeaf0d86f52bf (diff)
downloadtinygo-e2c8654237bd2893c256e1a268ce350952d4fb4c.tar.gz
tinygo-e2c8654237bd2893c256e1a268ce350952d4fb4c.zip
reflect: add support for struct types
Diffstat (limited to 'compiler/llvm.go')
-rw-r--r--compiler/llvm.go43
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
+}