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

Side by Side Diff: src/IceTargetLoweringX86BaseImpl.h

Issue 1559243002: Suzero. X8664. NaCl Sandboxing. (Closed) Base URL: https://chromium.googlesource.com/native_client/pnacl-subzero.git@master
Patch Set: Adds lit tests for the sandboxed call/ret sequences; add lit tests for the new pad_to_end bundle lo… Created 4 years, 11 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 //===- subzero/src/IceTargetLoweringX86BaseImpl.h - x86 lowering -*- C++ -*-==// 1 //===- subzero/src/IceTargetLoweringX86BaseImpl.h - x86 lowering -*- C++ -*-==//
2 // 2 //
3 // The Subzero Code Generator 3 // The Subzero Code Generator
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 /// \file 10 /// \file
(...skipping 290 matching lines...) Expand 10 before | Expand all | Expand 10 after
301 } 301 }
302 302
303 template <typename TraitsType> 303 template <typename TraitsType>
304 void TargetX86Base<TraitsType>::initNodeForLowering(CfgNode *Node) { 304 void TargetX86Base<TraitsType>::initNodeForLowering(CfgNode *Node) {
305 FoldingInfo.init(Node); 305 FoldingInfo.init(Node);
306 FoldingInfo.dump(Func); 306 FoldingInfo.dump(Func);
307 } 307 }
308 308
309 template <typename TraitsType> 309 template <typename TraitsType>
310 TargetX86Base<TraitsType>::TargetX86Base(Cfg *Func) 310 TargetX86Base<TraitsType>::TargetX86Base(Cfg *Func)
311 : TargetLowering(Func) { 311 : TargetLowering(Func), NeedSandboxing(Ctx->getFlags().getUseSandboxing()) {
312 static_assert( 312 static_assert(
313 (Traits::InstructionSet::End - Traits::InstructionSet::Begin) == 313 (Traits::InstructionSet::End - Traits::InstructionSet::Begin) ==
314 (TargetInstructionSet::X86InstructionSet_End - 314 (TargetInstructionSet::X86InstructionSet_End -
315 TargetInstructionSet::X86InstructionSet_Begin), 315 TargetInstructionSet::X86InstructionSet_Begin),
316 "Traits::InstructionSet range different from TargetInstructionSet"); 316 "Traits::InstructionSet range different from TargetInstructionSet");
317 if (Func->getContext()->getFlags().getTargetInstructionSet() != 317 if (Func->getContext()->getFlags().getTargetInstructionSet() !=
318 TargetInstructionSet::BaseInstructionSet) { 318 TargetInstructionSet::BaseInstructionSet) {
319 InstructionSet = static_cast<InstructionSetEnum>( 319 InstructionSet = static_cast<InstructionSetEnum>(
320 (Func->getContext()->getFlags().getTargetInstructionSet() - 320 (Func->getContext()->getFlags().getTargetInstructionSet() -
321 TargetInstructionSet::X86InstructionSet_Begin) + 321 TargetInstructionSet::X86InstructionSet_Begin) +
322 Traits::InstructionSet::Begin); 322 Traits::InstructionSet::Begin);
323 } 323 }
324 } 324 }
325 325
326 template <typename TraitsType> 326 template <typename TraitsType>
327 void TargetX86Base<TraitsType>::staticInit(const ClFlags &Flags) { 327 void TargetX86Base<TraitsType>::staticInit(const ClFlags &Flags) {
328 Traits::initRegisterSet(&TypeToRegisterSet, &RegisterAliases, &ScratchRegs); 328 Traits::initRegisterSet(Flags, &TypeToRegisterSet, &RegisterAliases,
329 &ScratchRegs);
329 PcRelFixup = Traits::FK_PcRel; 330 PcRelFixup = Traits::FK_PcRel;
330 AbsFixup = Flags.getUseNonsfi() ? Traits::FK_Gotoff : Traits::FK_Abs; 331 AbsFixup = Flags.getUseNonsfi() ? Traits::FK_Gotoff : Traits::FK_Abs;
331 } 332 }
332 333
333 template <typename TraitsType> void TargetX86Base<TraitsType>::translateO2() { 334 template <typename TraitsType> void TargetX86Base<TraitsType>::translateO2() {
334 TimerMarker T(TimerStack::TT_O2, Func); 335 TimerMarker T(TimerStack::TT_O2, Func);
335 336
336 if (!Traits::Is64Bit && Func->getContext()->getFlags().getUseNonsfi()) { 337 if (!Traits::Is64Bit && Func->getContext()->getFlags().getUseNonsfi()) {
337 GotVar = Func->makeVariable(IceType_i32); 338 GotVar = Func->makeVariable(IceType_i32);
338 } 339 }
340
341 if (NeedSandboxing) {
342 initSandbox();
343 }
344
339 genTargetHelperCalls(); 345 genTargetHelperCalls();
340 Func->dump("After target helper call insertion"); 346 Func->dump("After target helper call insertion");
341 347
342 // Merge Alloca instructions, and lay out the stack. 348 // Merge Alloca instructions, and lay out the stack.
343 static constexpr bool SortAndCombineAllocas = true; 349 static constexpr bool SortAndCombineAllocas = true;
344 Func->processAllocas(SortAndCombineAllocas); 350 Func->processAllocas(SortAndCombineAllocas);
345 Func->dump("After Alloca processing"); 351 Func->dump("After Alloca processing");
346 352
347 if (!Ctx->getFlags().getPhiEdgeSplit()) { 353 if (!Ctx->getFlags().getPhiEdgeSplit()) {
348 // Lower Phi instructions. 354 // Lower Phi instructions.
(...skipping 100 matching lines...) Expand 10 before | Expand all | Expand 10 after
449 // particular, no transformations that insert or reorder CfgNodes should be 455 // particular, no transformations that insert or reorder CfgNodes should be
450 // done after branch optimization. We go ahead and do it before nop insertion 456 // done after branch optimization. We go ahead and do it before nop insertion
451 // to reduce the amount of work needed for searching for opportunities. 457 // to reduce the amount of work needed for searching for opportunities.
452 Func->doBranchOpt(); 458 Func->doBranchOpt();
453 Func->dump("After branch optimization"); 459 Func->dump("After branch optimization");
454 460
455 // Nop insertion if -nop-insertion is enabled. 461 // Nop insertion if -nop-insertion is enabled.
456 Func->doNopInsertion(); 462 Func->doNopInsertion();
457 463
458 // Mark nodes that require sandbox alignment 464 // Mark nodes that require sandbox alignment
459 if (Ctx->getFlags().getUseSandboxing()) 465 if (NeedSandboxing) {
460 Func->markNodesForSandboxing(); 466 Func->markNodesForSandboxing();
467 }
461 } 468 }
462 469
463 template <typename TraitsType> void TargetX86Base<TraitsType>::translateOm1() { 470 template <typename TraitsType> void TargetX86Base<TraitsType>::translateOm1() {
464 TimerMarker T(TimerStack::TT_Om1, Func); 471 TimerMarker T(TimerStack::TT_Om1, Func);
465 472
466 if (!Traits::Is64Bit && Func->getContext()->getFlags().getUseNonsfi()) { 473 if (!Traits::Is64Bit && Func->getContext()->getFlags().getUseNonsfi()) {
467 GotVar = Func->makeVariable(IceType_i32); 474 GotVar = Func->makeVariable(IceType_i32);
468 } 475 }
476
477 if (NeedSandboxing) {
478 initSandbox();
479 }
480
469 genTargetHelperCalls(); 481 genTargetHelperCalls();
470 482
471 // Do not merge Alloca instructions, and lay out the stack. 483 // Do not merge Alloca instructions, and lay out the stack.
472 static constexpr bool SortAndCombineAllocas = false; 484 static constexpr bool SortAndCombineAllocas = false;
473 Func->processAllocas(SortAndCombineAllocas); 485 Func->processAllocas(SortAndCombineAllocas);
474 Func->dump("After Alloca processing"); 486 Func->dump("After Alloca processing");
475 487
476 Func->placePhiLoads(); 488 Func->placePhiLoads();
477 if (Func->hasError()) 489 if (Func->hasError())
478 return; 490 return;
(...skipping 22 matching lines...) Expand all
501 return; 513 return;
502 Func->dump("After stack frame mapping"); 514 Func->dump("After stack frame mapping");
503 515
504 // Shuffle basic block order if -reorder-basic-blocks is enabled. 516 // Shuffle basic block order if -reorder-basic-blocks is enabled.
505 Func->shuffleNodes(); 517 Func->shuffleNodes();
506 518
507 // Nop insertion if -nop-insertion is enabled. 519 // Nop insertion if -nop-insertion is enabled.
508 Func->doNopInsertion(); 520 Func->doNopInsertion();
509 521
510 // Mark nodes that require sandbox alignment 522 // Mark nodes that require sandbox alignment
511 if (Ctx->getFlags().getUseSandboxing()) 523 if (NeedSandboxing)
512 Func->markNodesForSandboxing(); 524 Func->markNodesForSandboxing();
513 } 525 }
514 526
515 inline bool canRMW(const InstArithmetic *Arith) { 527 inline bool canRMW(const InstArithmetic *Arith) {
516 Type Ty = Arith->getDest()->getType(); 528 Type Ty = Arith->getDest()->getType();
517 // X86 vector instructions write to a register and have no RMW option. 529 // X86 vector instructions write to a register and have no RMW option.
518 if (isVectorType(Ty)) 530 if (isVectorType(Ty))
519 return false; 531 return false;
520 bool isI64 = Ty == IceType_i64; 532 bool isI64 = Ty == IceType_i64;
521 533
(...skipping 281 matching lines...) Expand 10 before | Expand all | Expand 10 after
803 IceString TargetX86Base<TraitsType>::getRegName(SizeT RegNum, Type Ty) const { 815 IceString TargetX86Base<TraitsType>::getRegName(SizeT RegNum, Type Ty) const {
804 return Traits::getRegName(Traits::getGprForType(Ty, RegNum)); 816 return Traits::getRegName(Traits::getGprForType(Ty, RegNum));
805 } 817 }
806 818
807 template <typename TraitsType> 819 template <typename TraitsType>
808 void TargetX86Base<TraitsType>::emitVariable(const Variable *Var) const { 820 void TargetX86Base<TraitsType>::emitVariable(const Variable *Var) const {
809 if (!BuildDefs::dump()) 821 if (!BuildDefs::dump())
810 return; 822 return;
811 Ostream &Str = Ctx->getStrEmit(); 823 Ostream &Str = Ctx->getStrEmit();
812 if (Var->hasReg()) { 824 if (Var->hasReg()) {
813 Str << "%" << getRegName(Var->getRegNum(), Var->getType()); 825 const bool Is64BitSandboxing = Traits::Is64Bit && NeedSandboxing;
826 const Type VarType = (Var->isRematerializable() && Is64BitSandboxing)
827 ? IceType_i64
828 : Var->getType();
829 Str << "%" << getRegName(Var->getRegNum(), VarType);
814 return; 830 return;
815 } 831 }
816 if (Var->mustHaveReg()) { 832 if (Var->mustHaveReg()) {
817 llvm::report_fatal_error( 833 llvm::report_fatal_error(
818 "Infinite-weight Variable has no register assigned"); 834 "Infinite-weight Variable has no register assigned");
819 } 835 }
820 const int32_t Offset = Var->getStackOffset(); 836 const int32_t Offset = Var->getStackOffset();
821 int32_t BaseRegNum = Var->getBaseRegNum(); 837 int32_t BaseRegNum = Var->getBaseRegNum();
822 if (BaseRegNum == Variable::NoRegister) 838 if (BaseRegNum == Variable::NoRegister)
823 BaseRegNum = getFrameOrStackReg(); 839 BaseRegNum = getFrameOrStackReg();
(...skipping 92 matching lines...) Expand 10 before | Expand all | Expand 10 after
916 return Var64On32->getLo(); 932 return Var64On32->getLo();
917 if (auto *Const = llvm::dyn_cast<ConstantInteger64>(Operand)) { 933 if (auto *Const = llvm::dyn_cast<ConstantInteger64>(Operand)) {
918 auto *ConstInt = llvm::dyn_cast<ConstantInteger32>( 934 auto *ConstInt = llvm::dyn_cast<ConstantInteger32>(
919 Ctx->getConstantInt32(static_cast<int32_t>(Const->getValue()))); 935 Ctx->getConstantInt32(static_cast<int32_t>(Const->getValue())));
920 // Check if we need to blind/pool the constant. 936 // Check if we need to blind/pool the constant.
921 return legalize(ConstInt); 937 return legalize(ConstInt);
922 } 938 }
923 if (auto *Mem = llvm::dyn_cast<X86OperandMem>(Operand)) { 939 if (auto *Mem = llvm::dyn_cast<X86OperandMem>(Operand)) {
924 auto *MemOperand = X86OperandMem::create( 940 auto *MemOperand = X86OperandMem::create(
925 Func, IceType_i32, Mem->getBase(), Mem->getOffset(), Mem->getIndex(), 941 Func, IceType_i32, Mem->getBase(), Mem->getOffset(), Mem->getIndex(),
926 Mem->getShift(), Mem->getSegmentRegister(), Mem->getIsPIC()); 942 Mem->getShift(), Mem->getSegmentRegister(), Mem->getIsRebased());
927 // Test if we should randomize or pool the offset, if so randomize it or 943 // Test if we should randomize or pool the offset, if so randomize it or
928 // pool it then create mem operand with the blinded/pooled constant. 944 // pool it then create mem operand with the blinded/pooled constant.
929 // Otherwise, return the mem operand as ordinary mem operand. 945 // Otherwise, return the mem operand as ordinary mem operand.
930 return legalize(MemOperand); 946 return legalize(MemOperand);
931 } 947 }
932 llvm_unreachable("Unsupported operand type"); 948 llvm_unreachable("Unsupported operand type");
933 return nullptr; 949 return nullptr;
934 } 950 }
935 951
936 template <typename TraitsType> 952 template <typename TraitsType>
(...skipping 19 matching lines...) Expand all
956 } else if (auto *IntOffset = llvm::dyn_cast<ConstantInteger32>(Offset)) { 972 } else if (auto *IntOffset = llvm::dyn_cast<ConstantInteger32>(Offset)) {
957 Offset = Ctx->getConstantInt32(4 + IntOffset->getValue()); 973 Offset = Ctx->getConstantInt32(4 + IntOffset->getValue());
958 } else if (auto *SymOffset = llvm::dyn_cast<ConstantRelocatable>(Offset)) { 974 } else if (auto *SymOffset = llvm::dyn_cast<ConstantRelocatable>(Offset)) {
959 assert(!Utils::WouldOverflowAdd(SymOffset->getOffset(), 4)); 975 assert(!Utils::WouldOverflowAdd(SymOffset->getOffset(), 4));
960 Offset = 976 Offset =
961 Ctx->getConstantSym(4 + SymOffset->getOffset(), SymOffset->getName(), 977 Ctx->getConstantSym(4 + SymOffset->getOffset(), SymOffset->getName(),
962 SymOffset->getSuppressMangling()); 978 SymOffset->getSuppressMangling());
963 } 979 }
964 auto *MemOperand = X86OperandMem::create( 980 auto *MemOperand = X86OperandMem::create(
965 Func, IceType_i32, Mem->getBase(), Offset, Mem->getIndex(), 981 Func, IceType_i32, Mem->getBase(), Offset, Mem->getIndex(),
966 Mem->getShift(), Mem->getSegmentRegister(), Mem->getIsPIC()); 982 Mem->getShift(), Mem->getSegmentRegister(), Mem->getIsRebased());
967 // Test if the Offset is an eligible i32 constants for randomization and 983 // Test if the Offset is an eligible i32 constants for randomization and
968 // pooling. Blind/pool it if it is. Otherwise return as oridinary mem 984 // pooling. Blind/pool it if it is. Otherwise return as oridinary mem
969 // operand. 985 // operand.
970 return legalize(MemOperand); 986 return legalize(MemOperand);
971 } 987 }
972 llvm_unreachable("Unsupported operand type"); 988 llvm_unreachable("Unsupported operand type");
973 return nullptr; 989 return nullptr;
974 } 990 }
975 991
976 template <typename TraitsType> 992 template <typename TraitsType>
977 llvm::SmallBitVector 993 llvm::SmallBitVector
978 TargetX86Base<TraitsType>::getRegisterSet(RegSetMask Include, 994 TargetX86Base<TraitsType>::getRegisterSet(RegSetMask Include,
979 RegSetMask Exclude) const { 995 RegSetMask Exclude) const {
980 return Traits::getRegisterSet(Include, Exclude); 996 return Traits::getRegisterSet(Ctx->getFlags(), Include, Exclude);
981 } 997 }
982 998
983 template <typename TraitsType> 999 template <typename TraitsType>
984 void TargetX86Base<TraitsType>::initGotVarIfNeeded() { 1000 void TargetX86Base<TraitsType>::initGotVarIfNeeded() {
985 if (!Func->getContext()->getFlags().getUseNonsfi()) 1001 if (!Func->getContext()->getFlags().getUseNonsfi())
986 return; 1002 return;
987 if (Traits::Is64Bit) { 1003 if (Traits::Is64Bit) {
988 // Probably no implementation is needed, but error to be safe for now. 1004 // Probably no implementation is needed, but error to be safe for now.
989 llvm::report_fatal_error( 1005 llvm::report_fatal_error(
990 "Need to implement initGotVarIfNeeded() for 64-bit."); 1006 "Need to implement initGotVarIfNeeded() for 64-bit.");
(...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after
1030 _and(esp, Ctx->getConstantInt32(-Alignment)); 1046 _and(esp, Ctx->getConstantInt32(-Alignment));
1031 } 1047 }
1032 1048
1033 Variable *Dest = Inst->getDest(); 1049 Variable *Dest = Inst->getDest();
1034 Operand *TotalSize = legalize(Inst->getSizeInBytes()); 1050 Operand *TotalSize = legalize(Inst->getSizeInBytes());
1035 1051
1036 if (const auto *ConstantTotalSize = 1052 if (const auto *ConstantTotalSize =
1037 llvm::dyn_cast<ConstantInteger32>(TotalSize)) { 1053 llvm::dyn_cast<ConstantInteger32>(TotalSize)) {
1038 const uint32_t Value = 1054 const uint32_t Value =
1039 Utils::applyAlignment(ConstantTotalSize->getValue(), Alignment); 1055 Utils::applyAlignment(ConstantTotalSize->getValue(), Alignment);
1040 if (!UseFramePointer) { 1056 if (UseFramePointer) {
1057 _sub_sp(Ctx->getConstantInt32(Value));
1058 } else {
1041 // If we don't need a Frame Pointer, this alloca has a known offset to the 1059 // If we don't need a Frame Pointer, this alloca has a known offset to the
1042 // stack pointer. We don't need adjust the stack pointer, nor assign any 1060 // stack pointer. We don't need adjust the stack pointer, nor assign any
1043 // value to Dest, as Dest is rematerializable. 1061 // value to Dest, as Dest is rematerializable.
1044 assert(Dest->isRematerializable()); 1062 assert(Dest->isRematerializable());
1045 FixedAllocaSizeBytes += Value; 1063 FixedAllocaSizeBytes += Value;
1046 Context.insert<InstFakeDef>(Dest); 1064 Context.insert<InstFakeDef>(Dest);
1047 } else {
1048 _sub(esp, Ctx->getConstantInt32(Value));
1049 } 1065 }
1050 } else { 1066 } else {
1051 // Non-constant sizes need to be adjusted to the next highest multiple of 1067 // Non-constant sizes need to be adjusted to the next highest multiple of
1052 // the required alignment at runtime. 1068 // the required alignment at runtime.
1053 Variable *T = makeReg(Traits::WordType); 1069 Variable *T = nullptr;
1054 if (Traits::Is64Bit && TotalSize->getType() != IceType_i64) { 1070 if (Traits::Is64Bit && TotalSize->getType() != IceType_i64 &&
1071 !NeedSandboxing) {
1072 T = makeReg(IceType_i64);
1055 _movzx(T, TotalSize); 1073 _movzx(T, TotalSize);
1056 } else { 1074 } else {
1075 T = makeReg(IceType_i32);
1057 _mov(T, TotalSize); 1076 _mov(T, TotalSize);
1058 } 1077 }
1059 _add(T, Ctx->getConstantInt32(Alignment - 1)); 1078 _add(T, Ctx->getConstantInt32(Alignment - 1));
1060 _and(T, Ctx->getConstantInt32(-Alignment)); 1079 _and(T, Ctx->getConstantInt32(-Alignment));
1061 _sub(esp, T); 1080 _sub_sp(T);
1062 } 1081 }
1063 // Add enough to the returned address to account for the out args area. 1082 // Add enough to the returned address to account for the out args area.
1064 uint32_t OutArgsSize = maxOutArgsSizeBytes(); 1083 uint32_t OutArgsSize = maxOutArgsSizeBytes();
1065 if (OutArgsSize > 0) { 1084 if (OutArgsSize > 0) {
1066 Variable *T = makeReg(IceType_i32); 1085 Variable *T = makeReg(IceType_i32);
1067 auto *CalculateOperand = X86OperandMem::create( 1086 auto *CalculateOperand = X86OperandMem::create(
1068 Func, IceType_i32, esp, Ctx->getConstantInt(IceType_i32, OutArgsSize)); 1087 Func, IceType_void, esp, Ctx->getConstantInt(IceType_i32, OutArgsSize));
1069 _lea(T, CalculateOperand); 1088 _lea(T, CalculateOperand);
1070 _mov(Dest, T); 1089 _mov(Dest, T);
1071 } else { 1090 } else {
1072 _mov(Dest, esp); 1091 _mov(Dest, esp);
1073 } 1092 }
1074 } 1093 }
1075 1094
1076 /// Strength-reduce scalar integer multiplication by a constant (for i32 or 1095 /// Strength-reduce scalar integer multiplication by a constant (for i32 or
1077 /// narrower) for certain constants. The lea instruction can be used to multiply 1096 /// narrower) for certain constants. The lea instruction can be used to multiply
1078 /// by 3, 5, or 9, and the lsh instruction can be used to multiply by powers of 1097 /// by 3, 5, or 9, and the lsh instruction can be used to multiply by powers of
1079 /// 2. These can be combined such that e.g. multiplying by 100 can be done as 2 1098 /// 2. These can be combined such that e.g. multiplying by 100 can be done as 2
1080 /// lea-based multiplies by 5, combined with left-shifting by 2. 1099 /// lea-based multiplies by 5, combined with left-shifting by 2.
1081 template <typename TraitsType> 1100 template <typename TraitsType>
1082 bool TargetX86Base<TraitsType>::optimizeScalarMul(Variable *Dest, Operand *Src0, 1101 bool TargetX86Base<TraitsType>::optimizeScalarMul(Variable *Dest, Operand *Src0,
1083 int32_t Src1) { 1102 int32_t Src1) {
1084 // Disable this optimization for Om1 and O0, just to keep things simple 1103 // Disable this optimization for Om1 and O0, just to keep things simple
1085 // there. 1104 // there.
1086 if (Ctx->getFlags().getOptLevel() < Opt_1) 1105 if (Ctx->getFlags().getOptLevel() < Opt_1)
1087 return false; 1106 return false;
1088 Type Ty = Dest->getType(); 1107 Type Ty = Dest->getType();
1089 Variable *T = nullptr;
1090 if (Src1 == -1) { 1108 if (Src1 == -1) {
1109 Variable *T = nullptr;
1091 _mov(T, Src0); 1110 _mov(T, Src0);
1092 _neg(T); 1111 _neg(T);
1093 _mov(Dest, T); 1112 _mov(Dest, T);
1094 return true; 1113 return true;
1095 } 1114 }
1096 if (Src1 == 0) { 1115 if (Src1 == 0) {
1097 _mov(Dest, Ctx->getConstantZero(Ty)); 1116 _mov(Dest, Ctx->getConstantZero(Ty));
1098 return true; 1117 return true;
1099 } 1118 }
1100 if (Src1 == 1) { 1119 if (Src1 == 1) {
1120 Variable *T = nullptr;
1101 _mov(T, Src0); 1121 _mov(T, Src0);
1102 _mov(Dest, T); 1122 _mov(Dest, T);
1103 return true; 1123 return true;
1104 } 1124 }
1105 // Don't bother with the edge case where Src1 == MININT. 1125 // Don't bother with the edge case where Src1 == MININT.
1106 if (Src1 == -Src1) 1126 if (Src1 == -Src1)
1107 return false; 1127 return false;
1108 const bool Src1IsNegative = Src1 < 0; 1128 const bool Src1IsNegative = Src1 < 0;
1109 if (Src1IsNegative) 1129 if (Src1IsNegative)
1110 Src1 = -Src1; 1130 Src1 = -Src1;
(...skipping 18 matching lines...) Expand all
1129 } else if (Src1 % 2 == 0) { 1149 } else if (Src1 % 2 == 0) {
1130 if (Count2 == 0) 1150 if (Count2 == 0)
1131 ++CountOps; 1151 ++CountOps;
1132 ++Count2; 1152 ++Count2;
1133 Src1 /= 2; 1153 Src1 /= 2;
1134 } else { 1154 } else {
1135 return false; 1155 return false;
1136 } 1156 }
1137 } 1157 }
1138 // Lea optimization only works for i16 and i32 types, not i8. 1158 // Lea optimization only works for i16 and i32 types, not i8.
1139 if (Ty != IceType_i16 && Ty != IceType_i32 && (Count3 || Count5 || Count9)) 1159 if (Ty != IceType_i32 && !(Traits::Is64Bit && Ty == IceType_i64) &&
1160 (Count3 || Count5 || Count9))
1140 return false; 1161 return false;
1141 // Limit the number of lea/shl operations for a single multiply, to a 1162 // Limit the number of lea/shl operations for a single multiply, to a
1142 // somewhat arbitrary choice of 3. 1163 // somewhat arbitrary choice of 3.
1143 constexpr uint32_t MaxOpsForOptimizedMul = 3; 1164 constexpr uint32_t MaxOpsForOptimizedMul = 3;
1144 if (CountOps > MaxOpsForOptimizedMul) 1165 if (CountOps > MaxOpsForOptimizedMul)
1145 return false; 1166 return false;
1146 _mov(T, Src0); 1167 Variable *T = makeReg(Traits::WordType);
1168 if (typeWidthInBytes(Src0->getType()) < typeWidthInBytes(T->getType())) {
1169 _movzx(T, Src0);
1170 } else {
1171 _mov(T, Src0);
1172 }
1147 Constant *Zero = Ctx->getConstantZero(IceType_i32); 1173 Constant *Zero = Ctx->getConstantZero(IceType_i32);
1148 for (uint32_t i = 0; i < Count9; ++i) { 1174 for (uint32_t i = 0; i < Count9; ++i) {
1149 constexpr uint16_t Shift = 3; // log2(9-1) 1175 constexpr uint16_t Shift = 3; // log2(9-1)
1150 _lea(T, X86OperandMem::create(Func, IceType_void, T, Zero, T, Shift)); 1176 _lea(T, X86OperandMem::create(Func, IceType_void, T, Zero, T, Shift));
1151 } 1177 }
1152 for (uint32_t i = 0; i < Count5; ++i) { 1178 for (uint32_t i = 0; i < Count5; ++i) {
1153 constexpr uint16_t Shift = 2; // log2(5-1) 1179 constexpr uint16_t Shift = 2; // log2(5-1)
1154 _lea(T, X86OperandMem::create(Func, IceType_void, T, Zero, T, Shift)); 1180 _lea(T, X86OperandMem::create(Func, IceType_void, T, Zero, T, Shift));
1155 } 1181 }
1156 for (uint32_t i = 0; i < Count3; ++i) { 1182 for (uint32_t i = 0; i < Count3; ++i) {
(...skipping 2379 matching lines...) Expand 10 before | Expand all | Expand 10 after
3536 } 3562 }
3537 case Intrinsics::Memmove: { 3563 case Intrinsics::Memmove: {
3538 lowerMemmove(Instr->getArg(0), Instr->getArg(1), Instr->getArg(2)); 3564 lowerMemmove(Instr->getArg(0), Instr->getArg(1), Instr->getArg(2));
3539 return; 3565 return;
3540 } 3566 }
3541 case Intrinsics::Memset: { 3567 case Intrinsics::Memset: {
3542 lowerMemset(Instr->getArg(0), Instr->getArg(1), Instr->getArg(2)); 3568 lowerMemset(Instr->getArg(0), Instr->getArg(1), Instr->getArg(2));
3543 return; 3569 return;
3544 } 3570 }
3545 case Intrinsics::NaClReadTP: { 3571 case Intrinsics::NaClReadTP: {
3546 if (Ctx->getFlags().getUseSandboxing()) { 3572 if (NeedSandboxing) {
3547 Operand *Src = 3573 Operand *Src =
3548 dispatchToConcrete(&ConcreteTarget::createNaClReadTPSrcOperand); 3574 dispatchToConcrete(&ConcreteTarget::createNaClReadTPSrcOperand);
3549 Variable *Dest = Instr->getDest(); 3575 Variable *Dest = Instr->getDest();
3550 Variable *T = nullptr; 3576 Variable *T = nullptr;
3551 _mov(T, Src); 3577 _mov(T, Src);
3552 _mov(Dest, T); 3578 _mov(Dest, T);
3553 } else { 3579 } else {
3554 InstCall *Call = makeHelperCall(H_call_read_tp, Instr->getDest(), 0); 3580 InstCall *Call = makeHelperCall(H_call_read_tp, Instr->getDest(), 0);
3555 lowerCall(Call); 3581 lowerCall(Call);
3556 } 3582 }
3557 return; 3583 return;
3558 } 3584 }
3559 case Intrinsics::Setjmp: { 3585 case Intrinsics::Setjmp: {
3560 InstCall *Call = makeHelperCall(H_call_setjmp, Instr->getDest(), 1); 3586 InstCall *Call = makeHelperCall(H_call_setjmp, Instr->getDest(), 1);
3561 Call->addArg(Instr->getArg(0)); 3587 Call->addArg(Instr->getArg(0));
3562 lowerCall(Call); 3588 lowerCall(Call);
3563 return; 3589 return;
3564 } 3590 }
3565 case Intrinsics::Sqrt: { 3591 case Intrinsics::Sqrt: {
3566 Operand *Src = legalize(Instr->getArg(0)); 3592 Operand *Src = legalize(Instr->getArg(0));
3567 Variable *Dest = Instr->getDest(); 3593 Variable *Dest = Instr->getDest();
3568 Variable *T = makeReg(Dest->getType()); 3594 Variable *T = makeReg(Dest->getType());
3569 _sqrtss(T, Src); 3595 _sqrtss(T, Src);
3570 _mov(Dest, T); 3596 _mov(Dest, T);
3571 return; 3597 return;
3572 } 3598 }
3573 case Intrinsics::Stacksave: { 3599 case Intrinsics::Stacksave: {
3574 Variable *esp = 3600 if (!Traits::Is64Bit || !NeedSandboxing) {
3575 Func->getTarget()->getPhysicalRegister(getStackReg(), Traits::WordType); 3601 Variable *esp = Func->getTarget()->getPhysicalRegister(getStackReg(),
3602 Traits::WordType);
3603 Variable *Dest = Instr->getDest();
3604 _mov(Dest, esp);
3605 return;
3606 }
3607 Variable *esp = Func->getTarget()->getPhysicalRegister(
3608 Traits::RegisterSet::Reg_esp, IceType_i32);
3576 Variable *Dest = Instr->getDest(); 3609 Variable *Dest = Instr->getDest();
3577 _mov(Dest, esp); 3610 _mov(Dest, esp);
3611
3578 return; 3612 return;
3579 } 3613 }
3580 case Intrinsics::Stackrestore: { 3614 case Intrinsics::Stackrestore: {
3581 Operand *Src = Instr->getArg(0); 3615 Operand *Src = Instr->getArg(0);
3582 const Type SrcTy = Src->getType(); 3616 _mov_sp(Src);
3583 Variable *esp = Func->getTarget()->getPhysicalRegister(
3584 Traits::getGprForType(SrcTy, getStackReg()), SrcTy);
3585 _redefined(_mov(esp, Src));
3586 return; 3617 return;
3587 } 3618 }
3619
3588 case Intrinsics::Trap: 3620 case Intrinsics::Trap:
3589 _ud2(); 3621 _ud2();
3590 return; 3622 return;
3591 case Intrinsics::UnknownIntrinsic: 3623 case Intrinsics::UnknownIntrinsic:
3592 Func->setError("Should not be lowering UnknownIntrinsic"); 3624 Func->setError("Should not be lowering UnknownIntrinsic");
3593 return; 3625 return;
3594 } 3626 }
3595 return; 3627 return;
3596 } 3628 }
3597 3629
(...skipping 688 matching lines...) Expand 10 before | Expand all | Expand 10 after
4286 lowerCast(InstCast::create(Func, InstCast::Zext, ValExtVar, Val)); 4318 lowerCast(InstCast::create(Func, InstCast::Zext, ValExtVar, Val));
4287 ValExt = ValExtVar; 4319 ValExt = ValExtVar;
4288 } 4320 }
4289 InstCall *Call = makeHelperCall(H_call_memset, nullptr, 3); 4321 InstCall *Call = makeHelperCall(H_call_memset, nullptr, 3);
4290 Call->addArg(Dest); 4322 Call->addArg(Dest);
4291 Call->addArg(ValExt); 4323 Call->addArg(ValExt);
4292 Call->addArg(Count); 4324 Call->addArg(Count);
4293 lowerCall(Call); 4325 lowerCall(Call);
4294 } 4326 }
4295 4327
4296 template <typename TraitsType>
4297 void TargetX86Base<TraitsType>::lowerIndirectJump(Variable *JumpTarget) {
4298 const bool NeedSandboxing = Ctx->getFlags().getUseSandboxing();
4299 if (Traits::Is64Bit) {
4300 Variable *T = makeReg(IceType_i64);
4301 _movzx(T, JumpTarget);
4302 JumpTarget = T;
4303 }
4304 if (NeedSandboxing) {
4305 _bundle_lock();
4306 const SizeT BundleSize =
4307 1 << Func->getAssembler<>()->getBundleAlignLog2Bytes();
4308 _and(JumpTarget, Ctx->getConstantInt32(~(BundleSize - 1)));
4309 }
4310 _jmp(JumpTarget);
4311 if (NeedSandboxing)
4312 _bundle_unlock();
4313 }
4314
4315 inline bool isAdd(const Inst *Inst) { 4328 inline bool isAdd(const Inst *Inst) {
4316 if (auto *Arith = llvm::dyn_cast_or_null<const InstArithmetic>(Inst)) { 4329 if (auto *Arith = llvm::dyn_cast_or_null<const InstArithmetic>(Inst)) {
4317 return (Arith->getOp() == InstArithmetic::Add); 4330 return (Arith->getOp() == InstArithmetic::Add);
4318 } 4331 }
4319 return false; 4332 return false;
4320 } 4333 }
4321 4334
4322 inline void dumpAddressOpt(const Cfg *Func, 4335 inline void dumpAddressOpt(const Cfg *Func,
4323 const ConstantRelocatable *Relocatable, 4336 const ConstantRelocatable *Relocatable,
4324 int32_t Offset, const Variable *Base, 4337 int32_t Offset, const Variable *Base,
(...skipping 219 matching lines...) Expand 10 before | Expand all | Expand 10 after
4544 return false; 4557 return false;
4545 // Incorporate ConstantRelocatables. 4558 // Incorporate ConstantRelocatables.
4546 if (Reloc0) 4559 if (Reloc0)
4547 NewRelocatable = Reloc0; 4560 NewRelocatable = Reloc0;
4548 else if (Reloc1) 4561 else if (Reloc1)
4549 NewRelocatable = Reloc1; 4562 NewRelocatable = Reloc1;
4550 if ((Reloc0 || Reloc1) && BaseOther && GotVar) 4563 if ((Reloc0 || Reloc1) && BaseOther && GotVar)
4551 return false; 4564 return false;
4552 // Compute the updated constant offset. 4565 // Compute the updated constant offset.
4553 if (Const0) { 4566 if (Const0) {
4554 int32_t MoreOffset = IsAdd ? Const0->getValue() : -Const0->getValue(); 4567 const int32_t MoreOffset =
4568 IsAdd ? Const0->getValue() : -Const0->getValue();
4555 if (Utils::WouldOverflowAdd(NewOffset, MoreOffset)) 4569 if (Utils::WouldOverflowAdd(NewOffset, MoreOffset))
4556 return false; 4570 return false;
4557 NewOffset += MoreOffset; 4571 NewOffset += MoreOffset;
4558 } 4572 }
4559 if (Const1) { 4573 if (Const1) {
4560 int32_t MoreOffset = IsAdd ? Const1->getValue() : -Const1->getValue(); 4574 const int32_t MoreOffset =
4575 IsAdd ? Const1->getValue() : -Const1->getValue();
4561 if (Utils::WouldOverflowAdd(NewOffset, MoreOffset)) 4576 if (Utils::WouldOverflowAdd(NewOffset, MoreOffset))
4562 return false; 4577 return false;
4563 NewOffset += MoreOffset; 4578 NewOffset += MoreOffset;
4564 } 4579 }
4565 // Update the computed address parameters once we are sure optimization 4580 // Update the computed address parameters once we are sure optimization
4566 // is valid. 4581 // is valid.
4567 if ((Reloc0 || Reloc1) && GotVar) { 4582 if ((Reloc0 || Reloc1) && GotVar) {
4568 assert(BaseOther == nullptr); 4583 assert(BaseOther == nullptr);
4569 BaseOther = GotVar; 4584 BaseOther = GotVar;
4570 } 4585 }
4571 Base = NewBase; 4586 Base = NewBase;
4572 Offset = NewOffset; 4587 Offset = NewOffset;
4573 Relocatable = NewRelocatable; 4588 Relocatable = NewRelocatable;
4574 Reason = BaseInst; 4589 Reason = BaseInst;
4575 return true; 4590 return true;
4576 } 4591 }
4577 return false; 4592 return false;
4578 } 4593 }
4579 4594
4580 // Builds information for a canonical address expresion: 4595 // Builds information for a canonical address expresion:
4581 // <Relocatable + Offset>(Base, Index, Shift) 4596 // <Relocatable + Offset>(Base, Index, Shift)
4582 // On entry: 4597 // On entry:
4583 // Relocatable == null, 4598 // Relocatable == null,
4584 // Offset == 0, 4599 // Offset == 0,
4585 // Base is a Variable, 4600 // Base is a Variable,
4586 // Index == nullptr, 4601 // Index == nullptr,
4587 // Shift == 0 4602 // Shift == 0
4588 inline bool computeAddressOpt(Cfg *Func, const Inst *Instr, Variable *GotVar, 4603 inline bool computeAddressOpt(Cfg *Func, const Inst *Instr, Variable *GotVar,
4604 bool ReserveSlot,
4589 ConstantRelocatable *&Relocatable, 4605 ConstantRelocatable *&Relocatable,
4590 int32_t &Offset, Variable *&Base, 4606 int32_t &Offset, Variable *&Base,
4591 Variable *&Index, uint16_t &Shift) { 4607 Variable *&Index, uint16_t &Shift) {
4592 bool AddressWasOptimized = false; 4608 bool AddressWasOptimized = false;
4593 Func->resetCurrentNode(); 4609 Func->resetCurrentNode();
4594 if (Func->isVerbose(IceV_AddrOpt)) { 4610 if (Func->isVerbose(IceV_AddrOpt)) {
4595 OstreamLocker L(Func->getContext()); 4611 OstreamLocker L(Func->getContext());
4596 Ostream &Str = Func->getContext()->getStrDump(); 4612 Ostream &Str = Func->getContext()->getStrDump();
4597 Str << "\nStarting computeAddressOpt for instruction:\n "; 4613 Str << "\nStarting computeAddressOpt for instruction:\n ";
4598 Instr->dumpDecorated(Func); 4614 Instr->dumpDecorated(Func);
4599 } 4615 }
4600 if (Base == nullptr) 4616 if (Base == nullptr)
4601 return AddressWasOptimized; 4617 return AddressWasOptimized;
4602 // If the Base has more than one use or is live across multiple blocks, then 4618 // If the Base has more than one use or is live across multiple blocks, then
4603 // don't go further. Alternatively (?), never consider a transformation that 4619 // don't go further. Alternatively (?), never consider a transformation that
4604 // would change a variable that is currently *not* live across basic block 4620 // would change a variable that is currently *not* live across basic block
4605 // boundaries into one that *is*. 4621 // boundaries into one that *is*.
4606 if (Func->getVMetadata()->isMultiBlock(Base) /* || Base->getUseCount() > 1*/) 4622 if (Func->getVMetadata()->isMultiBlock(Base) /* || Base->getUseCount() > 1*/)
4607 return AddressWasOptimized; 4623 return AddressWasOptimized;
4608 4624
4609 const bool MockBounds = Func->getContext()->getFlags().getMockBoundsCheck(); 4625 const bool MockBounds = Func->getContext()->getFlags().getMockBoundsCheck();
4610 const VariablesMetadata *VMetadata = Func->getVMetadata(); 4626 const VariablesMetadata *VMetadata = Func->getVMetadata();
4611 const Inst *Reason = nullptr; 4627 const Inst *Reason = nullptr;
4612 do { 4628 do {
4629 assert(!ReserveSlot || Base == nullptr || Index == nullptr);
4613 if (Reason) { 4630 if (Reason) {
4614 dumpAddressOpt(Func, Relocatable, Offset, Base, Index, Shift, Reason); 4631 dumpAddressOpt(Func, Relocatable, Offset, Base, Index, Shift, Reason);
4615 AddressWasOptimized = true; 4632 AddressWasOptimized = true;
4616 Reason = nullptr; 4633 Reason = nullptr;
4617 } 4634 }
4618 // Update Base and Index to follow through assignments to definitions. 4635 // Update Base and Index to follow through assignments to definitions.
4619 if (matchAssign(VMetadata, GotVar, Base, Relocatable, Offset, Reason)) { 4636 if (matchAssign(VMetadata, GotVar, Base, Relocatable, Offset, Reason)) {
4620 // Assignments of Base from a Relocatable or ConstantInt32 can result 4637 // Assignments of Base from a Relocatable or ConstantInt32 can result
4621 // in Base becoming nullptr. To avoid code duplication in this loop we 4638 // in Base becoming nullptr. To avoid code duplication in this loop we
4622 // prefer that Base be non-nullptr if possible. 4639 // prefer that Base be non-nullptr if possible.
4623 if ((Base == nullptr) && (Index != nullptr) && Shift == 0) 4640 if ((Base == nullptr) && (Index != nullptr) && Shift == 0)
4624 std::swap(Base, Index); 4641 std::swap(Base, Index);
4625 continue; 4642 continue;
4626 } 4643 }
4627 if (matchAssign(VMetadata, GotVar, Index, Relocatable, Offset, Reason)) 4644 if (matchAssign(VMetadata, GotVar, Index, Relocatable, Offset, Reason))
4628 continue; 4645 continue;
4629 4646
4630 if (!MockBounds) { 4647 if (!MockBounds) {
4631 // Transition from: 4648 // Transition from:
4632 // <Relocatable + Offset>(Base) to 4649 // <Relocatable + Offset>(Base) to
4633 // <Relocatable + Offset>(Base, Index) 4650 // <Relocatable + Offset>(Base, Index)
4634 if (matchCombinedBaseIndex(VMetadata, Base, Index, Shift, Reason)) 4651 if (!ReserveSlot &&
4652 matchCombinedBaseIndex(VMetadata, Base, Index, Shift, Reason))
4635 continue; 4653 continue;
4636 // Recognize multiply/shift and update Shift amount. 4654 // Recognize multiply/shift and update Shift amount.
4637 // Index becomes Index=Var<<Const && Const+Shift<=3 ==> 4655 // Index becomes Index=Var<<Const && Const+Shift<=3 ==>
4638 // Index=Var, Shift+=Const 4656 // Index=Var, Shift+=Const
4639 // Index becomes Index=Const*Var && log2(Const)+Shift<=3 ==> 4657 // Index becomes Index=Const*Var && log2(Const)+Shift<=3 ==>
4640 // Index=Var, Shift+=log2(Const) 4658 // Index=Var, Shift+=log2(Const)
4641 if (matchShiftedIndex(VMetadata, Index, Shift, Reason)) 4659 if (matchShiftedIndex(VMetadata, Index, Shift, Reason))
4642 continue; 4660 continue;
4643 // If Shift is zero, the choice of Base and Index was purely arbitrary. 4661 // If Shift is zero, the choice of Base and Index was purely arbitrary.
4644 // Recognize multiply/shift and set Shift amount. 4662 // Recognize multiply/shift and set Shift amount.
(...skipping 112 matching lines...) Expand 10 before | Expand all | Expand 10 after
4757 Variable *Index = nullptr; 4775 Variable *Index = nullptr;
4758 ConstantRelocatable *Relocatable = nullptr; 4776 ConstantRelocatable *Relocatable = nullptr;
4759 uint16_t Shift = 0; 4777 uint16_t Shift = 0;
4760 int32_t Offset = 0; 4778 int32_t Offset = 0;
4761 // Vanilla ICE load instructions should not use the segment registers, and 4779 // Vanilla ICE load instructions should not use the segment registers, and
4762 // computeAddressOpt only works at the level of Variables and Constants, not 4780 // computeAddressOpt only works at the level of Variables and Constants, not
4763 // other X86OperandMem, so there should be no mention of segment 4781 // other X86OperandMem, so there should be no mention of segment
4764 // registers there either. 4782 // registers there either.
4765 constexpr auto SegmentReg = X86OperandMem::SegmentRegisters::DefaultSegment; 4783 constexpr auto SegmentReg = X86OperandMem::SegmentRegisters::DefaultSegment;
4766 auto *Base = llvm::dyn_cast<Variable>(Addr); 4784 auto *Base = llvm::dyn_cast<Variable>(Addr);
4767 if (computeAddressOpt(Func, Inst, GotVar, Relocatable, Offset, Base, Index, 4785 const bool ReserveSlot = Traits::Is64Bit && NeedSandboxing;
4768 Shift)) { 4786 if (computeAddressOpt(Func, Inst, GotVar, ReserveSlot, Relocatable, Offset,
4787 Base, Index, Shift)) {
4769 Inst->setDeleted(); 4788 Inst->setDeleted();
4770 Constant *OffsetOp = nullptr; 4789 Constant *OffsetOp = nullptr;
4771 if (Relocatable == nullptr) { 4790 if (Relocatable == nullptr) {
4772 OffsetOp = Ctx->getConstantInt32(Offset); 4791 OffsetOp = Ctx->getConstantInt32(Offset);
4773 } else { 4792 } else {
4774 OffsetOp = Ctx->getConstantSym(Relocatable->getOffset() + Offset, 4793 OffsetOp = Ctx->getConstantSym(Relocatable->getOffset() + Offset,
4775 Relocatable->getName(), 4794 Relocatable->getName(),
4776 Relocatable->getSuppressMangling()); 4795 Relocatable->getSuppressMangling());
4777 } 4796 }
4778 // The new mem operand is created without IsPIC being set, because 4797 // The new mem operand is created without IsRebased being set, because
4779 // computeAddressOpt() doesn't include GotVar in its final result. 4798 // computeAddressOpt() doesn't include GotVar in its final result.
4780 Addr = X86OperandMem::create(Func, Dest->getType(), Base, OffsetOp, Index, 4799 Addr = X86OperandMem::create(Func, Dest->getType(), Base, OffsetOp, Index,
4781 Shift, SegmentReg); 4800 Shift, SegmentReg);
4782 Context.insert<InstLoad>(Dest, Addr); 4801 Context.insert<InstLoad>(Dest, Addr);
4783 } 4802 }
4784 } 4803 }
4785 4804
4786 template <typename TraitsType> 4805 template <typename TraitsType>
4787 void TargetX86Base<TraitsType>::randomlyInsertNop(float Probability, 4806 void TargetX86Base<TraitsType>::randomlyInsertNop(float Probability,
4788 RandomNumberGenerator &RNG) { 4807 RandomNumberGenerator &RNG) {
(...skipping 273 matching lines...) Expand 10 before | Expand all | Expand 10 after
5062 Variable *Index = nullptr; 5081 Variable *Index = nullptr;
5063 ConstantRelocatable *Relocatable = nullptr; 5082 ConstantRelocatable *Relocatable = nullptr;
5064 uint16_t Shift = 0; 5083 uint16_t Shift = 0;
5065 int32_t Offset = 0; 5084 int32_t Offset = 0;
5066 auto *Base = llvm::dyn_cast<Variable>(Addr); 5085 auto *Base = llvm::dyn_cast<Variable>(Addr);
5067 // Vanilla ICE store instructions should not use the segment registers, and 5086 // Vanilla ICE store instructions should not use the segment registers, and
5068 // computeAddressOpt only works at the level of Variables and Constants, not 5087 // computeAddressOpt only works at the level of Variables and Constants, not
5069 // other X86OperandMem, so there should be no mention of segment 5088 // other X86OperandMem, so there should be no mention of segment
5070 // registers there either. 5089 // registers there either.
5071 constexpr auto SegmentReg = X86OperandMem::SegmentRegisters::DefaultSegment; 5090 constexpr auto SegmentReg = X86OperandMem::SegmentRegisters::DefaultSegment;
5072 if (computeAddressOpt(Func, Inst, GotVar, Relocatable, Offset, Base, Index, 5091 const bool ReserveSlot = Traits::Is64Bit && NeedSandboxing;
5073 Shift)) { 5092 if (computeAddressOpt(Func, Inst, GotVar, ReserveSlot, Relocatable, Offset,
5093 Base, Index, Shift)) {
5074 Inst->setDeleted(); 5094 Inst->setDeleted();
5075 Constant *OffsetOp = nullptr; 5095 Constant *OffsetOp = nullptr;
5076 if (Relocatable == nullptr) { 5096 if (Relocatable == nullptr) {
5077 OffsetOp = Ctx->getConstantInt32(Offset); 5097 OffsetOp = Ctx->getConstantInt32(Offset);
5078 } else { 5098 } else {
5079 OffsetOp = Ctx->getConstantSym(Relocatable->getOffset() + Offset, 5099 OffsetOp = Ctx->getConstantSym(Relocatable->getOffset() + Offset,
5080 Relocatable->getName(), 5100 Relocatable->getName(),
5081 Relocatable->getSuppressMangling()); 5101 Relocatable->getSuppressMangling());
5082 } 5102 }
5083 // The new mem operand is created without IsPIC being set, because 5103 // The new mem operand is created without IsRebased being set, because
5084 // computeAddressOpt() doesn't include GotVar in its final result. 5104 // computeAddressOpt() doesn't include GotVar in its final result.
5085 Addr = X86OperandMem::create(Func, Data->getType(), Base, OffsetOp, Index, 5105 Addr = X86OperandMem::create(Func, Data->getType(), Base, OffsetOp, Index,
5086 Shift, SegmentReg); 5106 Shift, SegmentReg);
5087 auto *NewStore = Context.insert<InstStore>(Data, Addr); 5107 auto *NewStore = Context.insert<InstStore>(Data, Addr);
5088 if (Inst->getDest()) 5108 if (Inst->getDest())
5089 NewStore->setRmwBeacon(Inst->getRmwBeacon()); 5109 NewStore->setRmwBeacon(Inst->getRmwBeacon());
5090 } 5110 }
5091 } 5111 }
5092 5112
5093 template <typename TraitsType> 5113 template <typename TraitsType>
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after
5127 _br(Traits::Cond::Br_a, SkipJumpTable); 5147 _br(Traits::Cond::Br_a, SkipJumpTable);
5128 } else { 5148 } else {
5129 _br(Traits::Cond::Br_a, DefaultTarget); 5149 _br(Traits::Cond::Br_a, DefaultTarget);
5130 } 5150 }
5131 5151
5132 InstJumpTable *JumpTable = Case.getJumpTable(); 5152 InstJumpTable *JumpTable = Case.getJumpTable();
5133 Context.insert(JumpTable); 5153 Context.insert(JumpTable);
5134 5154
5135 // Make sure the index is a register of the same width as the base 5155 // Make sure the index is a register of the same width as the base
5136 Variable *Index; 5156 Variable *Index;
5137 if (RangeIndex->getType() != getPointerType()) { 5157 const Type PointerType = getPointerType();
5138 Index = makeReg(getPointerType()); 5158 if (RangeIndex->getType() != PointerType) {
5159 Index = makeReg(PointerType);
5139 _movzx(Index, RangeIndex); 5160 _movzx(Index, RangeIndex);
5140 } else { 5161 } else {
5141 Index = legalizeToReg(RangeIndex); 5162 Index = legalizeToReg(RangeIndex);
5142 } 5163 }
5143 5164
5144 constexpr RelocOffsetT RelocOffset = 0; 5165 constexpr RelocOffsetT RelocOffset = 0;
5145 constexpr bool SuppressMangling = true; 5166 constexpr bool SuppressMangling = true;
5146 const bool IsPIC = Ctx->getFlags().getUseNonsfi(); 5167 const bool IsRebased = Ctx->getFlags().getUseNonsfi();
5147 IceString MangledName = Ctx->mangleName(Func->getFunctionName()); 5168 IceString MangledName = Ctx->mangleName(Func->getFunctionName());
5148 Variable *Base = IsPIC ? legalizeToReg(GotVar) : nullptr; 5169 Variable *Base = IsRebased ? legalizeToReg(GotVar) : nullptr;
5149 Constant *Offset = Ctx->getConstantSym( 5170 Constant *Offset = Ctx->getConstantSym(
5150 RelocOffset, InstJumpTable::makeName(MangledName, JumpTable->getId()), 5171 RelocOffset, InstJumpTable::makeName(MangledName, JumpTable->getId()),
5151 SuppressMangling); 5172 SuppressMangling);
5152 uint16_t Shift = typeWidthInBytesLog2(getPointerType()); 5173 uint16_t Shift = typeWidthInBytesLog2(PointerType);
5153 constexpr auto Segment = X86OperandMem::SegmentRegisters::DefaultSegment; 5174 constexpr auto Segment = X86OperandMem::SegmentRegisters::DefaultSegment;
5175
5176 Variable *Target = nullptr;
5177 if (Traits::Is64Bit && NeedSandboxing) {
5178 assert(Base == nullptr);
5179 assert(Index != nullptr && Index->getType() == IceType_i32);
5180 }
5154 auto *TargetInMemory = X86OperandMem::create( 5181 auto *TargetInMemory = X86OperandMem::create(
5155 Func, getPointerType(), Base, Offset, Index, Shift, Segment, IsPIC); 5182 Func, PointerType, Base, Offset, Index, Shift, Segment, IsRebased);
5156 Variable *Target = nullptr;
5157 _mov(Target, TargetInMemory); 5183 _mov(Target, TargetInMemory);
5184
5158 lowerIndirectJump(Target); 5185 lowerIndirectJump(Target);
5159 5186
5160 if (DefaultTarget == nullptr) 5187 if (DefaultTarget == nullptr)
5161 Context.insert(SkipJumpTable); 5188 Context.insert(SkipJumpTable);
5162 return; 5189 return;
5163 } 5190 }
5164 case CaseCluster::Range: { 5191 case CaseCluster::Range: {
5165 if (Case.isUnitRange()) { 5192 if (Case.isUnitRange()) {
5166 // Single item 5193 // Single item
5167 if (!DoneCmp) { 5194 if (!DoneCmp) {
(...skipping 848 matching lines...) Expand 10 before | Expand all | Expand 10 after
6016 } 6043 }
6017 6044
6018 if (auto *Mem = llvm::dyn_cast<X86OperandMem>(From)) { 6045 if (auto *Mem = llvm::dyn_cast<X86OperandMem>(From)) {
6019 // Before doing anything with a Mem operand, we need to ensure that the 6046 // Before doing anything with a Mem operand, we need to ensure that the
6020 // Base and Index components are in physical registers. 6047 // Base and Index components are in physical registers.
6021 Variable *Base = Mem->getBase(); 6048 Variable *Base = Mem->getBase();
6022 Variable *Index = Mem->getIndex(); 6049 Variable *Index = Mem->getIndex();
6023 Constant *Offset = Mem->getOffset(); 6050 Constant *Offset = Mem->getOffset();
6024 Variable *RegBase = nullptr; 6051 Variable *RegBase = nullptr;
6025 Variable *RegIndex = nullptr; 6052 Variable *RegIndex = nullptr;
6053 uint16_t Shift = Mem->getShift();
6026 if (Base) { 6054 if (Base) {
6027 RegBase = llvm::cast<Variable>( 6055 RegBase = llvm::cast<Variable>(
6028 legalize(Base, Legal_Reg | Legal_Rematerializable)); 6056 legalize(Base, Legal_Reg | Legal_Rematerializable));
6029 } 6057 }
6030 if (Index) { 6058 if (Index) {
6059 // TODO(jpp): perhaps we should only allow Legal_Reg if
6060 // Base->isRematerializable.
6031 RegIndex = llvm::cast<Variable>( 6061 RegIndex = llvm::cast<Variable>(
6032 legalize(Index, Legal_Reg | Legal_Rematerializable)); 6062 legalize(Index, Legal_Reg | Legal_Rematerializable));
6033 } 6063 }
6034 // For Non-SFI mode, if the Offset field is a ConstantRelocatable, we 6064 // For Non-SFI mode, if the Offset field is a ConstantRelocatable, we
6035 // replace either Base or Index with a legalized GotVar. At emission time, 6065 // replace either Base or Index with a legalized GotVar. At emission time,
6036 // the ConstantRelocatable will be emitted with the @GOTOFF relocation. 6066 // the ConstantRelocatable will be emitted with the @GOTOFF relocation.
6037 bool NeedPIC = false; 6067 bool IsRebased = false;
6038 if (UseNonsfi && !Mem->getIsPIC() && Offset && 6068 if (UseNonsfi && !Mem->getIsRebased() && Offset &&
6039 llvm::isa<ConstantRelocatable>(Offset)) { 6069 llvm::isa<ConstantRelocatable>(Offset)) {
6040 assert(!(Allowed & Legal_AddrAbs)); 6070 assert(!(Allowed & Legal_AddrAbs));
6041 NeedPIC = true; 6071 IsRebased = true;
6042 if (RegBase == nullptr) { 6072 if (RegBase == nullptr) {
6043 RegBase = legalizeToReg(GotVar); 6073 RegBase = legalizeToReg(GotVar);
6044 } else if (RegIndex == nullptr) { 6074 } else if (RegIndex == nullptr) {
6045 RegIndex = legalizeToReg(GotVar); 6075 RegIndex = legalizeToReg(GotVar);
6046 } else { 6076 } else {
6047 llvm::report_fatal_error( 6077 llvm::report_fatal_error(
6048 "Either Base or Index must be unused in Non-SFI mode"); 6078 "Either Base or Index must be unused in Non-SFI mode");
6049 } 6079 }
6050 } 6080 }
6051 if (Base != RegBase || Index != RegIndex) { 6081 if (Base != RegBase || Index != RegIndex) {
6052 Mem = X86OperandMem::create(Func, Ty, RegBase, Offset, RegIndex, 6082 Mem = X86OperandMem::create(Func, Ty, RegBase, Offset, RegIndex, Shift,
6053 Mem->getShift(), Mem->getSegmentRegister(), 6083 Mem->getSegmentRegister(), IsRebased);
6054 NeedPIC);
6055 } 6084 }
6056 6085
6057 // For all Memory Operands, we do randomization/pooling here 6086 // For all Memory Operands, we do randomization/pooling here
6058 From = randomizeOrPoolImmediate(Mem); 6087 From = randomizeOrPoolImmediate(Mem);
6059 6088
6060 if (!(Allowed & Legal_Mem)) { 6089 if (!(Allowed & Legal_Mem)) {
6061 From = copyToReg(From, RegNum); 6090 From = copyToReg(From, RegNum);
6062 } 6091 }
6063 return From; 6092 return From;
6064 } 6093 }
(...skipping 28 matching lines...) Expand all
6093 } 6122 }
6094 } 6123 }
6095 6124
6096 // If the operand is a ConstantRelocatable, and Legal_AddrAbs is not 6125 // If the operand is a ConstantRelocatable, and Legal_AddrAbs is not
6097 // specified, and UseNonsfi is indicated, we need to add GotVar. 6126 // specified, and UseNonsfi is indicated, we need to add GotVar.
6098 if (auto *CR = llvm::dyn_cast<ConstantRelocatable>(Const)) { 6127 if (auto *CR = llvm::dyn_cast<ConstantRelocatable>(Const)) {
6099 if (UseNonsfi && !(Allowed & Legal_AddrAbs)) { 6128 if (UseNonsfi && !(Allowed & Legal_AddrAbs)) {
6100 assert(Ty == IceType_i32); 6129 assert(Ty == IceType_i32);
6101 Variable *RegBase = legalizeToReg(GotVar); 6130 Variable *RegBase = legalizeToReg(GotVar);
6102 Variable *NewVar = makeReg(Ty, RegNum); 6131 Variable *NewVar = makeReg(Ty, RegNum);
6103 auto *Mem = Traits::X86OperandMem::create(Func, Ty, RegBase, CR); 6132 static constexpr bool IsRebased = true;
6104 Mem->setIsPIC(); 6133 auto *Mem =
6134 Traits::X86OperandMem::create(Func, Ty, RegBase, CR, IsRebased);
6105 _lea(NewVar, Mem); 6135 _lea(NewVar, Mem);
6106 From = NewVar; 6136 From = NewVar;
6107 } 6137 }
6108 } 6138 }
6109 6139
6110 // Convert a scalar floating point constant into an explicit memory 6140 // Convert a scalar floating point constant into an explicit memory
6111 // operand. 6141 // operand.
6112 if (isScalarFloatingType(Ty)) { 6142 if (isScalarFloatingType(Ty)) {
6113 if (auto *ConstFloat = llvm::dyn_cast<ConstantFloat>(Const)) { 6143 if (auto *ConstFloat = llvm::dyn_cast<ConstantFloat>(Const)) {
6114 if (Utils::isPositiveZero(ConstFloat->getValue())) 6144 if (Utils::isPositiveZero(ConstFloat->getValue()))
6115 return makeZeroedRegister(Ty, RegNum); 6145 return makeZeroedRegister(Ty, RegNum);
6116 } else if (auto *ConstDouble = llvm::dyn_cast<ConstantDouble>(Const)) { 6146 } else if (auto *ConstDouble = llvm::dyn_cast<ConstantDouble>(Const)) {
6117 if (Utils::isPositiveZero(ConstDouble->getValue())) 6147 if (Utils::isPositiveZero(ConstDouble->getValue()))
6118 return makeZeroedRegister(Ty, RegNum); 6148 return makeZeroedRegister(Ty, RegNum);
6119 } 6149 }
6120 Variable *Base = UseNonsfi ? legalizeToReg(GotVar) : nullptr; 6150 Variable *Base = UseNonsfi ? legalizeToReg(GotVar) : nullptr;
6121 std::string Buffer; 6151 std::string Buffer;
6122 llvm::raw_string_ostream StrBuf(Buffer); 6152 llvm::raw_string_ostream StrBuf(Buffer);
6123 llvm::cast<Constant>(From)->emitPoolLabel(StrBuf, Ctx); 6153 llvm::cast<Constant>(From)->emitPoolLabel(StrBuf, Ctx);
6124 llvm::cast<Constant>(From)->setShouldBePooled(true); 6154 llvm::cast<Constant>(From)->setShouldBePooled(true);
6125 Constant *Offset = Ctx->getConstantSym(0, StrBuf.str(), true); 6155 Constant *Offset = Ctx->getConstantSym(0, StrBuf.str(), true);
6126 auto *Mem = X86OperandMem::create(Func, Ty, Base, Offset); 6156 const bool IsRebased = Base != nullptr;
6127 if (UseNonsfi) 6157 auto *Mem = X86OperandMem::create(Func, Ty, Base, Offset, IsRebased);
6128 Mem->setIsPIC();
6129 From = Mem; 6158 From = Mem;
6130 } 6159 }
6131 bool NeedsReg = false; 6160 bool NeedsReg = false;
6132 if (!(Allowed & Legal_Imm) && !isScalarFloatingType(Ty)) 6161 if (!(Allowed & Legal_Imm) && !isScalarFloatingType(Ty))
6133 // Immediate specifically not allowed 6162 // Immediate specifically not allowed
6134 NeedsReg = true; 6163 NeedsReg = true;
6135 if (!(Allowed & Legal_Mem) && isScalarFloatingType(Ty)) 6164 if (!(Allowed & Legal_Mem) && isScalarFloatingType(Ty))
6136 // On x86, FP constants are lowered to mem operands. 6165 // On x86, FP constants are lowered to mem operands.
6137 NeedsReg = true; 6166 NeedsReg = true;
6138 if (NeedsReg) { 6167 if (NeedsReg) {
(...skipping 103 matching lines...) Expand 10 before | Expand all | Expand 10 after
6242 // we guarantee legalize(Offset) will return a Constant*. 6271 // we guarantee legalize(Offset) will return a Constant*.
6243 if (!llvm::isa<ConstantRelocatable>(Offset)) { 6272 if (!llvm::isa<ConstantRelocatable>(Offset)) {
6244 BoolFlagSaver B(RandomizationPoolingPaused, true); 6273 BoolFlagSaver B(RandomizationPoolingPaused, true);
6245 6274
6246 Offset = llvm::cast<Constant>(legalize(Offset)); 6275 Offset = llvm::cast<Constant>(legalize(Offset));
6247 } 6276 }
6248 6277
6249 assert(llvm::isa<ConstantInteger32>(Offset) || 6278 assert(llvm::isa<ConstantInteger32>(Offset) ||
6250 llvm::isa<ConstantRelocatable>(Offset)); 6279 llvm::isa<ConstantRelocatable>(Offset));
6251 } 6280 }
6252 // Not completely sure whether it's OK to leave IsPIC unset when creating 6281 // Not completely sure whether it's OK to leave IsRebased unset when
6282 // creating
6253 // the mem operand. If DoLegalize is true, it will definitely be applied 6283 // the mem operand. If DoLegalize is true, it will definitely be applied
6254 // during the legalize() call, but perhaps not during the 6284 // during the legalize() call, but perhaps not during the
6255 // randomizeOrPoolImmediate() call. In any case, the emit routines will 6285 // randomizeOrPoolImmediate() call. In any case, the emit routines will
6256 // assert that PIC legalization has been applied. 6286 // assert that PIC legalization has been applied.
6257 Mem = X86OperandMem::create(Func, Ty, Base, Offset); 6287 Mem = X86OperandMem::create(Func, Ty, Base, Offset);
6258 } 6288 }
6259 // Do legalization, which contains randomization/pooling or do 6289 // Do legalization, which contains randomization/pooling or do
6260 // randomization/pooling. 6290 // randomization/pooling.
6261 return llvm::cast<X86OperandMem>(DoLegalize ? legalize(Mem) 6291 return llvm::cast<X86OperandMem>(DoLegalize ? legalize(Mem)
6262 : randomizeOrPoolImmediate(Mem)); 6292 : randomizeOrPoolImmediate(Mem));
(...skipping 109 matching lines...) Expand 10 before | Expand all | Expand 10 after
6372 Operand * 6402 Operand *
6373 TargetX86Base<TraitsType>::randomizeOrPoolImmediate(Constant *Immediate, 6403 TargetX86Base<TraitsType>::randomizeOrPoolImmediate(Constant *Immediate,
6374 int32_t RegNum) { 6404 int32_t RegNum) {
6375 assert(llvm::isa<ConstantInteger32>(Immediate) || 6405 assert(llvm::isa<ConstantInteger32>(Immediate) ||
6376 llvm::isa<ConstantRelocatable>(Immediate)); 6406 llvm::isa<ConstantRelocatable>(Immediate));
6377 if (Ctx->getFlags().getRandomizeAndPoolImmediatesOption() == RPI_None || 6407 if (Ctx->getFlags().getRandomizeAndPoolImmediatesOption() == RPI_None ||
6378 RandomizationPoolingPaused == true) { 6408 RandomizationPoolingPaused == true) {
6379 // Immediates randomization/pooling off or paused 6409 // Immediates randomization/pooling off or paused
6380 return Immediate; 6410 return Immediate;
6381 } 6411 }
6382 if (Immediate->shouldBeRandomizedOrPooled(Ctx)) { 6412
6383 Ctx->statsUpdateRPImms(); 6413 if (Traits::Is64Bit && NeedSandboxing) {
6384 if (Ctx->getFlags().getRandomizeAndPoolImmediatesOption() == 6414 // Immediate randomization/pooling is currently disabled for x86-64
6385 RPI_Randomize) { 6415 // sandboxing for it could generate invalid memory operands.
6386 // blind the constant 6416 assert(false &&
6387 // FROM: 6417 "Constant pooling/randomization is disabled for x8664 sandbox.");
6388 // imm 6418 return Immediate;
6389 // TO: 6419 }
6390 // insert: mov imm+cookie, Reg 6420
6391 // insert: lea -cookie[Reg], Reg 6421 if (!Immediate->shouldBeRandomizedOrPooled(Ctx)) {
6392 // => Reg 6422 // the constant Immediate is not eligible for blinding/pooling
6393 // If we have already assigned a phy register, we must come from 6423 return Immediate;
6394 // advancedPhiLowering()=>lowerAssign(). In this case we should reuse the 6424 }
6395 // assigned register as this assignment is that start of its use-def 6425 Ctx->statsUpdateRPImms();
6396 // chain. So we add RegNum argument here. Note we use 'lea' instruction 6426 switch (Ctx->getFlags().getRandomizeAndPoolImmediatesOption()) {
6397 // instead of 'xor' to avoid affecting the flags. 6427 default:
6398 Variable *Reg = makeReg(IceType_i32, RegNum); 6428 llvm::report_fatal_error("Unsupported -randomize-pool-immediates option");
6399 auto *Integer = llvm::cast<ConstantInteger32>(Immediate); 6429 case RPI_Randomize: {
6400 uint32_t Value = Integer->getValue(); 6430 // blind the constant
6401 uint32_t Cookie = Func->getConstantBlindingCookie(); 6431 // FROM:
6402 _mov(Reg, Ctx->getConstantInt(IceType_i32, Cookie + Value)); 6432 // imm
6403 Constant *Offset = Ctx->getConstantInt(IceType_i32, 0 - Cookie); 6433 // TO:
6404 _lea(Reg, 6434 // insert: mov imm+cookie, Reg
6405 X86OperandMem::create(Func, IceType_i32, Reg, Offset, nullptr, 0)); 6435 // insert: lea -cookie[Reg], Reg
6406 if (Immediate->getType() != IceType_i32) { 6436 // => Reg
6407 Variable *TruncReg = makeReg(Immediate->getType(), RegNum); 6437 // If we have already assigned a phy register, we must come from
6408 _mov(TruncReg, Reg); 6438 // advancedPhiLowering()=>lowerAssign(). In this case we should reuse the
6409 return TruncReg; 6439 // assigned register as this assignment is that start of its use-def
6410 } 6440 // chain. So we add RegNum argument here. Note we use 'lea' instruction
6441 // instead of 'xor' to avoid affecting the flags.
6442 Variable *Reg = makeReg(IceType_i32, RegNum);
6443 auto *Integer = llvm::cast<ConstantInteger32>(Immediate);
6444 uint32_t Value = Integer->getValue();
6445 uint32_t Cookie = Func->getConstantBlindingCookie();
6446 _mov(Reg, Ctx->getConstantInt(IceType_i32, Cookie + Value));
6447 Constant *Offset = Ctx->getConstantInt(IceType_i32, 0 - Cookie);
6448 _lea(Reg, X86OperandMem::create(Func, IceType_i32, Reg, Offset));
6449 if (Immediate->getType() == IceType_i32) {
6411 return Reg; 6450 return Reg;
6412 } 6451 }
6413 if (Ctx->getFlags().getRandomizeAndPoolImmediatesOption() == RPI_Pool) { 6452 Variable *TruncReg = makeReg(Immediate->getType(), RegNum);
6414 // pool the constant 6453 _mov(TruncReg, Reg);
6415 // FROM: 6454 return TruncReg;
6416 // imm
6417 // TO:
6418 // insert: mov $label, Reg
6419 // => Reg
6420 assert(Ctx->getFlags().getRandomizeAndPoolImmediatesOption() == RPI_Pool);
6421 Immediate->setShouldBePooled(true);
6422 // if we have already assigned a phy register, we must come from
6423 // advancedPhiLowering()=>lowerAssign(). In this case we should reuse the
6424 // assigned register as this assignment is that start of its use-def
6425 // chain. So we add RegNum argument here.
6426 Variable *Reg = makeReg(Immediate->getType(), RegNum);
6427 IceString Label;
6428 llvm::raw_string_ostream Label_stream(Label);
6429 Immediate->emitPoolLabel(Label_stream, Ctx);
6430 constexpr RelocOffsetT Offset = 0;
6431 constexpr bool SuppressMangling = true;
6432 Constant *Symbol =
6433 Ctx->getConstantSym(Offset, Label_stream.str(), SuppressMangling);
6434 const bool UseNonsfi = Ctx->getFlags().getUseNonsfi();
6435 Variable *Base = UseNonsfi ? legalizeToReg(GotVar) : nullptr;
6436 X86OperandMem *MemOperand =
6437 X86OperandMem::create(Func, Immediate->getType(), Base, Symbol);
6438 if (UseNonsfi)
6439 MemOperand->setIsPIC();
6440 _mov(Reg, MemOperand);
6441 return Reg;
6442 }
6443 assert("Unsupported -randomize-pool-immediates option" && false);
6444 } 6455 }
6445 // the constant Immediate is not eligible for blinding/pooling 6456 case RPI_Pool: {
6446 return Immediate; 6457 // pool the constant
6458 // FROM:
6459 // imm
6460 // TO:
6461 // insert: mov $label, Reg
6462 // => Reg
6463 assert(Ctx->getFlags().getRandomizeAndPoolImmediatesOption() == RPI_Pool);
6464 Immediate->setShouldBePooled(true);
6465 // if we have already assigned a phy register, we must come from
6466 // advancedPhiLowering()=>lowerAssign(). In this case we should reuse the
6467 // assigned register as this assignment is that start of its use-def
6468 // chain. So we add RegNum argument here.
6469 Variable *Reg = makeReg(Immediate->getType(), RegNum);
6470 IceString Label;
6471 llvm::raw_string_ostream Label_stream(Label);
6472 Immediate->emitPoolLabel(Label_stream, Ctx);
6473 constexpr RelocOffsetT Offset = 0;
6474 constexpr bool SuppressMangling = true;
6475 Constant *Symbol =
6476 Ctx->getConstantSym(Offset, Label_stream.str(), SuppressMangling);
6477 const bool UseNonsfi = Ctx->getFlags().getUseNonsfi();
6478 Variable *Base = UseNonsfi ? legalizeToReg(GotVar) : nullptr;
6479 const bool IsRebased = Base != nullptr;
6480 X86OperandMem *MemOperand = X86OperandMem::create(
6481 Func, Immediate->getType(), Base, Symbol, IsRebased);
6482 _mov(Reg, MemOperand);
6483 return Reg;
6484 }
6485 }
6447 } 6486 }
6448 6487
6449 template <typename TraitsType> 6488 template <typename TraitsType>
6450 typename TargetX86Base<TraitsType>::X86OperandMem * 6489 typename TargetX86Base<TraitsType>::X86OperandMem *
6451 TargetX86Base<TraitsType>::randomizeOrPoolImmediate(X86OperandMem *MemOperand, 6490 TargetX86Base<TraitsType>::randomizeOrPoolImmediate(X86OperandMem *MemOperand,
6452 int32_t RegNum) { 6491 int32_t RegNum) {
6453 assert(MemOperand); 6492 assert(MemOperand);
6454 if (Ctx->getFlags().getRandomizeAndPoolImmediatesOption() == RPI_None || 6493 if (Ctx->getFlags().getRandomizeAndPoolImmediatesOption() == RPI_None ||
6455 RandomizationPoolingPaused == true) { 6494 RandomizationPoolingPaused == true) {
6456 // immediates randomization/pooling is turned off 6495 // immediates randomization/pooling is turned off
6457 return MemOperand; 6496 return MemOperand;
6458 } 6497 }
6459 6498
6499 if (Traits::Is64Bit && NeedSandboxing) {
6500 // Immediate randomization/pooling is currently disabled for x86-64
6501 // sandboxing for it could generate invalid memory operands.
6502 assert(false &&
6503 "Constant pooling/randomization is disabled for x8664 sandbox.");
6504 return MemOperand;
6505 }
6506
6460 // If this memory operand is already a randomized one, we do not randomize it 6507 // If this memory operand is already a randomized one, we do not randomize it
6461 // again. 6508 // again.
6462 if (MemOperand->getRandomized()) 6509 if (MemOperand->getRandomized())
6463 return MemOperand; 6510 return MemOperand;
6464 6511
6465 if (auto *C = llvm::dyn_cast_or_null<Constant>(MemOperand->getOffset())) { 6512 auto *C = llvm::dyn_cast_or_null<Constant>(MemOperand->getOffset());
6466 if (C->shouldBeRandomizedOrPooled(Ctx)) {
6467 // The offset of this mem operand should be blinded or pooled
6468 Ctx->statsUpdateRPImms();
6469 if (Ctx->getFlags().getRandomizeAndPoolImmediatesOption() ==
6470 RPI_Randomize) {
6471 // blind the constant offset
6472 // FROM:
6473 // offset[base, index, shift]
6474 // TO:
6475 // insert: lea offset+cookie[base], RegTemp
6476 // => -cookie[RegTemp, index, shift]
6477 uint32_t Value =
6478 llvm::dyn_cast<ConstantInteger32>(MemOperand->getOffset())
6479 ->getValue();
6480 uint32_t Cookie = Func->getConstantBlindingCookie();
6481 Constant *Mask1 = Ctx->getConstantInt(
6482 MemOperand->getOffset()->getType(), Cookie + Value);
6483 Constant *Mask2 =
6484 Ctx->getConstantInt(MemOperand->getOffset()->getType(), 0 - Cookie);
6485 6513
6486 X86OperandMem *TempMemOperand = X86OperandMem::create( 6514 if (C == nullptr) {
6487 Func, MemOperand->getType(), MemOperand->getBase(), Mask1); 6515 return MemOperand;
6488 // If we have already assigned a physical register, we must come from 6516 }
6489 // advancedPhiLowering()=>lowerAssign(). In this case we should reuse
6490 // the assigned register as this assignment is that start of its
6491 // use-def chain. So we add RegNum argument here.
6492 Variable *RegTemp = makeReg(MemOperand->getOffset()->getType(), RegNum);
6493 _lea(RegTemp, TempMemOperand);
6494 6517
6495 X86OperandMem *NewMemOperand = X86OperandMem::create( 6518 if (!C->shouldBeRandomizedOrPooled(Ctx)) {
6496 Func, MemOperand->getType(), RegTemp, Mask2, MemOperand->getIndex(), 6519 return MemOperand;
6497 MemOperand->getShift(), MemOperand->getSegmentRegister()); 6520 }
6498 6521
6499 // Label this memory operand as randomized, so we won't randomize it 6522 // The offset of this mem operand should be blinded or pooled
6500 // again in case we call legalize() multiple times on this memory 6523 Ctx->statsUpdateRPImms();
6501 // operand. 6524 switch (Ctx->getFlags().getRandomizeAndPoolImmediatesOption()) {
6502 NewMemOperand->setRandomized(true); 6525 default:
6503 return NewMemOperand; 6526 llvm::report_fatal_error("Unsupported -randomize-pool-immediates option");
6504 } 6527 case RPI_Randomize: {
6505 if (Ctx->getFlags().getRandomizeAndPoolImmediatesOption() == RPI_Pool) { 6528 // blind the constant offset
6506 // pool the constant offset 6529 // FROM:
6507 // FROM: 6530 // offset[base, index, shift]
6508 // offset[base, index, shift] 6531 // TO:
6509 // TO: 6532 // insert: lea offset+cookie[base], RegTemp
6510 // insert: mov $label, RegTemp 6533 // => -cookie[RegTemp, index, shift]
6511 // insert: lea [base, RegTemp], RegTemp 6534 uint32_t Value =
6512 // =>[RegTemp, index, shift] 6535 llvm::dyn_cast<ConstantInteger32>(MemOperand->getOffset())->getValue();
6513 assert(Ctx->getFlags().getRandomizeAndPoolImmediatesOption() == 6536 uint32_t Cookie = Func->getConstantBlindingCookie();
6514 RPI_Pool); 6537 Constant *Mask1 =
6515 // Memory operand should never exist as source operands in phi lowering 6538 Ctx->getConstantInt(MemOperand->getOffset()->getType(), Cookie + Value);
6516 // assignments, so there is no need to reuse any registers here. For 6539 Constant *Mask2 =
6517 // phi lowering, we should not ask for new physical registers in 6540 Ctx->getConstantInt(MemOperand->getOffset()->getType(), 0 - Cookie);
6518 // general. However, if we do meet Memory Operand during phi lowering, 6541
6519 // we should not blind or pool the immediates for now. 6542 X86OperandMem *TempMemOperand = X86OperandMem::create(
6520 if (RegNum != Variable::NoRegister) 6543 Func, MemOperand->getType(), MemOperand->getBase(), Mask1);
6521 return MemOperand; 6544 // If we have already assigned a physical register, we must come from
6522 Variable *RegTemp = makeReg(IceType_i32); 6545 // advancedPhiLowering()=>lowerAssign(). In this case we should reuse
6523 IceString Label; 6546 // the assigned register as this assignment is that start of its
6524 llvm::raw_string_ostream Label_stream(Label); 6547 // use-def chain. So we add RegNum argument here.
6525 MemOperand->getOffset()->emitPoolLabel(Label_stream, Ctx); 6548 Variable *RegTemp = makeReg(MemOperand->getOffset()->getType(), RegNum);
6526 MemOperand->getOffset()->setShouldBePooled(true); 6549 _lea(RegTemp, TempMemOperand);
6527 constexpr RelocOffsetT SymOffset = 0; 6550
6528 constexpr bool SuppressMangling = true; 6551 X86OperandMem *NewMemOperand = X86OperandMem::create(
6529 Constant *Symbol = Ctx->getConstantSym(SymOffset, Label_stream.str(), 6552 Func, MemOperand->getType(), RegTemp, Mask2, MemOperand->getIndex(),
6530 SuppressMangling); 6553 MemOperand->getShift(), MemOperand->getSegmentRegister(),
6531 const bool UseNonsfi = Ctx->getFlags().getUseNonsfi(); 6554 MemOperand->getIsRebased());
6532 Variable *Base = UseNonsfi ? legalizeToReg(GotVar) : nullptr; 6555
6533 X86OperandMem *SymbolOperand = X86OperandMem::create( 6556 // Label this memory operand as randomized, so we won't randomize it
6534 Func, MemOperand->getOffset()->getType(), Base, Symbol); 6557 // again in case we call legalize() multiple times on this memory
6535 if (UseNonsfi) 6558 // operand.
6536 SymbolOperand->setIsPIC(); 6559 NewMemOperand->setRandomized(true);
6537 _mov(RegTemp, SymbolOperand); 6560 return NewMemOperand;
6538 // If we have a base variable here, we should add the lea instruction 6561 }
6539 // to add the value of the base variable to RegTemp. If there is no 6562 case RPI_Pool: {
6540 // base variable, we won't need this lea instruction. 6563 // pool the constant offset
6541 if (MemOperand->getBase()) { 6564 // FROM:
6542 X86OperandMem *CalculateOperand = X86OperandMem::create( 6565 // offset[base, index, shift]
6543 Func, MemOperand->getType(), MemOperand->getBase(), nullptr, 6566 // TO:
6544 RegTemp, 0, MemOperand->getSegmentRegister()); 6567 // insert: mov $label, RegTemp
6545 _lea(RegTemp, CalculateOperand); 6568 // insert: lea [base, RegTemp], RegTemp
6546 } 6569 // =>[RegTemp, index, shift]
6547 X86OperandMem *NewMemOperand = X86OperandMem::create( 6570
6548 Func, MemOperand->getType(), RegTemp, nullptr, 6571 // Memory operand should never exist as source operands in phi lowering
6549 MemOperand->getIndex(), MemOperand->getShift(), 6572 // assignments, so there is no need to reuse any registers here. For
6550 MemOperand->getSegmentRegister()); 6573 // phi lowering, we should not ask for new physical registers in
6551 return NewMemOperand; 6574 // general. However, if we do meet Memory Operand during phi lowering,
6552 } 6575 // we should not blind or pool the immediates for now.
6553 assert("Unsupported -randomize-pool-immediates option" && false); 6576 if (RegNum != Variable::NoRegister)
6577 return MemOperand;
6578 Variable *RegTemp = makeReg(IceType_i32);
6579 IceString Label;
6580 llvm::raw_string_ostream Label_stream(Label);
6581 MemOperand->getOffset()->emitPoolLabel(Label_stream, Ctx);
6582 MemOperand->getOffset()->setShouldBePooled(true);
6583 constexpr RelocOffsetT SymOffset = 0;
6584 constexpr bool SuppressMangling = true;
6585 Constant *Symbol =
6586 Ctx->getConstantSym(SymOffset, Label_stream.str(), SuppressMangling);
6587 const bool UseNonsfi = Ctx->getFlags().getUseNonsfi();
6588 Variable *Base = UseNonsfi ? legalizeToReg(GotVar) : nullptr;
6589 const bool IsRebased = Base != nullptr;
6590 X86OperandMem *SymbolOperand = X86OperandMem::create(
6591 Func, MemOperand->getOffset()->getType(), Base, Symbol, IsRebased);
6592 _mov(RegTemp, SymbolOperand);
6593 // If we have a base variable here, we should add the lea instruction
6594 // to add the value of the base variable to RegTemp. If there is no
6595 // base variable, we won't need this lea instruction.
6596 if (MemOperand->getBase()) {
6597 X86OperandMem *CalculateOperand = X86OperandMem::create(
6598 Func, MemOperand->getType(), MemOperand->getBase(), nullptr, RegTemp,
6599 0, MemOperand->getSegmentRegister());
6600 _lea(RegTemp, CalculateOperand);
6554 } 6601 }
6602 X86OperandMem *NewMemOperand = X86OperandMem::create(
6603 Func, MemOperand->getType(), RegTemp, nullptr, MemOperand->getIndex(),
6604 MemOperand->getShift(), MemOperand->getSegmentRegister());
6605 return NewMemOperand;
6555 } 6606 }
6556 // the offset is not eligible for blinding or pooling, return the original 6607 }
6557 // mem operand
6558 return MemOperand;
6559 } 6608 }
6560
6561 } // end of namespace X86NAMESPACE 6609 } // end of namespace X86NAMESPACE
6562 } // end of namespace Ice 6610 } // end of namespace Ice
6563 6611
6564 #endif // SUBZERO_SRC_ICETARGETLOWERINGX86BASEIMPL_H 6612 #endif // SUBZERO_SRC_ICETARGETLOWERINGX86BASEIMPL_H
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698