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. |
(...skipping 70 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
81 } | 81 } |
82 return N.str(); | 82 return N.str(); |
83 } | 83 } |
84 | 84 |
85 bool PNaClABIVerifyFunctions::IsWhitelistedMetadata(unsigned MDKind) { | 85 bool PNaClABIVerifyFunctions::IsWhitelistedMetadata(unsigned MDKind) { |
86 return MDKind == LLVMContext::MD_dbg && PNaClABIAllowDebugMetadata; | 86 return MDKind == LLVMContext::MD_dbg && PNaClABIAllowDebugMetadata; |
87 } | 87 } |
88 | 88 |
89 // A valid pointer type is either: | 89 // A valid pointer type is either: |
90 // * a pointer to a valid PNaCl scalar type (except i1), or | 90 // * a pointer to a valid PNaCl scalar type (except i1), or |
| 91 // * a pointer to a valid PNaCl vector type (except i1 vector), or |
91 // * a function pointer (with valid argument and return types). | 92 // * a function pointer (with valid argument and return types). |
92 // | 93 // |
93 // i1 is disallowed so that all loads and stores are a whole number of | 94 // i1 is disallowed so that all loads and stores are a whole number of |
94 // bytes, and so that we do not need to define whether a store of i1 | 95 // bytes, and so that we do not need to define whether a store of i1 |
95 // zero-extends. | 96 // zero-extends. |
96 static bool isValidPointerType(Type *Ty) { | 97 static bool isValidPointerType(Type *Ty) { |
97 if (PointerType *PtrTy = dyn_cast<PointerType>(Ty)) { | 98 if (PointerType *PtrTy = dyn_cast<PointerType>(Ty)) { |
98 if (PtrTy->getAddressSpace() != 0) | 99 if (PtrTy->getAddressSpace() != 0) |
99 return false; | 100 return false; |
100 Type *EltTy = PtrTy->getElementType(); | 101 Type *EltTy = PtrTy->getElementType(); |
101 if (PNaClABITypeChecker::isValidScalarType(EltTy) && | 102 if ((PNaClABITypeChecker::isValidScalarType(EltTy) && |
102 !EltTy->isIntegerTy(1)) | 103 !EltTy->isIntegerTy(1)) || |
| 104 (PNaClABITypeChecker::isValidVectorType(EltTy) && |
| 105 !cast<VectorType>(EltTy)->getElementType()->isIntegerTy(1))) |
103 return true; | 106 return true; |
104 if (FunctionType *FTy = dyn_cast<FunctionType>(EltTy)) | 107 if (FunctionType *FTy = dyn_cast<FunctionType>(EltTy)) |
105 return PNaClABITypeChecker::isValidFunctionType(FTy); | 108 return PNaClABITypeChecker::isValidFunctionType(FTy); |
106 } | 109 } |
107 return false; | 110 return false; |
108 } | 111 } |
109 | 112 |
110 static bool isIntrinsicFunc(const Value *Val) { | 113 static bool isIntrinsicFunc(const Value *Val) { |
111 if (const Function *F = dyn_cast<Function>(Val)) | 114 if (const Function *F = dyn_cast<Function>(Val)) |
112 return F->isIntrinsic(); | 115 return F->isIntrinsic(); |
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
145 if (isa<Instruction>(Val) || isa<Argument>(Val) || isa<BasicBlock>(Val)) | 148 if (isa<Instruction>(Val) || isa<Argument>(Val) || isa<BasicBlock>(Val)) |
146 return true; | 149 return true; |
147 | 150 |
148 // Allow some Constants. Note that this excludes ConstantExprs. | 151 // Allow some Constants. Note that this excludes ConstantExprs. |
149 return PNaClABITypeChecker::isValidScalarType(Val->getType()) && | 152 return PNaClABITypeChecker::isValidScalarType(Val->getType()) && |
150 (isa<ConstantInt>(Val) || | 153 (isa<ConstantInt>(Val) || |
151 isa<ConstantFP>(Val) || | 154 isa<ConstantFP>(Val) || |
152 isa<UndefValue>(Val)); | 155 isa<UndefValue>(Val)); |
153 } | 156 } |
154 | 157 |
| 158 static bool isValidVectorOperand(const Value *Val) { |
| 159 // The types of Instructions and Arguments are checked elsewhere. |
| 160 if (isa<Instruction>(Val) || isa<Argument>(Val)) |
| 161 return true; |
| 162 // Contrary to scalars, constant vector values aren't allowed on |
| 163 // instructions, except for aggregate zero and undefined. |
| 164 return PNaClABITypeChecker::isValidVectorType(Val->getType()) && |
| 165 (isa<ConstantAggregateZero>(Val) || isa<UndefValue>(Val)); |
| 166 } |
| 167 |
155 static bool isAllowedAlignment(unsigned Alignment, Type *Ty) { | 168 static bool isAllowedAlignment(unsigned Alignment, Type *Ty) { |
156 // Non-atomic integer operations must always use "align 1", since we | 169 // Non-atomic integer operations must always use "align 1", since we |
157 // do not want the backend to generate code with non-portable | 170 // do not want the backend to generate code with non-portable |
158 // undefined behaviour (such as misaligned access faults) if user | 171 // undefined behaviour (such as misaligned access faults) if user |
159 // code specifies "align 4" but uses a misaligned pointer. As a | 172 // code specifies "align 4" but uses a misaligned pointer. As a |
160 // concession to performance, we allow larger alignment values for | 173 // concession to performance, we allow larger alignment values for |
161 // floating point types. | 174 // floating point types. |
162 // | 175 // |
163 // To reduce the set of alignment values that need to be encoded in | 176 // To reduce the set of alignment values that need to be encoded in |
164 // pexes, we disallow other alignment values. We require alignments | 177 // pexes, we disallow other alignment values. We require alignments |
165 // to be explicit by disallowing Alignment == 0. | 178 // to be explicit by disallowing Alignment == 0. |
| 179 // |
| 180 // Vector memory accesses go through their scalar elements, there is |
| 181 // therefore no such thing as vector alignment. |
166 return Alignment == 1 || | 182 return Alignment == 1 || |
167 (Ty->isDoubleTy() && Alignment == 8) || | 183 (Ty->isDoubleTy() && Alignment == 8) || |
168 (Ty->isFloatTy() && Alignment == 4); | 184 (Ty->isFloatTy() && Alignment == 4); |
169 } | 185 } |
170 | 186 |
171 static bool hasAllowedAtomicRMWOperation( | 187 static bool hasAllowedAtomicRMWOperation( |
172 const NaCl::AtomicIntrinsics::AtomicIntrinsic *I, const CallInst *Call) { | 188 const NaCl::AtomicIntrinsics::AtomicIntrinsic *I, const CallInst *Call) { |
173 for (size_t P = 0; P != I->NumParams; ++P) { | 189 for (size_t P = 0; P != I->NumParams; ++P) { |
174 if (I->ParamType[P] != NaCl::AtomicIntrinsics::RMW) | 190 if (I->ParamType[P] != NaCl::AtomicIntrinsics::RMW) |
175 continue; | 191 continue; |
(...skipping 70 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
246 // We expand GetElementPtr out into arithmetic. | 262 // We expand GetElementPtr out into arithmetic. |
247 case Instruction::GetElementPtr: | 263 case Instruction::GetElementPtr: |
248 // VAArg is expanded out by ExpandVarArgs. | 264 // VAArg is expanded out by ExpandVarArgs. |
249 case Instruction::VAArg: | 265 case Instruction::VAArg: |
250 // Zero-cost C++ exception handling is not supported yet. | 266 // Zero-cost C++ exception handling is not supported yet. |
251 case Instruction::Invoke: | 267 case Instruction::Invoke: |
252 case Instruction::LandingPad: | 268 case Instruction::LandingPad: |
253 case Instruction::Resume: | 269 case Instruction::Resume: |
254 // indirectbr may interfere with streaming | 270 // indirectbr may interfere with streaming |
255 case Instruction::IndirectBr: | 271 case Instruction::IndirectBr: |
256 // No vector instructions yet | 272 // TODO(jfb) Figure out ShuffleVector. |
257 case Instruction::ExtractElement: | |
258 case Instruction::InsertElement: | |
259 case Instruction::ShuffleVector: | 273 case Instruction::ShuffleVector: |
260 // ExtractValue and InsertValue operate on struct values. | 274 // ExtractValue and InsertValue operate on struct values. |
261 case Instruction::ExtractValue: | 275 case Instruction::ExtractValue: |
262 case Instruction::InsertValue: | 276 case Instruction::InsertValue: |
263 // Atomics should become NaCl intrinsics. | 277 // Atomics should become NaCl intrinsics. |
264 case Instruction::AtomicCmpXchg: | 278 case Instruction::AtomicCmpXchg: |
265 case Instruction::AtomicRMW: | 279 case Instruction::AtomicRMW: |
266 case Instruction::Fence: | 280 case Instruction::Fence: |
267 return "bad instruction opcode"; | 281 return "bad instruction opcode"; |
268 default: | 282 default: |
(...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
305 // Binary operations | 319 // Binary operations |
306 case Instruction::Add: | 320 case Instruction::Add: |
307 case Instruction::Sub: | 321 case Instruction::Sub: |
308 case Instruction::Mul: | 322 case Instruction::Mul: |
309 case Instruction::UDiv: | 323 case Instruction::UDiv: |
310 case Instruction::SDiv: | 324 case Instruction::SDiv: |
311 case Instruction::URem: | 325 case Instruction::URem: |
312 case Instruction::SRem: | 326 case Instruction::SRem: |
313 case Instruction::Shl: | 327 case Instruction::Shl: |
314 case Instruction::LShr: | 328 case Instruction::LShr: |
315 case Instruction::AShr: | 329 case Instruction::AShr: { |
316 if (Inst->getOperand(0)->getType()->isIntegerTy(1)) | 330 Type *Op0Ty = Inst->getOperand(0)->getType(); |
| 331 VectorType *Op0VTy = dyn_cast<VectorType>(Op0Ty); |
| 332 if (Op0Ty->isIntegerTy(1) || |
| 333 (Op0VTy && Op0VTy->getElementType()->isIntegerTy(1))) |
317 return "arithmetic on i1"; | 334 return "arithmetic on i1"; |
318 break; | 335 break; |
| 336 } |
| 337 |
| 338 // Vector. |
| 339 case Instruction::ExtractElement: |
| 340 case Instruction::InsertElement: { |
| 341 // Insert and extract element are restricted to constant indices |
| 342 // that are in range to prevent undefined behavior. |
| 343 Value *Vec = Inst->getOperand(0); |
| 344 Value *Idx = Inst->getOperand( |
| 345 Instruction::InsertElement == Inst->getOpcode() ? 2 : 1); |
| 346 if (!isa<ConstantInt>(Idx)) |
| 347 return "non-constant vector insert/extract index"; |
| 348 const APInt &I = cast<ConstantInt>(Idx)->getValue(); |
| 349 unsigned NumElements = cast<VectorType>(Vec->getType())->getNumElements(); |
| 350 if (!I.ult(NumElements)) |
| 351 return "out of range vector insert/extract index"; |
| 352 break; |
| 353 } |
319 | 354 |
320 // Memory accesses. | 355 // Memory accesses. |
321 case Instruction::Load: { | 356 case Instruction::Load: { |
| 357 // TODO(jfb): vectors |
322 const LoadInst *Load = cast<LoadInst>(Inst); | 358 const LoadInst *Load = cast<LoadInst>(Inst); |
323 PtrOperandIndex = Load->getPointerOperandIndex(); | 359 PtrOperandIndex = Load->getPointerOperandIndex(); |
324 if (Load->isAtomic()) | 360 if (Load->isAtomic()) |
325 return "atomic load"; | 361 return "atomic load"; |
326 if (Load->isVolatile()) | 362 if (Load->isVolatile()) |
327 return "volatile load"; | 363 return "volatile load"; |
| 364 if (Load->getType()->isVectorTy()) |
| 365 return "vector load"; |
328 if (!isAllowedAlignment(Load->getAlignment(), | 366 if (!isAllowedAlignment(Load->getAlignment(), |
329 Load->getType())) | 367 Load->getType())) |
330 return "bad alignment"; | 368 return "bad alignment"; |
331 if (!isNormalizedPtr(Inst->getOperand(PtrOperandIndex))) | 369 if (!isNormalizedPtr(Inst->getOperand(PtrOperandIndex))) |
332 return "bad pointer"; | 370 return "bad pointer"; |
333 break; | 371 break; |
334 } | 372 } |
335 case Instruction::Store: { | 373 case Instruction::Store: { |
| 374 // TODO(jfb): vectors |
336 const StoreInst *Store = cast<StoreInst>(Inst); | 375 const StoreInst *Store = cast<StoreInst>(Inst); |
337 PtrOperandIndex = Store->getPointerOperandIndex(); | 376 PtrOperandIndex = Store->getPointerOperandIndex(); |
338 if (Store->isAtomic()) | 377 if (Store->isAtomic()) |
339 return "atomic store"; | 378 return "atomic store"; |
340 if (Store->isVolatile()) | 379 if (Store->isVolatile()) |
341 return "volatile store"; | 380 return "volatile store"; |
| 381 if (Store->getValueOperand()->getType()->isVectorTy()) |
| 382 return "vector store"; |
342 if (!isAllowedAlignment(Store->getAlignment(), | 383 if (!isAllowedAlignment(Store->getAlignment(), |
343 Store->getValueOperand()->getType())) | 384 Store->getValueOperand()->getType())) |
344 return "bad alignment"; | 385 return "bad alignment"; |
345 if (!isNormalizedPtr(Inst->getOperand(PtrOperandIndex))) | 386 if (!isNormalizedPtr(Inst->getOperand(PtrOperandIndex))) |
346 return "bad pointer"; | 387 return "bad pointer"; |
347 break; | 388 break; |
348 } | 389 } |
349 | 390 |
350 // Casts. | 391 // Casts. |
351 case Instruction::BitCast: | 392 case Instruction::BitCast: |
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
385 if (Call->getCallingConv() != CallingConv::C) | 426 if (Call->getCallingConv() != CallingConv::C) |
386 return "bad calling convention"; | 427 return "bad calling convention"; |
387 | 428 |
388 // Intrinsic calls can have multiple pointer arguments and | 429 // Intrinsic calls can have multiple pointer arguments and |
389 // metadata arguments, so handle them specially. | 430 // metadata arguments, so handle them specially. |
390 if (const IntrinsicInst *Call = dyn_cast<IntrinsicInst>(Inst)) { | 431 if (const IntrinsicInst *Call = dyn_cast<IntrinsicInst>(Inst)) { |
391 for (unsigned ArgNum = 0, E = Call->getNumArgOperands(); | 432 for (unsigned ArgNum = 0, E = Call->getNumArgOperands(); |
392 ArgNum < E; ++ArgNum) { | 433 ArgNum < E; ++ArgNum) { |
393 const Value *Arg = Call->getArgOperand(ArgNum); | 434 const Value *Arg = Call->getArgOperand(ArgNum); |
394 if (!(isValidScalarOperand(Arg) || | 435 if (!(isValidScalarOperand(Arg) || |
| 436 isValidVectorOperand(Arg) || |
395 isNormalizedPtr(Arg) || | 437 isNormalizedPtr(Arg) || |
396 isa<MDNode>(Arg))) | 438 isa<MDNode>(Arg))) |
397 return "bad intrinsic operand"; | 439 return "bad intrinsic operand"; |
398 } | 440 } |
399 | 441 |
400 // Disallow alignments other than 1 on memcpy() etc., for the | 442 // Disallow alignments other than 1 on memcpy() etc., for the |
401 // same reason that we disallow them on integer loads and | 443 // same reason that we disallow them on integer loads and |
402 // stores. | 444 // stores. |
403 if (const MemIntrinsic *MemOp = dyn_cast<MemIntrinsic>(Call)) { | 445 if (const MemIntrinsic *MemOp = dyn_cast<MemIntrinsic>(Call)) { |
404 // Avoid the getAlignment() method here because it aborts if | 446 // Avoid the getAlignment() method here because it aborts if |
(...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
449 if (!isNormalizedPtr(Inst->getOperand(PtrOperandIndex))) | 491 if (!isNormalizedPtr(Inst->getOperand(PtrOperandIndex))) |
450 return "bad function callee operand"; | 492 return "bad function callee operand"; |
451 break; | 493 break; |
452 } | 494 } |
453 | 495 |
454 case Instruction::Switch: { | 496 case Instruction::Switch: { |
455 // SwitchInst represents switch cases using array and vector | 497 // SwitchInst represents switch cases using array and vector |
456 // constants, which we normally reject, so we must check | 498 // constants, which we normally reject, so we must check |
457 // SwitchInst specially here. | 499 // SwitchInst specially here. |
458 const SwitchInst *Switch = cast<SwitchInst>(Inst); | 500 const SwitchInst *Switch = cast<SwitchInst>(Inst); |
| 501 // TODO(jfb) Do we want to allow vectors here and cases below? |
459 if (!isValidScalarOperand(Switch->getCondition())) | 502 if (!isValidScalarOperand(Switch->getCondition())) |
460 return "bad switch condition"; | 503 return "bad switch condition"; |
461 if (Switch->getCondition()->getType()->isIntegerTy(1)) | 504 if (Switch->getCondition()->getType()->isIntegerTy(1)) |
462 return "switch on i1"; | 505 return "switch on i1"; |
463 | 506 |
464 // SwitchInst requires the cases to be ConstantInts, but it | 507 // SwitchInst requires the cases to be ConstantInts, but it |
465 // doesn't require their types to be the same as the condition | 508 // doesn't require their types to be the same as the condition |
466 // value, so check all the cases too. | 509 // value, so check all the cases too. |
467 for (SwitchInst::ConstCaseIt Case = Switch->case_begin(), | 510 for (SwitchInst::ConstCaseIt Case = Switch->case_begin(), |
468 E = Switch->case_end(); Case != E; ++Case) { | 511 E = Switch->case_end(); Case != E; ++Case) { |
469 if (!isValidScalarOperand(Case.getCaseValue())) | 512 if (!isValidScalarOperand(Case.getCaseValue())) |
470 return "bad switch case"; | 513 return "bad switch case"; |
471 } | 514 } |
472 | 515 |
473 // Allow the instruction and skip the later checks. | 516 // Allow the instruction and skip the later checks. |
474 return NULL; | 517 return NULL; |
475 } | 518 } |
476 } | 519 } |
477 | 520 |
478 // Check the instruction's operands. We have already checked any | 521 // Check the instruction's operands. We have already checked any |
479 // pointer operands. Any remaining operands must be scalars. | 522 // pointer operands. Any remaining operands must be scalars or vectors. |
480 for (unsigned OpNum = 0, E = Inst->getNumOperands(); OpNum < E; ++OpNum) { | 523 for (unsigned OpNum = 0, E = Inst->getNumOperands(); OpNum < E; ++OpNum) { |
481 if (OpNum != PtrOperandIndex && | 524 if (OpNum != PtrOperandIndex && |
482 !isValidScalarOperand(Inst->getOperand(OpNum))) | 525 !(isValidScalarOperand(Inst->getOperand(OpNum)) || |
| 526 isValidVectorOperand(Inst->getOperand(OpNum)))) |
483 return "bad operand"; | 527 return "bad operand"; |
484 } | 528 } |
485 | 529 |
486 // Check arithmetic attributes. | 530 // Check arithmetic attributes. |
487 if (const OverflowingBinaryOperator *Op = | 531 if (const OverflowingBinaryOperator *Op = |
488 dyn_cast<OverflowingBinaryOperator>(Inst)) { | 532 dyn_cast<OverflowingBinaryOperator>(Inst)) { |
489 if (Op->hasNoUnsignedWrap()) | 533 if (Op->hasNoUnsignedWrap()) |
490 return "has \"nuw\" attribute"; | 534 return "has \"nuw\" attribute"; |
491 if (Op->hasNoSignedWrap()) | 535 if (Op->hasNoSignedWrap()) |
492 return "has \"nsw\" attribute"; | 536 return "has \"nsw\" attribute"; |
(...skipping 16 matching lines...) Expand all Loading... |
509 FI != FE; ++FI) { | 553 FI != FE; ++FI) { |
510 for (BasicBlock::const_iterator BBI = FI->begin(), BBE = FI->end(); | 554 for (BasicBlock::const_iterator BBI = FI->begin(), BBE = FI->end(); |
511 BBI != BBE; ++BBI) { | 555 BBI != BBE; ++BBI) { |
512 const Instruction *Inst = BBI; | 556 const Instruction *Inst = BBI; |
513 // Check the instruction opcode first. This simplifies testing, | 557 // Check the instruction opcode first. This simplifies testing, |
514 // because some instruction opcodes must be rejected out of hand | 558 // because some instruction opcodes must be rejected out of hand |
515 // (regardless of the instruction's result type) and the tests | 559 // (regardless of the instruction's result type) and the tests |
516 // check the reason for rejection. | 560 // check the reason for rejection. |
517 const char *Error = checkInstruction(BBI); | 561 const char *Error = checkInstruction(BBI); |
518 // Check the instruction's result type. | 562 // Check the instruction's result type. |
| 563 bool BadResult = false; |
519 if (!Error && !(PNaClABITypeChecker::isValidScalarType(Inst->getType()) || | 564 if (!Error && !(PNaClABITypeChecker::isValidScalarType(Inst->getType()) || |
| 565 PNaClABITypeChecker::isValidVectorType(Inst->getType()) || |
520 isNormalizedPtr(Inst) || | 566 isNormalizedPtr(Inst) || |
521 isa<AllocaInst>(Inst))) { | 567 isa<AllocaInst>(Inst))) { |
522 Error = "bad result type"; | 568 Error = "bad result type"; |
| 569 BadResult = true; |
523 } | 570 } |
524 if (Error) { | 571 if (Error) { |
525 Reporter->addError() << "Function " << F.getName() << | 572 Reporter->addError() |
526 " disallowed: " << Error << ": " << *BBI << "\n"; | 573 << "Function " << F.getName() << " disallowed: " << Error << ": " |
| 574 << (BadResult ? PNaClABITypeChecker::getTypeName(BBI->getType()) |
| 575 : "") << " " << *BBI << "\n"; |
527 } | 576 } |
528 | 577 |
529 // Check instruction attachment metadata. | 578 // Check instruction attachment metadata. |
530 SmallVector<std::pair<unsigned, MDNode*>, 4> MDForInst; | 579 SmallVector<std::pair<unsigned, MDNode*>, 4> MDForInst; |
531 BBI->getAllMetadata(MDForInst); | 580 BBI->getAllMetadata(MDForInst); |
532 | 581 |
533 for (unsigned i = 0, e = MDForInst.size(); i != e; i++) { | 582 for (unsigned i = 0, e = MDForInst.size(); i != e; i++) { |
534 if (!IsWhitelistedMetadata(MDForInst[i].first)) { | 583 if (!IsWhitelistedMetadata(MDForInst[i].first)) { |
535 Reporter->addError() | 584 Reporter->addError() |
536 << "Function " << F.getName() | 585 << "Function " << F.getName() |
(...skipping 18 matching lines...) Expand all Loading... |
555 } | 604 } |
556 | 605 |
557 char PNaClABIVerifyFunctions::ID = 0; | 606 char PNaClABIVerifyFunctions::ID = 0; |
558 INITIALIZE_PASS(PNaClABIVerifyFunctions, "verify-pnaclabi-functions", | 607 INITIALIZE_PASS(PNaClABIVerifyFunctions, "verify-pnaclabi-functions", |
559 "Verify functions for PNaCl", false, true) | 608 "Verify functions for PNaCl", false, true) |
560 | 609 |
561 FunctionPass *llvm::createPNaClABIVerifyFunctionsPass( | 610 FunctionPass *llvm::createPNaClABIVerifyFunctionsPass( |
562 PNaClABIErrorReporter *Reporter) { | 611 PNaClABIErrorReporter *Reporter) { |
563 return new PNaClABIVerifyFunctions(Reporter); | 612 return new PNaClABIVerifyFunctions(Reporter); |
564 } | 613 } |
OLD | NEW |