Index: lib/Analysis/NaCl/PNaClABIVerifyModule.cpp |
diff --git a/lib/Analysis/NaCl/PNaClABIVerifyModule.cpp b/lib/Analysis/NaCl/PNaClABIVerifyModule.cpp |
index 44c027fba4690762eb1facec317d022db28bbf95..eacb4031b357d586dc2f403f703ce702c6768dc9 100644 |
--- a/lib/Analysis/NaCl/PNaClABIVerifyModule.cpp |
+++ b/lib/Analysis/NaCl/PNaClABIVerifyModule.cpp |
@@ -62,9 +62,9 @@ class PNaClABIVerifyModule : public ModulePass { |
bool runOnModule(Module &M); |
virtual void print(raw_ostream &O, const Module *M) const; |
private: |
- void CheckGlobalValueCommon(const GlobalValue *GV); |
- bool IsWhitelistedIntrinsic(const Function* F, unsigned ID); |
- bool IsWhitelistedMetadata(const NamedMDNode *MD); |
+ void checkGlobalValueCommon(const GlobalValue *GV); |
+ bool isWhitelistedIntrinsic(const Function *F, unsigned ID); |
+ bool isWhitelistedMetadata(const NamedMDNode *MD); |
PNaClABITypeChecker TC; |
PNaClABIErrorReporter *Reporter; |
bool ReporterIsOwned; |
@@ -100,7 +100,7 @@ static const char *linkageName(GlobalValue::LinkageTypes LT) { |
// Check linkage type and section attributes, which are the same for |
// GlobalVariables and Functions. |
-void PNaClABIVerifyModule::CheckGlobalValueCommon(const GlobalValue *GV) { |
+void PNaClABIVerifyModule::checkGlobalValueCommon(const GlobalValue *GV) { |
assert(!isa<GlobalAlias>(GV)); |
const char *GVTypeName = isa<GlobalVariable>(GV) ? |
"Variable " : "Function "; |
@@ -122,7 +122,32 @@ void PNaClABIVerifyModule::CheckGlobalValueCommon(const GlobalValue *GV) { |
} |
} |
-bool PNaClABIVerifyModule::IsWhitelistedIntrinsic(const Function* F, |
+static bool TypeAcceptable(const Type *T, |
+ const ArrayRef<Type*> &AcceptableTypes) { |
+ for (ArrayRef<Type*>::iterator I = AcceptableTypes.begin(), |
+ E = AcceptableTypes.end(); I != E; ++I) |
+ if (*I == T) |
+ return true; |
+ return false; |
+} |
+ |
+// We accept bswap for a limited set of types (i16, i32, i64). |
+// The various backends are able to generate instructions to |
+// implement the intrinsic. Also, i16 and i64 are easy to |
+// implement as along as there is a way to do i32. |
+static bool isWhitelistedBswap(const Function *F) { |
+ FunctionType *FT = F->getFunctionType(); |
+ if (FT->getNumParams() != 1) |
+ return false; |
+ Type *ParamType = FT->getParamType(0); |
+ LLVMContext &C = F->getContext(); |
+ Type *AcceptableTypes[] = { Type::getInt16Ty(C), |
+ Type::getInt32Ty(C), |
+ Type::getInt64Ty(C) }; |
+ return TypeAcceptable(ParamType, AcceptableTypes); |
+} |
+ |
+bool PNaClABIVerifyModule::isWhitelistedIntrinsic(const Function *F, |
unsigned ID) { |
// Keep 3 categories of intrinsics for now. |
// (1) Allowed always |
@@ -135,6 +160,7 @@ bool PNaClABIVerifyModule::IsWhitelistedIntrinsic(const Function* F, |
// Disallow by default. |
default: return false; |
// (1) Always allowed. |
+ case Intrinsic::bswap: return isWhitelistedBswap(F); |
case Intrinsic::invariant_end: |
case Intrinsic::invariant_start: |
case Intrinsic::lifetime_end: |
@@ -179,7 +205,6 @@ bool PNaClABIVerifyModule::IsWhitelistedIntrinsic(const Function* F, |
case Intrinsic::dbg_declare: |
case Intrinsic::dbg_value: |
return PNaClABIAllowDevIntrinsics || PNaClABIAllowDebugMetadata; |
- case Intrinsic::bswap: // Support via compiler_rt if arch doesn't have it? |
case Intrinsic::cos: // Rounding not defined: support with fast-math? |
case Intrinsic::ctlz: // Support via compiler_rt if arch doesn't have it? |
case Intrinsic::ctpop: // Support via compiler_rt if arch doesn't have it? |
@@ -187,7 +212,9 @@ bool PNaClABIVerifyModule::IsWhitelistedIntrinsic(const Function* F, |
case Intrinsic::exp: // Rounding not defined: support with fast-math? |
case Intrinsic::exp2: // Rounding not defined: support with fast-math? |
case Intrinsic::expect: // From __builtin_expect. |
- case Intrinsic::flt_rounds: |
+ case Intrinsic::flt_rounds: // For FLT_ROUNDS macro from float.h. |
+ // We do not have fesetround() in newlib, can we return a |
+ // consistent rounding mode though? |
case Intrinsic::log: // Rounding not defined: support with fast-math? |
case Intrinsic::log2: // Rounding not defined: support with fast-math? |
case Intrinsic::log10: // Rounding not defined: support with fast-math? |
@@ -196,9 +223,9 @@ bool PNaClABIVerifyModule::IsWhitelistedIntrinsic(const Function* F, |
case Intrinsic::powi: // Rounding not defined: support with fast-math? |
case Intrinsic::prefetch: // Could ignore if target doesn't support? |
case Intrinsic::sin: // Rounding not defined: support with fast-math? |
- case Intrinsic::sqrt: |
+ case Intrinsic::sqrt: // Rounding is defined, but setting errno up to libm. |
case Intrinsic::stackrestore: // Used to support C99 VLAs. |
- case Intrinsic::stacksave: |
+ case Intrinsic::stacksave: // Used to support C99 VLAs. |
// the *_with_overflow return struct types, so we'll need to fix these. |
case Intrinsic::sadd_with_overflow: // Introduced by -ftrapv |
case Intrinsic::ssub_with_overflow: |
@@ -210,7 +237,7 @@ bool PNaClABIVerifyModule::IsWhitelistedIntrinsic(const Function* F, |
} |
} |
-bool PNaClABIVerifyModule::IsWhitelistedMetadata(const NamedMDNode* MD) { |
+bool PNaClABIVerifyModule::isWhitelistedMetadata(const NamedMDNode *MD) { |
return MD->getName().startswith("llvm.dbg.") && PNaClABIAllowDebugMetadata; |
} |
@@ -234,7 +261,7 @@ bool PNaClABIVerifyModule::runOnModule(Module &M) { |
} |
} |
- CheckGlobalValueCommon(MI); |
+ checkGlobalValueCommon(MI); |
if (MI->isThreadLocal()) { |
Reporter->addError() << "Variable " << MI->getName() << |
@@ -252,7 +279,7 @@ bool PNaClABIVerifyModule::runOnModule(Module &M) { |
for (Module::const_iterator MI = M.begin(), ME = M.end(); MI != ME; ++MI) { |
// Check intrinsics. |
if (MI->isIntrinsic() |
- && !IsWhitelistedIntrinsic(MI, MI->getIntrinsicID())) { |
+ && !isWhitelistedIntrinsic(MI, MI->getIntrinsicID())) { |
Reporter->addError() << "Function " << MI->getName() |
<< " is a disallowed LLVM intrinsic\n"; |
} |
@@ -279,7 +306,7 @@ bool PNaClABIVerifyModule::runOnModule(Module &M) { |
" is a variable-argument function (disallowed)\n"; |
} |
- CheckGlobalValueCommon(MI); |
+ checkGlobalValueCommon(MI); |
if (MI->hasGC()) { |
Reporter->addError() << "Function " << MI->getName() << |
@@ -290,7 +317,7 @@ bool PNaClABIVerifyModule::runOnModule(Module &M) { |
// Check named metadata nodes |
for (Module::const_named_metadata_iterator I = M.named_metadata_begin(), |
E = M.named_metadata_end(); I != E; ++I) { |
- if (!IsWhitelistedMetadata(I)) { |
+ if (!isWhitelistedMetadata(I)) { |
Reporter->addError() << "Named metadata node " << I->getName() |
<< " is disallowed\n"; |
} else { |