mirror of
https://github.com/tinygo-org/tinygo.git
synced 2026-08-10 22:13:39 +00:00
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:
committed by
Ron Evans
parent
b1ed8a46b7
commit
387e1340bf
+7
-27
@@ -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
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user