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