diff --git a/interp/interp.go b/interp/interp.go index ba358384..78896179 100644 --- a/interp/interp.go +++ b/interp/interp.go @@ -28,6 +28,7 @@ type runner struct { builder llvm.Builder pointerSize uint32 // cached pointer size from the TargetData i8ptrType llvm.Type // often used type so created in advance + uintptrType llvm.Type // equivalent to uintptr in Go maxAlign int // maximum alignment of an object, alignment of runtime.alloc() result debug bool // log debug messages pkgName string // package name of the currently executing package @@ -50,6 +51,7 @@ func newRunner(mod llvm.Module, debug bool) *runner { } r.pointerSize = uint32(r.targetData.PointerSize()) r.i8ptrType = llvm.PointerType(mod.Context().Int8Type(), 0) + r.uintptrType = mod.Context().IntType(r.targetData.PointerSize() * 8) r.maxAlign = r.targetData.PrefTypeAlignment(r.i8ptrType) // assume pointers are maximally aligned (this is not always the case) return &r } diff --git a/interp/memory.go b/interp/memory.go index e358124e..c7828997 100644 --- a/interp/memory.go +++ b/interp/memory.go @@ -903,7 +903,14 @@ func (v rawValue) toLLVMValue(llvmType llvm.Type, mem *memoryView) (llvm.Value, return llvm.Value{}, err } if llvmValue.Type() != llvmType { - llvmValue = llvm.ConstBitCast(llvmValue, llvmType) + if llvmValue.Type().PointerAddressSpace() != llvmType.PointerAddressSpace() { + // Special case for AVR function pointers. + // Because go-llvm doesn't have addrspacecast at the moment, + // do it indirectly with a ptrtoint/inttoptr pair. + llvmValue = llvm.ConstIntToPtr(llvm.ConstPtrToInt(llvmValue, mem.r.uintptrType), llvmType) + } else { + llvmValue = llvm.ConstBitCast(llvmValue, llvmType) + } } return llvmValue, nil }