[clang] c8b2f3f - [ObjC] type method metadata `_imp`, messenger routine at callsite with program address space

Matt Jacobson via cfe-commits cfe-commits at lists.llvm.org
Thu Aug 4 02:42:36 PDT 2022


Author: Matt Jacobson
Date: 2022-08-04T05:40:32-04:00
New Revision: c8b2f3f51bd923afbf9d3ebd0823bce895629630

URL: https://github.com/llvm/llvm-project/commit/c8b2f3f51bd923afbf9d3ebd0823bce895629630
DIFF: https://github.com/llvm/llvm-project/commit/c8b2f3f51bd923afbf9d3ebd0823bce895629630.diff

LOG: [ObjC] type method metadata `_imp`, messenger routine at callsite with program address space

On targets with non-default program address space (e.g., Harvard
architectures), clang crashes when emitting Objective-C method metadata,
because the address of the method IMP cannot be bitcast to i8*. It similarly
crashes at messenger callsite with a failed bitcast.

Define the _imp field instead as i8 addrspace(1)* (or whatever the target's
program address space is). And in getMessageSendInfo(), create signatureType by
specifying the program address space.

Add a regression test using the AVR target. Test failed previously and passes
now. Checked codegen of the test for x86_64-apple-darwin19.6.0 and saw no
difference, as expected.

Reviewed By: rjmccall, dylanmckay

Differential Revision: https://reviews.llvm.org/D112113

Added: 
    clang/test/CodeGen/avr/objc-method.m

Modified: 
    clang/lib/CodeGen/CGObjCMac.cpp
    clang/lib/CodeGen/CGObjCRuntime.cpp

Removed: 
    


################################################################################
diff  --git a/clang/lib/CodeGen/CGObjCMac.cpp b/clang/lib/CodeGen/CGObjCMac.cpp
index 46e65eb1ed43d..2d704cec05761 100644
--- a/clang/lib/CodeGen/CGObjCMac.cpp
+++ b/clang/lib/CodeGen/CGObjCMac.cpp
@@ -174,6 +174,7 @@ class ObjCCommonTypesHelper {
 public:
   llvm::IntegerType *ShortTy, *IntTy, *LongTy;
   llvm::PointerType *Int8PtrTy, *Int8PtrPtrTy;
+  llvm::PointerType *Int8PtrProgramASTy;
   llvm::Type *IvarOffsetVarTy;
 
   /// ObjectPtrTy - LLVM type for object handles (typeof(id))
@@ -5739,11 +5740,13 @@ ObjCCommonTypesHelper::ObjCCommonTypesHelper(CodeGen::CodeGenModule &cgm)
 {
   CodeGen::CodeGenTypes &Types = CGM.getTypes();
   ASTContext &Ctx = CGM.getContext();
+  unsigned ProgramAS = CGM.getDataLayout().getProgramAddressSpace();
 
   ShortTy = cast<llvm::IntegerType>(Types.ConvertType(Ctx.ShortTy));
   IntTy = CGM.IntTy;
   LongTy = cast<llvm::IntegerType>(Types.ConvertType(Ctx.LongTy));
   Int8PtrTy = CGM.Int8PtrTy;
+  Int8PtrProgramASTy = llvm::PointerType::get(CGM.Int8Ty, ProgramAS);
   Int8PtrPtrTy = CGM.Int8PtrPtrTy;
 
   // arm64 targets use "int" ivar offset variables. All others,
@@ -5812,7 +5815,7 @@ ObjCCommonTypesHelper::ObjCCommonTypesHelper(CodeGen::CodeGenModule &cgm)
   //   char *_imp;
   // }
   MethodTy = llvm::StructType::create("struct._objc_method", SelectorPtrTy,
-                                      Int8PtrTy, Int8PtrTy);
+                                      Int8PtrTy, Int8PtrProgramASTy);
 
   // struct _objc_cache *
   CacheTy = llvm::StructType::create(VMContext, "struct._objc_cache");
@@ -6771,11 +6774,11 @@ void CGObjCNonFragileABIMac::emitMethodConstant(ConstantArrayBuilder &builder,
 
   if (forProtocol) {
     // Protocol methods have no implementation. So, this entry is always NULL.
-    method.addNullPointer(ObjCTypes.Int8PtrTy);
+    method.addNullPointer(ObjCTypes.Int8PtrProgramASTy);
   } else {
     llvm::Function *fn = GetMethodDefinition(MD);
     assert(fn && "no definition for method?");
-    method.addBitCast(fn, ObjCTypes.Int8PtrTy);
+    method.addBitCast(fn, ObjCTypes.Int8PtrProgramASTy);
   }
 
   method.finishAndAddTo(builder);

diff  --git a/clang/lib/CodeGen/CGObjCRuntime.cpp b/clang/lib/CodeGen/CGObjCRuntime.cpp
index 550fd3d70bdcc..7780a61aa648a 100644
--- a/clang/lib/CodeGen/CGObjCRuntime.cpp
+++ b/clang/lib/CodeGen/CGObjCRuntime.cpp
@@ -360,13 +360,15 @@ CGObjCRuntime::MessageSendInfo
 CGObjCRuntime::getMessageSendInfo(const ObjCMethodDecl *method,
                                   QualType resultType,
                                   CallArgList &callArgs) {
+  unsigned ProgramAS = CGM.getDataLayout().getProgramAddressSpace();
+
   // If there's a method, use information from that.
   if (method) {
     const CGFunctionInfo &signature =
       CGM.getTypes().arrangeObjCMessageSendSignature(method, callArgs[0].Ty);
 
     llvm::PointerType *signatureType =
-      CGM.getTypes().GetFunctionType(signature)->getPointerTo();
+      CGM.getTypes().GetFunctionType(signature)->getPointerTo(ProgramAS);
 
     const CGFunctionInfo &signatureForCall =
       CGM.getTypes().arrangeCall(signature, callArgs);
@@ -380,7 +382,7 @@ CGObjCRuntime::getMessageSendInfo(const ObjCMethodDecl *method,
 
   // Derive the signature to call from that.
   llvm::PointerType *signatureType =
-    CGM.getTypes().GetFunctionType(argsInfo)->getPointerTo();
+    CGM.getTypes().GetFunctionType(argsInfo)->getPointerTo(ProgramAS);
   return MessageSendInfo(argsInfo, signatureType);
 }
 

diff  --git a/clang/test/CodeGen/avr/objc-method.m b/clang/test/CodeGen/avr/objc-method.m
new file mode 100644
index 0000000000000..aeafb8e63466e
--- /dev/null
+++ b/clang/test/CodeGen/avr/objc-method.m
@@ -0,0 +1,21 @@
+// RUN: %clang_cc1 -triple avr -emit-llvm -fobjc-runtime=macosx %s -o /dev/null
+
+__attribute__((objc_root_class))
+ at interface Foo
+
+- (id)foo;
+- (id)bar;
+
+ at end
+
+ at implementation Foo
+
+- (id)foo {
+  return self;
+}
+
+- (id)bar {
+  return [self foo];
+}
+
+ at end


        


More information about the cfe-commits mailing list