CodeQL / Analyze (actions) (push) Canceled after 0s
CodeQL / Analyze (python) (push) Canceled after 0s
pre-commit / pre-commit (push) Canceled after 0s
Multi-Arch CI / setup (push) Canceled after 0s
Publish build_manylinux_x86_64 images / publish_build_manylinux_x86_64 (push) Canceled after 0s
Setup (Multi-Arch) / setup (push) Canceled after 0s
Multi-Arch CI / Linux::${{ fromJSON(needs.setup.outputs.linux_build_config || '{}').build_variant_label || 'skip' }} (push) Canceled after 0s
Publish TheRock Docker image / build-and-push-image (push) Canceled after 0s
Publish no_rocm_image_ubi10 image / publish_no_rocm_image_ubi10 (push) Canceled after 0s
Multi-Arch CI / Windows::${{ fromJSON(needs.setup.outputs.windows_build_config || '{}').build_variant_label || 'skip' }} (push) Canceled after 0s
Publish TheRock Docker image / build-and-push-image (push) Canceled after 0s
Multi-Arch CI / Manifest Diff (push) Canceled after 0s
TheRock Manifest Diff Report / Generate Manifest Diff Report (push) Canceled after 0s
Multi-Arch CI / CI Summary (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04 images / publish_no_rocm_image_ubuntu24_04 (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04_ocl_rt images / publish_no_rocm_image_ubuntu24_04_ocl_rt (push) Canceled after 0s
Publish TheRock Docker image / build-and-push-image (push) Canceled after 0s
Publish TheRock Docker image / build-and-push-image (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04 images / publish_no_rocm_image_ubuntu24_04_rocgdb (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04_rocgdb images / publish_no_rocm_image_ubuntu24_04_rocgdb (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04 images / publish_no_rocm_image_ubuntu24_04_ocl_rt (push) Canceled after 0s
Publish TheRock Docker image / build-and-push-image (push) Canceled after 0s
Unit Tests / Unit Tests :: ubuntu-24.04 (push) Canceled after 0s
Unit Tests / Unit Tests :: windows-2022 (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04 images / publish_no_rocm_image_ubuntu24_04_media (push) Canceled after 0s
Unit Tests / Unit Tests Summary (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04 images / publish_no_rocm_image_ubuntu24_04_openmpi (push) Canceled after 0s
140 lines
5.2 KiB
C++
140 lines
5.2 KiB
C++
//===-- ObjCARC.cpp -------------------------------------------------------===//
|
|
//
|
|
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
|
// See https://llvm.org/LICENSE.txt for license information.
|
|
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
|
//
|
|
//===----------------------------------------------------------------------===//
|
|
//
|
|
// This file implements common infrastructure for libLLVMObjCARCOpts.a, which
|
|
// implements several scalar transformations over the LLVM intermediate
|
|
// representation, including the C bindings for that library.
|
|
//
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
#include "ObjCARC.h"
|
|
#include "llvm/Analysis/ObjCARCUtil.h"
|
|
#include "llvm/IR/IRBuilder.h"
|
|
#include "llvm/IR/Instructions.h"
|
|
#include "llvm/Transforms/Utils/BasicBlockUtils.h"
|
|
|
|
using namespace llvm;
|
|
using namespace llvm::objcarc;
|
|
|
|
CallInst *objcarc::createCallInstWithColors(
|
|
FunctionCallee Func, ArrayRef<Value *> Args, const Twine &NameStr,
|
|
BasicBlock::iterator InsertBefore,
|
|
const DenseMap<BasicBlock *, ColorVector> &BlockColors) {
|
|
FunctionType *FTy = Func.getFunctionType();
|
|
Value *Callee = Func.getCallee();
|
|
SmallVector<OperandBundleDef, 1> OpBundles;
|
|
|
|
if (!BlockColors.empty()) {
|
|
const ColorVector &CV = BlockColors.find(InsertBefore->getParent())->second;
|
|
assert(CV.size() == 1 && "non-unique color for block!");
|
|
BasicBlock::iterator EHPad = CV.front()->getFirstNonPHIIt();
|
|
if (EHPad->isEHPad())
|
|
OpBundles.emplace_back("funclet", &*EHPad);
|
|
}
|
|
|
|
return CallInst::Create(FTy, Callee, Args, OpBundles, NameStr, InsertBefore);
|
|
}
|
|
|
|
std::pair<bool, bool>
|
|
BundledRetainClaimRVs::insertAfterInvokes(Function &F, DominatorTree *DT) {
|
|
bool Changed = false, CFGChanged = false;
|
|
|
|
for (BasicBlock &BB : F) {
|
|
auto *I = dyn_cast<InvokeInst>(BB.getTerminator());
|
|
|
|
if (!I)
|
|
continue;
|
|
|
|
if (!objcarc::hasAttachedCallOpBundle(I))
|
|
continue;
|
|
|
|
BasicBlock *DestBB = I->getNormalDest();
|
|
|
|
if (!DestBB->getSinglePredecessor()) {
|
|
assert(I->getSuccessor(0) == DestBB &&
|
|
"the normal dest is expected to be the first successor");
|
|
DestBB = SplitCriticalEdge(I, 0, CriticalEdgeSplittingOptions(DT));
|
|
CFGChanged = true;
|
|
}
|
|
|
|
// We don't have to call insertRVCallWithColors since DestBB is the normal
|
|
// destination of the invoke.
|
|
insertRVCall(DestBB->getFirstInsertionPt(), I);
|
|
Changed = true;
|
|
}
|
|
|
|
return std::make_pair(Changed, CFGChanged);
|
|
}
|
|
|
|
CallInst *BundledRetainClaimRVs::insertRVCall(BasicBlock::iterator InsertPt,
|
|
CallBase *AnnotatedCall) {
|
|
DenseMap<BasicBlock *, ColorVector> BlockColors;
|
|
return insertRVCallWithColors(InsertPt, AnnotatedCall, BlockColors);
|
|
}
|
|
|
|
CallInst *BundledRetainClaimRVs::insertRVCallWithColors(
|
|
BasicBlock::iterator InsertPt, CallBase *AnnotatedCall,
|
|
const DenseMap<BasicBlock *, ColorVector> &BlockColors) {
|
|
IRBuilder<> Builder(InsertPt->getParent(), InsertPt);
|
|
Function *Func = *objcarc::getAttachedARCFunction(AnnotatedCall);
|
|
assert(Func && "operand isn't a Function");
|
|
Type *ParamTy = Func->getArg(0)->getType();
|
|
Value *CallArg = Builder.CreateBitCast(AnnotatedCall, ParamTy);
|
|
auto *Call =
|
|
createCallInstWithColors(Func, CallArg, "", InsertPt, BlockColors);
|
|
RVCalls[Call] = AnnotatedCall;
|
|
return Call;
|
|
}
|
|
|
|
BundledRetainClaimRVs::~BundledRetainClaimRVs() {
|
|
for (auto P : RVCalls) {
|
|
if (ContractPass) {
|
|
CallBase *CB = P.second;
|
|
// At this point, we know that the annotated calls can't be tail calls
|
|
// as they are followed by marker instructions and retainRV/claimRV
|
|
// calls. Mark them as notail so that the backend knows these calls
|
|
// can't be tail calls.
|
|
if (auto *CI = dyn_cast<CallInst>(CB))
|
|
CI->setTailCallKind(CallInst::TCK_NoTail);
|
|
|
|
// We can also do one final optimization: modify the bundle in the
|
|
// annotated call, to change the bundle operand from
|
|
// objc_retainAutoreleasedReturnValue
|
|
// to:
|
|
// objc_claimAutoreleasedReturnValue
|
|
// allowing the marker to be omitted from the bundle expansion later.
|
|
//
|
|
// Note that, confusingly, ClaimRV is semantically equivalent to RetainRV,
|
|
// and only differs in that it doesn't require the marker.
|
|
// The bundle provides the guarantee that we're emitting the ClaimRV call
|
|
// adjacent to the original call, and providing that guarantee is the
|
|
// only difference between ClaimRV and RetainRV.
|
|
//
|
|
// UnsafeClaimRV has a different RC contract entirely.
|
|
|
|
// Find the clang.arc.attachedcall bundle, and rewrite its operand.
|
|
if (UseClaimRV) {
|
|
for (auto OBI : CB->bundle_op_infos()) {
|
|
auto OBU = CB->operandBundleFromBundleOpInfo(OBI);
|
|
if (OBU.getTagID() == LLVMContext::OB_clang_arc_attachedcall &&
|
|
OBU.Inputs[0] == EP.get(ARCRuntimeEntryPointKind::RetainRV)) {
|
|
CB->setOperand(OBI.Begin,
|
|
EP.get(ARCRuntimeEntryPointKind::ClaimRV));
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
// Erase the RV call we emitted earlier: it's already in the bundle.
|
|
EraseInstruction(P.first);
|
|
}
|
|
|
|
RVCalls.clear();
|
|
}
|