mhjacobson created this revision.
mhjacobson added reviewers: rjmccall, ddunbar.
Herald added subscribers: pengfei, Jim, dylanmckay.
mhjacobson requested review of this revision.
Herald added a project: clang.
Herald added a subscriber: cfe-commits.

On targets with non-default program address space (e.g., Harvard 
architectures), clang crashes (example backtrace below) 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.

Backtrace (when emitting method metadata):

  Assertion failed: (CastInst::castIsValid(Instruction::BitCast, C, DstTy) && 
"Invalid constantexpr bitcast!"), function getBitCast, file 
/Users/matt/src/llvm/llvm/lib/IR/Constants.cpp, line 2224.
  
  ...
  
  7  libsystem_c.dylib        0x00007fff6ec09ac6 err + 0
  8  clang-14                 0x0000000101800518 
llvm::ConstantExpr::getBitCast(llvm::Constant*, llvm::Type*, bool) + 120
  9  clang-14                 0x000000010394ca70 
clang::CodeGen::ConstantAggregateBuilderBase::addBitCast(llvm::Constant*, 
llvm::Type*) + 48
  10 clang-14                 0x0000000103999ac2 (anonymous 
namespace)::CGObjCNonFragileABIMac::emitMethodConstant(clang::CodeGen::ConstantArrayBuilder&,
 clang::ObjCMethodDecl const*, bool) + 402
  11 clang-14                 0x0000000103999102 (anonymous 
namespace)::CGObjCNonFragileABIMac::emitMethodList(llvm::Twine, (anonymous 
namespace)::(anonymous namespace)::MethodListType, 
llvm::ArrayRef<clang::ObjCMethodDecl const*>) + 1074
  12 clang-14                 0x000000010399a4c0 (anonymous 
namespace)::CGObjCNonFragileABIMac::BuildClassRoTInitializer(unsigned int, 
unsigned int, unsigned int, clang::ObjCImplementationDecl const*) + 1376
  13 clang-14                 0x0000000103990b9b (anonymous 
namespace)::CGObjCNonFragileABIMac::GenerateClass(clang::ObjCImplementationDecl 
const*) + 1995
  14 clang-14                 0x0000000103bb87d1 
clang::CodeGen::CodeGenModule::EmitTopLevelDecl(clang::Decl*) + 2065
  15 clang-14                 0x0000000103db5bf2 (anonymous 
namespace)::CodeGeneratorImpl::HandleTopLevelDecl(clang::DeclGroupRef) + 146
  16 clang-14                 0x0000000103b61014 
clang::BackendConsumer::HandleTopLevelDecl(clang::DeclGroupRef) + 228
  17 clang-14                 0x00000001070d7425 clang::ParseAST(clang::Sema&, 
bool, bool) + 533


Repository:
  rG LLVM Github Monorepo

https://reviews.llvm.org/D112113

Files:
  clang/lib/CodeGen/CGObjCMac.cpp
  clang/lib/CodeGen/CGObjCRuntime.cpp
  clang/test/CodeGen/avr/objc-method.m

Index: clang/test/CodeGen/avr/objc-method.m
===================================================================
--- /dev/null
+++ 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))
+@interface Foo
+
+- (id)foo;
+- (id)bar;
+
+@end
+
+@implementation Foo
+
+- (id)foo {
+  return self;
+}
+
+- (id)bar {
+  return [self foo];
+}
+
+@end
Index: clang/lib/CodeGen/CGObjCRuntime.cpp
===================================================================
--- clang/lib/CodeGen/CGObjCRuntime.cpp
+++ clang/lib/CodeGen/CGObjCRuntime.cpp
@@ -361,13 +361,15 @@
 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);
@@ -381,7 +383,7 @@
 
   // 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);
 }
 
Index: clang/lib/CodeGen/CGObjCMac.cpp
===================================================================
--- clang/lib/CodeGen/CGObjCMac.cpp
+++ clang/lib/CodeGen/CGObjCMac.cpp
@@ -174,6 +174,7 @@
 public:
   llvm::IntegerType *ShortTy, *IntTy, *LongTy;
   llvm::PointerType *Int8PtrTy, *Int8PtrPtrTy;
+  llvm::PointerType *Int8PtrProgramASTy;
   llvm::Type *IvarOffsetVarTy;
 
   /// ObjectPtrTy - LLVM type for object handles (typeof(id))
@@ -5792,11 +5793,13 @@
 {
   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,
@@ -5865,7 +5868,7 @@
   //   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");
@@ -6804,11 +6807,11 @@
 
   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);
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to