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