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

Side by Side Diff: lib/Analysis/NaCl/PNaClABIVerifyModule.cpp

Issue 14670017: Start a whitelist of intrinsics for the PNaCl ABI checker. (Closed) Base URL: http://git.chromium.org/native_client/pnacl-llvm.git@master
Patch Set: comment Created 7 years, 7 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 | « no previous file | test/NaCl/PNaClABI/intrinsics.ll » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 //===- PNaClABIVerifyModule.cpp - Verify PNaCl ABI rules --------===// 1 //===- PNaClABIVerifyModule.cpp - Verify PNaCl ABI rules --------===//
2 // 2 //
3 // The LLVM Compiler Infrastructure 3 // The LLVM Compiler Infrastructure
4 // 4 //
5 // This file is distributed under the University of Illinois Open Source 5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details. 6 // License. See LICENSE.TXT for details.
7 // 7 //
8 //===----------------------------------------------------------------------===// 8 //===----------------------------------------------------------------------===//
9 // 9 //
10 // Verify module-level PNaCl ABI requirements (specifically those that do not 10 // Verify module-level PNaCl ABI requirements (specifically those that do not
11 // require looking at the function bodies) 11 // require looking at the function bodies)
12 // 12 //
13 // 13 //
14 //===----------------------------------------------------------------------===// 14 //===----------------------------------------------------------------------===//
15 15
16 #include "llvm/Pass.h" 16 #include "llvm/Pass.h"
17 #include "llvm/ADT/Twine.h" 17 #include "llvm/ADT/Twine.h"
18 #include "llvm/Analysis/NaCl.h" 18 #include "llvm/Analysis/NaCl.h"
19 #include "llvm/IR/DerivedTypes.h" 19 #include "llvm/IR/DerivedTypes.h"
20 #include "llvm/IR/Intrinsics.h"
20 #include "llvm/IR/Module.h" 21 #include "llvm/IR/Module.h"
22 #include "llvm/Support/Debug.h"
21 #include "llvm/Support/raw_ostream.h" 23 #include "llvm/Support/raw_ostream.h"
22 24
23 #include "PNaClABITypeChecker.h" 25 #include "PNaClABITypeChecker.h"
24 using namespace llvm; 26 using namespace llvm;
25 27
26 namespace llvm { 28 namespace llvm {
27 cl::opt<bool> 29 cl::opt<bool>
28 PNaClABIAllowDebugMetadata("pnaclabi-allow-debug-metadata", 30 PNaClABIAllowDebugMetadata("pnaclabi-allow-debug-metadata",
29 cl::desc("Allow debug metadata during PNaCl ABI verification."), 31 cl::desc("Allow debug metadata during PNaCl ABI verification."),
30 cl::init(false)); 32 cl::init(false));
33
31 } 34 }
32 35
36 static cl::opt<bool>
37 PNaClABIAllowDevIntrinsics("pnaclabi-allow-dev-intrinsics",
38 cl::desc("Allow all LLVM intrinsics during PNaCl ABI verification."),
39 cl::init(true)); // TODO(jvoung): Make this false by default.
40
33 namespace { 41 namespace {
34 // This pass should not touch function bodies, to stay streaming-friendly 42 // This pass should not touch function bodies, to stay streaming-friendly
35 class PNaClABIVerifyModule : public ModulePass { 43 class PNaClABIVerifyModule : public ModulePass {
36 public: 44 public:
37 static char ID; 45 static char ID;
38 PNaClABIVerifyModule() : 46 PNaClABIVerifyModule() :
39 ModulePass(ID), 47 ModulePass(ID),
40 Reporter(new PNaClABIErrorReporter), 48 Reporter(new PNaClABIErrorReporter),
41 ReporterIsOwned(true) { 49 ReporterIsOwned(true) {
42 initializePNaClABIVerifyModulePass(*PassRegistry::getPassRegistry()); 50 initializePNaClABIVerifyModulePass(*PassRegistry::getPassRegistry());
43 } 51 }
44 explicit PNaClABIVerifyModule(PNaClABIErrorReporter *Reporter_) : 52 explicit PNaClABIVerifyModule(PNaClABIErrorReporter *Reporter_) :
45 ModulePass(ID), 53 ModulePass(ID),
46 Reporter(Reporter_), 54 Reporter(Reporter_),
47 ReporterIsOwned(false) { 55 ReporterIsOwned(false) {
48 initializePNaClABIVerifyModulePass(*PassRegistry::getPassRegistry()); 56 initializePNaClABIVerifyModulePass(*PassRegistry::getPassRegistry());
49 } 57 }
50 ~PNaClABIVerifyModule() { 58 ~PNaClABIVerifyModule() {
51 if (ReporterIsOwned) 59 if (ReporterIsOwned)
52 delete Reporter; 60 delete Reporter;
53 } 61 }
54 bool runOnModule(Module &M); 62 bool runOnModule(Module &M);
55 virtual void print(raw_ostream &O, const Module *M) const; 63 virtual void print(raw_ostream &O, const Module *M) const;
56 private: 64 private:
57 void CheckGlobalValueCommon(const GlobalValue *GV); 65 void CheckGlobalValueCommon(const GlobalValue *GV);
66 bool IsWhitelistedIntrinsic(const Function* F, unsigned ID);
58 bool IsWhitelistedMetadata(const NamedMDNode *MD); 67 bool IsWhitelistedMetadata(const NamedMDNode *MD);
59 PNaClABITypeChecker TC; 68 PNaClABITypeChecker TC;
60 PNaClABIErrorReporter *Reporter; 69 PNaClABIErrorReporter *Reporter;
61 bool ReporterIsOwned; 70 bool ReporterIsOwned;
62 }; 71 };
63 72
64 static const char *linkageName(GlobalValue::LinkageTypes LT) { 73 static const char *linkageName(GlobalValue::LinkageTypes LT) {
65 // This logic is taken from PrintLinkage in lib/VMCore/AsmWriter.cpp 74 // This logic is taken from PrintLinkage in lib/VMCore/AsmWriter.cpp
66 switch (LT) { 75 switch (LT) {
67 case GlobalValue::ExternalLinkage: return "external"; 76 case GlobalValue::ExternalLinkage: return "external";
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after
106 Reporter->addError() << GVTypeName << GV->getName() 115 Reporter->addError() << GVTypeName << GV->getName()
107 << " has disallowed linkage type: " 116 << " has disallowed linkage type: "
108 << linkageName(GV->getLinkage()) << "\n"; 117 << linkageName(GV->getLinkage()) << "\n";
109 } 118 }
110 if (GV->hasSection()) { 119 if (GV->hasSection()) {
111 Reporter->addError() << GVTypeName << GV->getName() << 120 Reporter->addError() << GVTypeName << GV->getName() <<
112 " has disallowed \"section\" attribute\n"; 121 " has disallowed \"section\" attribute\n";
113 } 122 }
114 } 123 }
115 124
125 bool PNaClABIVerifyModule::IsWhitelistedIntrinsic(const Function* F,
126 unsigned ID) {
127 // Keep 3 categories of intrinsics for now.
128 // (1) Allowed always
129 // (2) Never allowed
130 // (3) "Dev" intrinsics, which may or may not be allowed.
131 // "Dev" intrinsics are controlled by the PNaClABIAllowDevIntrinsics flag.
132 // Please keep these sorted within each category.
133 switch(ID) {
134 // Disallow by default.
135 default: return false;
136 // (1) Always allowed.
137 case Intrinsic::invariant_end:
138 case Intrinsic::invariant_start:
139 case Intrinsic::lifetime_end:
140 case Intrinsic::lifetime_start:
141 case Intrinsic::memcpy:
142 case Intrinsic::memmove:
143 case Intrinsic::memset:
144 case Intrinsic::nacl_read_tp:
145 case Intrinsic::trap:
146 return true;
147
148 // (2) Known to be never allowed.
149 case Intrinsic::not_intrinsic:
150 case Intrinsic::adjust_trampoline:
151 case Intrinsic::init_trampoline:
152 case Intrinsic::stackprotector:
153 case Intrinsic::vacopy:
154 case Intrinsic::vaend:
155 case Intrinsic::vastart:
156 return false;
157
158 // (3) Dev intrinsics.
159 case Intrinsic::dbg_declare:
160 case Intrinsic::dbg_value:
161 return PNaClABIAllowDevIntrinsics || PNaClABIAllowDebugMetadata;
162 case Intrinsic::bswap: // Support via compiler_rt if arch doesn't have it?
163 case Intrinsic::cos: // Rounding not defined: support with fast-math?
164 case Intrinsic::ctlz: // Support via compiler_rt if arch doesn't have it?
165 case Intrinsic::ctpop: // Support via compiler_rt if arch doesn't have it?
166 case Intrinsic::cttz: // Support via compiler_rt if arch doesn't have it?
167 case Intrinsic::eh_dwarf_cfa: // For EH tests.
168 case Intrinsic::exp: // Rounding not defined: support with fast-math?
169 case Intrinsic::exp2: // Rounding not defined: support with fast-math?
170 case Intrinsic::expect: // From __builtin_expect.
171 case Intrinsic::flt_rounds:
172 case Intrinsic::frameaddress: // Support for 0-level or not?
173 case Intrinsic::log: // Rounding not defined: support with fast-math?
174 case Intrinsic::log2: // Rounding not defined: support with fast-math?
175 case Intrinsic::log10: // Rounding not defined: support with fast-math?
176 case Intrinsic::nacl_target_arch: // Used by translator self-build.
177 case Intrinsic::pow: // Rounding not defined: support with fast-math?
178 case Intrinsic::prefetch: // Could ignore if target doesn't support?
179 case Intrinsic::returnaddress: // Support for 0-level or not?
180 case Intrinsic::sin: // Rounding not defined: support with fast-math?
181 case Intrinsic::sqrt:
182 case Intrinsic::stackrestore: // Used to support C99 VLAs.
183 case Intrinsic::stacksave:
184 // the *_with_overflow return struct types, so we'll need to fix these.
185 case Intrinsic::sadd_with_overflow: // Introduced by -ftrapv
186 case Intrinsic::ssub_with_overflow:
187 case Intrinsic::uadd_with_overflow:
188 case Intrinsic::usub_with_overflow:
189 case Intrinsic::smul_with_overflow:
190 case Intrinsic::umul_with_overflow: // Introduced by c++ new[x * y].
191 return PNaClABIAllowDevIntrinsics;
192 }
193 }
194
116 bool PNaClABIVerifyModule::IsWhitelistedMetadata(const NamedMDNode* MD) { 195 bool PNaClABIVerifyModule::IsWhitelistedMetadata(const NamedMDNode* MD) {
117 return MD->getName().startswith("llvm.dbg.") && PNaClABIAllowDebugMetadata; 196 return MD->getName().startswith("llvm.dbg.") && PNaClABIAllowDebugMetadata;
118 } 197 }
119 198
120 bool PNaClABIVerifyModule::runOnModule(Module &M) { 199 bool PNaClABIVerifyModule::runOnModule(Module &M) {
121 for (Module::const_global_iterator MI = M.global_begin(), ME = M.global_end(); 200 for (Module::const_global_iterator MI = M.global_begin(), ME = M.global_end();
122 MI != ME; ++MI) { 201 MI != ME; ++MI) {
123 // Check types of global variables and their initializers 202 // Check types of global variables and their initializers
124 if (!TC.isValidType(MI->getType())) { 203 if (!TC.isValidType(MI->getType())) {
125 // GVs are pointers, so print the pointed-to type for clarity 204 // GVs are pointers, so print the pointed-to type for clarity
(...skipping 20 matching lines...) Expand all
146 } 225 }
147 226
148 // No aliases allowed for now. 227 // No aliases allowed for now.
149 for (Module::alias_iterator MI = M.alias_begin(), 228 for (Module::alias_iterator MI = M.alias_begin(),
150 E = M.alias_end(); MI != E; ++MI) { 229 E = M.alias_end(); MI != E; ++MI) {
151 Reporter->addError() << "Variable " << MI->getName() << 230 Reporter->addError() << "Variable " << MI->getName() <<
152 " is an alias (disallowed)\n"; 231 " is an alias (disallowed)\n";
153 } 232 }
154 233
155 for (Module::const_iterator MI = M.begin(), ME = M.end(); MI != ME; ++MI) { 234 for (Module::const_iterator MI = M.begin(), ME = M.end(); MI != ME; ++MI) {
235 // Check intrinsics.
236 if (MI->isIntrinsic()
237 && !IsWhitelistedIntrinsic(MI, MI->getIntrinsicID())) {
238 Reporter->addError() << "Function " << MI->getName()
239 << " is a disallowed LLVM intrinsic\n";
240 }
241
156 // Check types of functions and their arguments 242 // Check types of functions and their arguments
157 FunctionType *FT = MI->getFunctionType(); 243 FunctionType *FT = MI->getFunctionType();
158 if (!TC.isValidType(FT->getReturnType())) { 244 if (!TC.isValidType(FT->getReturnType())) {
159 Reporter->addError() << "Function " << MI->getName() << 245 Reporter->addError() << "Function " << MI->getName() <<
160 " has disallowed return type: " << 246 " has disallowed return type: " <<
161 PNaClABITypeChecker::getTypeName(FT->getReturnType()) << "\n"; 247 PNaClABITypeChecker::getTypeName(FT->getReturnType()) << "\n";
162 } 248 }
163 for (unsigned I = 0, E = FT->getNumParams(); I < E; ++I) { 249 for (unsigned I = 0, E = FT->getNumParams(); I < E; ++I) {
164 Type *PT = FT->getParamType(I); 250 Type *PT = FT->getParamType(I);
165 if (!TC.isValidType(PT)) { 251 if (!TC.isValidType(PT)) {
(...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after
215 } 301 }
216 302
217 char PNaClABIVerifyModule::ID = 0; 303 char PNaClABIVerifyModule::ID = 0;
218 INITIALIZE_PASS(PNaClABIVerifyModule, "verify-pnaclabi-module", 304 INITIALIZE_PASS(PNaClABIVerifyModule, "verify-pnaclabi-module",
219 "Verify module for PNaCl", false, true) 305 "Verify module for PNaCl", false, true)
220 306
221 ModulePass *llvm::createPNaClABIVerifyModulePass( 307 ModulePass *llvm::createPNaClABIVerifyModulePass(
222 PNaClABIErrorReporter *Reporter) { 308 PNaClABIErrorReporter *Reporter) {
223 return new PNaClABIVerifyModule(Reporter); 309 return new PNaClABIVerifyModule(Reporter);
224 } 310 }
OLDNEW
« no previous file with comments | « no previous file | test/NaCl/PNaClABI/intrinsics.ll » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698