diff --git a/gen/tocall.cpp b/gen/tocall.cpp index 47259c3d59..615aa7ba3e 100644 --- a/gen/tocall.cpp +++ b/gen/tocall.cpp @@ -819,7 +819,7 @@ private: //////////////////////////////////////////////////////////////////////////////// -static LLValue *DtoCallableValue(llvm::FunctionType * ft,DValue *fn) { +static LLValue *DtoCallableValue(DValue *fn) { Type *type = fn->type->toBasetype(); if (type->ty == TY::Tfunction) { return DtoRVal(fn); @@ -829,7 +829,7 @@ static LLValue *DtoCallableValue(llvm::FunctionType * ft,DValue *fn) { LLValue *dg = DtoLVal(fn); llvm::StructType *st = isaStruct(DtoType(fn->type)); LLValue *funcptr = DtoGEP(st, dg, 0, 1); - return DtoLoad(ft->getPointerTo(), funcptr, ".funcptr"); + return DtoLoad(st->getElementType(1), funcptr, ".funcptr"); } LLValue *dg = DtoRVal(fn); assert(isaStruct(dg)); @@ -862,7 +862,7 @@ DValue *DtoCallFunction(const Loc &loc, Type *resulttype, DValue *fnval, } // get callee llvm value - LLValue *callable = DtoCallableValue(irFty.funcType, fnval); + LLValue *callable = DtoCallableValue(fnval); LLFunctionType *callableTy = irFty.funcType; if (dfnval && dfnval->func->isCsymbol()) { // See note in DtoDeclareFunction about K&R foward declared (void) functions diff --git a/ir/irtype.cpp b/ir/irtype.cpp index 0cf987d928..d00f35c538 100644 --- a/ir/irtype.cpp +++ b/ir/irtype.cpp @@ -118,10 +118,14 @@ IrTypePointer *IrTypePointer::get(Type *dt) { assert(!ctype); LLType *elemType; + unsigned addressSpace = 0; if (dt->ty == TY::Tnull) { elemType = llvm::Type::getInt8Ty(getGlobalContext()); } else { elemType = DtoMemType(dt->nextOf()); + if (dt->nextOf()->ty == TY::Tfunction) { + addressSpace = gDataLayout->getProgramAddressSpace(); + } // DtoType could have already created the same type, e.g. for // dt == Node* in struct Node { Node* n; }. @@ -130,7 +134,8 @@ IrTypePointer *IrTypePointer::get(Type *dt) { } } - auto t = new IrTypePointer(dt, llvm::PointerType::get(elemType, 0)); + auto t = + new IrTypePointer(dt, llvm::PointerType::get(elemType, addressSpace)); ctype = t; return t; } diff --git a/ir/irtypefunction.cpp b/ir/irtypefunction.cpp index 8a1a4ba9a9..0e830f187a 100644 --- a/ir/irtypefunction.cpp +++ b/ir/irtypefunction.cpp @@ -53,7 +53,8 @@ IrTypeDelegate *IrTypeDelegate::get(Type *t) { IrFuncTy irFty(tf); llvm::Type *ltf = DtoFunctionType(tf, irFty, nullptr, Type::tvoid->pointerTo()); - llvm::Type *types[] = {getVoidPtrType(), getPtrToType(ltf)}; + llvm::Type *fptr = ltf->getPointerTo(gDataLayout->getProgramAddressSpace()); + llvm::Type *types[] = {getVoidPtrType(), fptr}; LLStructType *lt = LLStructType::get(gIR->context(), types, false); // Could have already built the type as part of a struct forward reference, diff --git a/tests/compilable/funcptr_harvard_gh4432.d b/tests/compilable/funcptr_harvard_gh4432.d new file mode 100644 index 0000000000..74d6b9f2c6 --- /dev/null +++ b/tests/compilable/funcptr_harvard_gh4432.d @@ -0,0 +1,24 @@ +// A minimal test for function pointers/delegates on a Harvard architecture, +// with code residing in a separate address space. + +// REQUIRES: target_AVR +// RUN: %ldc -mtriple=avr -betterC -c %s + +alias FP = void function(); +alias DG = void delegate(); + +void foo(FP fp, DG dg) +{ + fp(); + dg(); +} + +void bar() +{ + foo(() {}, delegate() {}); + + FP fp = &bar; + DG dg; + dg.funcptr = &bar; + foo(fp, dg); +}