OLD | NEW |
1 //===- PNaClABIVerifyFunctions.cpp - Verify PNaCl ABI rules ---------------===// | 1 //===- PNaClABIVerifyFunctions.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 function-level PNaCl ABI requirements. | 10 // Verify function-level PNaCl ABI requirements. |
11 // | 11 // |
12 // | 12 // |
13 //===----------------------------------------------------------------------===// | 13 //===----------------------------------------------------------------------===// |
14 | 14 |
| 15 #include "llvm/ADT/OwningPtr.h" |
15 #include "llvm/ADT/Twine.h" | 16 #include "llvm/ADT/Twine.h" |
16 #include "llvm/Analysis/NaCl.h" | 17 #include "llvm/Analysis/NaCl.h" |
17 #include "llvm/IR/Function.h" | 18 #include "llvm/IR/Function.h" |
18 #include "llvm/IR/Instructions.h" | 19 #include "llvm/IR/Instructions.h" |
19 #include "llvm/IR/IntrinsicInst.h" | 20 #include "llvm/IR/IntrinsicInst.h" |
20 #include "llvm/IR/LLVMContext.h" | 21 #include "llvm/IR/LLVMContext.h" |
21 #include "llvm/IR/Metadata.h" | 22 #include "llvm/IR/Metadata.h" |
| 23 #include "llvm/IR/Module.h" |
| 24 #include "llvm/IR/NaClAtomicIntrinsics.h" |
22 #include "llvm/IR/Operator.h" | 25 #include "llvm/IR/Operator.h" |
23 #include "llvm/Pass.h" | 26 #include "llvm/Pass.h" |
24 #include "llvm/Support/raw_ostream.h" | 27 #include "llvm/Support/raw_ostream.h" |
25 | 28 |
26 #include "PNaClABITypeChecker.h" | 29 #include "PNaClABITypeChecker.h" |
27 using namespace llvm; | 30 using namespace llvm; |
28 | 31 |
29 namespace { | 32 namespace { |
30 | 33 |
31 // Checks that examine anything in the function body should be in | 34 // Checks that examine anything in the function body should be in |
(...skipping 10 matching lines...) Expand all Loading... |
42 explicit PNaClABIVerifyFunctions(PNaClABIErrorReporter *Reporter_) : | 45 explicit PNaClABIVerifyFunctions(PNaClABIErrorReporter *Reporter_) : |
43 FunctionPass(ID), | 46 FunctionPass(ID), |
44 Reporter(Reporter_), | 47 Reporter(Reporter_), |
45 ReporterIsOwned(false) { | 48 ReporterIsOwned(false) { |
46 initializePNaClABIVerifyFunctionsPass(*PassRegistry::getPassRegistry()); | 49 initializePNaClABIVerifyFunctionsPass(*PassRegistry::getPassRegistry()); |
47 } | 50 } |
48 ~PNaClABIVerifyFunctions() { | 51 ~PNaClABIVerifyFunctions() { |
49 if (ReporterIsOwned) | 52 if (ReporterIsOwned) |
50 delete Reporter; | 53 delete Reporter; |
51 } | 54 } |
| 55 virtual bool doInitialization(Module &M) { |
| 56 AtomicIntrinsics.reset(new NaCl::AtomicIntrinsics(M.getContext())); |
| 57 return false; |
| 58 } |
52 bool runOnFunction(Function &F); | 59 bool runOnFunction(Function &F); |
53 virtual void print(raw_ostream &O, const Module *M) const; | 60 virtual void print(raw_ostream &O, const Module *M) const; |
54 private: | 61 private: |
55 bool IsWhitelistedMetadata(unsigned MDKind); | 62 bool IsWhitelistedMetadata(unsigned MDKind); |
56 const char *checkInstruction(const Instruction *Inst); | 63 const char *checkInstruction(const Instruction *Inst); |
57 PNaClABIErrorReporter *Reporter; | 64 PNaClABIErrorReporter *Reporter; |
58 bool ReporterIsOwned; | 65 bool ReporterIsOwned; |
| 66 OwningPtr<NaCl::AtomicIntrinsics> AtomicIntrinsics; |
59 }; | 67 }; |
60 | 68 |
61 } // and anonymous namespace | 69 } // and anonymous namespace |
62 | 70 |
63 // There's no built-in way to get the name of an MDNode, so use a | 71 // There's no built-in way to get the name of an MDNode, so use a |
64 // string ostream to print it. | 72 // string ostream to print it. |
65 static std::string getMDNodeString(unsigned Kind, | 73 static std::string getMDNodeString(unsigned Kind, |
66 const SmallVectorImpl<StringRef> &MDNames) { | 74 const SmallVectorImpl<StringRef> &MDNames) { |
67 std::string MDName; | 75 std::string MDName; |
68 raw_string_ostream N(MDName); | 76 raw_string_ostream N(MDName); |
(...skipping 68 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
137 if (isa<Instruction>(Val) || isa<Argument>(Val) || isa<BasicBlock>(Val)) | 145 if (isa<Instruction>(Val) || isa<Argument>(Val) || isa<BasicBlock>(Val)) |
138 return true; | 146 return true; |
139 | 147 |
140 // Allow some Constants. Note that this excludes ConstantExprs. | 148 // Allow some Constants. Note that this excludes ConstantExprs. |
141 return PNaClABITypeChecker::isValidScalarType(Val->getType()) && | 149 return PNaClABITypeChecker::isValidScalarType(Val->getType()) && |
142 (isa<ConstantInt>(Val) || | 150 (isa<ConstantInt>(Val) || |
143 isa<ConstantFP>(Val) || | 151 isa<ConstantFP>(Val) || |
144 isa<UndefValue>(Val)); | 152 isa<UndefValue>(Val)); |
145 } | 153 } |
146 | 154 |
147 static bool isAllowedAlignment(unsigned Alignment, Type *Ty, bool IsAtomic) { | 155 static bool isAllowedAlignment(unsigned Alignment, Type *Ty) { |
148 if (IsAtomic) { | |
149 // For atomic operations, the alignment must match the size of the type. | |
150 if (Ty->isIntegerTy()) { | |
151 unsigned Bits = Ty->getIntegerBitWidth(); | |
152 return Bits % 8 == 0 && Alignment == Bits / 8; | |
153 } | |
154 return (Ty->isDoubleTy() && Alignment == 8) || | |
155 (Ty->isFloatTy() && Alignment == 4); | |
156 } | |
157 // Non-atomic integer operations must always use "align 1", since we | 156 // Non-atomic integer operations must always use "align 1", since we |
158 // do not want the backend to generate code with non-portable | 157 // do not want the backend to generate code with non-portable |
159 // undefined behaviour (such as misaligned access faults) if user | 158 // undefined behaviour (such as misaligned access faults) if user |
160 // code specifies "align 4" but uses a misaligned pointer. As a | 159 // code specifies "align 4" but uses a misaligned pointer. As a |
161 // concession to performance, we allow larger alignment values for | 160 // concession to performance, we allow larger alignment values for |
162 // floating point types. | 161 // floating point types. |
163 // | 162 // |
164 // To reduce the set of alignment values that need to be encoded in | 163 // To reduce the set of alignment values that need to be encoded in |
165 // pexes, we disallow other alignment values. We require alignments | 164 // pexes, we disallow other alignment values. We require alignments |
166 // to be explicit by disallowing Alignment == 0. | 165 // to be explicit by disallowing Alignment == 0. |
167 return Alignment == 1 || | 166 return Alignment == 1 || |
168 (Ty->isDoubleTy() && Alignment == 8) || | 167 (Ty->isDoubleTy() && Alignment == 8) || |
169 (Ty->isFloatTy() && Alignment == 4); | 168 (Ty->isFloatTy() && Alignment == 4); |
170 } | 169 } |
171 | 170 |
| 171 static bool hasAllowedAtomicRMWOperation( |
| 172 const NaCl::AtomicIntrinsics::AtomicIntrinsic *I, const CallInst *Call) { |
| 173 for (size_t P = 0; P != I->NumParams; ++P) { |
| 174 if (I->ParamType[P] != NaCl::AtomicIntrinsics::RMW) |
| 175 continue; |
| 176 |
| 177 const Value *Operation = Call->getOperand(P); |
| 178 if (!Operation) |
| 179 return false; |
| 180 const Constant *C = dyn_cast<Constant>(Operation); |
| 181 if (!C) |
| 182 return false; |
| 183 const APInt &I = C->getUniqueInteger(); |
| 184 if (I.ule(NaCl::AtomicInvalid) || I.uge(NaCl::AtomicNum)) |
| 185 return false; |
| 186 } |
| 187 return true; |
| 188 } |
| 189 |
| 190 static bool hasAllowedAtomicMemoryOrder( |
| 191 const NaCl::AtomicIntrinsics::AtomicIntrinsic *I, const CallInst *Call) { |
| 192 for (size_t P = 0; P != I->NumParams; ++P) { |
| 193 if (I->ParamType[P] != NaCl::AtomicIntrinsics::Mem) |
| 194 continue; |
| 195 |
| 196 const Value *MemoryOrder = Call->getOperand(P); |
| 197 if (!MemoryOrder) |
| 198 return false; |
| 199 const Constant *C = dyn_cast<Constant>(MemoryOrder); |
| 200 if (!C) |
| 201 return false; |
| 202 const APInt &I = C->getUniqueInteger(); |
| 203 if (I.ule(NaCl::MemoryOrderInvalid) || I.uge(NaCl::MemoryOrderNum)) |
| 204 return false; |
| 205 // TODO For now only sequential consistency is allowed. When more |
| 206 // are allowed we need to validate that the memory order is |
| 207 // allowed on the specific atomic operation (e.g. no store |
| 208 // acquire, and relationship between success/failure memory |
| 209 // order on compare exchange). |
| 210 if (I != NaCl::MemoryOrderSequentiallyConsistent) |
| 211 return false; |
| 212 } |
| 213 return true; |
| 214 } |
| 215 |
172 // Check the instruction's opcode and its operands. The operands may | 216 // Check the instruction's opcode and its operands. The operands may |
173 // require opcode-specific checking. | 217 // require opcode-specific checking. |
174 // | 218 // |
175 // This returns an error string if the instruction is rejected, or | 219 // This returns an error string if the instruction is rejected, or |
176 // NULL if the instruction is allowed. | 220 // NULL if the instruction is allowed. |
177 const char *PNaClABIVerifyFunctions::checkInstruction(const Instruction *Inst) { | 221 const char *PNaClABIVerifyFunctions::checkInstruction(const Instruction *Inst) { |
178 // If the instruction has a single pointer operand, PtrOperandIndex is | 222 // If the instruction has a single pointer operand, PtrOperandIndex is |
179 // set to its operand index. | 223 // set to its operand index. |
180 unsigned PtrOperandIndex = -1; | 224 unsigned PtrOperandIndex = -1; |
181 | 225 |
182 switch (Inst->getOpcode()) { | 226 switch (Inst->getOpcode()) { |
183 // Disallowed instructions. Default is to disallow. | 227 // Disallowed instructions. Default is to disallow. |
184 // We expand GetElementPtr out into arithmetic. | 228 // We expand GetElementPtr out into arithmetic. |
185 case Instruction::GetElementPtr: | 229 case Instruction::GetElementPtr: |
186 // VAArg is expanded out by ExpandVarArgs. | 230 // VAArg is expanded out by ExpandVarArgs. |
187 case Instruction::VAArg: | 231 case Instruction::VAArg: |
188 // Zero-cost C++ exception handling is not supported yet. | 232 // Zero-cost C++ exception handling is not supported yet. |
189 case Instruction::Invoke: | 233 case Instruction::Invoke: |
190 case Instruction::LandingPad: | 234 case Instruction::LandingPad: |
191 case Instruction::Resume: | 235 case Instruction::Resume: |
192 // indirectbr may interfere with streaming | 236 // indirectbr may interfere with streaming |
193 case Instruction::IndirectBr: | 237 case Instruction::IndirectBr: |
194 // No vector instructions yet | 238 // No vector instructions yet |
195 case Instruction::ExtractElement: | 239 case Instruction::ExtractElement: |
196 case Instruction::InsertElement: | 240 case Instruction::InsertElement: |
197 case Instruction::ShuffleVector: | 241 case Instruction::ShuffleVector: |
198 // ExtractValue and InsertValue operate on struct values. | 242 // ExtractValue and InsertValue operate on struct values. |
199 case Instruction::ExtractValue: | 243 case Instruction::ExtractValue: |
200 case Instruction::InsertValue: | 244 case Instruction::InsertValue: |
| 245 // Atomics should become NaCl intrinsics. |
| 246 case Instruction::AtomicCmpXchg: |
| 247 case Instruction::AtomicRMW: |
| 248 case Instruction::Fence: |
201 return "bad instruction opcode"; | 249 return "bad instruction opcode"; |
202 default: | 250 default: |
203 return "unknown instruction opcode"; | 251 return "unknown instruction opcode"; |
204 | 252 |
205 // Terminator instructions | 253 // Terminator instructions |
206 case Instruction::Ret: | 254 case Instruction::Ret: |
207 case Instruction::Br: | 255 case Instruction::Br: |
208 case Instruction::Unreachable: | 256 case Instruction::Unreachable: |
209 // Binary operations | 257 // Binary operations |
210 case Instruction::FAdd: | 258 case Instruction::FAdd: |
211 case Instruction::FSub: | 259 case Instruction::FSub: |
212 case Instruction::FMul: | 260 case Instruction::FMul: |
213 case Instruction::FDiv: | 261 case Instruction::FDiv: |
214 case Instruction::FRem: | 262 case Instruction::FRem: |
215 // Bitwise binary operations | 263 // Bitwise binary operations |
216 case Instruction::And: | 264 case Instruction::And: |
217 case Instruction::Or: | 265 case Instruction::Or: |
218 case Instruction::Xor: | 266 case Instruction::Xor: |
219 // Memory instructions | |
220 case Instruction::Fence: | |
221 // Conversion operations | 267 // Conversion operations |
222 case Instruction::Trunc: | 268 case Instruction::Trunc: |
223 case Instruction::ZExt: | 269 case Instruction::ZExt: |
224 case Instruction::SExt: | 270 case Instruction::SExt: |
225 case Instruction::FPTrunc: | 271 case Instruction::FPTrunc: |
226 case Instruction::FPExt: | 272 case Instruction::FPExt: |
227 case Instruction::FPToUI: | 273 case Instruction::FPToUI: |
228 case Instruction::FPToSI: | 274 case Instruction::FPToSI: |
229 case Instruction::UIToFP: | 275 case Instruction::UIToFP: |
230 case Instruction::SIToFP: | 276 case Instruction::SIToFP: |
(...skipping 18 matching lines...) Expand all Loading... |
249 case Instruction::Shl: | 295 case Instruction::Shl: |
250 case Instruction::LShr: | 296 case Instruction::LShr: |
251 case Instruction::AShr: | 297 case Instruction::AShr: |
252 if (Inst->getOperand(0)->getType()->isIntegerTy(1)) | 298 if (Inst->getOperand(0)->getType()->isIntegerTy(1)) |
253 return "arithmetic on i1"; | 299 return "arithmetic on i1"; |
254 break; | 300 break; |
255 | 301 |
256 // Memory accesses. | 302 // Memory accesses. |
257 case Instruction::Load: { | 303 case Instruction::Load: { |
258 const LoadInst *Load = cast<LoadInst>(Inst); | 304 const LoadInst *Load = cast<LoadInst>(Inst); |
| 305 PtrOperandIndex = Load->getPointerOperandIndex(); |
| 306 if (Load->isAtomic()) |
| 307 return "atomic load"; |
| 308 if (Load->isVolatile()) |
| 309 return "volatile load"; |
259 if (!isAllowedAlignment(Load->getAlignment(), | 310 if (!isAllowedAlignment(Load->getAlignment(), |
260 Load->getType(), | 311 Load->getType())) |
261 Load->isAtomic())) | |
262 return "bad alignment"; | 312 return "bad alignment"; |
263 PtrOperandIndex = 0; | |
264 if (!isNormalizedPtr(Inst->getOperand(PtrOperandIndex))) | 313 if (!isNormalizedPtr(Inst->getOperand(PtrOperandIndex))) |
265 return "bad pointer"; | 314 return "bad pointer"; |
266 break; | 315 break; |
267 } | 316 } |
268 case Instruction::Store: { | 317 case Instruction::Store: { |
269 const StoreInst *Store = cast<StoreInst>(Inst); | 318 const StoreInst *Store = cast<StoreInst>(Inst); |
| 319 PtrOperandIndex = Store->getPointerOperandIndex(); |
| 320 if (Store->isAtomic()) |
| 321 return "atomic store"; |
| 322 if (Store->isVolatile()) |
| 323 return "volatile store"; |
270 if (!isAllowedAlignment(Store->getAlignment(), | 324 if (!isAllowedAlignment(Store->getAlignment(), |
271 Store->getValueOperand()->getType(), | 325 Store->getValueOperand()->getType())) |
272 Store->isAtomic())) | |
273 return "bad alignment"; | 326 return "bad alignment"; |
274 PtrOperandIndex = 1; | |
275 if (!isNormalizedPtr(Inst->getOperand(PtrOperandIndex))) | 327 if (!isNormalizedPtr(Inst->getOperand(PtrOperandIndex))) |
276 return "bad pointer"; | 328 return "bad pointer"; |
277 break; | 329 break; |
278 } | 330 } |
279 case Instruction::AtomicCmpXchg: | |
280 case Instruction::AtomicRMW: | |
281 PtrOperandIndex = 0; | |
282 if (!isNormalizedPtr(Inst->getOperand(PtrOperandIndex))) | |
283 return "bad pointer"; | |
284 break; | |
285 | 331 |
286 // Casts. | 332 // Casts. |
287 case Instruction::BitCast: | 333 case Instruction::BitCast: |
288 if (Inst->getType()->isPointerTy()) { | 334 if (Inst->getType()->isPointerTy()) { |
289 PtrOperandIndex = 0; | 335 PtrOperandIndex = 0; |
290 if (!isInherentPtr(Inst->getOperand(PtrOperandIndex))) | 336 if (!isInherentPtr(Inst->getOperand(PtrOperandIndex))) |
291 return "operand not InherentPtr"; | 337 return "operand not InherentPtr"; |
292 } | 338 } |
293 break; | 339 break; |
294 case Instruction::IntToPtr: | 340 case Instruction::IntToPtr: |
(...skipping 30 matching lines...) Expand all Loading... |
325 // metadata arguments, so handle them specially. | 371 // metadata arguments, so handle them specially. |
326 if (const IntrinsicInst *Call = dyn_cast<IntrinsicInst>(Inst)) { | 372 if (const IntrinsicInst *Call = dyn_cast<IntrinsicInst>(Inst)) { |
327 for (unsigned ArgNum = 0, E = Call->getNumArgOperands(); | 373 for (unsigned ArgNum = 0, E = Call->getNumArgOperands(); |
328 ArgNum < E; ++ArgNum) { | 374 ArgNum < E; ++ArgNum) { |
329 const Value *Arg = Call->getArgOperand(ArgNum); | 375 const Value *Arg = Call->getArgOperand(ArgNum); |
330 if (!(isValidScalarOperand(Arg) || | 376 if (!(isValidScalarOperand(Arg) || |
331 isNormalizedPtr(Arg) || | 377 isNormalizedPtr(Arg) || |
332 isa<MDNode>(Arg))) | 378 isa<MDNode>(Arg))) |
333 return "bad intrinsic operand"; | 379 return "bad intrinsic operand"; |
334 } | 380 } |
| 381 |
335 // Disallow alignments other than 1 on memcpy() etc., for the | 382 // Disallow alignments other than 1 on memcpy() etc., for the |
336 // same reason that we disallow them on integer loads and | 383 // same reason that we disallow them on integer loads and |
337 // stores. | 384 // stores. |
338 if (const MemIntrinsic *MemOp = dyn_cast<MemIntrinsic>(Call)) { | 385 if (const MemIntrinsic *MemOp = dyn_cast<MemIntrinsic>(Call)) { |
339 // Avoid the getAlignment() method here because it aborts if | 386 // Avoid the getAlignment() method here because it aborts if |
340 // the alignment argument is not a Constant. | 387 // the alignment argument is not a Constant. |
341 Value *AlignArg = MemOp->getArgOperand(3); | 388 Value *AlignArg = MemOp->getArgOperand(3); |
342 if (!isa<ConstantInt>(AlignArg) || | 389 if (!isa<ConstantInt>(AlignArg) || |
343 cast<ConstantInt>(AlignArg)->getZExtValue() != 1) { | 390 cast<ConstantInt>(AlignArg)->getZExtValue() != 1) { |
344 return "bad alignment"; | 391 return "bad alignment"; |
345 } | 392 } |
346 } | 393 } |
| 394 |
| 395 // Disallow NaCl atomic intrinsics which don't have valid |
| 396 // constant NaCl::AtomicOperation and NaCl::MemoryOrder |
| 397 // parameters. |
| 398 switch (Call->getIntrinsicID()) { |
| 399 default: break; // Non-atomic intrinsic. |
| 400 case Intrinsic::nacl_atomic_load: |
| 401 case Intrinsic::nacl_atomic_store: |
| 402 case Intrinsic::nacl_atomic_rmw: |
| 403 case Intrinsic::nacl_atomic_cmpxchg: |
| 404 case Intrinsic::nacl_atomic_fence: { |
| 405 // All overloads have memory order and RMW operation in the |
| 406 // same parameter, arbitrarily use the I32 overload. |
| 407 Type *T = Type::getInt32Ty( |
| 408 Inst->getParent()->getParent()->getContext()); |
| 409 const NaCl::AtomicIntrinsics::AtomicIntrinsic *I = |
| 410 AtomicIntrinsics->find(Call->getIntrinsicID(), T); |
| 411 if (!hasAllowedAtomicMemoryOrder(I, Call)) |
| 412 return "invalid memory order"; |
| 413 if (!hasAllowedAtomicRMWOperation(I, Call)) |
| 414 return "invalid atomicRMW operation"; |
| 415 } break; |
| 416 } |
| 417 |
347 // Allow the instruction and skip the later checks. | 418 // Allow the instruction and skip the later checks. |
348 return NULL; | 419 return NULL; |
349 } | 420 } |
350 | 421 |
351 // The callee is the last operand. | 422 // The callee is the last operand. |
352 PtrOperandIndex = Inst->getNumOperands() - 1; | 423 PtrOperandIndex = Inst->getNumOperands() - 1; |
353 if (!isNormalizedPtr(Inst->getOperand(PtrOperandIndex))) | 424 if (!isNormalizedPtr(Inst->getOperand(PtrOperandIndex))) |
354 return "bad function callee operand"; | 425 return "bad function callee operand"; |
355 break; | 426 break; |
356 } | 427 } |
(...skipping 109 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
466 } | 537 } |
467 | 538 |
468 char PNaClABIVerifyFunctions::ID = 0; | 539 char PNaClABIVerifyFunctions::ID = 0; |
469 INITIALIZE_PASS(PNaClABIVerifyFunctions, "verify-pnaclabi-functions", | 540 INITIALIZE_PASS(PNaClABIVerifyFunctions, "verify-pnaclabi-functions", |
470 "Verify functions for PNaCl", false, true) | 541 "Verify functions for PNaCl", false, true) |
471 | 542 |
472 FunctionPass *llvm::createPNaClABIVerifyFunctionsPass( | 543 FunctionPass *llvm::createPNaClABIVerifyFunctionsPass( |
473 PNaClABIErrorReporter *Reporter) { | 544 PNaClABIErrorReporter *Reporter) { |
474 return new PNaClABIVerifyFunctions(Reporter); | 545 return new PNaClABIVerifyFunctions(Reporter); |
475 } | 546 } |
OLD | NEW |