forked from OSchip/llvm-project
* Export method to merge identically named methods
* Add code to fix PHI nodes that are missing arguments. These PHI nodes can be generated by GCC if there is an uninitialized variable flowing into a merge point. For example: int foo(int y) { int X; if (y) X = 1; return X; } llvm-svn: 1110
This commit is contained in:
parent
cf5befef63
commit
784c623efb
|
@ -118,7 +118,10 @@ static void ConvertCallTo(CallInst *CI, Method *Dest) {
|
|||
// because of the way things are declared in C. If this is the case, patch
|
||||
// things up.
|
||||
//
|
||||
static bool PatchUpMethodReferences(SymbolTable *ST) {
|
||||
bool CleanupGCCOutput::PatchUpMethodReferences(Module *M) {
|
||||
SymbolTable *ST = M->getSymbolTable();
|
||||
if (!ST) return false;
|
||||
|
||||
map<string, vector<Method*> > Methods;
|
||||
|
||||
// Loop over the entries in the symbol table. If an entry is a method pointer,
|
||||
|
@ -149,6 +152,9 @@ static bool PatchUpMethodReferences(SymbolTable *ST) {
|
|||
Method *Implementation = 0; // Find the implementation
|
||||
Method *Concrete = 0;
|
||||
for (unsigned i = 0; i < Methods.size(); ++i) {
|
||||
// TODO: Ignore methods that are never USED! DCE them.
|
||||
// Remove their name. this should fix a majority of problems here.
|
||||
|
||||
if (!Methods[i]->isExternal()) { // Found an implementation
|
||||
assert(Implementation == 0 && "Multiple definitions of the same"
|
||||
" method. Case not handled yet!");
|
||||
|
@ -260,7 +266,7 @@ bool CleanupGCCOutput::doPassInitialization(Module *M) {
|
|||
// void "foo"(...) and void "foo"(int, int) because of the way things are
|
||||
// declared in C. If this is the case, patch things up.
|
||||
//
|
||||
Changed |= PatchUpMethodReferences(ST);
|
||||
Changed |= PatchUpMethodReferences(M);
|
||||
|
||||
|
||||
// If the module has a symbol table, they might be referring to the malloc
|
||||
|
@ -348,11 +354,82 @@ bool CleanupGCCOutput::doOneCleanupPass(Method *M) {
|
|||
|
||||
|
||||
|
||||
// CheckIncomingValueFor - Make sure that the specified PHI node has an entry
|
||||
// for the provided basic block. If it doesn't, add one and return true.
|
||||
//
|
||||
static inline bool CheckIncomingValueFor(PHINode *PN, BasicBlock *BB) {
|
||||
unsigned NumArgs = PN->getNumIncomingValues();
|
||||
for (unsigned i = 0; i < NumArgs; ++i)
|
||||
if (PN->getIncomingBlock(i) == BB) return false; // Already has value
|
||||
|
||||
Value *NewVal = 0;
|
||||
const Type *Ty = PN->getType();
|
||||
if (const PointerType *PT = dyn_cast<PointerType>(Ty))
|
||||
NewVal = ConstPoolPointerNull::get(PT);
|
||||
else if (Ty == Type::BoolTy)
|
||||
NewVal = ConstPoolBool::True;
|
||||
else if (Ty == Type::FloatTy || Ty == Type::DoubleTy)
|
||||
NewVal = ConstPoolFP::get(Ty, 42);
|
||||
else if (Ty->isIntegral())
|
||||
NewVal = ConstPoolInt::get(Ty, 42);
|
||||
|
||||
assert(NewVal && "Unknown PHI node type!");
|
||||
PN->addIncoming(NewVal, BB);
|
||||
return true;
|
||||
}
|
||||
|
||||
// fixLocalProblems - Loop through the method and fix problems with the PHI
|
||||
// nodes in the current method. The two problems that are handled are:
|
||||
//
|
||||
// 1. PHI nodes with multiple entries for the same predecessor.
|
||||
//
|
||||
// 2. PHI nodes with fewer arguments than predecessors.
|
||||
// These can be generated by GCC if a variable is uninitalized over a path
|
||||
// in the CFG. We fix this by adding an entry for the missing predecessors
|
||||
// that is initialized to either 42 for a numeric/FP value, or null if it's
|
||||
// a pointer value. This problem can be generated by code that looks like
|
||||
// this:
|
||||
// int foo(int y) {
|
||||
// int X;
|
||||
// if (y) X = 1;
|
||||
// return X;
|
||||
// }
|
||||
//
|
||||
static bool fixLocalProblems(Method *M) {
|
||||
bool Changed = false;
|
||||
// Don't use iterators because invalidation gets messy...
|
||||
for (unsigned MI = 0; MI < M->size(); ++MI) {
|
||||
BasicBlock *BB = M->getBasicBlocks()[MI];
|
||||
|
||||
if (isa<PHINode>(BB->front())) {
|
||||
const vector<BasicBlock*> Preds(BB->pred_begin(), BB->pred_end());
|
||||
|
||||
// Loop over all of the PHI nodes in the current BB. These PHI nodes are
|
||||
// guaranteed to be at the beginning of the basic block.
|
||||
//
|
||||
for (BasicBlock::iterator I = BB->begin();
|
||||
PHINode *PN = dyn_cast<PHINode>(*I); ++I) {
|
||||
|
||||
// Handle problem #2.
|
||||
if (PN->getNumIncomingValues() != Preds.size()) {
|
||||
assert(PN->getNumIncomingValues() <= Preds.size() &&
|
||||
"Can't handle extra arguments to PHI nodes!");
|
||||
for (unsigned i = 0; i < Preds.size(); ++i)
|
||||
Changed |= CheckIncomingValueFor(PN, Preds[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return Changed;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
// doPerMethodWork - This method simplifies the specified method hopefully.
|
||||
//
|
||||
bool CleanupGCCOutput::doPerMethodWork(Method *M) {
|
||||
bool Changed = false;
|
||||
bool Changed = fixLocalProblems(M);
|
||||
while (doOneCleanupPass(M)) Changed = true;
|
||||
return Changed;
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue