| Index: lib/Analysis/NaCl/PNaClABIVerifyModule.cpp
|
| diff --git a/lib/Analysis/NaCl/PNaClABIVerifyModule.cpp b/lib/Analysis/NaCl/PNaClABIVerifyModule.cpp
|
| index 7836484c2f868e02590d9507e11c6dd72c69ac33..049150a99b4a904cabc3ed44dea8f638b02136ad 100644
|
| --- a/lib/Analysis/NaCl/PNaClABIVerifyModule.cpp
|
| +++ b/lib/Analysis/NaCl/PNaClABIVerifyModule.cpp
|
| @@ -13,13 +13,15 @@
|
| //
|
| //===----------------------------------------------------------------------===//
|
|
|
| -#include "llvm/Pass.h"
|
| #include "llvm/ADT/Twine.h"
|
| #include "llvm/Analysis/NaCl.h"
|
| #include "llvm/IR/Constants.h"
|
| #include "llvm/IR/DerivedTypes.h"
|
| +#include "llvm/IR/NaClIntrinsics.h"
|
| +#include "llvm/IR/Instructions.h"
|
| #include "llvm/IR/Intrinsics.h"
|
| #include "llvm/IR/Module.h"
|
| +#include "llvm/Pass.h"
|
| #include "llvm/Support/Debug.h"
|
| #include "llvm/Support/raw_ostream.h"
|
|
|
| @@ -66,7 +68,8 @@ class PNaClABIVerifyModule : public ModulePass {
|
| virtual void print(raw_ostream &O, const Module *M) const;
|
| private:
|
| void checkGlobalValueCommon(const GlobalValue *GV);
|
| - bool isWhitelistedIntrinsic(const Function *F, unsigned ID);
|
| + bool isWhitelistedIntrinsic(const NaCl::AtomicIntrinsics *AI,
|
| + const Function *F, Intrinsic::ID ID);
|
| bool isWhitelistedMetadata(const NamedMDNode *MD);
|
| void checkGlobalIsFlattened(const GlobalVariable *GV);
|
| PNaClABIErrorReporter *Reporter;
|
| @@ -170,6 +173,23 @@ static bool isWhitelistedBswap(const Function *F) {
|
| return TypeAcceptable(ParamType, AcceptableTypes);
|
| }
|
|
|
| +static bool isWhitelistedAtomic(const NaCl::AtomicIntrinsics *AI,
|
| + const Function *F, Intrinsic::ID ID) {
|
| + FunctionType *FT = F->getFunctionType();
|
| + for (NaCl::AtomicIntrinsics::const_iterator I = AI->begin(ID),
|
| + E = AI->end(ID);
|
| + I != E; ++I) {
|
| + bool Match = true;
|
| + for (size_t P = 0; P != I->NumParams; ++P) {
|
| + if (I->Parameter(P) != FT->getParamType(P))
|
| + Match = false;
|
| + }
|
| + if (Match)
|
| + return true;
|
| + }
|
| + return false;
|
| +}
|
| +
|
| // We accept cttz, ctlz, and ctpop for a limited set of types (i32, i64).
|
| static bool isWhitelistedCountBits(const Function *F, unsigned num_params) {
|
| FunctionType *FT = F->getFunctionType();
|
| @@ -181,11 +201,11 @@ static bool isWhitelistedCountBits(const Function *F, unsigned num_params) {
|
| return TypeAcceptable(ParamType, AcceptableTypes);
|
| }
|
|
|
| -bool PNaClABIVerifyModule::isWhitelistedIntrinsic(const Function *F,
|
| - unsigned ID) {
|
| +bool PNaClABIVerifyModule::isWhitelistedIntrinsic(
|
| + const NaCl::AtomicIntrinsics *AI, const Function *F, Intrinsic::ID ID) {
|
| // Keep 3 categories of intrinsics for now.
|
| - // (1) Allowed always
|
| - // (2) Never allowed
|
| + // (1) Allowed.
|
| + // (2) Never allowed.
|
| // (3) "Dev" intrinsics, which may or may not be allowed.
|
| // "Dev" intrinsics are controlled by the PNaClABIAllowDevIntrinsics flag.
|
| // Please keep these sorted or grouped in a sensible way, within
|
| @@ -193,19 +213,25 @@ bool PNaClABIVerifyModule::isWhitelistedIntrinsic(const Function *F,
|
| switch(ID) {
|
| // Disallow by default.
|
| default: return false;
|
| - // (1) Always allowed.
|
| - case Intrinsic::bswap: return isWhitelistedBswap(F);
|
| - case Intrinsic::ctlz:
|
| - case Intrinsic::cttz: return isWhitelistedCountBits(F, 2);
|
| - case Intrinsic::ctpop: return isWhitelistedCountBits(F, 1);
|
| + // (1) Allowed.
|
| case Intrinsic::memcpy:
|
| case Intrinsic::memmove:
|
| case Intrinsic::memset:
|
| - case Intrinsic::nacl_read_tp:
|
| case Intrinsic::nacl_setjmp:
|
| case Intrinsic::nacl_longjmp:
|
| + case Intrinsic::nacl_read_tp:
|
| case Intrinsic::trap:
|
| return true;
|
| + case Intrinsic::nacl_atomic_load:
|
| + case Intrinsic::nacl_atomic_store:
|
| + case Intrinsic::nacl_atomic_rmw:
|
| + case Intrinsic::nacl_atomic_cmpxchg:
|
| + case Intrinsic::nacl_atomic_fence:
|
| + return isWhitelistedAtomic(AI, F, ID);
|
| + case Intrinsic::bswap: return isWhitelistedBswap(F);
|
| + case Intrinsic::ctlz:
|
| + case Intrinsic::cttz: return isWhitelistedCountBits(F, 2);
|
| + case Intrinsic::ctpop: return isWhitelistedCountBits(F, 1);
|
|
|
| // (2) Known to be never allowed.
|
| case Intrinsic::not_intrinsic:
|
| @@ -394,10 +420,12 @@ bool PNaClABIVerifyModule::runOnModule(Module &M) {
|
| " is an alias (disallowed)\n";
|
| }
|
|
|
| + NaCl::AtomicIntrinsics AI(M.getContext());
|
| for (Module::const_iterator MI = M.begin(), ME = M.end(); MI != ME; ++MI) {
|
| if (MI->isIntrinsic()) {
|
| // Check intrinsics.
|
| - if (!isWhitelistedIntrinsic(MI, MI->getIntrinsicID())) {
|
| + Intrinsic::ID ID = (Intrinsic::ID) MI->getIntrinsicID();
|
| + if (!isWhitelistedIntrinsic(&AI, MI, ID)) {
|
| Reporter->addError() << "Function " << MI->getName()
|
| << " is a disallowed LLVM intrinsic\n";
|
| }
|
|
|