compiler: refactor packing of word-sized values in integers

There are two places that try to store values directly in pointers, if
possible: closures and interfaces. Use the same functions for both.
This commit is contained in:
Ayke van Laethem
2019-04-29 00:06:49 +02:00
committed by Ron Evans
parent b1ed8a46b7
commit 387e1340bf
4 changed files with 124 additions and 147 deletions
+7 -27
View File
@@ -743,38 +743,18 @@ func (c *Compiler) parseFunc(frame *Frame) {
context.SetName("context")
}
if len(frame.fn.FreeVars) != 0 {
// Determine the context type. It's a struct containing all variables.
freeVarTypes := make([]llvm.Type, 0, len(frame.fn.FreeVars))
for _, freeVar := range frame.fn.FreeVars {
freeVarTypes = append(freeVarTypes, c.getLLVMType(freeVar.Type()))
}
contextType := c.ctx.StructType(freeVarTypes, false)
// Get a correctly-typed pointer to the context.
contextAlloc := llvm.Value{}
if c.targetData.TypeAllocSize(contextType) <= c.targetData.TypeAllocSize(c.i8ptrType) {
// Context stored directly in pointer. Load it using an alloca.
contextRawAlloc := c.builder.CreateAlloca(llvm.PointerType(c.i8ptrType, 0), "context.raw.alloc")
contextRawValue := c.builder.CreateBitCast(context, llvm.PointerType(c.i8ptrType, 0), "context.raw.value")
c.builder.CreateStore(contextRawValue, contextRawAlloc)
contextAlloc = c.builder.CreateBitCast(contextRawAlloc, llvm.PointerType(contextType, 0), "context.alloc")
} else {
// Context stored in the heap. Bitcast the passed-in pointer to the
// correct pointer type.
contextAlloc = c.builder.CreateBitCast(context, llvm.PointerType(contextType, 0), "context.raw.ptr")
// Get a list of all variable types in the context.
freeVarTypes := make([]llvm.Type, len(frame.fn.FreeVars))
for i, freeVar := range frame.fn.FreeVars {
freeVarTypes[i] = c.getLLVMType(freeVar.Type())
}
// Load each free variable from the context.
// Load each free variable from the context pointer.
// A free variable is always a pointer when this is a closure, but it
// can be another type when it is a wrapper for a bound method (these
// wrappers are generated by the ssa package).
for i, freeVar := range frame.fn.FreeVars {
indices := []llvm.Value{
llvm.ConstInt(c.ctx.Int32Type(), 0, false),
llvm.ConstInt(c.ctx.Int32Type(), uint64(i), false),
}
gep := c.builder.CreateInBoundsGEP(contextAlloc, indices, "")
frame.locals[freeVar] = c.builder.CreateLoad(gep, "")
for i, val := range c.emitPointerUnpack(context, freeVarTypes) {
frame.locals[frame.fn.FreeVars[i]] = val
}
}