LowerTypeTests: Thread summary and action from the API and command line into the pass.

Also move command line handling out of the pass constructor and into
a separate function.

Differential Revision: https://reviews.llvm.org/D28422

llvm-svn: 291323
This commit is contained in:
Peter Collingbourne 2017-01-07 01:17:24 +00:00
parent 12195f1f03
commit d79e49d807
3 changed files with 87 additions and 38 deletions

View File

@ -215,9 +215,20 @@ ModulePass *createMetaRenamerPass();
/// manager.
ModulePass *createBarrierNoopPass();
/// What to do with the summary when running the LowerTypeTests pass.
enum class LowerTypeTestsSummaryAction {
None, ///< Do nothing.
Import, ///< Import typeid resolutions from summary and globals.
Export, ///< Export typeid resolutions to summary and globals.
};
/// \brief This pass lowers type metadata and the llvm.type.test intrinsic to
/// bitsets.
ModulePass *createLowerTypeTestsPass();
/// \param Action What to do with the summary passed as Index.
/// \param Index The summary to use for importing or exporting, this can be null
/// when Action is None.
ModulePass *createLowerTypeTestsPass(LowerTypeTestsSummaryAction Action,
ModuleSummaryIndex *Index);
/// \brief This pass export CFI checks for use by external modules.
ModulePass *createCrossDSOCFIPass();

View File

@ -42,6 +42,8 @@
using namespace llvm;
using namespace lowertypetests;
using SummaryAction = LowerTypeTestsSummaryAction;
#define DEBUG_TYPE "lowertypetests"
STATISTIC(ByteArraySizeBits, "Byte array size in bits");
@ -55,9 +57,15 @@ static cl::opt<bool> AvoidReuse(
cl::desc("Try to avoid reuse of byte array addresses using aliases"),
cl::Hidden, cl::init(true));
static cl::opt<std::string> ClSummaryAction(
static cl::opt<SummaryAction> ClSummaryAction(
"lowertypetests-summary-action",
cl::desc("What to do with the summary when running this pass"), cl::Hidden);
cl::desc("What to do with the summary when running this pass"),
cl::values(clEnumValN(SummaryAction::None, "none", "Do nothing"),
clEnumValN(SummaryAction::Import, "import",
"Import typeid resolutions from summary and globals"),
clEnumValN(SummaryAction::Export, "export",
"Export typeid resolutions to summary and globals")),
cl::Hidden);
static cl::opt<std::string> ClReadSummary(
"lowertypetests-read-summary",
@ -226,8 +234,8 @@ public:
class LowerTypeTestsModule {
Module &M;
// This is for testing purposes only.
std::unique_ptr<ModuleSummaryIndex> OwnedSummary;
SummaryAction Action;
ModuleSummaryIndex *Summary;
bool LinkerSubsectionsViaSymbols;
Triple::ArchType Arch;
@ -319,21 +327,38 @@ class LowerTypeTestsModule {
void createJumpTable(Function *F, ArrayRef<GlobalTypeMember *> Functions);
public:
LowerTypeTestsModule(Module &M);
~LowerTypeTestsModule();
LowerTypeTestsModule(Module &M, SummaryAction Action,
ModuleSummaryIndex *Summary);
bool lower();
// Lower the module using the action and summary passed as command line
// arguments. For testing purposes only.
static bool runForTesting(Module &M);
};
struct LowerTypeTests : public ModulePass {
static char ID;
LowerTypeTests() : ModulePass(ID) {
bool UseCommandLine = false;
SummaryAction Action;
ModuleSummaryIndex *Summary;
LowerTypeTests() : ModulePass(ID), UseCommandLine(true) {
initializeLowerTypeTestsPass(*PassRegistry::getPassRegistry());
}
LowerTypeTests(SummaryAction Action, ModuleSummaryIndex *Summary)
: ModulePass(ID), Action(Action), Summary(Summary) {
initializeLowerTypeTestsPass(*PassRegistry::getPassRegistry());
}
bool runOnModule(Module &M) override {
if (skipModule(M))
return false;
return LowerTypeTestsModule(M).lower();
if (UseCommandLine)
return LowerTypeTestsModule::runForTesting(M);
return LowerTypeTestsModule(M, Action, Summary).lower();
}
};
@ -343,7 +368,10 @@ INITIALIZE_PASS(LowerTypeTests, "lowertypetests", "Lower type metadata", false,
false)
char LowerTypeTests::ID = 0;
ModulePass *llvm::createLowerTypeTestsPass() { return new LowerTypeTests; }
ModulePass *llvm::createLowerTypeTestsPass(SummaryAction Action,
ModuleSummaryIndex *Summary) {
return new LowerTypeTests(Action, Summary);
}
/// Build a bit set for TypeId using the object layouts in
/// GlobalLayout.
@ -1145,22 +1173,12 @@ void LowerTypeTestsModule::buildBitSetsFromDisjointSet(
}
/// Lower all type tests in this module.
LowerTypeTestsModule::LowerTypeTestsModule(Module &M) : M(M) {
// Handle the command-line summary arguments. This code is for testing
// purposes only, so we handle errors directly.
if (!ClSummaryAction.empty()) {
OwnedSummary = make_unique<ModuleSummaryIndex>();
if (!ClReadSummary.empty()) {
ExitOnError ExitOnErr("-lowertypetests-read-summary: " + ClReadSummary +
": ");
auto ReadSummaryFile =
ExitOnErr(errorOrToExpected(MemoryBuffer::getFile(ClReadSummary)));
yaml::Input In(ReadSummaryFile->getBuffer());
In >> *OwnedSummary;
ExitOnErr(errorCodeToError(In.error()));
}
}
LowerTypeTestsModule::LowerTypeTestsModule(Module &M, SummaryAction Action,
ModuleSummaryIndex *Summary)
: M(M), Action(Action), Summary(Summary) {
// FIXME: Use these fields.
(void)this->Action;
(void)this->Summary;
Triple TargetTriple(M.getTargetTriple());
LinkerSubsectionsViaSymbols = TargetTriple.isMacOSX();
@ -1169,18 +1187,36 @@ LowerTypeTestsModule::LowerTypeTestsModule(Module &M) : M(M) {
ObjectFormat = TargetTriple.getObjectFormat();
}
LowerTypeTestsModule::~LowerTypeTestsModule() {
if (ClSummaryAction.empty() || ClWriteSummary.empty())
return;
bool LowerTypeTestsModule::runForTesting(Module &M) {
ModuleSummaryIndex Summary;
ExitOnError ExitOnErr("-lowertypetests-write-summary: " + ClWriteSummary +
": ");
std::error_code EC;
raw_fd_ostream OS(ClWriteSummary, EC, sys::fs::F_Text);
ExitOnErr(errorCodeToError(EC));
// Handle the command-line summary arguments. This code is for testing
// purposes only, so we handle errors directly.
if (!ClReadSummary.empty()) {
ExitOnError ExitOnErr("-lowertypetests-read-summary: " + ClReadSummary +
": ");
auto ReadSummaryFile =
ExitOnErr(errorOrToExpected(MemoryBuffer::getFile(ClReadSummary)));
yaml::Output Out(OS);
Out << *OwnedSummary;
yaml::Input In(ReadSummaryFile->getBuffer());
In >> Summary;
ExitOnErr(errorCodeToError(In.error()));
}
bool Changed = LowerTypeTestsModule(M, ClSummaryAction, &Summary).lower();
if (!ClWriteSummary.empty()) {
ExitOnError ExitOnErr("-lowertypetests-write-summary: " + ClWriteSummary +
": ");
std::error_code EC;
raw_fd_ostream OS(ClWriteSummary, EC, sys::fs::F_Text);
ExitOnErr(errorCodeToError(EC));
yaml::Output Out(OS);
Out << Summary;
}
return Changed;
}
bool LowerTypeTestsModule::lower() {
@ -1313,7 +1349,8 @@ bool LowerTypeTestsModule::lower() {
PreservedAnalyses LowerTypeTestsPass::run(Module &M,
ModuleAnalysisManager &AM) {
bool Changed = LowerTypeTestsModule(M).lower();
bool Changed =
LowerTypeTestsModule(M, SummaryAction::None, /*Summary=*/nullptr).lower();
if (!Changed)
return PreservedAnalyses::all();
return PreservedAnalyses::none();

View File

@ -857,7 +857,8 @@ void PassManagerBuilder::populateLTOPassManager(legacy::PassManagerBase &PM) {
// Lower type metadata and the type.test intrinsic. This pass supports Clang's
// control flow integrity mechanisms (-fsanitize=cfi*) and needs to run at
// link time if CFI is enabled. The pass does nothing if CFI is disabled.
PM.add(createLowerTypeTestsPass());
PM.add(createLowerTypeTestsPass(LowerTypeTestsSummaryAction::None,
/*Summary=*/nullptr));
if (OptLevel != 0)
addLateLTOOptimizationPasses(PM);