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

Side by Side 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: Fix whitespace. 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 unified diff | Download patch
OLDNEW
1 //===- PNaClABIVerifyModule.cpp - Verify PNaCl ABI rules ------------------===// 1 //===- PNaClABIVerifyModule.cpp - Verify PNaCl ABI rules ------------------===//
2 // 2 //
3 // The LLVM Compiler Infrastructure 3 // The LLVM Compiler Infrastructure
4 // 4 //
5 // This file is distributed under the University of Illinois Open Source 5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details. 6 // License. See LICENSE.TXT for details.
7 // 7 //
8 //===----------------------------------------------------------------------===// 8 //===----------------------------------------------------------------------===//
9 // 9 //
10 // Verify module-level PNaCl ABI requirements (specifically those that do not 10 // Verify module-level PNaCl ABI requirements (specifically those that do not
11 // require looking at the function bodies) 11 // require looking at the function bodies)
12 // 12 //
13 // 13 //
14 //===----------------------------------------------------------------------===// 14 //===----------------------------------------------------------------------===//
15 15
16 #include "llvm/Pass.h"
17 #include "llvm/ADT/Twine.h" 16 #include "llvm/ADT/Twine.h"
18 #include "llvm/Analysis/NaCl.h" 17 #include "llvm/Analysis/NaCl.h"
19 #include "llvm/IR/Constants.h" 18 #include "llvm/IR/Constants.h"
20 #include "llvm/IR/DerivedTypes.h" 19 #include "llvm/IR/DerivedTypes.h"
20 #include "llvm/IR/Instructions.h"
21 #include "llvm/IR/Intrinsics.h" 21 #include "llvm/IR/Intrinsics.h"
22 #include "llvm/IR/Module.h" 22 #include "llvm/IR/Module.h"
23 #include "llvm/IR/NaCl.h"
24 #include "llvm/Pass.h"
23 #include "llvm/Support/Debug.h" 25 #include "llvm/Support/Debug.h"
24 #include "llvm/Support/raw_ostream.h" 26 #include "llvm/Support/raw_ostream.h"
25 27
26 #include "PNaClABITypeChecker.h" 28 #include "PNaClABITypeChecker.h"
27 using namespace llvm; 29 using namespace llvm;
28 30
29 namespace llvm { 31 namespace llvm {
30 cl::opt<bool> 32 cl::opt<bool>
31 PNaClABIAllowDebugMetadata("pnaclabi-allow-debug-metadata", 33 PNaClABIAllowDebugMetadata("pnaclabi-allow-debug-metadata",
32 cl::desc("Allow debug metadata during PNaCl ABI verification."), 34 cl::desc("Allow debug metadata during PNaCl ABI verification."),
(...skipping 141 matching lines...) Expand 10 before | Expand all | Expand 10 after
174 static bool isWhitelistedCountBits(const Function *F, unsigned num_params) { 176 static bool isWhitelistedCountBits(const Function *F, unsigned num_params) {
175 FunctionType *FT = F->getFunctionType(); 177 FunctionType *FT = F->getFunctionType();
176 if (FT->getNumParams() != num_params) 178 if (FT->getNumParams() != num_params)
177 return false; 179 return false;
178 Type *ParamType = FT->getParamType(0); 180 Type *ParamType = FT->getParamType(0);
179 LLVMContext &C = F->getContext(); 181 LLVMContext &C = F->getContext();
180 Type *AcceptableTypes[] = { Type::getInt32Ty(C), Type::getInt64Ty(C) }; 182 Type *AcceptableTypes[] = { Type::getInt32Ty(C), Type::getInt64Ty(C) };
181 return TypeAcceptable(ParamType, AcceptableTypes); 183 return TypeAcceptable(ParamType, AcceptableTypes);
182 } 184 }
183 185
186 // The signature for atomics is:
187 // T nacl.atomic.<size>(int32_t operation, T *location, T value,
Derek Schuff 2013/06/26 17:03:29 should be llvm.nacl.atomic.<size> when represented
JF 2013/06/26 23:41:12 Yes, I fixed all of these in a previous change.
188 // T old_value, int32_t memory_order);
189 // With:
190 // - T in {i8, i16, i32, i64}.
191 // - operation as a valid NaCl::AtomicOperation.
192 // - memory_order as a valid NaCl::MemoryOrder.
193 static bool isWhitelistedAtomic(const Function *F, unsigned ID) {
194 LLVMContext &C = F->getContext();
195 FunctionType *FT = F->getFunctionType();
196
197 Type *ReturnType = FT->getReturnType();
198 switch (ID) {
199 default: llvm_unreachable("unhandled atomic intrinsic");
200 case Intrinsic::nacl_atomic_8:
201 if (ReturnType != Type::getInt8Ty(C)) return false;
202 break;
203 case Intrinsic::nacl_atomic_16:
204 if (ReturnType != Type::getInt16Ty(C)) return false;
205 break;
206 case Intrinsic::nacl_atomic_32:
207 if (ReturnType != Type::getInt32Ty(C)) return false;
208 break;
209 case Intrinsic::nacl_atomic_64:
210 if (ReturnType != Type::getInt64Ty(C)) return false;
211 break;
212 }
213
214 if ((FT->getNumParams() != 5) ||
215 (FT->getParamType(0) != Type::getInt32Ty(C)) ||
216 (!FT->getParamType(1)->isPointerTy()) ||
217 (FT->getParamType(1)->getPointerElementType() != ReturnType) ||
218 (FT->getParamType(2) != ReturnType) ||
219 (FT->getParamType(3) != ReturnType) ||
220 (FT->getParamType(4) != Type::getInt32Ty(C)))
221 return false;
222
223 // Validate the operation and memory_order arguments have whitelisted values.
224 for (Value::const_use_iterator Call(F->use_begin()), CallEnd(F->use_end());
Derek Schuff 2013/06/26 17:03:29 = instead of constructor syntax here too.
JF 2013/06/26 23:41:12 Done in a previous change.
225 Call != CallEnd; ++Call) {
226 if (const CallInst *C = dyn_cast<CallInst>(*Call)) {
227 assert(C->getNumArgOperands() == 5 && "call should have as many "
228 "arguments as the corresponding intrinsic");
229 const Value *Operation = C->getArgOperand(0);
230 const Value *MemoryOrder = C->getArgOperand(4);
231 const Constant *OperationC = dyn_cast<Constant>(Operation);
232 const Constant *MemoryOrderC = dyn_cast<Constant>(MemoryOrder);
233 if (!Operation || !MemoryOrder)
234 return false;
235 const APInt &OperationI = OperationC->getUniqueInteger();
236 const APInt &MemoryOrderI = MemoryOrderC->getUniqueInteger();
237 if (OperationI.ule(NaCl::AtomicInvalid) ||
238 OperationI.uge(NaCl::AtomicNum))
239 return false;
240 if (MemoryOrderI.ule(NaCl::MemoryOrderInvalid) ||
241 MemoryOrderI.uge(NaCl::MemoryOrderNum))
242 return false;
243 // TODO For now only sequential consistency is allowed.
244 if (MemoryOrderI != NaCl::MemoryOrderSequentiallyConsistent)
245 return false;
246 } else {
247 return false;
248 }
249 }
250
251 return true;
252 }
253
184 bool PNaClABIVerifyModule::isWhitelistedIntrinsic(const Function *F, 254 bool PNaClABIVerifyModule::isWhitelistedIntrinsic(const Function *F,
185 unsigned ID) { 255 unsigned ID) {
186 // Keep 3 categories of intrinsics for now. 256 // Keep 3 categories of intrinsics for now.
Derek Schuff 2013/06/26 17:03:29 new! now with 33% more categories!
JF 2013/06/26 23:41:12 <marquee>
187 // (1) Allowed always 257 // (1) Allowed always
188 // (2) Never allowed 258 // (2) Allowed with certain restrictions.
189 // (3) "Dev" intrinsics, which may or may not be allowed. 259 // (3) Never allowed
260 // (4) "Dev" intrinsics, which may or may not be allowed.
190 // "Dev" intrinsics are controlled by the PNaClABIAllowDevIntrinsics flag. 261 // "Dev" intrinsics are controlled by the PNaClABIAllowDevIntrinsics flag.
191 // Please keep these sorted or grouped in a sensible way, within 262 // Please keep these sorted or grouped in a sensible way, within
192 // each category. 263 // each category.
193 switch(ID) { 264 switch(ID) {
194 // Disallow by default. 265 // Disallow by default.
195 default: return false; 266 default: return false;
196 // (1) Always allowed. 267 // (1) Always allowed.
197 case Intrinsic::bswap: return isWhitelistedBswap(F);
198 case Intrinsic::ctlz:
199 case Intrinsic::cttz: return isWhitelistedCountBits(F, 2);
200 case Intrinsic::ctpop: return isWhitelistedCountBits(F, 1);
201 case Intrinsic::memcpy: 268 case Intrinsic::memcpy:
202 case Intrinsic::memmove: 269 case Intrinsic::memmove:
203 case Intrinsic::memset: 270 case Intrinsic::memset:
204 case Intrinsic::nacl_read_tp: 271 case Intrinsic::nacl_read_tp:
205 case Intrinsic::nacl_setjmp: 272 case Intrinsic::nacl_setjmp:
206 case Intrinsic::nacl_longjmp: 273 case Intrinsic::nacl_longjmp:
207 case Intrinsic::trap: 274 case Intrinsic::trap:
208 return true; 275 return true;
209 276
210 // (2) Known to be never allowed. 277 // (2) Allowed with certain restrictions.
278 case Intrinsic::bswap: return isWhitelistedBswap(F);
279 case Intrinsic::ctlz:
280 case Intrinsic::cttz: return isWhitelistedCountBits(F, 2);
281 case Intrinsic::ctpop: return isWhitelistedCountBits(F, 1);
282 case Intrinsic::nacl_atomic_8:
283 case Intrinsic::nacl_atomic_16:
284 case Intrinsic::nacl_atomic_32:
285 case Intrinsic::nacl_atomic_64: return isWhitelistedAtomic(F, ID);
286
287 // (3) Known to be never allowed.
211 case Intrinsic::not_intrinsic: 288 case Intrinsic::not_intrinsic:
212 // Trampolines depend on a target-specific-sized/aligned buffer. 289 // Trampolines depend on a target-specific-sized/aligned buffer.
213 case Intrinsic::adjust_trampoline: 290 case Intrinsic::adjust_trampoline:
214 case Intrinsic::init_trampoline: 291 case Intrinsic::init_trampoline:
215 // CXX exception handling is not stable. 292 // CXX exception handling is not stable.
216 case Intrinsic::eh_dwarf_cfa: 293 case Intrinsic::eh_dwarf_cfa:
217 case Intrinsic::eh_return_i32: 294 case Intrinsic::eh_return_i32:
218 case Intrinsic::eh_return_i64: 295 case Intrinsic::eh_return_i64:
219 case Intrinsic::eh_sjlj_callsite: 296 case Intrinsic::eh_sjlj_callsite:
220 case Intrinsic::eh_sjlj_functioncontext: 297 case Intrinsic::eh_sjlj_functioncontext:
(...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after
262 case Intrinsic::sin: // Rounding not defined: support with fast-math? 339 case Intrinsic::sin: // Rounding not defined: support with fast-math?
263 // We run -lower-expect to convert Intrinsic::expect into branch weights 340 // We run -lower-expect to convert Intrinsic::expect into branch weights
264 // and consume in the middle-end. The backend just ignores llvm.expect. 341 // and consume in the middle-end. The backend just ignores llvm.expect.
265 case Intrinsic::expect: 342 case Intrinsic::expect:
266 // For FLT_ROUNDS macro from float.h. It works for ARM and X86 343 // For FLT_ROUNDS macro from float.h. It works for ARM and X86
267 // (but not MIPS). Also, wait until we add a set_flt_rounds intrinsic 344 // (but not MIPS). Also, wait until we add a set_flt_rounds intrinsic
268 // before we bless this. 345 // before we bless this.
269 case Intrinsic::flt_rounds: 346 case Intrinsic::flt_rounds:
270 return false; 347 return false;
271 348
272 // (3) Dev intrinsics. 349 // (4) Dev intrinsics.
273 case Intrinsic::dbg_declare: 350 case Intrinsic::dbg_declare:
274 case Intrinsic::dbg_value: 351 case Intrinsic::dbg_value:
275 return PNaClABIAllowDevIntrinsics || PNaClABIAllowDebugMetadata; 352 return PNaClABIAllowDevIntrinsics || PNaClABIAllowDebugMetadata;
276 case Intrinsic::nacl_target_arch: // Used by translator self-build. 353 case Intrinsic::nacl_target_arch: // Used by translator self-build.
277 case Intrinsic::pow: // Rounding is supposed to be the same as libm. 354 case Intrinsic::pow: // Rounding is supposed to be the same as libm.
278 case Intrinsic::powi: // Rounding not defined: support with fast-math? 355 case Intrinsic::powi: // Rounding not defined: support with fast-math?
279 case Intrinsic::prefetch: // Could ignore if target doesn't support? 356 case Intrinsic::prefetch: // Could ignore if target doesn't support?
280 case Intrinsic::sqrt: // Rounding is defined, but setting errno up to libm. 357 case Intrinsic::sqrt: // Rounding is defined, but setting errno up to libm.
281 case Intrinsic::stackrestore: // Used to support C99 VLAs. 358 case Intrinsic::stackrestore: // Used to support C99 VLAs.
282 case Intrinsic::stacksave: // Used to support C99 VLAs. 359 case Intrinsic::stacksave: // Used to support C99 VLAs.
(...skipping 188 matching lines...) Expand 10 before | Expand all | Expand 10 after
471 } 548 }
472 549
473 char PNaClABIVerifyModule::ID = 0; 550 char PNaClABIVerifyModule::ID = 0;
474 INITIALIZE_PASS(PNaClABIVerifyModule, "verify-pnaclabi-module", 551 INITIALIZE_PASS(PNaClABIVerifyModule, "verify-pnaclabi-module",
475 "Verify module for PNaCl", false, true) 552 "Verify module for PNaCl", false, true)
476 553
477 ModulePass *llvm::createPNaClABIVerifyModulePass( 554 ModulePass *llvm::createPNaClABIVerifyModulePass(
478 PNaClABIErrorReporter *Reporter, bool StreamingMode) { 555 PNaClABIErrorReporter *Reporter, bool StreamingMode) {
479 return new PNaClABIVerifyModule(Reporter, StreamingMode); 556 return new PNaClABIVerifyModule(Reporter, StreamingMode);
480 } 557 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698