llvmbot wrote:

<!--LLVM PR SUMMARY COMMENT-->

@llvm/pr-subscribers-clangir

Author: Justin Riddell (Arghnews)

<details>
<summary>Changes</summary>

Add upstream support for handling implicit FunctionToPointerDecay casts in 
ClangIR, for task #<!-- -->153657, migrate code from clangir repo

Passes `check-clang` test target, have run `git-clang-format` from repo as 
instructed

Appreciate any feedback

Notes:
- Omitted `clang::CIRGen::TBAAAccessInfo` from `emitPointerWithAlignment` as it 
looks like a large task to include that and not necessary
- Omitted `KnownNonNull_t` param too, although this is much smaller but would 
have to alter all sites where it's currently used in clangir, in llvm
- Copied `emitFunctionDeclLValue` from clangir
- Have just used the simple example test given in the task + the existing 
`function-to-pointer-decay.c` test, maybe the CHECKs can be improved or more 
test cases are needed (if so please specify what, am a CIR noob)
- Left `llvm_unreachable("NYI");` as those rather than a longer string, other 
instances in file have the same

---
Full diff: https://github.com/llvm/llvm-project/pull/154060.diff


3 Files Affected:

- (modified) clang/lib/CIR/CodeGen/CIRGenExpr.cpp (+86-14) 
- (modified) clang/lib/CIR/CodeGen/CIRGenExprScalar.cpp (+2) 
- (added) clang/test/CIR/CodeGen/function-to-pointer-decay.c (+25) 


``````````diff
diff --git a/clang/lib/CIR/CodeGen/CIRGenExpr.cpp 
b/clang/lib/CIR/CodeGen/CIRGenExpr.cpp
index 8bcca6f5d1803..e8a25b6f9ecf4 100644
--- a/clang/lib/CIR/CodeGen/CIRGenExpr.cpp
+++ b/clang/lib/CIR/CodeGen/CIRGenExpr.cpp
@@ -73,21 +73,59 @@ Address CIRGenFunction::emitPointerWithAlignment(const Expr 
*expr,
 
   // Casts:
   if (auto const *ce = dyn_cast<CastExpr>(expr)) {
-    if (isa<ExplicitCastExpr>(ce)) {
-      cgm.errorNYI(expr->getSourceRange(),
-                   "emitPointerWithAlignment: explicit cast");
-      return Address::invalid();
-    }
+    if (const auto *ece = dyn_cast<ExplicitCastExpr>(ce))
+      cgm.emitExplicitCastExprType(ece);
 
     switch (ce->getCastKind()) {
     // Non-converting casts (but not C's implicit conversion from void*).
     case CK_BitCast:
     case CK_NoOp:
     case CK_AddressSpaceConversion: {
-      cgm.errorNYI(expr->getSourceRange(),
-                   "emitPointerWithAlignment: noop cast");
-      return Address::invalid();
-    } break;
+      if (const auto *ptrTy =
+              ce->getSubExpr()->getType()->getAs<PointerType>()) {
+        if (ptrTy->getPointeeType()->isVoidType())
+          break;
+
+        LValueBaseInfo innerBaseInfo;
+        Address addr =
+            emitPointerWithAlignment(ce->getSubExpr(), &innerBaseInfo);
+        if (baseInfo)
+          *baseInfo = innerBaseInfo;
+
+        if (isa<ExplicitCastExpr>(ce)) {
+          LValueBaseInfo targetTypeBaseInfo;
+
+          const QualType pointeeType = expr->getType()->getPointeeType();
+          const CharUnits align =
+              cgm.getNaturalTypeAlignment(pointeeType, &targetTypeBaseInfo);
+
+          // If the source l-value is opaque, honor the alignment of the
+          // casted-to type.
+          if (innerBaseInfo.getAlignmentSource() != AlignmentSource::Decl) {
+            if (baseInfo)
+              baseInfo->mergeForCast(targetTypeBaseInfo);
+            addr = Address(addr.getPointer(), addr.getElementType(), align);
+          }
+        }
+
+        if (sanOpts.has(SanitizerKind::CFIUnrelatedCast) &&
+            ce->getCastKind() == CK_BitCast) {
+          if (expr->getType()->getAs<PointerType>())
+            llvm_unreachable("NYI");
+        }
+
+        const auto eltTy = 
convertTypeForMem(expr->getType()->getPointeeType());
+        addr = 
getBuilder().createElementBitCast(getLoc(expr->getSourceRange()),
+                                                 addr, eltTy);
+        if (ce->getCastKind() == CK_AddressSpaceConversion) {
+          assert(!cir::MissingFeatures::addressSpace());
+          llvm_unreachable("NYI");
+        }
+
+        return addr;
+      }
+      break;
+    }
 
     // Array-to-pointer decay. TODO(cir): BaseInfo and TBAAInfo.
     case CK_ArrayToPointerDecay: {
@@ -553,6 +591,35 @@ RValue CIRGenFunction::emitLoadOfLValue(LValue lv, 
SourceLocation loc) {
   return RValue::get(nullptr);
 }
 
+static cir::FuncOp emitFunctionDeclPointer(CIRGenModule &cgm, GlobalDecl gd) {
+  assert(!cir::MissingFeatures::weakRefReference());
+  return cgm.getAddrOfFunction(gd);
+}
+
+static LValue emitFunctionDeclLValue(CIRGenFunction &CGF, const Expr *E,
+                                     GlobalDecl GD) {
+  const FunctionDecl *FD = cast<FunctionDecl>(GD.getDecl());
+  auto funcOp = emitFunctionDeclPointer(CGF.cgm, GD);
+  auto loc = CGF.getLoc(E->getSourceRange());
+  CharUnits align = CGF.getContext().getDeclAlign(FD);
+
+  mlir::Type fnTy = funcOp.getFunctionType();
+  auto ptrTy = cir::PointerType::get(fnTy);
+  mlir::Value addr = CGF.getBuilder().create<cir::GetGlobalOp>(
+      loc, ptrTy, funcOp.getSymName());
+
+  if (funcOp.getFunctionType() != CGF.convertType(FD->getType())) {
+    fnTy = CGF.convertType(FD->getType());
+    ptrTy = cir::PointerType::get(fnTy);
+
+    addr = CGF.getBuilder().create<cir::CastOp>(addr.getLoc(), ptrTy,
+                                                cir::CastKind::bitcast, addr);
+  }
+
+  return CGF.makeAddrLValue(Address(addr, fnTy, align), E->getType(),
+                            AlignmentSource::Decl);
+}
+
 LValue CIRGenFunction::emitDeclRefLValue(const DeclRefExpr *e) {
   const NamedDecl *nd = e->getDecl();
   QualType ty = e->getType();
@@ -609,6 +676,16 @@ LValue CIRGenFunction::emitDeclRefLValue(const DeclRefExpr 
*e) {
     return emitLValue(bd->getBinding());
   }
 
+  if (const auto *FD = dyn_cast<FunctionDecl>(nd)) {
+    LValue LV = emitFunctionDeclLValue(*this, e, FD);
+
+    // Emit debuginfo for the function declaration if the target wants to.
+    if (getContext().getTargetInfo().allowDebugInfoForExternalRef())
+      assert(!cir::MissingFeatures::generateDebugInfo());
+
+    return LV;
+  }
+
   cgm.errorNYI(e->getSourceRange(), "emitDeclRefLValue: unhandled decl type");
   return LValue();
 }
@@ -1386,11 +1463,6 @@ RValue CIRGenFunction::emitAnyExpr(const Expr *e, 
AggValueSlot aggSlot) {
   llvm_unreachable("bad evaluation kind");
 }
 
-static cir::FuncOp emitFunctionDeclPointer(CIRGenModule &cgm, GlobalDecl gd) {
-  assert(!cir::MissingFeatures::weakRefReference());
-  return cgm.getAddrOfFunction(gd);
-}
-
 // Detect the unusual situation where an inline version is shadowed by a
 // non-inline version. In that case we should pick the external one
 // everywhere. That's GCC behavior too.
diff --git a/clang/lib/CIR/CodeGen/CIRGenExprScalar.cpp 
b/clang/lib/CIR/CodeGen/CIRGenExprScalar.cpp
index 8649bab91ce8e..bdda362818784 100644
--- a/clang/lib/CIR/CodeGen/CIRGenExprScalar.cpp
+++ b/clang/lib/CIR/CodeGen/CIRGenExprScalar.cpp
@@ -1879,6 +1879,8 @@ mlir::Value ScalarExprEmitter::VisitCastExpr(CastExpr 
*ce) {
         cgf.getLoc(subExpr->getSourceRange()), cgf.convertType(destTy),
         Visit(subExpr));
   }
+  case CK_FunctionToPointerDecay:
+    return cgf.emitLValue(subExpr).getPointer();
 
   default:
     cgf.getCIRGenModule().errorNYI(subExpr->getSourceRange(),
diff --git a/clang/test/CIR/CodeGen/function-to-pointer-decay.c 
b/clang/test/CIR/CodeGen/function-to-pointer-decay.c
new file mode 100644
index 0000000000000..96c4294ef2466
--- /dev/null
+++ b/clang/test/CIR/CodeGen/function-to-pointer-decay.c
@@ -0,0 +1,25 @@
+// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -fclangir -emit-cir %s -o 
- | FileCheck %s
+
+int f1();
+void f2() {
+  int (*t)() = f1;
+}
+
+// CHECK: cir.func {{.*}}@f2()
+// CHECK: %[[SLOT:.*]] = cir.alloca
+// CHECK: %[[F1:.+]] = cir.get_global @f1
+// CHECK: cir.store {{.*}} %[[F1]], %[[SLOT]] : {{.*}}
+
+// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -fclangir -emit-cir %s -o 
- | FileCheck %s
+
+void f(void);
+
+void test_call_lvalue_cast() {
+  (*(void (*)(int))f)(42);
+}
+
+// CHECK: cir.func {{.*}}@test_call_lvalue_cast()
+// CHECK: [[F:%.+]] = cir.get_global @f
+// CHECK: [[CASTED:%.+]] = cir.cast(bitcast, [[F]]
+// CHECK: [[CONST:%.+]] = cir.const #cir.int<42>
+// CHECK: cir.call [[CASTED]]([[CONST]])

``````````

</details>


https://github.com/llvm/llvm-project/pull/154060
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to