mirror of
https://github.com/c64scene-ar/llvm-6502.git
synced 2025-01-01 00:33:09 +00:00
Allow the block extractor take to take a list of basic blocks to not extract
from a file containing Function/BasicBlock pairings. This is not safe against anonymous or abnormally-named Funcs or BBs. Make bugpoint use this interface to pass the BBs list to the child bugpoint. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@44101 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
parent
1b12d8855d
commit
6fa98b1320
@ -21,10 +21,13 @@
|
||||
#include "llvm/Pass.h"
|
||||
#include "llvm/Analysis/Dominators.h"
|
||||
#include "llvm/Analysis/LoopInfo.h"
|
||||
#include "llvm/Support/CommandLine.h"
|
||||
#include "llvm/Support/Compiler.h"
|
||||
#include "llvm/Transforms/Scalar.h"
|
||||
#include "llvm/Transforms/Utils/FunctionUtils.h"
|
||||
#include "llvm/ADT/Statistic.h"
|
||||
#include <fstream>
|
||||
#include <set>
|
||||
using namespace llvm;
|
||||
|
||||
STATISTIC(NumExtracted, "Number of loops extracted");
|
||||
@ -144,15 +147,28 @@ FunctionPass *llvm::createSingleLoopExtractorPass() {
|
||||
|
||||
|
||||
namespace {
|
||||
// BlockFile - A file which contains a list of blocks that should not be
|
||||
// extracted.
|
||||
cl::opt<std::string>
|
||||
BlockFile("extract-blocks-file", cl::value_desc("filename"),
|
||||
cl::desc("A file containing list of basic blocks to not extract"),
|
||||
cl::Hidden);
|
||||
|
||||
/// BlockExtractorPass - This pass is used by bugpoint to extract all blocks
|
||||
/// from the module into their own functions except for those specified by the
|
||||
/// BlocksToNotExtract list.
|
||||
class BlockExtractorPass : public ModulePass {
|
||||
void LoadFile(const char *Filename);
|
||||
|
||||
std::vector<BasicBlock*> BlocksToNotExtract;
|
||||
std::vector<std::pair<std::string, std::string> > BlocksToNotExtractByName;
|
||||
public:
|
||||
static char ID; // Pass identification, replacement for typeid
|
||||
explicit BlockExtractorPass(const std::vector<BasicBlock*> &B)
|
||||
: ModulePass((intptr_t)&ID), BlocksToNotExtract(B) {}
|
||||
: ModulePass((intptr_t)&ID), BlocksToNotExtract(B) {
|
||||
if (!BlockFile.empty())
|
||||
LoadFile(BlockFile.c_str());
|
||||
}
|
||||
BlockExtractorPass() : ModulePass((intptr_t)&ID) {}
|
||||
|
||||
bool runOnModule(Module &M);
|
||||
@ -171,6 +187,24 @@ ModulePass *llvm::createBlockExtractorPass(const std::vector<BasicBlock*> &BTNE)
|
||||
return new BlockExtractorPass(BTNE);
|
||||
}
|
||||
|
||||
void BlockExtractorPass::LoadFile(const char *Filename) {
|
||||
// Load the BlockFile...
|
||||
std::ifstream In(Filename);
|
||||
if (!In.good()) {
|
||||
cerr << "WARNING: BlockExtractor couldn't load file '" << Filename
|
||||
<< "'!\n";
|
||||
return;
|
||||
}
|
||||
while (In) {
|
||||
std::string FunctionName, BlockName;
|
||||
In >> FunctionName;
|
||||
In >> BlockName;
|
||||
if (!BlockName.empty())
|
||||
BlocksToNotExtractByName.push_back(
|
||||
std::make_pair(FunctionName, BlockName));
|
||||
}
|
||||
}
|
||||
|
||||
bool BlockExtractorPass::runOnModule(Module &M) {
|
||||
std::set<BasicBlock*> TranslatedBlocksToNotExtract;
|
||||
for (unsigned i = 0, e = BlocksToNotExtract.size(); i != e; ++i) {
|
||||
@ -187,6 +221,29 @@ bool BlockExtractorPass::runOnModule(Module &M) {
|
||||
TranslatedBlocksToNotExtract.insert(BBI);
|
||||
}
|
||||
|
||||
while (!BlocksToNotExtractByName.empty()) {
|
||||
// There's no way to find BBs by name without looking at every BB inside
|
||||
// every Function. Fortunately, this is always empty except when used by
|
||||
// bugpoint in which case correctness is more important than performance.
|
||||
|
||||
std::string &FuncName = BlocksToNotExtractByName.back().first;
|
||||
std::string &BlockName = BlocksToNotExtractByName.back().second;
|
||||
|
||||
for (Module::iterator FI = M.begin(), FE = M.end(); FI != FE; ++FI) {
|
||||
Function &F = *FI;
|
||||
if (F.getName() != FuncName) continue;
|
||||
|
||||
for (Function::iterator BI = F.begin(), BE = F.end(); BI != BE; ++BI) {
|
||||
BasicBlock &BB = *BI;
|
||||
if (BB.getName() != BlockName) continue;
|
||||
|
||||
TranslatedBlocksToNotExtract.insert(BI);
|
||||
}
|
||||
}
|
||||
|
||||
BlocksToNotExtractByName.pop_back();
|
||||
}
|
||||
|
||||
// Now that we know which blocks to not extract, figure out which ones we WANT
|
||||
// to extract.
|
||||
std::vector<BasicBlock*> BlocksToExtract;
|
||||
|
@ -234,7 +234,8 @@ public:
|
||||
/// automatically attempt to track down a crashing pass if one exists, and
|
||||
/// this method will never return null.
|
||||
Module *runPassesOn(Module *M, const std::vector<const PassInfo*> &Passes,
|
||||
bool AutoDebugCrashes = false);
|
||||
bool AutoDebugCrashes = false, unsigned NumExtraArgs = 0,
|
||||
const char * const *ExtraArgs = NULL);
|
||||
|
||||
/// runPasses - Run the specified passes on Program, outputting a bitcode
|
||||
/// file and writting the filename into OutputFile if successful. If the
|
||||
@ -242,11 +243,13 @@ public:
|
||||
/// otherwise return false. If DeleteOutput is set to true, the bitcode is
|
||||
/// deleted on success, and the filename string is undefined. This prints to
|
||||
/// cout a single line message indicating whether compilation was successful
|
||||
/// or failed, unless Quiet is set.
|
||||
/// or failed, unless Quiet is set. ExtraArgs specifies additional arguments
|
||||
/// to pass to the child bugpoint instance.
|
||||
///
|
||||
bool runPasses(const std::vector<const PassInfo*> &PassesToRun,
|
||||
std::string &OutputFilename, bool DeleteOutput = false,
|
||||
bool Quiet = false) const;
|
||||
bool Quiet = false, unsigned NumExtraArgs = 0,
|
||||
const char * const *ExtraArgs = NULL) const;
|
||||
|
||||
/// runManyPasses - Take the specified pass list and create different
|
||||
/// combinations of passes to compile the program with. Compile the program with
|
||||
|
@ -27,7 +27,10 @@
|
||||
#include "llvm/Support/CommandLine.h"
|
||||
#include "llvm/Support/Debug.h"
|
||||
#include "llvm/Support/FileUtilities.h"
|
||||
#include "llvm/System/Path.h"
|
||||
#include "llvm/System/Signals.h"
|
||||
#include <set>
|
||||
#include <fstream>
|
||||
#include <iostream>
|
||||
using namespace llvm;
|
||||
|
||||
@ -305,10 +308,51 @@ Module *llvm::SplitFunctionsOutOfModule(Module *M,
|
||||
Module *BugDriver::ExtractMappedBlocksFromModule(const
|
||||
std::vector<BasicBlock*> &BBs,
|
||||
Module *M) {
|
||||
char *ExtraArg = NULL;
|
||||
|
||||
sys::Path uniqueFilename("bugpoint-extractblocks");
|
||||
std::string ErrMsg;
|
||||
if (uniqueFilename.createTemporaryFileOnDisk(true, &ErrMsg)) {
|
||||
std::cout << "*** Basic Block extraction failed!\n";
|
||||
std::cerr << "Error creating temporary file: " << ErrMsg << "\n";
|
||||
M = swapProgramIn(M);
|
||||
EmitProgressBitcode("basicblockextractfail", true);
|
||||
swapProgramIn(M);
|
||||
return 0;
|
||||
}
|
||||
sys::RemoveFileOnSignal(uniqueFilename);
|
||||
|
||||
std::ofstream BlocksToNotExtractFile(uniqueFilename.c_str());
|
||||
if (!BlocksToNotExtractFile) {
|
||||
std::cout << "*** Basic Block extraction failed!\n";
|
||||
std::cerr << "Error writing list of blocks to not extract: " << ErrMsg
|
||||
<< "\n";
|
||||
M = swapProgramIn(M);
|
||||
EmitProgressBitcode("basicblockextractfail", true);
|
||||
swapProgramIn(M);
|
||||
return 0;
|
||||
}
|
||||
for (std::vector<BasicBlock*>::const_iterator I = BBs.begin(), E = BBs.end();
|
||||
I != E; ++I) {
|
||||
BasicBlock *BB = *I;
|
||||
BlocksToNotExtractFile << BB->getParent()->getName() << " "
|
||||
<< BB->getName() << "\n";
|
||||
}
|
||||
BlocksToNotExtractFile.close();
|
||||
|
||||
const char *uniqueFN = uniqueFilename.c_str();
|
||||
ExtraArg = (char*)malloc(23 + strlen(uniqueFN));
|
||||
strcat(strcpy(ExtraArg, "--extract-blocks-file="), uniqueFN);
|
||||
|
||||
std::vector<const PassInfo*> PI;
|
||||
// FIXME: BBs is actually ignored. See http://llvm.org/PR1775
|
||||
PI.push_back(getPI(createBlockExtractorPass(BBs)));
|
||||
Module *Ret = runPassesOn(M, PI);
|
||||
std::vector<BasicBlock *> EmptyBBs; // This parameter is ignored.
|
||||
PI.push_back(getPI(createBlockExtractorPass(EmptyBBs)));
|
||||
Module *Ret = runPassesOn(M, PI, false, 1, &ExtraArg);
|
||||
|
||||
if (uniqueFilename.exists())
|
||||
uniqueFilename.eraseFromDisk(); // Free disk space
|
||||
free(ExtraArg);
|
||||
|
||||
if (Ret == 0) {
|
||||
std::cout << "*** Basic Block extraction failed, please report a bug!\n";
|
||||
M = swapProgramIn(M);
|
||||
|
@ -223,7 +223,7 @@ bool ReduceMiscompilingFunctions::TestFuncs(const std::vector<Function*>&Funcs){
|
||||
Module *ToNotOptimize = CloneModule(BD.getProgram());
|
||||
Module *ToOptimize = SplitFunctionsOutOfModule(ToNotOptimize, Funcs);
|
||||
|
||||
// Run the predicate, not that the predicate will delete both input modules.
|
||||
// Run the predicate, note that the predicate will delete both input modules.
|
||||
return TestFn(BD, ToOptimize, ToNotOptimize);
|
||||
}
|
||||
|
||||
|
@ -124,7 +124,8 @@ int BugDriver::runPassesAsChild(const std::vector<const PassInfo*> &Passes) {
|
||||
///
|
||||
bool BugDriver::runPasses(const std::vector<const PassInfo*> &Passes,
|
||||
std::string &OutputFilename, bool DeleteOutput,
|
||||
bool Quiet) const {
|
||||
bool Quiet, unsigned NumExtraArgs,
|
||||
const char * const *ExtraArgs) const {
|
||||
// setup the output file name
|
||||
cout << std::flush;
|
||||
sys::Path uniqueFilename("bugpoint-output.bc");
|
||||
@ -156,7 +157,7 @@ bool BugDriver::runPasses(const std::vector<const PassInfo*> &Passes,
|
||||
// setup the child process' arguments
|
||||
const char** args = (const char**)
|
||||
alloca(sizeof(const char*) *
|
||||
(Passes.size()+13+2*PluginLoader::getNumPlugins()));
|
||||
(Passes.size()+13+2*PluginLoader::getNumPlugins()+NumExtraArgs));
|
||||
int n = 0;
|
||||
sys::Path tool = sys::Program::FindProgramByName(ToolName);
|
||||
if (UseValgrind) {
|
||||
@ -182,6 +183,8 @@ bool BugDriver::runPasses(const std::vector<const PassInfo*> &Passes,
|
||||
E = pass_args.end(); I != E; ++I )
|
||||
args[n++] = I->c_str();
|
||||
args[n++] = inputFilename.c_str();
|
||||
for (unsigned i = 0; i < NumExtraArgs; ++i)
|
||||
args[n++] = *ExtraArgs;
|
||||
args[n++] = 0;
|
||||
|
||||
sys::Path prog;
|
||||
@ -225,10 +228,12 @@ bool BugDriver::runPasses(const std::vector<const PassInfo*> &Passes,
|
||||
/// failure.
|
||||
Module *BugDriver::runPassesOn(Module *M,
|
||||
const std::vector<const PassInfo*> &Passes,
|
||||
bool AutoDebugCrashes) {
|
||||
bool AutoDebugCrashes, unsigned NumExtraArgs,
|
||||
const char * const *ExtraArgs) {
|
||||
Module *OldProgram = swapProgramIn(M);
|
||||
std::string BitcodeResult;
|
||||
if (runPasses(Passes, BitcodeResult, false/*delete*/, true/*quiet*/)) {
|
||||
if (runPasses(Passes, BitcodeResult, false/*delete*/, true/*quiet*/,
|
||||
NumExtraArgs, ExtraArgs)) {
|
||||
if (AutoDebugCrashes) {
|
||||
cerr << " Error running this sequence of passes"
|
||||
<< " on the input program!\n";
|
||||
|
Loading…
Reference in New Issue
Block a user