Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions clang/include/clang/AST/DeclObjC.h
Original file line number Diff line number Diff line change
Expand Up @@ -482,6 +482,12 @@ class ObjCMethodDecl : public NamedDecl, public DeclContext {
/// True if the method is tagged as objc_direct
bool isDirectMethod() const;

/// Check if this direct method can move nil-check to thunk.
/// Variadic functions cannot use thunks (musttail incompatible with va_arg)
bool canHaveNilCheckThunk() const {
return isDirectMethod() && !isVariadic();
}

/// True if the method has a parameter that's destroyed in the callee.
bool hasParamDestroyedInCallee() const;

Expand Down
2 changes: 2 additions & 0 deletions clang/include/clang/Basic/CodeGenOptions.def
Original file line number Diff line number Diff line change
Expand Up @@ -210,6 +210,8 @@ ENUM_CODEGENOPT(ObjCDispatchMethod, ObjCDispatchMethodKind, 2, Legacy, Benign)
/// Replace certain message sends with calls to ObjC runtime entrypoints
CODEGENOPT(ObjCConvertMessagesToRuntimeCalls , 1, 1, Benign)
CODEGENOPT(ObjCAvoidHeapifyLocalBlocks, 1, 0, Benign)
/// Expose objc_direct method symbols publicly and optimize nil checks.
CODEGENOPT(ObjCExposeDirectMethods, 1, 0, Benign)


// The optimization options affect frontend options, which in turn do affect the AST.
Expand Down
5 changes: 5 additions & 0 deletions clang/include/clang/Options/Options.td
Original file line number Diff line number Diff line change
Expand Up @@ -3775,6 +3775,11 @@ defm objc_avoid_heapify_local_blocks : BoolFOption<"objc-avoid-heapify-local-blo
PosFlag<SetTrue, [], [ClangOption], "Try">,
NegFlag<SetFalse, [], [ClangOption], "Don't try">,
BothFlags<[], [CC1Option], " to avoid heapifying local blocks">>;
defm objc_expose_direct_methods : BoolFOption<"objc-expose-direct-methods",
CodeGenOpts<"ObjCExposeDirectMethods">, DefaultFalse,
PosFlag<SetTrue, [], [ClangOption, CC1Option],
"Expose direct method symbols and move nil checks to caller-side thunks">,
NegFlag<SetFalse>>;
defm disable_block_signature_string : BoolFOption<"disable-block-signature-string",
CodeGenOpts<"DisableBlockSignatureString">, DefaultFalse,
PosFlag<SetTrue, [], [ClangOption], "Disable">,
Expand Down
4 changes: 3 additions & 1 deletion clang/lib/CodeGen/CGDecl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2757,7 +2757,9 @@ void CodeGenFunction::EmitParmDecl(const VarDecl &D, ParamValue Arg,
llvm::Value *ArgVal = (DoStore ? Arg.getDirectValue() : nullptr);

LValue lv = MakeAddrLValue(DeclPtr, Ty);
if (IsScalar) {
// If this is a thunk, don't bother with ARC lifetime management.
// The true implementation will take care of that.
if (IsScalar && !CurFuncIsThunk) {
Qualifiers qs = Ty.getQualifiers();
if (Qualifiers::ObjCLifetime lt = qs.getObjCLifetime()) {
// We honor __attribute__((ns_consumed)) for types with lifetime.
Expand Down
17 changes: 12 additions & 5 deletions clang/lib/CodeGen/CGObjC.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -761,7 +761,18 @@ void CodeGenFunction::StartObjCMethod(const ObjCMethodDecl *OMD,

const CGFunctionInfo &FI = CGM.getTypes().arrangeObjCMethodDeclaration(OMD);
if (OMD->isDirectMethod()) {
Fn->setVisibility(llvm::Function::HiddenVisibility);
Fn->setVisibility(llvm::GlobalValue::HiddenVisibility);
if (CGM.shouldExposeSymbol(OMD)) {
// Find the decl that may have visibility set (property or method)
const NamedDecl *Decl = OMD;
if (const auto *PD = OMD->findPropertyDecl()) {
Decl = PD;
}
// and respect source level visibility setting
if (auto V = Decl->getExplicitVisibility(NamedDecl::VisibilityForValue)) {
Fn->setVisibility(CGM.GetLLVMVisibility(*V));
}
}
CGM.SetLLVMFunctionAttributes(OMD, FI, Fn, /*IsThunk=*/false);
CGM.SetLLVMFunctionAttributesForDefinition(OMD, Fn);
} else {
Expand All @@ -781,10 +792,6 @@ void CodeGenFunction::StartObjCMethod(const ObjCMethodDecl *OMD,
OMD->getLocation(), StartLoc);

if (OMD->isDirectMethod()) {
// This function is a direct call, it has to implement a nil check
// on entry.
//
// TODO: possibly have several entry points to elide the check
CGM.getObjCRuntime().GenerateDirectMethodPrologue(*this, Fn, OMD, CD);
}

Expand Down
9 changes: 9 additions & 0 deletions clang/lib/CodeGen/CGObjCGNU.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -600,6 +600,9 @@ class CGObjCGNU : public CGObjCRuntime {
// Map to unify direct method definitions.
llvm::DenseMap<const ObjCMethodDecl *, llvm::Function *>
DirectMethodDefinitions;
void GenerateDirectMethodsPreconditionCheck(
CodeGenFunction &CGF, llvm::Function *Fn, const ObjCMethodDecl *OMD,
const ObjCContainerDecl *CD) override;
void GenerateDirectMethodPrologue(CodeGenFunction &CGF, llvm::Function *Fn,
const ObjCMethodDecl *OMD,
const ObjCContainerDecl *CD) override;
Expand Down Expand Up @@ -4196,6 +4199,12 @@ llvm::Function *CGObjCGNU::GenerateMethod(const ObjCMethodDecl *OMD,
return Fn;
}

void CGObjCGNU::GenerateDirectMethodsPreconditionCheck(
CodeGenFunction &CGF, llvm::Function *Fn, const ObjCMethodDecl *OMD,
const ObjCContainerDecl *CD) {
// GNU runtime doesn't support direct calls at this time
}

void CGObjCGNU::GenerateDirectMethodPrologue(CodeGenFunction &CGF,
llvm::Function *Fn,
const ObjCMethodDecl *OMD,
Expand Down
Loading
Loading