Files
swift-mirror/lib/LLVMPasses/LLVMSwiftRCIdentity.cpp
Mike Ash 46309d9794 [Runtime] Rename swift_unknown* functions to swift_unknownObject*.
These functions don't accept local variable heap memory, although the names make it sound like they work on anything. When you try, they mistakenly identify such things as ObjC objects, call through to the equivalent objc_* function, and crash confusingly. This adds Object to the name of each one to make it more clear what they accept.

rdar://problem/37285743
2018-08-15 17:48:23 -04:00

95 lines
2.6 KiB
C++

//===--- LLVMSwiftRCIdentity.cpp - LLVM RCIdentity Analysis for Swift -----===//
//
// This source file is part of the Swift.org open source project
//
// Copyright (c) 2014 - 2017 Apple Inc. and the Swift project authors
// Licensed under Apache License v2.0 with Runtime Library Exception
//
// See https://swift.org/LICENSE.txt for license information
// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
//
//===----------------------------------------------------------------------===//
#include "swift/LLVMPasses/Passes.h"
#include "LLVMARCOpts.h"
#include "llvm/IR/Module.h"
using namespace llvm;
using swift::SwiftRCIdentity;
// Register this pass...
char SwiftRCIdentity::ID = 0;
INITIALIZE_PASS(SwiftRCIdentity, "swift-rc-identity",
"Swift RC Identity Analysis", false, true)
bool SwiftRCIdentity::doInitialization(Module &M) {
return true;
}
llvm::Value *
SwiftRCIdentity::stripPointerCasts(llvm::Value *Val) {
return Val->stripPointerCasts();
}
llvm::Value *
SwiftRCIdentity::stripReferenceForwarding(llvm::Value *Val) {
auto Inst = dyn_cast<Instruction>(Val);
if (!Inst)
return Val;
auto Kind = classifyInstruction(*Inst);
switch(Kind) {
case RT_RetainN:
case RT_UnknownObjectRetainN:
case RT_BridgeRetainN:
case RT_ReleaseN:
case RT_UnknownObjectReleaseN:
case RT_BridgeReleaseN:
case RT_FixLifetime:
case RT_Retain:
case RT_UnknownObjectRetain:
case RT_Release:
case RT_UnknownObjectRelease:
case RT_Unknown:
case RT_AllocObject:
case RT_NoMemoryAccessed:
case RT_BridgeRelease:
case RT_BridgeRetain:
case RT_RetainUnowned:
case RT_CheckUnowned:
case RT_ObjCRelease:
case RT_EndBorrow:
break;
// ObjC forwards references.
case RT_ObjCRetain:
Val = cast<CallInst>(Inst)->getArgOperand(0);
break;
}
return Val;
}
llvm::Value *
SwiftRCIdentity::getSwiftRCIdentityRoot(llvm::Value *Val) {
// Only allow this method to go up a fixed number of levels to make sure
// we don't explode compile time.
llvm::Value *OldVal = Val;
unsigned levels = 0;
do {
llvm::Value *NewVal = Val;
// Try to strip off pointer casts and reference forwarding.
Val = stripPointerCasts(Val);
Val = stripReferenceForwarding(Val);
// Nothing was stripped off.
if (NewVal == Val)
break;
// Hit max number of levels.
if (++levels > MaxRecursionDepth)
return OldVal;
} while (true);
return Val;
}
llvm::ImmutablePass *swift::createSwiftRCIdentityPass() {
initializeSwiftRCIdentityPass(*PassRegistry::getPassRegistry());
return new SwiftRCIdentity();
}