Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(101)

Side by Side Diff: tools/pnacl-hack-memset/pnacl-hack-memset.cpp

Issue 2262373002: Create one-off tool pnacl-hack-memset (Closed) Base URL: https://chromium.googlesource.com/native_client/pnacl-llvm.git@master
Patch Set: Fix comments as suggested in patch set 2. Created 4 years, 4 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « tools/pnacl-hack-memset/Makefile ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(Empty)
1 /* Copyright 2016 The Native Client Authors. All rights reserved.
2 * Use of this source code is governed by a BSD-style license that can
3 * be found in the LICENSE file.
4 */
5
6 //===-- pnacl-hack-memset.cpp - Fix (interim) Subzero bug -----------------===//
7 //
8 //===----------------------------------------------------------------------===//
9 //
10 // Fixes generated pexe's so that a Subzero bug (fixed but not yet fully
11 // deployed until 10/2016). Does this by replacing calls to memset with a
12 // constant (negative) byte value, and corresponding constant count arguments,
13 // with a zero-add to the count. This causes the broken (and fixed) optimization
14 // to not be fired.
15 //
16 //===----------------------------------------------------------------------===//
17
18 #include "llvm/Bitcode/NaCl/NaClReaderWriter.h"
19 #include "llvm/IR/Constants.h"
20 #include "llvm/IR/InstIterator.h"
21 #include "llvm/IR/Instructions.h"
22 #include "llvm/IR/LLVMContext.h"
23 #include "llvm/IR/Module.h"
24 #include "llvm/Support/CommandLine.h"
25 #include "llvm/Support/DataStream.h"
26 #include "llvm/Support/FileSystem.h"
27 #include "llvm/Support/ManagedStatic.h"
28 #include "llvm/Support/PrettyStackTrace.h"
29 #include "llvm/Support/Signals.h"
30 #include "llvm/Support/StreamingMemoryObject.h"
31 #include "llvm/Support/ToolOutputFile.h"
32
33 using namespace llvm;
34
35 namespace {
36
37 cl::opt<std::string>
38 OutputFilename("o", cl::desc("Specify fixed pexe filename"),
39 cl::value_desc("fixed pexe file"), cl::init("-"));
40
41 cl::opt<std::string>
42 InputFilename(cl::Positional, cl::desc("<pexe file>"), cl::init("-"));
43
44 cl::opt<bool>
45 ShowFixes("show-fixes", cl::desc("Show fixes to memset"), cl::init(false));
46
47 void WriteOutputFile(const Module *M) {
48
49 std::error_code EC;
50 std::unique_ptr<tool_output_file> Out(
51 new tool_output_file(OutputFilename, EC, sys::fs::F_None));
52 if (EC) {
53 errs() << EC.message() << '\n';
54 exit(1);
55 }
56
57 NaClWriteBitcodeToFile(M, Out->os(), /* AcceptSupportedOnly = */ false);
58
59 // Declare success.
60 Out->keep();
61 }
62
63 Module *readBitcode(std::string &Filename, LLVMContext &Context,
64 std::string &ErrorMessage) {
65 // Use the bitcode streaming interface
66 DataStreamer *Streamer = getDataFileStreamer(InputFilename, &ErrorMessage);
67 if (Streamer == nullptr)
68 return nullptr;
69 std::unique_ptr<StreamingMemoryObject> Buffer(
70 new StreamingMemoryObjectImpl(Streamer));
71 std::string DisplayFilename;
72 if (Filename == "-")
73 DisplayFilename = "<stdin>";
74 else
75 DisplayFilename = Filename;
76 DiagnosticHandlerFunction DiagnosticHandler = nullptr;
77 Module *M = getNaClStreamedBitcodeModule(
78 DisplayFilename, Buffer.release(), Context, DiagnosticHandler,
79 &ErrorMessage, /*AcceptSupportedOnly=*/false);
80 if (!M)
81 return nullptr;
82 if (std::error_code EC = M->materializeAllPermanently()) {
83 ErrorMessage = EC.message();
84 delete M;
85 return nullptr;
86 }
87 return M;
88 }
89
90 // Fixes the memset call if appropriate. Returns 1 if the Call to memset has
91 // been fixed, and zero otherwise.
92 size_t fixCallToMemset(CallInst *Call) {
93 if (Call->getNumArgOperands() != 5)
94 return 0;
95 Value *Val = Call->getArgOperand(1);
96 auto *CVal = dyn_cast<ConstantInt>(Val);
97 if (CVal == nullptr)
98 return 0;
99 if (!CVal->getType()->isIntegerTy(8))
100 return 0;
101 const APInt &IVal = CVal->getUniqueInteger();
102 if (!IVal.isNegative())
103 return 0;
104 Value *Count = Call->getArgOperand(2);
105 auto *CCount = dyn_cast<ConstantInt>(Count);
106 if (CCount == nullptr)
107 return 0;
108 if (!CCount->getType()->isIntegerTy(32))
109 return 0;
110 if (ShowFixes) {
111 Call->print(errs());
112 errs() << "\n-->\n";
113 }
114 auto *Zero = ConstantInt::getSigned(CCount->getType(), 0);
115 auto *Add = BinaryOperator::Create(Instruction::BinaryOps::Add, CCount, Zero);
116 auto *IAdd = dyn_cast<Instruction>(Add);
117 if (IAdd == nullptr)
118 return 0;
119 Call->setArgOperand(2, Add);
120 IAdd->insertBefore(Call);
121 if (ShowFixes) {
122 IAdd->print(errs());
123 errs() << "\n";
124 Call->print(errs());
125 errs() << "\n\n";
126 }
127 return 1;
128 }
129
130 // Fixes the instruction Inst, if it is a memset call that needs to be fixed.
131 // Returns 1 if the instruction Inst has been fixed, and zero otherwise.
132 size_t fixCallToMemset(Instruction *Inst) {
133 size_t Count = 0;
134 if (auto *Call = dyn_cast<CallInst>(Inst)) {
135 if (Function *Fcn = Call->getCalledFunction()) {
136 if ("llvm.memset.p0i8.i32" == Fcn->getName()) {
137 Count += fixCallToMemset(Call);
138 }
139 }
140 }
141 return Count;
142 }
143
144 // Fixes appropriate memset calls in the basic Block. Returns the number of
145 // fixed memset calls in the given basic Block.
146 size_t fixCallsToMemset(BasicBlock *Block) {
147 size_t Count = 0;
148 for (auto &Inst : *Block) {
149 Count += fixCallToMemset(&Inst);
150 }
151 return Count;
152 }
153
154 // Fixes appropriate memset calls in the function Fcn. Returns the number of
155 // fixed memset calls for the given function.
156 size_t fixCallsToMemset(Function *Fcn) {
157 size_t Count = 0;
158 for (auto &Block : *Fcn) {
159 Count += fixCallsToMemset(&Block);
160 }
161 return Count;
162 }
163
164 // Fixes appropriate memset calls in module M> Returns the number of fixed
165 // memset calls.
166 size_t fixCallsToMemset(Module *M) {
167 size_t ErrorCount = 0;
168 for (auto &Fcn : *M) {
169 if (!Fcn.isDeclaration())
170 ErrorCount += fixCallsToMemset(&Fcn);
171 }
172 return ErrorCount;
173 }
174
175 } // end of anonymous namespace
176
177 int main(int argc, char **argv) {
178 // Print a stack trace if we signal out.
179 sys::PrintStackTraceOnErrorSignal();
180 PrettyStackTraceProgram X(argc, argv);
181
182 LLVMContext &Context = getGlobalContext();
183 llvm_shutdown_obj Y; // Call llvm_shutdown() on exit.
184
185 cl::ParseCommandLineOptions(
186 argc, argv, "Converts NaCl pexe wire format into LLVM bitcode format\n");
187
188 std::string ErrorMessage;
189 std::unique_ptr<Module> M(readBitcode(InputFilename, Context, ErrorMessage));
190
191 if (!M.get()) {
192 errs() << argv[0] << ": ";
193 if (ErrorMessage.size())
194 errs() << ErrorMessage << "\n";
195 else
196 errs() << "bitcode didn't read correctly.\n";
197 return 1;
198 }
199
200 size_t ErrorCount = fixCallsToMemset(M.get());
201 if (ErrorCount > 0) {
202 errs() << argv[0] << ": Fixed " << ErrorCount << " calls to memset.\n";
203 }
204
205 WriteOutputFile(M.get());
206 return 0;
207 }
OLDNEW
« no previous file with comments | « tools/pnacl-hack-memset/Makefile ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698