aboutsummaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
Diffstat (limited to 'lib')
-rw-r--r--lib/Analysis/NaCl/PNaClABIVerifyModule.cpp55
1 files changed, 41 insertions, 14 deletions
diff --git a/lib/Analysis/NaCl/PNaClABIVerifyModule.cpp b/lib/Analysis/NaCl/PNaClABIVerifyModule.cpp
index 44c027fba4..eacb4031b3 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 {