Chromium Code Reviews| Index: tools/pnacl-hack-memset/pnacl-hack-memset.cpp |
| diff --git a/tools/pnacl-thaw/pnacl-thaw.cpp b/tools/pnacl-hack-memset/pnacl-hack-memset.cpp |
| similarity index 53% |
| copy from tools/pnacl-thaw/pnacl-thaw.cpp |
| copy to tools/pnacl-hack-memset/pnacl-hack-memset.cpp |
| index 5adebdebea0cbd21d3b55afd287e3d4ee2a50e25..caf77ef2689193a3de932db1d0392e73a6732e0b 100644 |
| --- a/tools/pnacl-thaw/pnacl-thaw.cpp |
| +++ b/tools/pnacl-hack-memset/pnacl-hack-memset.cpp |
| @@ -1,4 +1,4 @@ |
| -/* Copyright 2013 The Native Client Authors. All rights reserved. |
| +/* Copyright 2016 The Native Client Authors. All rights reserved. |
| * Use of this source code is governed by a BSD-style license that can |
| * be found in the LICENSE file. |
| */ |
| @@ -12,7 +12,9 @@ |
| //===----------------------------------------------------------------------===// |
| #include "llvm/Bitcode/NaCl/NaClReaderWriter.h" |
| -#include "llvm/Bitcode/ReaderWriter.h" |
| +#include "llvm/IR/Constants.h" |
| +#include "llvm/IR/InstIterator.h" |
| +#include "llvm/IR/Instructions.h" |
| #include "llvm/IR/LLVMContext.h" |
| #include "llvm/IR/Module.h" |
| #include "llvm/Support/CommandLine.h" |
| @@ -29,11 +31,14 @@ using namespace llvm; |
| namespace { |
| static cl::opt<std::string> |
| -OutputFilename("o", cl::desc("Specify thawed pexe filename"), |
| - cl::value_desc("filename"), cl::init("-")); |
| +OutputFilename("o", cl::desc("Specify fixed pexe filename"), |
| + cl::value_desc("fixed pexe file"), cl::init("-")); |
| static cl::opt<std::string> |
| -InputFilename(cl::Positional, cl::desc("<frozen file>"), cl::init("-")); |
| +InputFilename(cl::Positional, cl::desc("<pexe file>"), cl::init("-")); |
| + |
| +static cl::opt<bool> |
| +ShowFixes("show-fixes", cl::desc("Show fixes to memset"), cl::init(false)); |
| static void WriteOutputFile(const Module *M) { |
| @@ -45,7 +50,7 @@ static void WriteOutputFile(const Module *M) { |
| exit(1); |
| } |
| - WriteBitcodeToFile(M, Out->os()); |
| + NaClWriteBitcodeToFile(M, Out->os(), /* AcceptSupportedOnly = */ false); |
| // Declare success. |
| Out->keep(); |
| @@ -78,6 +83,82 @@ static Module *readBitcode(std::string &Filename, LLVMContext &Context, |
| return M; |
| } |
| +size_t fixCallToMemset(CallInst &Call) { |
|
Jim Stichnoth
2016/08/22 21:55:43
Document return value
Jim Stichnoth
2016/08/22 21:55:44
Can this be CallInst *Call? Makes it clearer at t
Karl
2016/08/23 15:17:31
Done.
|
| + if (Call.getNumArgOperands() != 5) |
| + return 0; |
| + Value* Val = Call.getArgOperand(1); |
|
Jim Stichnoth
2016/08/22 21:55:43
"Value *Val" rather than "Value* Val", right?
here
Karl
2016/08/23 15:17:31
Correct. Fixing. I was getting too used to the Chr
|
| + auto* CVal = dyn_cast<ConstantInt>(Val); |
| + if (CVal == nullptr) |
| + return 0; |
| + if (!CVal->getType()->isIntegerTy(8)) |
| + return 0; |
| + const APInt & IVal = CVal->getUniqueInteger(); |
| + if (!IVal.isNegative()) |
| + return 0; |
| + Value* Count = Call.getArgOperand(2); |
| + auto* CCount = dyn_cast<ConstantInt>(Count); |
| + if (CCount == nullptr) |
| + return 0; |
| + if (!CCount->getType()->isIntegerTy(32)) |
| + return 0; |
| + if (ShowFixes) { |
| + Call.print(errs()); |
| + errs() << "\n-->\n"; |
| + } |
| + auto* Zero = ConstantInt::getSigned(CCount->getType(), 0); |
| + Value* Add = BinaryOperator::Create(Instruction::BinaryOps::Add, |
| + CCount, Zero); |
| + auto *IAdd = dyn_cast<Instruction>(Add); |
| + if (IAdd == nullptr) |
| + return 0; |
| + Call.setArgOperand(2, Add); |
| + IAdd->insertBefore(&Call); |
| + if (ShowFixes) { |
| + IAdd->print(errs()); |
| + errs() << "\n"; |
| + Call.print(errs()); |
| + errs() << "\n\n"; |
| + } |
| + return 1; |
| +} |
| + |
| +size_t fixCallsToMemset(Instruction &I) { |
| + size_t Count = 0; |
| + if (auto *Call = dyn_cast<CallInst>(&I)) { |
| + if (Function *F = Call->getCalledFunction()) { |
| + if ("llvm.memset.p0i8.i32" == F->getName()) { |
| + Count += fixCallToMemset(*Call); |
| + } |
| + } |
| + } |
| + return Count; |
| +} |
| + |
| +size_t fixCallsToMemset(BasicBlock &B) { |
| + size_t Count = 0; |
| + for (auto &I : B) { |
| + Count += fixCallsToMemset(I); |
| + } |
| + return Count; |
| +} |
| + |
| +size_t fixCallsToMemset(Function &F) { |
| + size_t Count = 0; |
| + for (auto &B : F) { |
| + Count += fixCallsToMemset(B); |
| + } |
| + return Count; |
| +} |
| + |
| +size_t fixCallsToMemset(Module *M) { |
| + size_t ErrorCount = 0; |
| + for (auto &F : *M) { |
| + if (!F.isDeclaration()) |
| + ErrorCount += fixCallsToMemset(F); |
| + } |
| + return ErrorCount; |
| +} |
| + |
| } // end of anonymous namespace |
| int main(int argc, char **argv) { |
| @@ -103,6 +184,11 @@ int main(int argc, char **argv) { |
| return 1; |
| } |
| + size_t ErrorCount = fixCallsToMemset(M.get()); |
| + if (ErrorCount > 0) { |
| + errs() << argv[0] << ": " << "Fixed " << ErrorCount << " calls to memset.\n"; |
|
Jim Stichnoth
2016/08/22 21:55:43
80-col
Jim Stichnoth
2016/08/22 21:55:43
... << ": Fixed " << ...
i.e. concatenate strings
Karl
2016/08/23 15:17:31
Done.
|
| + } |
| + |
| WriteOutputFile(M.get()); |
| return 0; |
| } |