Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(266)

Unified Diff: lib/Analysis/NaCl/PNaClABIVerifyModule.cpp

Issue 17777004: Concurrency support for PNaCl ABI (Closed) Base URL: http://git.chromium.org/native_client/pnacl-llvm.git@master
Patch Set: Created 7 years, 6 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: lib/Analysis/NaCl/PNaClABIVerifyModule.cpp
diff --git a/lib/Analysis/NaCl/PNaClABIVerifyModule.cpp b/lib/Analysis/NaCl/PNaClABIVerifyModule.cpp
index 7836484c2f868e02590d9507e11c6dd72c69ac33..48fe8baeeb7b722d604e1a817234febd01c9e0dc 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/Instructions.h"
#include "llvm/IR/Intrinsics.h"
#include "llvm/IR/Module.h"
+#include "llvm/IR/NaCl.h"
+#include "llvm/Pass.h"
#include "llvm/Support/Debug.h"
#include "llvm/Support/raw_ostream.h"
@@ -181,12 +183,81 @@ static bool isWhitelistedCountBits(const Function *F, unsigned num_params) {
return TypeAcceptable(ParamType, AcceptableTypes);
}
+// The signature for atomics is:
+// T nacl.atomic.<size>(int32_t operation, T *location, T value,
+// T old_value, int32_t memory_order);
+// With:
+// - T in {i8, i16, i32, i64}.
+// - operation as a valid NaCl::AtomicOperation.
+// - memory_order as a valid NaCl::MemoryOrder.
+static bool isWhitelistedAtomic(const Function *F, unsigned ID) {
+ LLVMContext &C = F->getContext();
+ FunctionType *FT = F->getFunctionType();
+
+ Type *ReturnType = FT->getReturnType();
+ switch (ID) {
+ default: llvm_unreachable("unhandled atomic intrinsic");
+ case Intrinsic::nacl_atomic_8:
+ if (ReturnType != Type::getInt8Ty(C)) return false;
eliben 2013/06/26 16:20:57 Let's separate type checking from an intrinsic bei
JF 2013/06/26 22:23:12 Done.
+ break;
+ case Intrinsic::nacl_atomic_16:
Mark Seaborn 2013/06/26 14:33:41 I don't think we have validator support for 16-bit
JF 2013/06/26 15:52:29 Vlad thinks it can be in for M30. Presumably this
Mark Seaborn 2013/06/26 16:47:01 I don't think we should block PNaCl ABI stability
JF 2013/06/26 22:56:36 Agreed, and this in no way blocks PNaCl ABI stabil
Mark Seaborn 2013/06/27 01:04:33 I'm not suggesting *permanently* penalizing pexes.
JF 2013/06/27 01:31:39 16-bit atomics are supported on all architectures.
+ if (ReturnType != Type::getInt16Ty(C)) return false;
+ break;
+ case Intrinsic::nacl_atomic_32:
+ if (ReturnType != Type::getInt32Ty(C)) return false;
+ break;
+ case Intrinsic::nacl_atomic_64:
Mark Seaborn 2013/06/26 14:33:41 I think we should omit 64-bit atomics, because MIP
JF 2013/06/26 15:52:29 Our users will, and atomic support through locks i
+ if (ReturnType != Type::getInt64Ty(C)) return false;
+ break;
+ }
+
+ if ((FT->getNumParams() != 5) ||
+ (FT->getParamType(0) != Type::getInt32Ty(C)) ||
+ (!FT->getParamType(1)->isPointerTy()) ||
+ (FT->getParamType(1)->getPointerElementType() != ReturnType) ||
+ (FT->getParamType(2) != ReturnType) ||
+ (FT->getParamType(3) != ReturnType) ||
+ (FT->getParamType(4) != Type::getInt32Ty(C)))
+ return false;
eliben 2013/06/26 16:20:57 Ditto.
JF 2013/06/26 22:23:12 Moved to a separate function, with the above too.
+
+ // Validate the operation and memory_order arguments have whitelisted values.
+ for (Value::const_use_iterator Call(F->use_begin()), CallEnd(F->use_end());
eliben 2013/06/26 16:20:57 Is there a reason here to use constructor syntax f
JF 2013/06/26 22:23:12 Done.
+ Call != CallEnd; ++Call) {
+ if (const CallInst *C = dyn_cast<CallInst>(*Call)) {
+ assert(C->getNumArgOperands() == 5 && "call should have as many "
eliben 2013/06/26 16:20:57 Should this not be caught by LLVM's normal verific
JF 2013/06/26 22:23:12 Yes, that's why I used an assert.
+ "arguments as the corresponding intrinsic");
+ const Value *Operation = C->getArgOperand(0);
+ const Value *MemoryOrder = C->getArgOperand(4);
+ const Constant *OperationC = dyn_cast<Constant>(Operation);
+ const Constant *MemoryOrderC = dyn_cast<Constant>(MemoryOrder);
+ if (!Operation || !MemoryOrder)
eliben 2013/06/26 16:20:57 This is even worse :) You're type checking calls t
JF 2013/06/26 22:23:12 I don't agree: it's part of the intrinsic's requir
+ return false;
+ const APInt &OperationI = OperationC->getUniqueInteger();
+ const APInt &MemoryOrderI = MemoryOrderC->getUniqueInteger();
+ if (OperationI.ule(NaCl::AtomicInvalid) ||
+ OperationI.uge(NaCl::AtomicNum))
+ return false;
+ if (MemoryOrderI.ule(NaCl::MemoryOrderInvalid) ||
+ MemoryOrderI.uge(NaCl::MemoryOrderNum))
+ return false;
+ // TODO For now only sequential consistency is allowed.
+ if (MemoryOrderI != NaCl::MemoryOrderSequentiallyConsistent)
+ return false;
+ } else {
+ return false;
+ }
+ }
+
+ return true;
+}
+
bool PNaClABIVerifyModule::isWhitelistedIntrinsic(const Function *F,
unsigned ID) {
// Keep 3 categories of intrinsics for now.
eliben 2013/06/26 16:20:57 I don't think the distinction between "always allo
JF 2013/06/26 22:23:12 If it's allowed always then it should always be al
// (1) Allowed always
- // (2) Never allowed
- // (3) "Dev" intrinsics, which may or may not be allowed.
+ // (2) Allowed with certain restrictions.
+ // (3) Never allowed
+ // (4) "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
// each category.
@@ -194,10 +265,6 @@ bool PNaClABIVerifyModule::isWhitelistedIntrinsic(const Function *F,
// 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);
case Intrinsic::memcpy:
case Intrinsic::memmove:
case Intrinsic::memset:
@@ -207,7 +274,17 @@ bool PNaClABIVerifyModule::isWhitelistedIntrinsic(const Function *F,
case Intrinsic::trap:
return true;
- // (2) Known to be never allowed.
+ // (2) Allowed with certain restrictions.
+ case Intrinsic::bswap: return isWhitelistedBswap(F);
+ case Intrinsic::ctlz:
+ case Intrinsic::cttz: return isWhitelistedCountBits(F, 2);
+ case Intrinsic::ctpop: return isWhitelistedCountBits(F, 1);
+ case Intrinsic::nacl_atomic_8:
+ case Intrinsic::nacl_atomic_16:
+ case Intrinsic::nacl_atomic_32:
+ case Intrinsic::nacl_atomic_64: return isWhitelistedAtomic(F, ID);
+
+ // (3) Known to be never allowed.
case Intrinsic::not_intrinsic:
// Trampolines depend on a target-specific-sized/aligned buffer.
case Intrinsic::adjust_trampoline:
@@ -269,7 +346,7 @@ bool PNaClABIVerifyModule::isWhitelistedIntrinsic(const Function *F,
case Intrinsic::flt_rounds:
return false;
- // (3) Dev intrinsics.
+ // (4) Dev intrinsics.
case Intrinsic::dbg_declare:
case Intrinsic::dbg_value:
return PNaClABIAllowDevIntrinsics || PNaClABIAllowDebugMetadata;

Powered by Google App Engine
This is Rietveld 408576698