func (c *compiler) makeInterface(v *LLVMValue, iface types.Type) *LLVMValue { llv := v.LLVMValue() lltyp := llv.Type() i8ptr := llvm.PointerType(llvm.Int8Type(), 0) if lltyp.TypeKind() == llvm.PointerTypeKind { llv = c.builder.CreateBitCast(llv, i8ptr, "") } else { // If the value fits exactly in a pointer, then we can just // bitcast it. Otherwise we need to malloc. if c.target.TypeStoreSize(lltyp) <= uint64(c.target.PointerSize()) { bits := c.target.TypeSizeInBits(lltyp) if bits > 0 { llv = coerce(c.builder, llv, llvm.IntType(int(bits))) llv = c.builder.CreateIntToPtr(llv, i8ptr, "") } else { llv = llvm.ConstNull(i8ptr) } } else { ptr := c.createTypeMalloc(lltyp) c.builder.CreateStore(llv, ptr) llv = c.builder.CreateBitCast(ptr, i8ptr, "") } } value := llvm.Undef(c.types.ToLLVM(iface)) rtype := c.types.ToRuntime(v.Type()) rtype = c.builder.CreateBitCast(rtype, llvm.PointerType(llvm.Int8Type(), 0), "") value = c.builder.CreateInsertValue(value, rtype, 0, "") value = c.builder.CreateInsertValue(value, llv, 1, "") if iface.Underlying().(*types.Interface).NumMethods() > 0 { result := c.NewValue(value, types.NewInterface(nil, nil)) result, _ = result.convertE2I(iface) return result } return c.NewValue(value, iface) }
func (tm *TypeMap) interfaceFuncWrapper(f llvm.Value) llvm.Value { ftyp := f.Type().ElementType() paramTypes := ftyp.ParamTypes() recvType := paramTypes[0] paramTypes[0] = llvm.PointerType(llvm.Int8Type(), 0) newf := llvm.AddFunction(f.GlobalParent(), f.Name()+".ifn", llvm.FunctionType( ftyp.ReturnType(), paramTypes, ftyp.IsFunctionVarArg(), )) b := llvm.GlobalContext().NewBuilder() defer b.Dispose() entry := llvm.AddBasicBlock(newf, "entry") b.SetInsertPointAtEnd(entry) args := make([]llvm.Value, len(paramTypes)) for i := range paramTypes { args[i] = newf.Param(i) } recvBits := int(tm.target.TypeSizeInBits(recvType)) if recvBits > 0 { args[0] = b.CreatePtrToInt(args[0], tm.target.IntPtrType(), "") if args[0].Type().IntTypeWidth() > recvBits { args[0] = b.CreateTrunc(args[0], llvm.IntType(recvBits), "") } args[0] = coerce(b, args[0], recvType) } else { args[0] = llvm.ConstNull(recvType) } result := b.CreateCall(f, args, "") if result.Type().TypeKind() == llvm.VoidTypeKind { b.CreateRetVoid() } else { b.CreateRet(result) } return newf }