Auto-upgrade malloc instructions to malloc calls.

Reviewed by Devang Patel.



git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@82694 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/lib/AsmParser/LLLexer.cpp b/lib/AsmParser/LLLexer.cpp
index 315048c..05b6f7f 100644
--- a/lib/AsmParser/LLLexer.cpp
+++ b/lib/AsmParser/LLLexer.cpp
@@ -602,6 +602,9 @@
     // Scan CurPtr ahead, seeing if there is just whitespace before the newline.
     if (JustWhitespaceNewLine(CurPtr))
       return lltok::kw_zeroext;
+  } else if (Len == 6 && !memcmp(StartChar, "malloc", 6)) {
+    // Autoupgrade malloc instruction
+    return lltok::kw_malloc;
   }
 
   // Keywords for instructions.
@@ -641,7 +644,6 @@
   INSTKEYWORD(unwind,      Unwind);
   INSTKEYWORD(unreachable, Unreachable);
 
-  INSTKEYWORD(malloc,      Malloc);
   INSTKEYWORD(alloca,      Alloca);
   INSTKEYWORD(free,        Free);
   INSTKEYWORD(load,        Load);
diff --git a/lib/AsmParser/LLParser.cpp b/lib/AsmParser/LLParser.cpp
index 0ecf847..d90588d 100644
--- a/lib/AsmParser/LLParser.cpp
+++ b/lib/AsmParser/LLParser.cpp
@@ -69,6 +69,27 @@
 /// ValidateEndOfModule - Do final validity and sanity checks at the end of the
 /// module.
 bool LLParser::ValidateEndOfModule() {
+  // Update auto-upgraded malloc calls from "autoupgrade_malloc" to "malloc".
+  if (MallocF) {
+    MallocF->setName("malloc");
+    // If setName() does not set the name to "malloc", then there is already a 
+    // declaration of "malloc".  In that case, iterate over all calls to MallocF
+    // and get them to call the declared "malloc" instead.
+    if (MallocF->getName() != "malloc") {
+      Function* realMallocF = M->getFunction("malloc");
+      for (User::use_iterator UI = MallocF->use_begin(), UE= MallocF->use_end();
+           UI != UE; ) {
+        User* user = *UI;
+        UI++;
+        if (CallInst *Call = dyn_cast<CallInst>(user))
+          Call->setCalledFunction(realMallocF);
+      }
+      if (!realMallocF->doesNotAlias(0)) realMallocF->setDoesNotAlias(0);
+      MallocF->eraseFromParent();
+      MallocF = NULL;
+    }
+  }
+
   if (!ForwardRefTypes.empty())
     return Error(ForwardRefTypes.begin()->second.second,
                  "use of undefined type named '" +
@@ -2776,8 +2797,8 @@
   case lltok::kw_call:           return ParseCall(Inst, PFS, false);
   case lltok::kw_tail:           return ParseCall(Inst, PFS, true);
   // Memory.
-  case lltok::kw_alloca:
-  case lltok::kw_malloc:         return ParseAlloc(Inst, PFS, KeywordVal);
+  case lltok::kw_alloca:         return ParseAlloc(Inst, PFS);
+  case lltok::kw_malloc:         return ParseAlloc(Inst, PFS, BB, false);
   case lltok::kw_free:           return ParseFree(Inst, PFS);
   case lltok::kw_load:           return ParseLoad(Inst, PFS, false);
   case lltok::kw_store:          return ParseStore(Inst, PFS, false);
@@ -3286,7 +3307,7 @@
 }
 
 /// ParsePHI
-///   ::= 'phi' Type '[' Value ',' Value ']' (',' '[' Value ',' Valueß ']')*
+///   ::= 'phi' Type '[' Value ',' Value ']' (',' '[' Value ',' Valueß ']')*
 bool LLParser::ParsePHI(Instruction *&Inst, PerFunctionState &PFS) {
   PATypeHolder Ty(Type::getVoidTy(Context));
   Value *Op0, *Op1;
@@ -3431,7 +3452,7 @@
 ///   ::= 'malloc' Type (',' TypeAndValue)? (',' OptionalInfo)?
 ///   ::= 'alloca' Type (',' TypeAndValue)? (',' OptionalInfo)?
 bool LLParser::ParseAlloc(Instruction *&Inst, PerFunctionState &PFS,
-                          unsigned Opc) {
+                          BasicBlock* BB, bool isAlloca) {
   PATypeHolder Ty(Type::getVoidTy(Context));
   Value *Size = 0;
   LocTy SizeLoc;
@@ -3451,10 +3472,21 @@
   if (Size && Size->getType() != Type::getInt32Ty(Context))
     return Error(SizeLoc, "element count must be i32");
 
-  if (Opc == Instruction::Malloc)
-    Inst = new MallocInst(Ty, Size, Alignment);
-  else
+  if (isAlloca)
     Inst = new AllocaInst(Ty, Size, Alignment);
+  else {
+    // Autoupgrade old malloc instruction to malloc call.
+    const Type* IntPtrTy = Type::getInt32Ty(Context);
+    const Type* Int8PtrTy = PointerType::getUnqual(Type::getInt8Ty(Context));
+    if (!MallocF)
+      // Prototype malloc as "void *autoupgrade_malloc(int32)".
+      MallocF = cast<Function>(M->getOrInsertFunction("autoupgrade_malloc",
+                               Int8PtrTy, IntPtrTy, NULL));
+      // "autoupgrade_malloc" updated to "malloc" in ValidateEndOfModule().
+
+    Inst = cast<Instruction>(CallInst::CreateMalloc(BB, IntPtrTy, Ty,
+                                                    Size, MallocF));
+  }
   return false;
 }
 
diff --git a/lib/AsmParser/LLParser.h b/lib/AsmParser/LLParser.h
index 3420fcf..43e9bd8 100644
--- a/lib/AsmParser/LLParser.h
+++ b/lib/AsmParser/LLParser.h
@@ -75,9 +75,11 @@
     std::map<std::string, std::pair<GlobalValue*, LocTy> > ForwardRefVals;
     std::map<unsigned, std::pair<GlobalValue*, LocTy> > ForwardRefValIDs;
     std::vector<GlobalValue*> NumberedVals;
+    Function* MallocF;
   public:
     LLParser(MemoryBuffer *F, SourceMgr &SM, SMDiagnostic &Err, Module *m) : 
-      Context(m->getContext()), Lex(F, SM, Err, m->getContext()), M(m) {}
+      Context(m->getContext()), Lex(F, SM, Err, m->getContext()),
+      M(m), MallocF(NULL) {}
     bool Run();
 
     LLVMContext& getContext() { return Context; }
@@ -276,7 +278,8 @@
     bool ParseShuffleVector(Instruction *&I, PerFunctionState &PFS);
     bool ParsePHI(Instruction *&I, PerFunctionState &PFS);
     bool ParseCall(Instruction *&I, PerFunctionState &PFS, bool isTail);
-    bool ParseAlloc(Instruction *&I, PerFunctionState &PFS, unsigned Opc);
+    bool ParseAlloc(Instruction *&I, PerFunctionState &PFS,
+                    BasicBlock *BB = 0, bool isAlloca = true);
     bool ParseFree(Instruction *&I, PerFunctionState &PFS);
     bool ParseLoad(Instruction *&I, PerFunctionState &PFS, bool isVolatile);
     bool ParseStore(Instruction *&I, PerFunctionState &PFS, bool isVolatile);