// 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,
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!");
// 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
+// 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;
}