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

Side by Side Diff: lib/Analysis/NaCl/PNaClABIVerifyFunctions.cpp

Issue 17777004: Concurrency support for PNaCl ABI (Closed) Base URL: http://git.chromium.org/native_client/pnacl-llvm.git@master
Patch Set: Update PNaClLangRef to reflect the implementation work I will now go forward with. Created 7 years, 5 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 //===- PNaClABIVerifyFunctions.cpp - Verify PNaCl ABI rules ---------------===// 1 //===- PNaClABIVerifyFunctions.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 function-level PNaCl ABI requirements. 10 // Verify function-level PNaCl ABI requirements.
11 // 11 //
12 // 12 //
13 //===----------------------------------------------------------------------===// 13 //===----------------------------------------------------------------------===//
14 14
15 #include "llvm/ADT/Twine.h" 15 #include "llvm/ADT/Twine.h"
16 #include "llvm/Analysis/NaCl.h" 16 #include "llvm/Analysis/NaCl.h"
17 #include "llvm/IR/Function.h" 17 #include "llvm/IR/Function.h"
18 #include "llvm/IR/Instructions.h" 18 #include "llvm/IR/Instructions.h"
19 #include "llvm/IR/IntrinsicInst.h" 19 #include "llvm/IR/IntrinsicInst.h"
20 #include "llvm/IR/LLVMContext.h" 20 #include "llvm/IR/LLVMContext.h"
21 #include "llvm/IR/Metadata.h" 21 #include "llvm/IR/Metadata.h"
22 #include "llvm/IR/NaClIntrinsics.h"
22 #include "llvm/IR/Operator.h" 23 #include "llvm/IR/Operator.h"
23 #include "llvm/Pass.h" 24 #include "llvm/Pass.h"
24 #include "llvm/Support/raw_ostream.h" 25 #include "llvm/Support/raw_ostream.h"
25 26
26 #include "PNaClABITypeChecker.h" 27 #include "PNaClABITypeChecker.h"
27 using namespace llvm; 28 using namespace llvm;
28 29
29 namespace { 30 namespace {
30 31
31 // Checks that examine anything in the function body should be in 32 // Checks that examine anything in the function body should be in
(...skipping 99 matching lines...) Expand 10 before | Expand all | Expand 10 after
131 if (isa<Instruction>(Val) || isa<Argument>(Val) || isa<BasicBlock>(Val)) 132 if (isa<Instruction>(Val) || isa<Argument>(Val) || isa<BasicBlock>(Val))
132 return true; 133 return true;
133 134
134 // Allow some Constants. Note that this excludes ConstantExprs. 135 // Allow some Constants. Note that this excludes ConstantExprs.
135 return PNaClABITypeChecker::isValidScalarType(Val->getType()) && 136 return PNaClABITypeChecker::isValidScalarType(Val->getType()) &&
136 (isa<ConstantInt>(Val) || 137 (isa<ConstantInt>(Val) ||
137 isa<ConstantFP>(Val) || 138 isa<ConstantFP>(Val) ||
138 isa<UndefValue>(Val)); 139 isa<UndefValue>(Val));
139 } 140 }
140 141
141 static bool isAllowedAlignment(unsigned Alignment, Type *Ty, bool IsAtomic) { 142 static bool isAllowedAlignment(unsigned Alignment, Type *Ty) {
142 if (IsAtomic) {
143 // For atomic operations, the alignment must match the size of the type.
144 if (Ty->isIntegerTy()) {
145 unsigned Bits = Ty->getIntegerBitWidth();
146 return Bits % 8 == 0 && Alignment == Bits / 8;
147 }
148 return (Ty->isDoubleTy() && Alignment == 8) ||
149 (Ty->isFloatTy() && Alignment == 4);
150 }
151 // Non-atomic integer operations must always use "align 1", since we 143 // Non-atomic integer operations must always use "align 1", since we
152 // do not want the backend to generate code with non-portable 144 // do not want the backend to generate code with non-portable
153 // undefined behaviour (such as misaligned access faults) if user 145 // undefined behaviour (such as misaligned access faults) if user
154 // code specifies "align 4" but uses a misaligned pointer. As a 146 // code specifies "align 4" but uses a misaligned pointer. As a
155 // concession to performance, we allow larger alignment values for 147 // concession to performance, we allow larger alignment values for
156 // floating point types. 148 // floating point types.
157 // 149 //
158 // To reduce the set of alignment values that need to be encoded in 150 // To reduce the set of alignment values that need to be encoded in
159 // pexes, we disallow other alignment values. We require alignments 151 // pexes, we disallow other alignment values. We require alignments
160 // to be explicit by disallowing Alignment == 0. 152 // to be explicit by disallowing Alignment == 0.
(...skipping 24 matching lines...) Expand all
185 case Instruction::Resume: 177 case Instruction::Resume:
186 // indirectbr may interfere with streaming 178 // indirectbr may interfere with streaming
187 case Instruction::IndirectBr: 179 case Instruction::IndirectBr:
188 // No vector instructions yet 180 // No vector instructions yet
189 case Instruction::ExtractElement: 181 case Instruction::ExtractElement:
190 case Instruction::InsertElement: 182 case Instruction::InsertElement:
191 case Instruction::ShuffleVector: 183 case Instruction::ShuffleVector:
192 // ExtractValue and InsertValue operate on struct values. 184 // ExtractValue and InsertValue operate on struct values.
193 case Instruction::ExtractValue: 185 case Instruction::ExtractValue:
194 case Instruction::InsertValue: 186 case Instruction::InsertValue:
187 // Atomics should become NaCl intrinsics.
188 case Instruction::AtomicCmpXchg:
189 case Instruction::AtomicRMW:
190 case Instruction::Fence:
195 return "bad instruction opcode"; 191 return "bad instruction opcode";
196 default: 192 default:
197 return "unknown instruction opcode"; 193 return "unknown instruction opcode";
198 194
199 // Terminator instructions 195 // Terminator instructions
200 case Instruction::Ret: 196 case Instruction::Ret:
201 case Instruction::Br: 197 case Instruction::Br:
202 case Instruction::Unreachable: 198 case Instruction::Unreachable:
203 // Binary operations 199 // Binary operations
204 case Instruction::Add: 200 case Instruction::Add:
205 case Instruction::FAdd: 201 case Instruction::FAdd:
206 case Instruction::Sub: 202 case Instruction::Sub:
207 case Instruction::FSub: 203 case Instruction::FSub:
208 case Instruction::Mul: 204 case Instruction::Mul:
209 case Instruction::FMul: 205 case Instruction::FMul:
210 case Instruction::UDiv: 206 case Instruction::UDiv:
211 case Instruction::SDiv: 207 case Instruction::SDiv:
212 case Instruction::FDiv: 208 case Instruction::FDiv:
213 case Instruction::URem: 209 case Instruction::URem:
214 case Instruction::SRem: 210 case Instruction::SRem:
215 case Instruction::FRem: 211 case Instruction::FRem:
216 // Bitwise binary operations 212 // Bitwise binary operations
217 case Instruction::Shl: 213 case Instruction::Shl:
218 case Instruction::LShr: 214 case Instruction::LShr:
219 case Instruction::AShr: 215 case Instruction::AShr:
220 case Instruction::And: 216 case Instruction::And:
221 case Instruction::Or: 217 case Instruction::Or:
222 case Instruction::Xor: 218 case Instruction::Xor:
223 // Memory instructions
224 case Instruction::Fence:
225 // Conversion operations 219 // Conversion operations
226 case Instruction::Trunc: 220 case Instruction::Trunc:
227 case Instruction::ZExt: 221 case Instruction::ZExt:
228 case Instruction::SExt: 222 case Instruction::SExt:
229 case Instruction::FPTrunc: 223 case Instruction::FPTrunc:
230 case Instruction::FPExt: 224 case Instruction::FPExt:
231 case Instruction::FPToUI: 225 case Instruction::FPToUI:
232 case Instruction::FPToSI: 226 case Instruction::FPToSI:
233 case Instruction::UIToFP: 227 case Instruction::UIToFP:
234 case Instruction::SIToFP: 228 case Instruction::SIToFP:
235 // Other operations 229 // Other operations
236 case Instruction::ICmp: 230 case Instruction::ICmp:
237 case Instruction::FCmp: 231 case Instruction::FCmp:
238 case Instruction::PHI: 232 case Instruction::PHI:
239 case Instruction::Select: 233 case Instruction::Select:
240 break; 234 break;
241 235
242 // Memory accesses. 236 // Memory accesses.
243 case Instruction::Load: { 237 case Instruction::Load: {
244 const LoadInst *Load = cast<LoadInst>(Inst); 238 const LoadInst *Load = cast<LoadInst>(Inst);
239 PtrOperandIndex = Load->getPointerOperandIndex();
240 if (Load->isAtomic())
241 return "atomic";
242 if (Load->isVolatile())
243 return "volatile";
245 if (!isAllowedAlignment(Load->getAlignment(), 244 if (!isAllowedAlignment(Load->getAlignment(),
246 Load->getType(), 245 Load->getType()))
247 Load->isAtomic()))
248 return "bad alignment"; 246 return "bad alignment";
249 PtrOperandIndex = 0;
250 if (!isNormalizedPtr(Inst->getOperand(PtrOperandIndex))) 247 if (!isNormalizedPtr(Inst->getOperand(PtrOperandIndex)))
251 return "bad pointer"; 248 return "bad pointer";
252 break; 249 break;
253 } 250 }
254 case Instruction::Store: { 251 case Instruction::Store: {
255 const StoreInst *Store = cast<StoreInst>(Inst); 252 const StoreInst *Store = cast<StoreInst>(Inst);
253 PtrOperandIndex = Store->getPointerOperandIndex();
254 if (Store->isAtomic())
255 return "atomic";
256 if (Store->isVolatile())
257 return "volatile";
256 if (!isAllowedAlignment(Store->getAlignment(), 258 if (!isAllowedAlignment(Store->getAlignment(),
257 Store->getValueOperand()->getType(), 259 Store->getValueOperand()->getType()))
258 Store->isAtomic()))
259 return "bad alignment"; 260 return "bad alignment";
260 PtrOperandIndex = 1;
261 if (!isNormalizedPtr(Inst->getOperand(PtrOperandIndex))) 261 if (!isNormalizedPtr(Inst->getOperand(PtrOperandIndex)))
262 return "bad pointer"; 262 return "bad pointer";
263 break; 263 break;
264 } 264 }
265 case Instruction::AtomicCmpXchg:
266 case Instruction::AtomicRMW:
267 PtrOperandIndex = 0;
268 if (!isNormalizedPtr(Inst->getOperand(PtrOperandIndex)))
269 return "bad pointer";
270 break;
271 265
272 // Casts. 266 // Casts.
273 case Instruction::BitCast: 267 case Instruction::BitCast:
274 if (Inst->getType()->isPointerTy()) { 268 if (Inst->getType()->isPointerTy()) {
275 PtrOperandIndex = 0; 269 PtrOperandIndex = 0;
276 if (!isInherentPtr(Inst->getOperand(PtrOperandIndex))) 270 if (!isInherentPtr(Inst->getOperand(PtrOperandIndex)))
277 return "operand not InherentPtr"; 271 return "operand not InherentPtr";
278 } 272 }
279 break; 273 break;
280 case Instruction::IntToPtr: 274 case Instruction::IntToPtr:
(...skipping 27 matching lines...) Expand all
308 // metadata arguments, so handle them specially. 302 // metadata arguments, so handle them specially.
309 if (const IntrinsicInst *Call = dyn_cast<IntrinsicInst>(Inst)) { 303 if (const IntrinsicInst *Call = dyn_cast<IntrinsicInst>(Inst)) {
310 for (unsigned ArgNum = 0, E = Call->getNumArgOperands(); 304 for (unsigned ArgNum = 0, E = Call->getNumArgOperands();
311 ArgNum < E; ++ArgNum) { 305 ArgNum < E; ++ArgNum) {
312 const Value *Arg = Call->getArgOperand(ArgNum); 306 const Value *Arg = Call->getArgOperand(ArgNum);
313 if (!(isValidScalarOperand(Arg) || 307 if (!(isValidScalarOperand(Arg) ||
314 isNormalizedPtr(Arg) || 308 isNormalizedPtr(Arg) ||
315 isa<MDNode>(Arg))) 309 isa<MDNode>(Arg)))
316 return "bad intrinsic operand"; 310 return "bad intrinsic operand";
317 } 311 }
312
318 // Disallow alignments other than 1 on memcpy() etc., for the 313 // Disallow alignments other than 1 on memcpy() etc., for the
319 // same reason that we disallow them on integer loads and 314 // same reason that we disallow them on integer loads and
320 // stores. 315 // stores.
321 if (const MemIntrinsic *MemOp = dyn_cast<MemIntrinsic>(Call)) { 316 if (const MemIntrinsic *MemOp = dyn_cast<MemIntrinsic>(Call)) {
322 // Avoid the getAlignment() method here because it aborts if 317 // Avoid the getAlignment() method here because it aborts if
323 // the alignment argument is not a Constant. 318 // the alignment argument is not a Constant.
324 Value *AlignArg = MemOp->getArgOperand(3); 319 Value *AlignArg = MemOp->getArgOperand(3);
325 if (!isa<ConstantInt>(AlignArg) || 320 if (!isa<ConstantInt>(AlignArg) ||
326 cast<ConstantInt>(AlignArg)->getZExtValue() != 1) { 321 cast<ConstantInt>(AlignArg)->getZExtValue() != 1) {
327 return "bad alignment"; 322 return "bad alignment";
328 } 323 }
329 } 324 }
325
326 // Disallow NaCl atomic intrinsics which don't have valid
327 // constant NaCl::AtomicOperation and NaCl::MemoryOrder
328 // parameters.
329 for (size_t II = 0; II != NaCl::NumAtomicIntrinsics; ++II) {
330 if (Call->getIntrinsicID() == NaCl::AtomicIntrinsics[II].ID) {
331 const Value *Operation = Call->getArgOperand(0);
332 const Value *MemoryOrder = Call->getArgOperand(4);
333 const Constant *OperationC = dyn_cast<Constant>(Operation);
334 const Constant *MemoryOrderC = dyn_cast<Constant>(MemoryOrder);
335 if (!Operation)
336 return "non-constant atomic operation";
337 if(!MemoryOrder)
338 return "non-constant atomic memory order";
339 const APInt &OperationI = OperationC->getUniqueInteger();
340 const APInt &MemoryOrderI = MemoryOrderC->getUniqueInteger();
341 if (OperationI.ule(NaCl::AtomicInvalid) ||
342 OperationI.uge(NaCl::AtomicNum))
343 return "invalid atomic operation";
344 if (MemoryOrderI.ule(NaCl::MemoryOrderInvalid) ||
345 MemoryOrderI.uge(NaCl::MemoryOrderNum))
346 return "invalid atomic memory order";
347 // TODO For now only sequential consistency is allowed.
348 if (MemoryOrderI != NaCl::MemoryOrderSequentiallyConsistent)
349 return "only sequential consistency is currently allowed "
350 "as memory order";
351 }
352 }
353
330 // Allow the instruction and skip the later checks. 354 // Allow the instruction and skip the later checks.
331 return NULL; 355 return NULL;
332 } 356 }
333 357
334 // The callee is the last operand. 358 // The callee is the last operand.
335 PtrOperandIndex = Inst->getNumOperands() - 1; 359 PtrOperandIndex = Inst->getNumOperands() - 1;
336 if (!isNormalizedPtr(Inst->getOperand(PtrOperandIndex))) 360 if (!isNormalizedPtr(Inst->getOperand(PtrOperandIndex)))
337 return "bad function callee operand"; 361 return "bad function callee operand";
338 break; 362 break;
339 } 363 }
(...skipping 107 matching lines...) Expand 10 before | Expand all | Expand 10 after
447 } 471 }
448 472
449 char PNaClABIVerifyFunctions::ID = 0; 473 char PNaClABIVerifyFunctions::ID = 0;
450 INITIALIZE_PASS(PNaClABIVerifyFunctions, "verify-pnaclabi-functions", 474 INITIALIZE_PASS(PNaClABIVerifyFunctions, "verify-pnaclabi-functions",
451 "Verify functions for PNaCl", false, true) 475 "Verify functions for PNaCl", false, true)
452 476
453 FunctionPass *llvm::createPNaClABIVerifyFunctionsPass( 477 FunctionPass *llvm::createPNaClABIVerifyFunctionsPass(
454 PNaClABIErrorReporter *Reporter) { 478 PNaClABIErrorReporter *Reporter) {
455 return new PNaClABIVerifyFunctions(Reporter); 479 return new PNaClABIVerifyFunctions(Reporter);
456 } 480 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698