From 4d5553f545cd9170b3b373a7501a22023a5f0f73 Mon Sep 17 00:00:00 2001 From: Martin Kinkelin <mkinkelin@symmetryinvestments.com> Date: Sat, 5 Aug 2023 12:21:26 +0200 Subject: [PATCH 1/4] [slight cleanup] --- gen/declarations.cpp | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/gen/declarations.cpp b/gen/declarations.cpp index c0d2ad3ad47..d98652a2ebb 100644 --- a/gen/declarations.cpp +++ b/gen/declarations.cpp @@ -419,17 +419,16 @@ class CodegenVisitor : public Visitor { std::string arg = ("/DEFAULTLIB:\"" + name + "\"").str(); gIR->addLinkerOption(llvm::StringRef(arg)); } else { - bool isStaticLib = name.endswith(".a"); + const bool isStaticLib = name.endswith(".a"); + const size_t nameLen = name.size(); - size_t const nameLen = name.size(); - size_t const n = nameLen + 3; char *arg = nullptr; - - if (isStaticLib == false) { + if (!isStaticLib) { // name => -lname + const size_t n = nameLen + 3; arg = static_cast<char *>(mem.xmalloc(n)); arg[0] = '-'; arg[1] = 'l'; - memcpy(arg + 2, name.data(), name.size()); + memcpy(arg + 2, name.data(), nameLen); arg[n - 1] = 0; } else { arg = static_cast<char *>((mem.xmalloc(nameLen + 1))); From 87b22436e41c6d71fec7c35ff855aa74ca7346d0 Mon Sep 17 00:00:00 2001 From: Martin Kinkelin <mkinkelin@symmetryinvestments.com> Date: Sat, 5 Aug 2023 12:12:07 +0200 Subject: [PATCH 2/4] Fix function pointers/delegates on Harvard architectures Resolves issue #4432 by setting the address space of such IR pointers. --- gen/tocall.cpp | 6 +++--- ir/irtype.cpp | 7 ++++++- ir/irtypefunction.cpp | 3 ++- tests/compilable/funcptr_harvard_gh4432.d | 24 +++++++++++++++++++++++ 4 files changed, 35 insertions(+), 5 deletions(-) create mode 100644 tests/compilable/funcptr_harvard_gh4432.d diff --git a/gen/tocall.cpp b/gen/tocall.cpp index 47259c3d596..615aa7ba3ea 100644 --- a/gen/tocall.cpp +++ b/gen/tocall.cpp @@ -819,7 +819,7 @@ class ImplicitArgumentsBuilder { //////////////////////////////////////////////////////////////////////////////// -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 0cf987d9284..d00f35c5386 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 8a1a4ba9a9d..0e830f187af 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 00000000000..74d6b9f2c62 --- /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); +} From 0d5ea6a2e97c765fb2d33058813e2c4b838c9560 Mon Sep 17 00:00:00 2001 From: Martin Kinkelin <mkinkelin@symmetryinvestments.com> Date: Sat, 5 Aug 2023 15:53:58 +0200 Subject: [PATCH 3/4] [extend test] --- tests/codegen/funcptr_harvard_gh4432.d | 37 +++++++++++++++++++++++ tests/compilable/funcptr_harvard_gh4432.d | 24 --------------- 2 files changed, 37 insertions(+), 24 deletions(-) create mode 100644 tests/codegen/funcptr_harvard_gh4432.d delete mode 100644 tests/compilable/funcptr_harvard_gh4432.d diff --git a/tests/codegen/funcptr_harvard_gh4432.d b/tests/codegen/funcptr_harvard_gh4432.d new file mode 100644 index 00000000000..9400d982b07 --- /dev/null +++ b/tests/codegen/funcptr_harvard_gh4432.d @@ -0,0 +1,37 @@ +// Tests function pointers/delegates on a Harvard architecture, +// with code residing in a separate address space. + +// REQUIRES: target_AVR +// RUN: %ldc -mtriple=avr -betterC -output-ll -of=%t.ll %s && FileCheck %s < %t.ll +// RUN: %ldc -mtriple=avr -betterC -c %s + +alias FP = void function(); +alias DG = void delegate(); + +// CHECK: @_D22funcptr_harvard_gh44328globalFPPFZv = global {{void \(\) addrspace\(1\)\*|ptr addrspace\(1\)}} @_D22funcptr_harvard_gh44323barFZv, align 2 +__gshared FP globalFP = &bar; +// CHECK: @_D22funcptr_harvard_gh443217globalDataPointerPPFZv = global {{void \(\) addrspace\(1\)\*\*|ptr}} @_D22funcptr_harvard_gh44328globalFPPFZv, align 2 +__gshared FP* globalDataPointer = &globalFP; + +// CHECK: define void @_D22funcptr_harvard_gh44323fooFPFZvDQeZv({{.*}} addrspace(1){{\*?}} %fp_arg, { {{.*}} addrspace(1){{\*?}} } %dg_arg) addrspace(1) +void foo(FP fp, DG dg) +{ + // CHECK: call addrspace(1) void %1() + fp(); + // CHECK: call addrspace(1) void %.funcptr + dg(); + // CHECK-NEXT: ret void +} + +void bar() +{ + foo(() {}, delegate() {}); + + FP fp = &bar; + DG dg; + dg.funcptr = &bar; + foo(fp, dg); + + dg.funcptr = *globalDataPointer; + foo(globalFP, dg); +} diff --git a/tests/compilable/funcptr_harvard_gh4432.d b/tests/compilable/funcptr_harvard_gh4432.d deleted file mode 100644 index 74d6b9f2c62..00000000000 --- a/tests/compilable/funcptr_harvard_gh4432.d +++ /dev/null @@ -1,24 +0,0 @@ -// 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); -} From ab137601df45bb65580fc5ad25b4c1f469f78f32 Mon Sep 17 00:00:00 2001 From: Martin Kinkelin <mkinkelin@symmetryinvestments.com> Date: Sat, 5 Aug 2023 16:10:16 +0200 Subject: [PATCH 4/4] [add changelog entry] --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index de9002914d1..5a9809c9d74 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,7 @@ - Supports LLVM 11.0 - 15.0. #### Bug fixes +- Fix function pointers/delegates on Harvard architectures (e.g., AVR). (#4432, #4465) # LDC 1.33.0 (2023-07-23)