diff options
author | Jan Voung <jvoung@chromium.org> | 2013-05-22 14:34:10 -0700 |
---|---|---|
committer | Jan Voung <jvoung@chromium.org> | 2013-05-22 14:34:10 -0700 |
commit | 501900058c0815d35e630d416e3d4e1373b75b9c (patch) | |
tree | 4d75fbe1728d3922cce31a3c29247e89dd5e0c50 /lib/Analysis/NaCl | |
parent | 9f0ec130483d6bfb0357dcf05b49fa91d6c265f5 (diff) |
Promote bswap i16, i32, and i64 to be allowed llvm intrinsics.
Disallow i1, i8, which don't make sense for "byte" swapping.
None of these generate outcalls to compiler_rt.
Test coverage:
* test/CodeGen/AArch64/dp1.ll (only testing i32, i64)
* test/CodeGen/ARM/rev.ll (only testing i16)
* test/CodeGen/Mips/bswap.ll (only testing i32, i64)
* test/CodeGen/X86/bswap.ll (i16, i32, i64, on i686)
* test/NaCl/{ARM,X86}/intrinsics-bitmanip.ll (i16, i32, i64)
(maybe the last set of tests could be merged into the
upstream tests)
For targets without native i16 bswap, the i16 could just be
a bswap on an i32 plus a shift right 16.
Other test coverage:
* gcc/testsuite/gcc.dg/builtin-bswap-[1,2,3,4,5].c
Misc: style cleanups, and add comments to the undocumented intrinsics in the dev list.
BUG=https://code.google.com/p/nativeclient/issues/detail?id=3378
R=dschuff@chromium.org
Review URL: https://codereview.chromium.org/14914011
Diffstat (limited to 'lib/Analysis/NaCl')
-rw-r--r-- | lib/Analysis/NaCl/PNaClABIVerifyModule.cpp | 55 |
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 { |