| OLD | NEW |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 } |
| OLD | NEW |