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

Side by Side Diff: src/IceTargetLoweringX86BaseImpl.h

Issue 1506653002: Subzero: Add Non-SFI support for x86-32. (Closed) Base URL: https://chromium.googlesource.com/native_client/pnacl-subzero.git@master
Patch Set: Fill in part of the lit test Created 5 years 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 306 matching lines...) Expand 10 before | Expand all | Expand 10 after
317 "Traits::InstructionSet range different from TargetInstructionSet"); 317 "Traits::InstructionSet range different from TargetInstructionSet");
318 if (Func->getContext()->getFlags().getTargetInstructionSet() != 318 if (Func->getContext()->getFlags().getTargetInstructionSet() !=
319 TargetInstructionSet::BaseInstructionSet) { 319 TargetInstructionSet::BaseInstructionSet) {
320 InstructionSet = static_cast<typename Traits::InstructionSet>( 320 InstructionSet = static_cast<typename Traits::InstructionSet>(
321 (Func->getContext()->getFlags().getTargetInstructionSet() - 321 (Func->getContext()->getFlags().getTargetInstructionSet() -
322 TargetInstructionSet::X86InstructionSet_Begin) + 322 TargetInstructionSet::X86InstructionSet_Begin) +
323 Traits::InstructionSet::Begin); 323 Traits::InstructionSet::Begin);
324 } 324 }
325 } 325 }
326 326
327 template <class Machine> void TargetX86Base<Machine>::staticInit() { 327 template <class Machine>
328 void TargetX86Base<Machine>::staticInit(const ClFlags &Flags) {
328 Traits::initRegisterSet(&TypeToRegisterSet, &RegisterAliases, &ScratchRegs); 329 Traits::initRegisterSet(&TypeToRegisterSet, &RegisterAliases, &ScratchRegs);
330 PcRelFixup = Traits::FixupKindPcRel;
331 RelFixup =
332 Flags.getUseNonsfi() ? Traits::FixupKindGotoff : Traits::FixupKindAbs;
329 } 333 }
330 334
331 template <class Machine> void TargetX86Base<Machine>::translateO2() { 335 template <class Machine> void TargetX86Base<Machine>::translateO2() {
332 TimerMarker T(TimerStack::TT_O2, Func); 336 TimerMarker T(TimerStack::TT_O2, Func);
333 337
338 if (!Traits::Is64Bit && Func->getContext()->getFlags().getUseNonsfi()) {
339 GotVar = Func->makeVariable(IceType_i32);
340 }
334 genTargetHelperCalls(); 341 genTargetHelperCalls();
335 Func->dump("After target helper call insertion"); 342 Func->dump("After target helper call insertion");
336 343
337 // Merge Alloca instructions, and lay out the stack. 344 // Merge Alloca instructions, and lay out the stack.
338 static constexpr bool SortAndCombineAllocas = true; 345 static constexpr bool SortAndCombineAllocas = true;
339 Func->processAllocas(SortAndCombineAllocas); 346 Func->processAllocas(SortAndCombineAllocas);
340 Func->dump("After Alloca processing"); 347 Func->dump("After Alloca processing");
341 348
342 if (!Ctx->getFlags().getPhiEdgeSplit()) { 349 if (!Ctx->getFlags().getPhiEdgeSplit()) {
343 // Lower Phi instructions. 350 // Lower Phi instructions.
(...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after
392 Func->dump("After x86 address mode opt"); 399 Func->dump("After x86 address mode opt");
393 400
394 // Disable constant blinding or pooling for load optimization. 401 // Disable constant blinding or pooling for load optimization.
395 { 402 {
396 BoolFlagSaver B(RandomizationPoolingPaused, true); 403 BoolFlagSaver B(RandomizationPoolingPaused, true);
397 doLoadOpt(); 404 doLoadOpt();
398 } 405 }
399 Func->genCode(); 406 Func->genCode();
400 if (Func->hasError()) 407 if (Func->hasError())
401 return; 408 return;
409 initGotVar();
402 Func->dump("After x86 codegen"); 410 Func->dump("After x86 codegen");
403 411
404 // Register allocation. This requires instruction renumbering and full 412 // Register allocation. This requires instruction renumbering and full
405 // liveness analysis. Loops must be identified before liveness so variable 413 // liveness analysis. Loops must be identified before liveness so variable
406 // use weights are correct. 414 // use weights are correct.
407 Func->renumberInstructions(); 415 Func->renumberInstructions();
408 if (Func->hasError()) 416 if (Func->hasError())
409 return; 417 return;
410 Func->liveness(Liveness_Intervals); 418 Func->liveness(Liveness_Intervals);
411 if (Func->hasError()) 419 if (Func->hasError())
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after
450 Func->doNopInsertion(); 458 Func->doNopInsertion();
451 459
452 // Mark nodes that require sandbox alignment 460 // Mark nodes that require sandbox alignment
453 if (Ctx->getFlags().getUseSandboxing()) 461 if (Ctx->getFlags().getUseSandboxing())
454 Func->markNodesForSandboxing(); 462 Func->markNodesForSandboxing();
455 } 463 }
456 464
457 template <class Machine> void TargetX86Base<Machine>::translateOm1() { 465 template <class Machine> void TargetX86Base<Machine>::translateOm1() {
458 TimerMarker T(TimerStack::TT_Om1, Func); 466 TimerMarker T(TimerStack::TT_Om1, Func);
459 467
468 if (!Traits::Is64Bit && Func->getContext()->getFlags().getUseNonsfi()) {
469 GotVar = Func->makeVariable(IceType_i32);
470 }
460 genTargetHelperCalls(); 471 genTargetHelperCalls();
461 472
462 // Do not merge Alloca instructions, and lay out the stack. 473 // Do not merge Alloca instructions, and lay out the stack.
463 static constexpr bool SortAndCombineAllocas = false; 474 static constexpr bool SortAndCombineAllocas = false;
464 Func->processAllocas(SortAndCombineAllocas); 475 Func->processAllocas(SortAndCombineAllocas);
465 Func->dump("After Alloca processing"); 476 Func->dump("After Alloca processing");
466 477
467 Func->placePhiLoads(); 478 Func->placePhiLoads();
468 if (Func->hasError()) 479 if (Func->hasError())
469 return; 480 return;
470 Func->placePhiStores(); 481 Func->placePhiStores();
471 if (Func->hasError()) 482 if (Func->hasError())
472 return; 483 return;
473 Func->deletePhis(); 484 Func->deletePhis();
474 if (Func->hasError()) 485 if (Func->hasError())
475 return; 486 return;
476 Func->dump("After Phi lowering"); 487 Func->dump("After Phi lowering");
477 488
478 Func->doArgLowering(); 489 Func->doArgLowering();
479 Func->genCode(); 490 Func->genCode();
480 if (Func->hasError()) 491 if (Func->hasError())
481 return; 492 return;
493 initGotVar();
John 2015/12/22 15:44:38 My first thought here was "a if (SFI) is missing."
Jim Stichnoth 2015/12/28 07:54:07 Done - renamed to initGotVarIfNeeded().
482 Func->dump("After initial x8632 codegen"); 494 Func->dump("After initial x8632 codegen");
483 495
484 regAlloc(RAK_InfOnly); 496 regAlloc(RAK_InfOnly);
485 if (Func->hasError()) 497 if (Func->hasError())
486 return; 498 return;
487 Func->dump("After regalloc of infinite-weight variables"); 499 Func->dump("After regalloc of infinite-weight variables");
488 500
489 Func->genFrame(); 501 Func->genFrame();
490 if (Func->hasError()) 502 if (Func->hasError())
491 return; 503 return;
(...skipping 305 matching lines...) Expand 10 before | Expand all | Expand 10 after
797 template <class Machine> 809 template <class Machine>
798 void TargetX86Base<Machine>::emitVariable(const Variable *Var) const { 810 void TargetX86Base<Machine>::emitVariable(const Variable *Var) const {
799 if (!BuildDefs::dump()) 811 if (!BuildDefs::dump())
800 return; 812 return;
801 Ostream &Str = Ctx->getStrEmit(); 813 Ostream &Str = Ctx->getStrEmit();
802 if (Var->hasReg()) { 814 if (Var->hasReg()) {
803 Str << "%" << getRegName(Var->getRegNum(), Var->getType()); 815 Str << "%" << getRegName(Var->getRegNum(), Var->getType());
804 return; 816 return;
805 } 817 }
806 if (Var->mustHaveReg()) { 818 if (Var->mustHaveReg()) {
807 llvm_unreachable("Infinite-weight Variable has no register assigned"); 819 llvm::report_fatal_error(
820 "Infinite-weight Variable has no register assigned");
808 } 821 }
809 const int32_t Offset = Var->getStackOffset(); 822 const int32_t Offset = Var->getStackOffset();
810 int32_t BaseRegNum = Var->getBaseRegNum(); 823 int32_t BaseRegNum = Var->getBaseRegNum();
811 if (BaseRegNum == Variable::NoRegister) 824 if (BaseRegNum == Variable::NoRegister)
812 BaseRegNum = getFrameOrStackReg(); 825 BaseRegNum = getFrameOrStackReg();
813 // Print in the form "Offset(%reg)", taking care that: 826 // Print in the form "Offset(%reg)", taking care that:
814 // - Offset is never printed when it is 0 827 // - Offset is never printed when it is 0
815 828
816 const bool DecorateAsm = Func->getContext()->getFlags().getDecorateAsm(); 829 const bool DecorateAsm = Func->getContext()->getFlags().getDecorateAsm();
817 // Only print Offset when it is nonzero, regardless of DecorateAsm. 830 // Only print Offset when it is nonzero, regardless of DecorateAsm.
818 if (Offset) { 831 if (Offset) {
819 if (DecorateAsm) { 832 if (DecorateAsm) {
820 Str << Var->getSymbolicStackOffset(Func); 833 Str << Var->getSymbolicStackOffset(Func);
821 } else { 834 } else {
822 Str << Offset; 835 Str << Offset;
823 } 836 }
824 } 837 }
825 const Type FrameSPTy = Traits::WordType; 838 const Type FrameSPTy = Traits::WordType;
826 Str << "(%" << getRegName(BaseRegNum, FrameSPTy) << ")"; 839 Str << "(%" << getRegName(BaseRegNum, FrameSPTy) << ")";
827 } 840 }
828 841
829 template <class Machine> 842 template <class Machine>
830 typename TargetX86Base<Machine>::Traits::Address 843 typename TargetX86Base<Machine>::Traits::Address
831 TargetX86Base<Machine>::stackVarToAsmOperand(const Variable *Var) const { 844 TargetX86Base<Machine>::stackVarToAsmOperand(const Variable *Var) const {
832 if (Var->hasReg()) 845 if (Var->hasReg())
833 llvm_unreachable("Stack Variable has a register assigned"); 846 llvm::report_fatal_error("Stack Variable has a register assigned");
834 if (Var->mustHaveReg()) { 847 if (Var->mustHaveReg()) {
835 llvm_unreachable("Infinite-weight Variable has no register assigned"); 848 llvm::report_fatal_error(
849 "Infinite-weight Variable has no register assigned");
836 } 850 }
837 int32_t Offset = Var->getStackOffset(); 851 int32_t Offset = Var->getStackOffset();
838 int32_t BaseRegNum = Var->getBaseRegNum(); 852 int32_t BaseRegNum = Var->getBaseRegNum();
839 if (Var->getBaseRegNum() == Variable::NoRegister) 853 if (Var->getBaseRegNum() == Variable::NoRegister)
840 BaseRegNum = getFrameOrStackReg(); 854 BaseRegNum = getFrameOrStackReg();
841 return typename Traits::Address(Traits::getEncodedGPR(BaseRegNum), Offset, 855 return typename Traits::Address(Traits::getEncodedGPR(BaseRegNum), Offset,
842 AssemblerFixup::NoFixup); 856 AssemblerFixup::NoFixup);
843 } 857 }
844 858
845 /// Helper function for addProlog(). 859 /// Helper function for addProlog().
(...skipping 60 matching lines...) Expand 10 before | Expand all | Expand 10 after
906 return Var64On32->getLo(); 920 return Var64On32->getLo();
907 if (auto *Const = llvm::dyn_cast<ConstantInteger64>(Operand)) { 921 if (auto *Const = llvm::dyn_cast<ConstantInteger64>(Operand)) {
908 auto *ConstInt = llvm::dyn_cast<ConstantInteger32>( 922 auto *ConstInt = llvm::dyn_cast<ConstantInteger32>(
909 Ctx->getConstantInt32(static_cast<int32_t>(Const->getValue()))); 923 Ctx->getConstantInt32(static_cast<int32_t>(Const->getValue())));
910 // Check if we need to blind/pool the constant. 924 // Check if we need to blind/pool the constant.
911 return legalize(ConstInt); 925 return legalize(ConstInt);
912 } 926 }
913 if (auto *Mem = llvm::dyn_cast<typename Traits::X86OperandMem>(Operand)) { 927 if (auto *Mem = llvm::dyn_cast<typename Traits::X86OperandMem>(Operand)) {
914 auto *MemOperand = Traits::X86OperandMem::create( 928 auto *MemOperand = Traits::X86OperandMem::create(
915 Func, IceType_i32, Mem->getBase(), Mem->getOffset(), Mem->getIndex(), 929 Func, IceType_i32, Mem->getBase(), Mem->getOffset(), Mem->getIndex(),
916 Mem->getShift(), Mem->getSegmentRegister()); 930 Mem->getShift(), Mem->getSegmentRegister(), Mem->getIsPIC());
917 // Test if we should randomize or pool the offset, if so randomize it or 931 // Test if we should randomize or pool the offset, if so randomize it or
918 // pool it then create mem operand with the blinded/pooled constant. 932 // pool it then create mem operand with the blinded/pooled constant.
919 // Otherwise, return the mem operand as ordinary mem operand. 933 // Otherwise, return the mem operand as ordinary mem operand.
920 return legalize(MemOperand); 934 return legalize(MemOperand);
921 } 935 }
922 llvm_unreachable("Unsupported operand type"); 936 llvm_unreachable("Unsupported operand type");
923 return nullptr; 937 return nullptr;
924 } 938 }
925 939
926 template <class Machine> 940 template <class Machine>
(...skipping 19 matching lines...) Expand all
946 } else if (auto *IntOffset = llvm::dyn_cast<ConstantInteger32>(Offset)) { 960 } else if (auto *IntOffset = llvm::dyn_cast<ConstantInteger32>(Offset)) {
947 Offset = Ctx->getConstantInt32(4 + IntOffset->getValue()); 961 Offset = Ctx->getConstantInt32(4 + IntOffset->getValue());
948 } else if (auto *SymOffset = llvm::dyn_cast<ConstantRelocatable>(Offset)) { 962 } else if (auto *SymOffset = llvm::dyn_cast<ConstantRelocatable>(Offset)) {
949 assert(!Utils::WouldOverflowAdd(SymOffset->getOffset(), 4)); 963 assert(!Utils::WouldOverflowAdd(SymOffset->getOffset(), 4));
950 Offset = 964 Offset =
951 Ctx->getConstantSym(4 + SymOffset->getOffset(), SymOffset->getName(), 965 Ctx->getConstantSym(4 + SymOffset->getOffset(), SymOffset->getName(),
952 SymOffset->getSuppressMangling()); 966 SymOffset->getSuppressMangling());
953 } 967 }
954 auto *MemOperand = Traits::X86OperandMem::create( 968 auto *MemOperand = Traits::X86OperandMem::create(
955 Func, IceType_i32, Mem->getBase(), Offset, Mem->getIndex(), 969 Func, IceType_i32, Mem->getBase(), Offset, Mem->getIndex(),
956 Mem->getShift(), Mem->getSegmentRegister()); 970 Mem->getShift(), Mem->getSegmentRegister(), Mem->getIsPIC());
957 // Test if the Offset is an eligible i32 constants for randomization and 971 // Test if the Offset is an eligible i32 constants for randomization and
958 // pooling. Blind/pool it if it is. Otherwise return as oridinary mem 972 // pooling. Blind/pool it if it is. Otherwise return as oridinary mem
959 // operand. 973 // operand.
960 return legalize(MemOperand); 974 return legalize(MemOperand);
961 } 975 }
962 llvm_unreachable("Unsupported operand type"); 976 llvm_unreachable("Unsupported operand type");
963 return nullptr; 977 return nullptr;
964 } 978 }
965 979
966 template <class Machine> 980 template <class Machine>
967 llvm::SmallBitVector 981 llvm::SmallBitVector
968 TargetX86Base<Machine>::getRegisterSet(RegSetMask Include, 982 TargetX86Base<Machine>::getRegisterSet(RegSetMask Include,
969 RegSetMask Exclude) const { 983 RegSetMask Exclude) const {
970 return Traits::getRegisterSet(Include, Exclude); 984 return Traits::getRegisterSet(Include, Exclude);
971 } 985 }
972 986
987 template <class Machine> void TargetX86Base<Machine>::initGotVar() {
988 if (Traits::Is64Bit) {
989 // Probably no implementation is needed, but error to be safe for now.
990 llvm::report_fatal_error("Need to implement initGotVar() for 64-bit.");
991 }
992 if (!Func->getContext()->getFlags().getUseNonsfi())
993 return;
994 // Insert the GotVar assignment as the very first lowered instruction. Later,
995 // it will be moved into the right place - after the stack frame is set up but
996 // before in-args are copied into registers.
997 Context.init(Func->getEntryNode());
998 Context.setInsertPoint(Context.getCur());
999 Context.insert(InstX86GetIP<Machine>::create(Func, GotVar));
1000 }
1001
973 template <class Machine> 1002 template <class Machine>
974 void TargetX86Base<Machine>::lowerAlloca(const InstAlloca *Inst) { 1003 void TargetX86Base<Machine>::lowerAlloca(const InstAlloca *Inst) {
975 // Conservatively require the stack to be aligned. Some stack adjustment 1004 // Conservatively require the stack to be aligned. Some stack adjustment
976 // operations implemented below assume that the stack is aligned before the 1005 // operations implemented below assume that the stack is aligned before the
977 // alloca. All the alloca code ensures that the stack alignment is preserved 1006 // alloca. All the alloca code ensures that the stack alignment is preserved
978 // after the alloca. The stack alignment restriction can be relaxed in some 1007 // after the alloca. The stack alignment restriction can be relaxed in some
979 // cases. 1008 // cases.
980 NeedsStackAlignment = true; 1009 NeedsStackAlignment = true;
981 1010
982 // For default align=0, set it to the real value 1, to avoid any 1011 // For default align=0, set it to the real value 1, to avoid any
(...skipping 2985 matching lines...) Expand 10 before | Expand all | Expand 10 after
3968 } 3997 }
3969 _test(SecondVar, SecondVar); 3998 _test(SecondVar, SecondVar);
3970 _cmov(T_Dest2, T_Dest, Traits::Cond::Br_e); 3999 _cmov(T_Dest2, T_Dest, Traits::Cond::Br_e);
3971 _mov(DestLo, T_Dest2); 4000 _mov(DestLo, T_Dest2);
3972 _mov(DestHi, Ctx->getConstantZero(IceType_i32)); 4001 _mov(DestHi, Ctx->getConstantZero(IceType_i32));
3973 } 4002 }
3974 4003
3975 template <class Machine> 4004 template <class Machine>
3976 void TargetX86Base<Machine>::typedLoad(Type Ty, Variable *Dest, Variable *Base, 4005 void TargetX86Base<Machine>::typedLoad(Type Ty, Variable *Dest, Variable *Base,
3977 Constant *Offset) { 4006 Constant *Offset) {
4007 // If Offset is a ConstantRelocatable in Non-SFI mode, we will need to
4008 // legalize Mem properly.
4009 if (Offset)
4010 assert(!llvm::isa<ConstantRelocatable>(Offset));
4011
3978 auto *Mem = Traits::X86OperandMem::create(Func, Ty, Base, Offset); 4012 auto *Mem = Traits::X86OperandMem::create(Func, Ty, Base, Offset);
3979 4013
3980 if (isVectorType(Ty)) 4014 if (isVectorType(Ty))
3981 _movp(Dest, Mem); 4015 _movp(Dest, Mem);
3982 else if (Ty == IceType_f64) 4016 else if (Ty == IceType_f64)
3983 _movq(Dest, Mem); 4017 _movq(Dest, Mem);
3984 else 4018 else
3985 _mov(Dest, Mem); 4019 _mov(Dest, Mem);
3986 } 4020 }
3987 4021
3988 template <class Machine> 4022 template <class Machine>
3989 void TargetX86Base<Machine>::typedStore(Type Ty, Variable *Value, 4023 void TargetX86Base<Machine>::typedStore(Type Ty, Variable *Value,
3990 Variable *Base, Constant *Offset) { 4024 Variable *Base, Constant *Offset) {
4025 // If Offset is a ConstantRelocatable in Non-SFI mode, we will need to
4026 // legalize Mem properly.
4027 if (Offset)
4028 assert(!llvm::isa<ConstantRelocatable>(Offset));
4029
3991 auto *Mem = Traits::X86OperandMem::create(Func, Ty, Base, Offset); 4030 auto *Mem = Traits::X86OperandMem::create(Func, Ty, Base, Offset);
3992 4031
3993 if (isVectorType(Ty)) 4032 if (isVectorType(Ty))
3994 _storep(Value, Mem); 4033 _storep(Value, Mem);
3995 else if (Ty == IceType_f64) 4034 else if (Ty == IceType_f64)
3996 _storeq(Value, Mem); 4035 _storeq(Value, Mem);
3997 else 4036 else
3998 _store(Value, Mem); 4037 _store(Value, Mem);
3999 } 4038 }
4000 4039
(...skipping 283 matching lines...) Expand 10 before | Expand all | Expand 10 after
4284 Str << "<null>"; 4323 Str << "<null>";
4285 Str << ", Index="; 4324 Str << ", Index=";
4286 if (Index) 4325 if (Index)
4287 Index->dump(Func); 4326 Index->dump(Func);
4288 else 4327 else
4289 Str << "<null>"; 4328 Str << "<null>";
4290 Str << ", Shift=" << Shift << ", Offset=" << Offset 4329 Str << ", Shift=" << Shift << ", Offset=" << Offset
4291 << ", Relocatable=" << Relocatable << "\n"; 4330 << ", Relocatable=" << Relocatable << "\n";
4292 } 4331 }
4293 4332
4294 inline bool matchAssign(const VariablesMetadata *VMetadata, Variable *&Var, 4333 inline bool matchAssign(const VariablesMetadata *VMetadata, Variable *GotVar,
4295 ConstantRelocatable *&Relocatable, int32_t &Offset, 4334 Variable *&Var, ConstantRelocatable *&Relocatable,
4296 const Inst *&Reason) { 4335 int32_t &Offset, const Inst *&Reason) {
4297 // Var originates from Var=SrcVar ==> set Var:=SrcVar 4336 // Var originates from Var=SrcVar ==> set Var:=SrcVar
4298 if (Var == nullptr) 4337 if (Var == nullptr)
4299 return false; 4338 return false;
4300 if (const Inst *VarAssign = VMetadata->getSingleDefinition(Var)) { 4339 if (const Inst *VarAssign = VMetadata->getSingleDefinition(Var)) {
4301 assert(!VMetadata->isMultiDef(Var)); 4340 assert(!VMetadata->isMultiDef(Var));
4302 if (llvm::isa<InstAssign>(VarAssign)) { 4341 if (llvm::isa<InstAssign>(VarAssign)) {
4303 Operand *SrcOp = VarAssign->getSrc(0); 4342 Operand *SrcOp = VarAssign->getSrc(0);
4304 assert(SrcOp); 4343 assert(SrcOp);
4305 if (auto *SrcVar = llvm::dyn_cast<Variable>(SrcOp)) { 4344 if (auto *SrcVar = llvm::dyn_cast<Variable>(SrcOp)) {
4306 if (!VMetadata->isMultiDef(SrcVar) && 4345 if (!VMetadata->isMultiDef(SrcVar) &&
4307 // TODO: ensure SrcVar stays single-BB 4346 // TODO: ensure SrcVar stays single-BB
4308 true) { 4347 true) {
4309 Var = SrcVar; 4348 Var = SrcVar;
4310 Reason = VarAssign; 4349 Reason = VarAssign;
4311 return true; 4350 return true;
4312 } 4351 }
4313 } else if (auto *Const = llvm::dyn_cast<ConstantInteger32>(SrcOp)) { 4352 } else if (auto *Const = llvm::dyn_cast<ConstantInteger32>(SrcOp)) {
4314 int32_t MoreOffset = Const->getValue(); 4353 int32_t MoreOffset = Const->getValue();
4315 if (Utils::WouldOverflowAdd(Offset, MoreOffset)) 4354 if (Utils::WouldOverflowAdd(Offset, MoreOffset))
4316 return false; 4355 return false;
4317 Var = nullptr; 4356 Var = nullptr;
4318 Offset += MoreOffset; 4357 Offset += MoreOffset;
4319 Reason = VarAssign; 4358 Reason = VarAssign;
4320 return true; 4359 return true;
4321 } else if (auto *AddReloc = llvm::dyn_cast<ConstantRelocatable>(SrcOp)) { 4360 } else if (auto *AddReloc = llvm::dyn_cast<ConstantRelocatable>(SrcOp)) {
4322 if (Relocatable == nullptr) { 4361 if (Relocatable == nullptr) {
4323 Var = nullptr; 4362 Var = GotVar;
4324 Relocatable = AddReloc; 4363 Relocatable = AddReloc;
4325 Reason = VarAssign; 4364 Reason = VarAssign;
4326 return true; 4365 return true;
4327 } 4366 }
4328 } 4367 }
4329 } 4368 }
4330 } 4369 }
4331 return false; 4370 return false;
4332 } 4371 }
4333 4372
(...skipping 98 matching lines...) Expand 10 before | Expand all | Expand 10 after
4432 return true; 4471 return true;
4433 } 4472 }
4434 } 4473 }
4435 } 4474 }
4436 } 4475 }
4437 } 4476 }
4438 } 4477 }
4439 return false; 4478 return false;
4440 } 4479 }
4441 4480
4442 inline bool matchOffsetBase(const VariablesMetadata *VMetadata, Variable *&Base, 4481 inline bool matchOffsetBase(const VariablesMetadata *VMetadata,
4482 Variable *GotVar, Variable *&Base,
4483 Variable *&BaseOther,
4443 ConstantRelocatable *&Relocatable, int32_t &Offset, 4484 ConstantRelocatable *&Relocatable, int32_t &Offset,
4444 const Inst *&Reason) { 4485 const Inst *&Reason) {
4445 // Base is Base=Var+Const || Base is Base=Const+Var ==> 4486 // Base is Base=Var+Const || Base is Base=Const+Var ==>
4446 // set Base=Var, Offset+=Const 4487 // set Base=Var, Offset+=Const
4447 // Base is Base=Var-Const ==> 4488 // Base is Base=Var-Const ==>
4448 // set Base=Var, Offset-=Const 4489 // set Base=Var, Offset-=Const
4449 if (Base == nullptr) { 4490 if (Base == nullptr) {
4450 return false; 4491 return false;
4451 } 4492 }
4452 const Inst *BaseInst = VMetadata->getSingleDefinition(Base); 4493 const Inst *BaseInst = VMetadata->getSingleDefinition(Base);
(...skipping 30 matching lines...) Expand all
4483 if ((Relocatable && (Reloc0 || Reloc1)) || (Reloc0 && Reloc1)) 4524 if ((Relocatable && (Reloc0 || Reloc1)) || (Reloc0 && Reloc1))
4484 return false; 4525 return false;
4485 // Don't know how to subtract a relocatable. 4526 // Don't know how to subtract a relocatable.
4486 if (!IsAdd && Reloc1) 4527 if (!IsAdd && Reloc1)
4487 return false; 4528 return false;
4488 // Incorporate ConstantRelocatables. 4529 // Incorporate ConstantRelocatables.
4489 if (Reloc0) 4530 if (Reloc0)
4490 NewRelocatable = Reloc0; 4531 NewRelocatable = Reloc0;
4491 else if (Reloc1) 4532 else if (Reloc1)
4492 NewRelocatable = Reloc1; 4533 NewRelocatable = Reloc1;
4534 if (NewRelocatable && BaseOther && GotVar)
4535 return false;
4493 // Compute the updated constant offset. 4536 // Compute the updated constant offset.
4494 if (Const0) { 4537 if (Const0) {
4495 int32_t MoreOffset = IsAdd ? Const0->getValue() : -Const0->getValue(); 4538 int32_t MoreOffset = IsAdd ? Const0->getValue() : -Const0->getValue();
4496 if (Utils::WouldOverflowAdd(NewOffset, MoreOffset)) 4539 if (Utils::WouldOverflowAdd(NewOffset, MoreOffset))
4497 return false; 4540 return false;
4498 NewOffset += MoreOffset; 4541 NewOffset += MoreOffset;
4499 } 4542 }
4500 if (Const1) { 4543 if (Const1) {
4501 int32_t MoreOffset = IsAdd ? Const1->getValue() : -Const1->getValue(); 4544 int32_t MoreOffset = IsAdd ? Const1->getValue() : -Const1->getValue();
4502 if (Utils::WouldOverflowAdd(NewOffset, MoreOffset)) 4545 if (Utils::WouldOverflowAdd(NewOffset, MoreOffset))
4503 return false; 4546 return false;
4504 NewOffset += MoreOffset; 4547 NewOffset += MoreOffset;
4505 } 4548 }
4506 // Update the computed address parameters once we are sure optimization 4549 // Update the computed address parameters once we are sure optimization
4507 // is valid. 4550 // is valid.
4551 if (NewRelocatable && GotVar) {
4552 assert(BaseOther == nullptr);
4553 BaseOther = GotVar;
4554 }
4508 Base = NewBase; 4555 Base = NewBase;
4509 Offset = NewOffset; 4556 Offset = NewOffset;
4510 Relocatable = NewRelocatable; 4557 Relocatable = NewRelocatable;
4511 Reason = BaseInst; 4558 Reason = BaseInst;
4512 return true; 4559 return true;
4513 } 4560 }
4514 return false; 4561 return false;
4515 } 4562 }
4516 4563
4517 // Builds information for a canonical address expresion: 4564 // Builds information for a canonical address expresion:
4518 // <Relocatable + Offset>(Base, Index, Shift) 4565 // <Relocatable + Offset>(Base, Index, Shift)
4519 // On entry: 4566 // On entry:
4520 // Relocatable == null, 4567 // Relocatable == null,
4521 // Offset == 0, 4568 // Offset == 0,
4522 // Base is a Variable, 4569 // Base is a Variable,
4523 // Index == nullptr, 4570 // Index == nullptr,
4524 // Shift == 0 4571 // Shift == 0
4525 inline bool computeAddressOpt(Cfg *Func, const Inst *Instr, 4572 inline bool computeAddressOpt(Cfg *Func, const Inst *Instr, Variable *GotVar,
4526 ConstantRelocatable *&Relocatable, 4573 ConstantRelocatable *&Relocatable,
4527 int32_t &Offset, Variable *&Base, 4574 int32_t &Offset, Variable *&Base,
4528 Variable *&Index, uint16_t &Shift) { 4575 Variable *&Index, uint16_t &Shift) {
4529 bool AddressWasOptimized = false; 4576 bool AddressWasOptimized = false;
4530 Func->resetCurrentNode(); 4577 Func->resetCurrentNode();
4531 if (Func->isVerbose(IceV_AddrOpt)) { 4578 if (Func->isVerbose(IceV_AddrOpt)) {
4532 OstreamLocker L(Func->getContext()); 4579 OstreamLocker L(Func->getContext());
4533 Ostream &Str = Func->getContext()->getStrDump(); 4580 Ostream &Str = Func->getContext()->getStrDump();
4534 Str << "\nStarting computeAddressOpt for instruction:\n "; 4581 Str << "\nStarting computeAddressOpt for instruction:\n ";
4535 Instr->dumpDecorated(Func); 4582 Instr->dumpDecorated(Func);
(...skipping 10 matching lines...) Expand all
4546 const bool MockBounds = Func->getContext()->getFlags().getMockBoundsCheck(); 4593 const bool MockBounds = Func->getContext()->getFlags().getMockBoundsCheck();
4547 const VariablesMetadata *VMetadata = Func->getVMetadata(); 4594 const VariablesMetadata *VMetadata = Func->getVMetadata();
4548 const Inst *Reason = nullptr; 4595 const Inst *Reason = nullptr;
4549 do { 4596 do {
4550 if (Reason) { 4597 if (Reason) {
4551 dumpAddressOpt(Func, Relocatable, Offset, Base, Index, Shift, Reason); 4598 dumpAddressOpt(Func, Relocatable, Offset, Base, Index, Shift, Reason);
4552 AddressWasOptimized = true; 4599 AddressWasOptimized = true;
4553 Reason = nullptr; 4600 Reason = nullptr;
4554 } 4601 }
4555 // Update Base and Index to follow through assignments to definitions. 4602 // Update Base and Index to follow through assignments to definitions.
4556 if (matchAssign(VMetadata, Base, Relocatable, Offset, Reason)) { 4603 if (matchAssign(VMetadata, GotVar, Base, Relocatable, Offset, Reason)) {
4557 // Assignments of Base from a Relocatable or ConstantInt32 can result 4604 // Assignments of Base from a Relocatable or ConstantInt32 can result
4558 // in Base becoming nullptr. To avoid code duplication in this loop we 4605 // in Base becoming nullptr. To avoid code duplication in this loop we
4559 // prefer that Base be non-nullptr if possible. 4606 // prefer that Base be non-nullptr if possible.
4560 if ((Base == nullptr) && (Index != nullptr) && Shift == 0) 4607 if ((Base == nullptr) && (Index != nullptr) && Shift == 0)
4561 std::swap(Base, Index); 4608 std::swap(Base, Index);
4562 continue; 4609 continue;
4563 } 4610 }
4564 if (matchAssign(VMetadata, Index, Relocatable, Offset, Reason)) 4611 if (matchAssign(VMetadata, GotVar, Index, Relocatable, Offset, Reason))
4565 continue; 4612 continue;
4566 4613
4567 if (!MockBounds) { 4614 if (!MockBounds) {
4568 // Transition from: 4615 // Transition from:
4569 // <Relocatable + Offset>(Base) to 4616 // <Relocatable + Offset>(Base) to
4570 // <Relocatable + Offset>(Base, Index) 4617 // <Relocatable + Offset>(Base, Index)
4571 if (matchCombinedBaseIndex(VMetadata, Base, Index, Shift, Reason)) 4618 if (matchCombinedBaseIndex(VMetadata, Base, Index, Shift, Reason))
4572 continue; 4619 continue;
4573 // Recognize multiply/shift and update Shift amount. 4620 // Recognize multiply/shift and update Shift amount.
4574 // Index becomes Index=Var<<Const && Const+Shift<=3 ==> 4621 // Index becomes Index=Var<<Const && Const+Shift<=3 ==>
4575 // Index=Var, Shift+=Const 4622 // Index=Var, Shift+=Const
4576 // Index becomes Index=Const*Var && log2(Const)+Shift<=3 ==> 4623 // Index becomes Index=Const*Var && log2(Const)+Shift<=3 ==>
4577 // Index=Var, Shift+=log2(Const) 4624 // Index=Var, Shift+=log2(Const)
4578 if (matchShiftedIndex(VMetadata, Index, Shift, Reason)) 4625 if (matchShiftedIndex(VMetadata, Index, Shift, Reason))
4579 continue; 4626 continue;
4580 // If Shift is zero, the choice of Base and Index was purely arbitrary. 4627 // If Shift is zero, the choice of Base and Index was purely arbitrary.
4581 // Recognize multiply/shift and set Shift amount. 4628 // Recognize multiply/shift and set Shift amount.
4582 // Shift==0 && Base is Base=Var*Const && log2(Const)+Shift<=3 ==> 4629 // Shift==0 && Base is Base=Var*Const && log2(Const)+Shift<=3 ==>
4583 // swap(Index,Base) 4630 // swap(Index,Base)
4584 // Similar for Base=Const*Var and Base=Var<<Const 4631 // Similar for Base=Const*Var and Base=Var<<Const
4585 if (Shift == 0 && matchShiftedIndex(VMetadata, Base, Shift, Reason)) { 4632 if (Shift == 0 && matchShiftedIndex(VMetadata, Base, Shift, Reason)) {
4586 std::swap(Base, Index); 4633 std::swap(Base, Index);
4587 continue; 4634 continue;
4588 } 4635 }
4589 } 4636 }
4590 // Update Offset to reflect additions/subtractions with constants and 4637 // Update Offset to reflect additions/subtractions with constants and
4591 // relocatables. 4638 // relocatables.
4592 // TODO: consider overflow issues with respect to Offset. 4639 // TODO: consider overflow issues with respect to Offset.
4593 if (matchOffsetBase(VMetadata, Base, Relocatable, Offset, Reason)) 4640 if (matchOffsetBase(VMetadata, GotVar, Base, Index, Relocatable, Offset,
4641 Reason))
4594 continue; 4642 continue;
4595 if (Shift == 0 && 4643 if (Shift == 0 && matchOffsetBase(VMetadata, GotVar, Index, Base,
4596 matchOffsetBase(VMetadata, Index, Relocatable, Offset, Reason)) 4644 Relocatable, Offset, Reason))
4597 continue; 4645 continue;
4598 // TODO(sehr, stichnot): Handle updates of Index with Shift != 0. 4646 // TODO(sehr, stichnot): Handle updates of Index with Shift != 0.
4599 // Index is Index=Var+Const ==> 4647 // Index is Index=Var+Const ==>
4600 // set Index=Var, Offset+=(Const<<Shift) 4648 // set Index=Var, Offset+=(Const<<Shift)
4601 // Index is Index=Const+Var ==> 4649 // Index is Index=Const+Var ==>
4602 // set Index=Var, Offset+=(Const<<Shift) 4650 // set Index=Var, Offset+=(Const<<Shift)
4603 // Index is Index=Var-Const ==> 4651 // Index is Index=Var-Const ==>
4604 // set Index=Var, Offset-=(Const<<Shift) 4652 // set Index=Var, Offset-=(Const<<Shift)
4605 break; 4653 break;
4606 } while (Reason); 4654 } while (Reason);
4655 // Undo any addition of GotVar. It will be added back when the mem operand is
4656 // legalized.
4657 if (Base == GotVar)
4658 Base = nullptr;
4659 if (Index == GotVar)
4660 Index = nullptr;
4607 return AddressWasOptimized; 4661 return AddressWasOptimized;
4608 } 4662 }
4609 4663
4610 /// Add a mock bounds check on the memory address before using it as a load or 4664 /// Add a mock bounds check on the memory address before using it as a load or
4611 /// store operand. The basic idea is that given a memory operand [reg], we 4665 /// store operand. The basic idea is that given a memory operand [reg], we
4612 /// would first add bounds-check code something like: 4666 /// would first add bounds-check code something like:
4613 /// 4667 ///
4614 /// cmp reg, <lb> 4668 /// cmp reg, <lb>
4615 /// jl out_of_line_error 4669 /// jl out_of_line_error
4616 /// cmp reg, <ub> 4670 /// cmp reg, <ub>
(...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after
4662 _br(Traits::Cond::Br_e, Label); 4716 _br(Traits::Cond::Br_e, Label);
4663 _cmp(Opnd, Ctx->getConstantInt32(1)); 4717 _cmp(Opnd, Ctx->getConstantInt32(1));
4664 _br(Traits::Cond::Br_e, Label); 4718 _br(Traits::Cond::Br_e, Label);
4665 Context.insert(Label); 4719 Context.insert(Label);
4666 } 4720 }
4667 4721
4668 template <class Machine> 4722 template <class Machine>
4669 void TargetX86Base<Machine>::lowerLoad(const InstLoad *Load) { 4723 void TargetX86Base<Machine>::lowerLoad(const InstLoad *Load) {
4670 // A Load instruction can be treated the same as an Assign instruction, after 4724 // A Load instruction can be treated the same as an Assign instruction, after
4671 // the source operand is transformed into an Traits::X86OperandMem operand. 4725 // the source operand is transformed into an Traits::X86OperandMem operand.
4672 // Note that the address mode optimization already creates an 4726 // Note that the address mode optimization already creates a
4673 // Traits::X86OperandMem operand, so it doesn't need another level of 4727 // Traits::X86OperandMem operand, so it doesn't need another level of
4674 // transformation. 4728 // transformation.
4675 Variable *DestLoad = Load->getDest(); 4729 Variable *DestLoad = Load->getDest();
4676 Type Ty = DestLoad->getType(); 4730 Type Ty = DestLoad->getType();
4677 Operand *Src0 = formMemoryOperand(Load->getSourceAddress(), Ty); 4731 Operand *Src0 = formMemoryOperand(Load->getSourceAddress(), Ty);
4678 doMockBoundsCheck(Src0); 4732 doMockBoundsCheck(Src0);
4679 auto *Assign = InstAssign::create(Func, DestLoad, Src0); 4733 auto *Assign = InstAssign::create(Func, DestLoad, Src0);
4680 lowerAssign(Assign); 4734 lowerAssign(Assign);
4681 } 4735 }
4682 4736
4683 template <class Machine> void TargetX86Base<Machine>::doAddressOptLoad() { 4737 template <class Machine> void TargetX86Base<Machine>::doAddressOptLoad() {
4684 Inst *Inst = Context.getCur(); 4738 Inst *Inst = Context.getCur();
4685 Variable *Dest = Inst->getDest(); 4739 Variable *Dest = Inst->getDest();
4686 Operand *Addr = Inst->getSrc(0); 4740 Operand *Addr = Inst->getSrc(0);
4687 Variable *Index = nullptr; 4741 Variable *Index = nullptr;
4688 ConstantRelocatable *Relocatable = nullptr; 4742 ConstantRelocatable *Relocatable = nullptr;
4689 uint16_t Shift = 0; 4743 uint16_t Shift = 0;
4690 int32_t Offset = 0; 4744 int32_t Offset = 0;
4691 // Vanilla ICE load instructions should not use the segment registers, and 4745 // Vanilla ICE load instructions should not use the segment registers, and
4692 // computeAddressOpt only works at the level of Variables and Constants, not 4746 // computeAddressOpt only works at the level of Variables and Constants, not
4693 // other Traits::X86OperandMem, so there should be no mention of segment 4747 // other Traits::X86OperandMem, so there should be no mention of segment
4694 // registers there either. 4748 // registers there either.
4695 const typename Traits::X86OperandMem::SegmentRegisters SegmentReg = 4749 constexpr auto SegmentReg = Traits::X86OperandMem::DefaultSegment;
4696 Traits::X86OperandMem::DefaultSegment;
4697 auto *Base = llvm::dyn_cast<Variable>(Addr); 4750 auto *Base = llvm::dyn_cast<Variable>(Addr);
4698 if (computeAddressOpt(Func, Inst, Relocatable, Offset, Base, Index, Shift)) { 4751 if (computeAddressOpt(Func, Inst, GotVar, Relocatable, Offset, Base, Index,
4752 Shift)) {
4699 Inst->setDeleted(); 4753 Inst->setDeleted();
4700 Constant *OffsetOp = nullptr; 4754 Constant *OffsetOp = nullptr;
4701 if (Relocatable == nullptr) { 4755 if (Relocatable == nullptr) {
4702 OffsetOp = Ctx->getConstantInt32(Offset); 4756 OffsetOp = Ctx->getConstantInt32(Offset);
4703 } else { 4757 } else {
4704 OffsetOp = Ctx->getConstantSym(Relocatable->getOffset() + Offset, 4758 OffsetOp = Ctx->getConstantSym(Relocatable->getOffset() + Offset,
4705 Relocatable->getName(), 4759 Relocatable->getName(),
4706 Relocatable->getSuppressMangling()); 4760 Relocatable->getSuppressMangling());
4707 } 4761 }
4762 // The new mem operand is created without IsPIC being set, because
4763 // computeAddressOpt() doesn't include GotVar in its final result.
4708 Addr = Traits::X86OperandMem::create(Func, Dest->getType(), Base, OffsetOp, 4764 Addr = Traits::X86OperandMem::create(Func, Dest->getType(), Base, OffsetOp,
4709 Index, Shift, SegmentReg); 4765 Index, Shift, SegmentReg);
4710 Context.insert<InstLoad>(Dest, Addr); 4766 Context.insert<InstLoad>(Dest, Addr);
4711 } 4767 }
4712 } 4768 }
4713 4769
4714 template <class Machine> 4770 template <class Machine>
4715 void TargetX86Base<Machine>::randomlyInsertNop(float Probability, 4771 void TargetX86Base<Machine>::randomlyInsertNop(float Probability,
4716 RandomNumberGenerator &RNG) { 4772 RandomNumberGenerator &RNG) {
4717 RandomNumberGeneratorWrapper RNGW(RNG); 4773 RandomNumberGeneratorWrapper RNGW(RNG);
(...skipping 274 matching lines...) Expand 10 before | Expand all | Expand 10 after
4992 Operand *Addr = Inst->getAddr(); 5048 Operand *Addr = Inst->getAddr();
4993 Variable *Index = nullptr; 5049 Variable *Index = nullptr;
4994 ConstantRelocatable *Relocatable = nullptr; 5050 ConstantRelocatable *Relocatable = nullptr;
4995 uint16_t Shift = 0; 5051 uint16_t Shift = 0;
4996 int32_t Offset = 0; 5052 int32_t Offset = 0;
4997 auto *Base = llvm::dyn_cast<Variable>(Addr); 5053 auto *Base = llvm::dyn_cast<Variable>(Addr);
4998 // Vanilla ICE store instructions should not use the segment registers, and 5054 // Vanilla ICE store instructions should not use the segment registers, and
4999 // computeAddressOpt only works at the level of Variables and Constants, not 5055 // computeAddressOpt only works at the level of Variables and Constants, not
5000 // other Traits::X86OperandMem, so there should be no mention of segment 5056 // other Traits::X86OperandMem, so there should be no mention of segment
5001 // registers there either. 5057 // registers there either.
5002 const typename Traits::X86OperandMem::SegmentRegisters SegmentReg = 5058 constexpr auto SegmentReg = Traits::X86OperandMem::DefaultSegment;
John 2015/12/22 15:44:38 I personally like this idiom, but this is an "unsa
Jim Stichnoth 2015/12/28 07:54:07 OK, I modified it such that the fully written out
5003 Traits::X86OperandMem::DefaultSegment; 5059 if (computeAddressOpt(Func, Inst, GotVar, Relocatable, Offset, Base, Index,
5004 if (computeAddressOpt(Func, Inst, Relocatable, Offset, Base, Index, Shift)) { 5060 Shift)) {
5005 Inst->setDeleted(); 5061 Inst->setDeleted();
5006 Constant *OffsetOp = nullptr; 5062 Constant *OffsetOp = nullptr;
5007 if (Relocatable == nullptr) { 5063 if (Relocatable == nullptr) {
5008 OffsetOp = Ctx->getConstantInt32(Offset); 5064 OffsetOp = Ctx->getConstantInt32(Offset);
5009 } else { 5065 } else {
5010 OffsetOp = Ctx->getConstantSym(Relocatable->getOffset() + Offset, 5066 OffsetOp = Ctx->getConstantSym(Relocatable->getOffset() + Offset,
5011 Relocatable->getName(), 5067 Relocatable->getName(),
5012 Relocatable->getSuppressMangling()); 5068 Relocatable->getSuppressMangling());
5013 } 5069 }
5070 // The new mem operand is created without IsPIC being set, because
5071 // computeAddressOpt() doesn't include GotVar in its final result.
5014 Addr = Traits::X86OperandMem::create(Func, Data->getType(), Base, OffsetOp, 5072 Addr = Traits::X86OperandMem::create(Func, Data->getType(), Base, OffsetOp,
5015 Index, Shift, SegmentReg); 5073 Index, Shift, SegmentReg);
5016 auto *NewStore = Context.insert<InstStore>(Data, Addr); 5074 auto *NewStore = Context.insert<InstStore>(Data, Addr);
5017 if (Inst->getDest()) 5075 if (Inst->getDest())
5018 NewStore->setRmwBeacon(Inst->getRmwBeacon()); 5076 NewStore->setRmwBeacon(Inst->getRmwBeacon());
5019 } 5077 }
5020 } 5078 }
5021 5079
5022 template <class Machine> 5080 template <class Machine>
5023 Operand *TargetX86Base<Machine>::lowerCmpRange(Operand *Comparison, 5081 Operand *TargetX86Base<Machine>::lowerCmpRange(Operand *Comparison,
(...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after
5064 Variable *Index; 5122 Variable *Index;
5065 if (RangeIndex->getType() != getPointerType()) { 5123 if (RangeIndex->getType() != getPointerType()) {
5066 Index = makeReg(getPointerType()); 5124 Index = makeReg(getPointerType());
5067 _movzx(Index, RangeIndex); 5125 _movzx(Index, RangeIndex);
5068 } else { 5126 } else {
5069 Index = legalizeToReg(RangeIndex); 5127 Index = legalizeToReg(RangeIndex);
5070 } 5128 }
5071 5129
5072 constexpr RelocOffsetT RelocOffset = 0; 5130 constexpr RelocOffsetT RelocOffset = 0;
5073 constexpr bool SuppressMangling = true; 5131 constexpr bool SuppressMangling = true;
5132 const bool IsPIC = Ctx->getFlags().getUseNonsfi();
5074 IceString MangledName = Ctx->mangleName(Func->getFunctionName()); 5133 IceString MangledName = Ctx->mangleName(Func->getFunctionName());
5075 Constant *Base = Ctx->getConstantSym( 5134 Variable *Base = IsPIC ? legalizeToReg(GotVar) : nullptr;
5135 Constant *Offset = Ctx->getConstantSym(
5076 RelocOffset, InstJumpTable::makeName(MangledName, JumpTable->getId()), 5136 RelocOffset, InstJumpTable::makeName(MangledName, JumpTable->getId()),
5077 SuppressMangling); 5137 SuppressMangling);
5078 Constant *Offset = nullptr;
5079 uint16_t Shift = typeWidthInBytesLog2(getPointerType()); 5138 uint16_t Shift = typeWidthInBytesLog2(getPointerType());
5080 // TODO(ascull): remove need for legalize by allowing null base in memop 5139 constexpr auto Segment = Traits::X86OperandMem::DefaultSegment;
5081 auto *TargetInMemory = Traits::X86OperandMem::create( 5140 auto *TargetInMemory = Traits::X86OperandMem::create(
5082 Func, getPointerType(), legalizeToReg(Base), Offset, Index, Shift); 5141 Func, getPointerType(), Base, Offset, Index, Shift, Segment, IsPIC);
5083 Variable *Target = nullptr; 5142 Variable *Target = nullptr;
5084 _mov(Target, TargetInMemory); 5143 _mov(Target, TargetInMemory);
5085 lowerIndirectJump(Target); 5144 lowerIndirectJump(Target);
5086 5145
5087 if (DefaultTarget == nullptr) 5146 if (DefaultTarget == nullptr)
5088 Context.insert(SkipJumpTable); 5147 Context.insert(SkipJumpTable);
5089 return; 5148 return;
5090 } 5149 }
5091 case CaseCluster::Range: { 5150 case CaseCluster::Range: {
5092 if (Case.isUnitRange()) { 5151 if (Case.isUnitRange()) {
(...skipping 310 matching lines...) Expand 10 before | Expand all | Expand 10 after
5403 if (const auto *RMW = 5462 if (const auto *RMW =
5404 llvm::dyn_cast<typename Traits::Insts::FakeRMW>(Instr)) { 5463 llvm::dyn_cast<typename Traits::Insts::FakeRMW>(Instr)) {
5405 lowerRMW(RMW); 5464 lowerRMW(RMW);
5406 } else { 5465 } else {
5407 TargetLowering::lowerOther(Instr); 5466 TargetLowering::lowerOther(Instr);
5408 } 5467 }
5409 } 5468 }
5410 5469
5411 /// Turn an i64 Phi instruction into a pair of i32 Phi instructions, to preserve 5470 /// Turn an i64 Phi instruction into a pair of i32 Phi instructions, to preserve
5412 /// integrity of liveness analysis. Undef values are also turned into zeroes, 5471 /// integrity of liveness analysis. Undef values are also turned into zeroes,
5413 /// since loOperand() and hiOperand() don't expect Undef input. 5472 /// since loOperand() and hiOperand() don't expect Undef input. Also, in
5473 /// Non-SFI mode, add a FakeUse(GotVar) for every pooled constant operand.
5414 template <class Machine> void TargetX86Base<Machine>::prelowerPhis() { 5474 template <class Machine> void TargetX86Base<Machine>::prelowerPhis() {
5475 if (Ctx->getFlags().getUseNonsfi()) {
5476 assert(GotVar);
5477 CfgNode *Node = Context.getNode();
5478 uint32_t GotVarUseCount = 0;
5479 for (Inst &I : Node->getPhis()) {
5480 auto *Phi = llvm::dyn_cast<InstPhi>(&I);
5481 if (Phi->isDeleted())
5482 continue;
5483 for (SizeT I = 0; I < Phi->getSrcSize(); ++I) {
5484 Operand *Src = Phi->getSrc(I);
5485 // TODO(stichnot): This over-counts for +0.0, and under-counts for other
5486 // kinds of pooling.
5487 if (llvm::isa<ConstantRelocatable>(Src) ||
5488 llvm::isa<ConstantFloat>(Src) || llvm::isa<ConstantDouble>(Src)) {
5489 ++GotVarUseCount;
5490 }
5491 }
5492 }
5493 if (GotVarUseCount) {
5494 Node->getInsts().push_front(InstFakeUse::create(Func, GotVar));
5495 }
5496 }
5415 if (Traits::Is64Bit) { 5497 if (Traits::Is64Bit) {
5416 // On x86-64 we don't need to prelower phis -- the architecture can handle 5498 // On x86-64 we don't need to prelower phis -- the architecture can handle
5417 // 64-bit integer natively. 5499 // 64-bit integer natively.
5418 return; 5500 return;
5419 } 5501 }
5420 5502
5421 // Pause constant blinding or pooling, blinding or pooling will be done later 5503 // Pause constant blinding or pooling, blinding or pooling will be done later
5422 // during phi lowering assignments 5504 // during phi lowering assignments
5423 BoolFlagSaver B(RandomizationPoolingPaused, true); 5505 BoolFlagSaver B(RandomizationPoolingPaused, true);
5424 PhiLowering::prelowerPhis32Bit<TargetX86Base<Machine>>( 5506 PhiLowering::prelowerPhis32Bit<TargetX86Base<Machine>>(
(...skipping 460 matching lines...) Expand 10 before | Expand all | Expand 10 after
5885 _movp(Reg, Src); 5967 _movp(Reg, Src);
5886 } else { 5968 } else {
5887 _mov(Reg, Src); 5969 _mov(Reg, Src);
5888 } 5970 }
5889 return Reg; 5971 return Reg;
5890 } 5972 }
5891 5973
5892 template <class Machine> 5974 template <class Machine>
5893 Operand *TargetX86Base<Machine>::legalize(Operand *From, LegalMask Allowed, 5975 Operand *TargetX86Base<Machine>::legalize(Operand *From, LegalMask Allowed,
5894 int32_t RegNum) { 5976 int32_t RegNum) {
5895 Type Ty = From->getType(); 5977 const bool UseNonsfi = Func->getContext()->getFlags().getUseNonsfi();
5978 const Type Ty = From->getType();
5896 // Assert that a physical register is allowed. To date, all calls to 5979 // Assert that a physical register is allowed. To date, all calls to
5897 // legalize() allow a physical register. If a physical register needs to be 5980 // legalize() allow a physical register. If a physical register needs to be
5898 // explicitly disallowed, then new code will need to be written to force a 5981 // explicitly disallowed, then new code will need to be written to force a
5899 // spill. 5982 // spill.
5900 assert(Allowed & Legal_Reg); 5983 assert(Allowed & Legal_Reg);
5901 // If we're asking for a specific physical register, make sure we're not 5984 // If we're asking for a specific physical register, make sure we're not
5902 // allowing any other operand kinds. (This could be future work, e.g. allow 5985 // allowing any other operand kinds. (This could be future work, e.g. allow
5903 // the shl shift amount to be either an immediate or in ecx.) 5986 // the shl shift amount to be either an immediate or in ecx.)
5904 assert(RegNum == Variable::NoRegister || Allowed == Legal_Reg); 5987 assert(RegNum == Variable::NoRegister || Allowed == Legal_Reg);
5905 5988
(...skipping 13 matching lines...) Expand all
5919 } 6002 }
5920 } 6003 }
5921 } 6004 }
5922 } 6005 }
5923 6006
5924 if (auto *Mem = llvm::dyn_cast<typename Traits::X86OperandMem>(From)) { 6007 if (auto *Mem = llvm::dyn_cast<typename Traits::X86OperandMem>(From)) {
5925 // Before doing anything with a Mem operand, we need to ensure that the 6008 // Before doing anything with a Mem operand, we need to ensure that the
5926 // Base and Index components are in physical registers. 6009 // Base and Index components are in physical registers.
5927 Variable *Base = Mem->getBase(); 6010 Variable *Base = Mem->getBase();
5928 Variable *Index = Mem->getIndex(); 6011 Variable *Index = Mem->getIndex();
6012 Constant *Offset = Mem->getOffset();
5929 Variable *RegBase = nullptr; 6013 Variable *RegBase = nullptr;
5930 Variable *RegIndex = nullptr; 6014 Variable *RegIndex = nullptr;
5931 if (Base) { 6015 if (Base) {
5932 RegBase = llvm::cast<Variable>( 6016 RegBase = llvm::cast<Variable>(
5933 legalize(Base, Legal_Reg | Legal_Rematerializable)); 6017 legalize(Base, Legal_Reg | Legal_Rematerializable));
5934 } 6018 }
5935 if (Index) { 6019 if (Index) {
5936 RegIndex = llvm::cast<Variable>( 6020 RegIndex = llvm::cast<Variable>(
5937 legalize(Index, Legal_Reg | Legal_Rematerializable)); 6021 legalize(Index, Legal_Reg | Legal_Rematerializable));
5938 } 6022 }
6023 // For Non-SFI mode, if the Offset field is a ConstantRelocatable, we
6024 // replace either Base or Index with a legalized GotVar. At emission time,
6025 // the ConstantRelocatable will be emitted with the @GOTOFF relocation.
6026 bool NeedPIC = false;
6027 if (UseNonsfi && !Mem->getIsPIC() && Offset &&
6028 llvm::isa<ConstantRelocatable>(Offset)) {
6029 assert(!(Allowed & Legal_AddrAbs));
6030 NeedPIC = true;
6031 if (RegBase == nullptr) {
6032 RegBase = legalizeToReg(GotVar);
6033 } else if (RegIndex == nullptr) {
6034 RegIndex = legalizeToReg(GotVar);
6035 } else {
6036 llvm::report_fatal_error(
6037 "Either Base or Index must be unused in Non-SFI mode");
6038 }
6039 }
5939 if (Base != RegBase || Index != RegIndex) { 6040 if (Base != RegBase || Index != RegIndex) {
5940 Mem = Traits::X86OperandMem::create(Func, Ty, RegBase, Mem->getOffset(), 6041 Mem = Traits::X86OperandMem::create(Func, Ty, RegBase, Offset, RegIndex,
5941 RegIndex, Mem->getShift(), 6042 Mem->getShift(),
5942 Mem->getSegmentRegister()); 6043 Mem->getSegmentRegister(), NeedPIC);
5943 } 6044 }
5944 6045
5945 // For all Memory Operands, we do randomization/pooling here 6046 // For all Memory Operands, we do randomization/pooling here
5946 From = randomizeOrPoolImmediate(Mem); 6047 From = randomizeOrPoolImmediate(Mem);
5947 6048
5948 if (!(Allowed & Legal_Mem)) { 6049 if (!(Allowed & Legal_Mem)) {
5949 From = copyToReg(From, RegNum); 6050 From = copyToReg(From, RegNum);
5950 } 6051 }
5951 return From; 6052 return From;
5952 } 6053 }
6054
5953 if (auto *Const = llvm::dyn_cast<Constant>(From)) { 6055 if (auto *Const = llvm::dyn_cast<Constant>(From)) {
5954 if (llvm::isa<ConstantUndef>(Const)) { 6056 if (llvm::isa<ConstantUndef>(Const)) {
5955 From = legalizeUndef(Const, RegNum); 6057 From = legalizeUndef(Const, RegNum);
5956 if (isVectorType(Ty)) 6058 if (isVectorType(Ty))
5957 return From; 6059 return From;
5958 Const = llvm::cast<Constant>(From); 6060 Const = llvm::cast<Constant>(From);
5959 } 6061 }
5960 // There should be no constants of vector type (other than undef). 6062 // There should be no constants of vector type (other than undef).
5961 assert(!isVectorType(Ty)); 6063 assert(!isVectorType(Ty));
5962 6064
5963 // If the operand is a 64 bit constant integer we need to legalize it to a 6065 // If the operand is a 64 bit constant integer we need to legalize it to a
5964 // register in x86-64. 6066 // register in x86-64.
5965 if (Traits::Is64Bit) { 6067 if (Traits::Is64Bit) {
5966 if (llvm::isa<ConstantInteger64>(Const)) { 6068 if (llvm::isa<ConstantInteger64>(Const)) {
5967 Variable *V = copyToReg(Const, RegNum); 6069 Variable *V = copyToReg(Const, RegNum);
5968 return V; 6070 return V;
5969 } 6071 }
5970 } 6072 }
5971 6073
5972 // If the operand is an 32 bit constant integer, we should check whether we 6074 // If the operand is an 32 bit constant integer, we should check whether we
5973 // need to randomize it or pool it. 6075 // need to randomize it or pool it.
5974 if (auto *C = llvm::dyn_cast<ConstantInteger32>(Const)) { 6076 if (auto *C = llvm::dyn_cast<ConstantInteger32>(Const)) {
5975 Operand *NewConst = randomizeOrPoolImmediate(C, RegNum); 6077 Operand *NewConst = randomizeOrPoolImmediate(C, RegNum);
5976 if (NewConst != Const) { 6078 if (NewConst != Const) {
5977 return NewConst; 6079 return NewConst;
5978 } 6080 }
5979 } 6081 }
5980 6082
6083 // If the operand is a ConstantRelocatable, and Legal_AddrAbs is not
6084 // specified, and UseNonsfi is indicated, we need to add GotVar.
6085 if (auto *CR = llvm::dyn_cast<ConstantRelocatable>(Const)) {
6086 if (UseNonsfi && !(Allowed & Legal_AddrAbs)) {
6087 assert(Ty == IceType_i32);
6088 Variable *RegBase = legalizeToReg(GotVar);
6089 Variable *NewVar = makeReg(Ty, RegNum);
6090 auto *Mem = Traits::X86OperandMem::create(Func, Ty, RegBase, CR);
6091 Mem->setIsPIC();
6092 _lea(NewVar, Mem);
6093 From = NewVar;
6094 }
6095 }
6096
5981 // Convert a scalar floating point constant into an explicit memory 6097 // Convert a scalar floating point constant into an explicit memory
5982 // operand. 6098 // operand.
5983 if (isScalarFloatingType(Ty)) { 6099 if (isScalarFloatingType(Ty)) {
5984 if (auto *ConstFloat = llvm::dyn_cast<ConstantFloat>(Const)) { 6100 if (auto *ConstFloat = llvm::dyn_cast<ConstantFloat>(Const)) {
5985 if (Utils::isPositiveZero(ConstFloat->getValue())) 6101 if (Utils::isPositiveZero(ConstFloat->getValue()))
5986 return makeZeroedRegister(Ty, RegNum); 6102 return makeZeroedRegister(Ty, RegNum);
5987 } else if (auto *ConstDouble = llvm::dyn_cast<ConstantDouble>(Const)) { 6103 } else if (auto *ConstDouble = llvm::dyn_cast<ConstantDouble>(Const)) {
5988 if (Utils::isPositiveZero(ConstDouble->getValue())) 6104 if (Utils::isPositiveZero(ConstDouble->getValue()))
5989 return makeZeroedRegister(Ty, RegNum); 6105 return makeZeroedRegister(Ty, RegNum);
5990 } 6106 }
5991 Variable *Base = nullptr; 6107 Variable *Base = UseNonsfi ? legalizeToReg(GotVar) : nullptr;
5992 std::string Buffer; 6108 std::string Buffer;
5993 llvm::raw_string_ostream StrBuf(Buffer); 6109 llvm::raw_string_ostream StrBuf(Buffer);
5994 llvm::cast<Constant>(From)->emitPoolLabel(StrBuf, Ctx); 6110 llvm::cast<Constant>(From)->emitPoolLabel(StrBuf, Ctx);
5995 llvm::cast<Constant>(From)->setShouldBePooled(true); 6111 llvm::cast<Constant>(From)->setShouldBePooled(true);
5996 Constant *Offset = Ctx->getConstantSym(0, StrBuf.str(), true); 6112 Constant *Offset = Ctx->getConstantSym(0, StrBuf.str(), true);
5997 From = Traits::X86OperandMem::create(Func, Ty, Base, Offset); 6113 auto *Mem = Traits::X86OperandMem::create(Func, Ty, Base, Offset);
6114 if (UseNonsfi)
6115 Mem->setIsPIC();
6116 From = Mem;
5998 } 6117 }
5999 bool NeedsReg = false; 6118 bool NeedsReg = false;
6000 if (!(Allowed & Legal_Imm) && !isScalarFloatingType(Ty)) 6119 if (!(Allowed & Legal_Imm) && !isScalarFloatingType(Ty))
6001 // Immediate specifically not allowed 6120 // Immediate specifically not allowed
6002 NeedsReg = true; 6121 NeedsReg = true;
6003 if (!(Allowed & Legal_Mem) && isScalarFloatingType(Ty)) 6122 if (!(Allowed & Legal_Mem) && isScalarFloatingType(Ty))
6004 // On x86, FP constants are lowered to mem operands. 6123 // On x86, FP constants are lowered to mem operands.
6005 NeedsReg = true; 6124 NeedsReg = true;
6006 if (NeedsReg) { 6125 if (NeedsReg) {
6007 From = copyToReg(From, RegNum); 6126 From = copyToReg(From, RegNum);
6008 } 6127 }
6009 return From; 6128 return From;
6010 } 6129 }
6130
6011 if (auto *Var = llvm::dyn_cast<Variable>(From)) { 6131 if (auto *Var = llvm::dyn_cast<Variable>(From)) {
6012 // Check if the variable is guaranteed a physical register. This can happen 6132 // Check if the variable is guaranteed a physical register. This can happen
6013 // either when the variable is pre-colored or when it is assigned infinite 6133 // either when the variable is pre-colored or when it is assigned infinite
6014 // weight. 6134 // weight.
6015 bool MustHaveRegister = (Var->hasReg() || Var->mustHaveReg()); 6135 bool MustHaveRegister = (Var->hasReg() || Var->mustHaveReg());
6016 bool MustRematerialize = 6136 bool MustRematerialize =
6017 (Var->isRematerializable() && !(Allowed & Legal_Rematerializable)); 6137 (Var->isRematerializable() && !(Allowed & Legal_Rematerializable));
6018 // We need a new physical register for the operand if: 6138 // We need a new physical register for the operand if:
6019 // - Mem is not allowed and Var isn't guaranteed a physical register, or 6139 // - Mem is not allowed and Var isn't guaranteed a physical register, or
6020 // - RegNum is required and Var->getRegNum() doesn't match, or 6140 // - RegNum is required and Var->getRegNum() doesn't match, or
6021 // - Var is a rematerializable variable and rematerializable pass-through is 6141 // - Var is a rematerializable variable and rematerializable pass-through is
6022 // not allowed (in which case we need an lea instruction). 6142 // not allowed (in which case we need an lea instruction).
6023 if (MustRematerialize) { 6143 if (MustRematerialize) {
6024 assert(Ty == IceType_i32); 6144 assert(Ty == IceType_i32);
6025 Variable *NewVar = makeReg(Ty, RegNum); 6145 Variable *NewVar = makeReg(Ty, RegNum);
6026 // Since Var is rematerializable, the offset will be added when the lea is 6146 // Since Var is rematerializable, the offset will be added when the lea is
6027 // emitted. 6147 // emitted.
6028 constexpr Constant *NoOffset = nullptr; 6148 constexpr Constant *NoOffset = nullptr;
6029 auto *Mem = Traits::X86OperandMem::create(Func, Ty, Var, NoOffset); 6149 auto *Mem = Traits::X86OperandMem::create(Func, Ty, Var, NoOffset);
6030 _lea(NewVar, Mem); 6150 _lea(NewVar, Mem);
6031 From = NewVar; 6151 From = NewVar;
6032 } else if ((!(Allowed & Legal_Mem) && !MustHaveRegister) || 6152 } else if ((!(Allowed & Legal_Mem) && !MustHaveRegister) ||
6033 (RegNum != Variable::NoRegister && RegNum != Var->getRegNum()) || 6153 (RegNum != Variable::NoRegister && RegNum != Var->getRegNum()) ||
6034 MustRematerialize) { 6154 MustRematerialize) {
6035 From = copyToReg(From, RegNum); 6155 From = copyToReg(From, RegNum);
6036 } 6156 }
6037 return From; 6157 return From;
6038 } 6158 }
6039 llvm_unreachable("Unhandled operand kind in legalize()"); 6159
6160 llvm::report_fatal_error("Unhandled operand kind in legalize()");
6040 return From; 6161 return From;
6041 } 6162 }
6042 6163
6043 /// Provide a trivial wrapper to legalize() for this common usage. 6164 /// Provide a trivial wrapper to legalize() for this common usage.
6044 template <class Machine> 6165 template <class Machine>
6045 Variable *TargetX86Base<Machine>::legalizeToReg(Operand *From, int32_t RegNum) { 6166 Variable *TargetX86Base<Machine>::legalizeToReg(Operand *From, int32_t RegNum) {
6046 return llvm::cast<Variable>(legalize(From, Legal_Reg, RegNum)); 6167 return llvm::cast<Variable>(legalize(From, Legal_Reg, RegNum));
6047 } 6168 }
6048 6169
6049 /// Legalize undef values to concrete values. 6170 /// Legalize undef values to concrete values.
(...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after
6097 // transformation. 6218 // transformation.
6098 if (!Mem) { 6219 if (!Mem) {
6099 auto *Base = llvm::dyn_cast<Variable>(Opnd); 6220 auto *Base = llvm::dyn_cast<Variable>(Opnd);
6100 auto *Offset = llvm::dyn_cast<Constant>(Opnd); 6221 auto *Offset = llvm::dyn_cast<Constant>(Opnd);
6101 assert(Base || Offset); 6222 assert(Base || Offset);
6102 if (Offset) { 6223 if (Offset) {
6103 // During memory operand building, we do not blind or pool the constant 6224 // During memory operand building, we do not blind or pool the constant
6104 // offset, we will work on the whole memory operand later as one entity 6225 // offset, we will work on the whole memory operand later as one entity
6105 // later, this save one instruction. By turning blinding and pooling off, 6226 // later, this save one instruction. By turning blinding and pooling off,
6106 // we guarantee legalize(Offset) will return a Constant*. 6227 // we guarantee legalize(Offset) will return a Constant*.
6107 { 6228 if (!llvm::isa<ConstantRelocatable>(Offset)) {
6108 BoolFlagSaver B(RandomizationPoolingPaused, true); 6229 BoolFlagSaver B(RandomizationPoolingPaused, true);
6109 6230
6110 Offset = llvm::cast<Constant>(legalize(Offset)); 6231 Offset = llvm::cast<Constant>(legalize(Offset));
6111 } 6232 }
6112 6233
6113 assert(llvm::isa<ConstantInteger32>(Offset) || 6234 assert(llvm::isa<ConstantInteger32>(Offset) ||
6114 llvm::isa<ConstantRelocatable>(Offset)); 6235 llvm::isa<ConstantRelocatable>(Offset));
6115 } 6236 }
6237 // Not completely sure whether it's OK to leave IsPIC unset when creating
6238 // the mem operand. If DoLegalize is true, it will definitely be applied
6239 // during the legalize() call, but perhaps not during the
6240 // randomizeOrPoolImmediate() call. In any case, the emit routines will
6241 // assert that PIC legalization has been applied.
6116 Mem = Traits::X86OperandMem::create(Func, Ty, Base, Offset); 6242 Mem = Traits::X86OperandMem::create(Func, Ty, Base, Offset);
6117 } 6243 }
6118 // Do legalization, which contains randomization/pooling or do 6244 // Do legalization, which contains randomization/pooling or do
6119 // randomization/pooling. 6245 // randomization/pooling.
6120 return llvm::cast<typename Traits::X86OperandMem>( 6246 return llvm::cast<typename Traits::X86OperandMem>(
6121 DoLegalize ? legalize(Mem) : randomizeOrPoolImmediate(Mem)); 6247 DoLegalize ? legalize(Mem) : randomizeOrPoolImmediate(Mem));
6122 } 6248 }
6123 6249
6124 template <class Machine> 6250 template <class Machine>
6125 Variable *TargetX86Base<Machine>::makeReg(Type Type, int32_t RegNum) { 6251 Variable *TargetX86Base<Machine>::makeReg(Type Type, int32_t RegNum) {
(...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after
6174 const llvm::SmallBitVector &ExcludeRegisters, uint64_t Salt) const { 6300 const llvm::SmallBitVector &ExcludeRegisters, uint64_t Salt) const {
6175 Traits::makeRandomRegisterPermutation(Ctx, Func, Permutation, 6301 Traits::makeRandomRegisterPermutation(Ctx, Func, Permutation,
6176 ExcludeRegisters, Salt); 6302 ExcludeRegisters, Salt);
6177 } 6303 }
6178 6304
6179 template <class Machine> 6305 template <class Machine>
6180 void TargetX86Base<Machine>::emit(const ConstantInteger32 *C) const { 6306 void TargetX86Base<Machine>::emit(const ConstantInteger32 *C) const {
6181 if (!BuildDefs::dump()) 6307 if (!BuildDefs::dump())
6182 return; 6308 return;
6183 Ostream &Str = Ctx->getStrEmit(); 6309 Ostream &Str = Ctx->getStrEmit();
6184 Str << getConstantPrefix() << C->getValue(); 6310 Str << "$" << C->getValue();
6185 } 6311 }
6186 6312
6187 template <class Machine> 6313 template <class Machine>
6188 void TargetX86Base<Machine>::emit(const ConstantInteger64 *C) const { 6314 void TargetX86Base<Machine>::emit(const ConstantInteger64 *C) const {
6189 if (!Traits::Is64Bit) { 6315 if (!Traits::Is64Bit) {
6190 llvm::report_fatal_error("Not expecting to emit 64-bit integers"); 6316 llvm::report_fatal_error("Not expecting to emit 64-bit integers");
6191 } else { 6317 } else {
6192 if (!BuildDefs::dump()) 6318 if (!BuildDefs::dump())
6193 return; 6319 return;
6194 Ostream &Str = Ctx->getStrEmit(); 6320 Ostream &Str = Ctx->getStrEmit();
6195 Str << getConstantPrefix() << C->getValue(); 6321 Str << "$" << C->getValue();
6196 } 6322 }
6197 } 6323 }
6198 6324
6199 template <class Machine> 6325 template <class Machine>
6200 void TargetX86Base<Machine>::emit(const ConstantFloat *C) const { 6326 void TargetX86Base<Machine>::emit(const ConstantFloat *C) const {
6201 if (!BuildDefs::dump()) 6327 if (!BuildDefs::dump())
6202 return; 6328 return;
6203 Ostream &Str = Ctx->getStrEmit(); 6329 Ostream &Str = Ctx->getStrEmit();
6204 C->emitPoolLabel(Str, Ctx); 6330 C->emitPoolLabel(Str, Ctx);
6205 } 6331 }
6206 6332
6207 template <class Machine> 6333 template <class Machine>
6208 void TargetX86Base<Machine>::emit(const ConstantDouble *C) const { 6334 void TargetX86Base<Machine>::emit(const ConstantDouble *C) const {
6209 if (!BuildDefs::dump()) 6335 if (!BuildDefs::dump())
6210 return; 6336 return;
6211 Ostream &Str = Ctx->getStrEmit(); 6337 Ostream &Str = Ctx->getStrEmit();
6212 C->emitPoolLabel(Str, Ctx); 6338 C->emitPoolLabel(Str, Ctx);
6213 } 6339 }
6214 6340
6215 template <class Machine> 6341 template <class Machine>
6216 void TargetX86Base<Machine>::emit(const ConstantUndef *) const { 6342 void TargetX86Base<Machine>::emit(const ConstantUndef *) const {
6217 llvm::report_fatal_error("undef value encountered by emitter."); 6343 llvm::report_fatal_error("undef value encountered by emitter.");
6218 } 6344 }
6219 6345
6346 template <class Machine>
6347 void TargetX86Base<Machine>::emit(const ConstantRelocatable *C) const {
6348 if (!BuildDefs::dump())
6349 return;
6350 assert(!Ctx->getFlags().getUseNonsfi());
6351 Ostream &Str = Ctx->getStrEmit();
6352 Str << "$";
6353 emitWithoutPrefix(C);
6354 }
6355
6220 /// Randomize or pool an Immediate. 6356 /// Randomize or pool an Immediate.
6221 template <class Machine> 6357 template <class Machine>
6222 Operand *TargetX86Base<Machine>::randomizeOrPoolImmediate(Constant *Immediate, 6358 Operand *TargetX86Base<Machine>::randomizeOrPoolImmediate(Constant *Immediate,
6223 int32_t RegNum) { 6359 int32_t RegNum) {
6224 assert(llvm::isa<ConstantInteger32>(Immediate) || 6360 assert(llvm::isa<ConstantInteger32>(Immediate) ||
6225 llvm::isa<ConstantRelocatable>(Immediate)); 6361 llvm::isa<ConstantRelocatable>(Immediate));
6226 if (Ctx->getFlags().getRandomizeAndPoolImmediatesOption() == RPI_None || 6362 if (Ctx->getFlags().getRandomizeAndPoolImmediatesOption() == RPI_None ||
6227 RandomizationPoolingPaused == true) { 6363 RandomizationPoolingPaused == true) {
6228 // Immediates randomization/pooling off or paused 6364 // Immediates randomization/pooling off or paused
6229 return Immediate; 6365 return Immediate;
(...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after
6273 // assigned register as this assignment is that start of its use-def 6409 // assigned register as this assignment is that start of its use-def
6274 // chain. So we add RegNum argument here. 6410 // chain. So we add RegNum argument here.
6275 Variable *Reg = makeReg(Immediate->getType(), RegNum); 6411 Variable *Reg = makeReg(Immediate->getType(), RegNum);
6276 IceString Label; 6412 IceString Label;
6277 llvm::raw_string_ostream Label_stream(Label); 6413 llvm::raw_string_ostream Label_stream(Label);
6278 Immediate->emitPoolLabel(Label_stream, Ctx); 6414 Immediate->emitPoolLabel(Label_stream, Ctx);
6279 constexpr RelocOffsetT Offset = 0; 6415 constexpr RelocOffsetT Offset = 0;
6280 constexpr bool SuppressMangling = true; 6416 constexpr bool SuppressMangling = true;
6281 Constant *Symbol = 6417 Constant *Symbol =
6282 Ctx->getConstantSym(Offset, Label_stream.str(), SuppressMangling); 6418 Ctx->getConstantSym(Offset, Label_stream.str(), SuppressMangling);
6419 const bool UseNonsfi = Ctx->getFlags().getUseNonsfi();
6420 Variable *Base = UseNonsfi ? legalizeToReg(GotVar) : nullptr;
6283 typename Traits::X86OperandMem *MemOperand = 6421 typename Traits::X86OperandMem *MemOperand =
6284 Traits::X86OperandMem::create(Func, Immediate->getType(), nullptr, 6422 Traits::X86OperandMem::create(Func, Immediate->getType(), Base,
6285 Symbol); 6423 Symbol);
6424 if (UseNonsfi)
6425 MemOperand->setIsPIC();
6286 _mov(Reg, MemOperand); 6426 _mov(Reg, MemOperand);
6287 return Reg; 6427 return Reg;
6288 } 6428 }
6289 assert("Unsupported -randomize-pool-immediates option" && false); 6429 assert("Unsupported -randomize-pool-immediates option" && false);
6290 } 6430 }
6291 // the constant Immediate is not eligible for blinding/pooling 6431 // the constant Immediate is not eligible for blinding/pooling
6292 return Immediate; 6432 return Immediate;
6293 } 6433 }
6294 6434
6295 template <class Machine> 6435 template <class Machine>
(...skipping 74 matching lines...) Expand 10 before | Expand all | Expand 10 after
6370 return MemOperand; 6510 return MemOperand;
6371 Variable *RegTemp = makeReg(IceType_i32); 6511 Variable *RegTemp = makeReg(IceType_i32);
6372 IceString Label; 6512 IceString Label;
6373 llvm::raw_string_ostream Label_stream(Label); 6513 llvm::raw_string_ostream Label_stream(Label);
6374 MemOperand->getOffset()->emitPoolLabel(Label_stream, Ctx); 6514 MemOperand->getOffset()->emitPoolLabel(Label_stream, Ctx);
6375 MemOperand->getOffset()->setShouldBePooled(true); 6515 MemOperand->getOffset()->setShouldBePooled(true);
6376 constexpr RelocOffsetT SymOffset = 0; 6516 constexpr RelocOffsetT SymOffset = 0;
6377 constexpr bool SuppressMangling = true; 6517 constexpr bool SuppressMangling = true;
6378 Constant *Symbol = Ctx->getConstantSym(SymOffset, Label_stream.str(), 6518 Constant *Symbol = Ctx->getConstantSym(SymOffset, Label_stream.str(),
6379 SuppressMangling); 6519 SuppressMangling);
6520 const bool UseNonsfi = Ctx->getFlags().getUseNonsfi();
6521 Variable *Base = UseNonsfi ? legalizeToReg(GotVar) : nullptr;
6380 typename Traits::X86OperandMem *SymbolOperand = 6522 typename Traits::X86OperandMem *SymbolOperand =
6381 Traits::X86OperandMem::create( 6523 Traits::X86OperandMem::create(
6382 Func, MemOperand->getOffset()->getType(), nullptr, Symbol); 6524 Func, MemOperand->getOffset()->getType(), Base, Symbol);
6525 if (UseNonsfi)
6526 SymbolOperand->setIsPIC();
6383 _mov(RegTemp, SymbolOperand); 6527 _mov(RegTemp, SymbolOperand);
6384 // If we have a base variable here, we should add the lea instruction 6528 // If we have a base variable here, we should add the lea instruction
6385 // to add the value of the base variable to RegTemp. If there is no 6529 // to add the value of the base variable to RegTemp. If there is no
6386 // base variable, we won't need this lea instruction. 6530 // base variable, we won't need this lea instruction.
6387 if (MemOperand->getBase()) { 6531 if (MemOperand->getBase()) {
6388 typename Traits::X86OperandMem *CalculateOperand = 6532 typename Traits::X86OperandMem *CalculateOperand =
6389 Traits::X86OperandMem::create( 6533 Traits::X86OperandMem::create(
6390 Func, MemOperand->getType(), MemOperand->getBase(), nullptr, 6534 Func, MemOperand->getType(), MemOperand->getBase(), nullptr,
6391 RegTemp, 0, MemOperand->getSegmentRegister()); 6535 RegTemp, 0, MemOperand->getSegmentRegister());
6392 _lea(RegTemp, CalculateOperand); 6536 _lea(RegTemp, CalculateOperand);
(...skipping 10 matching lines...) Expand all
6403 } 6547 }
6404 // the offset is not eligible for blinding or pooling, return the original 6548 // the offset is not eligible for blinding or pooling, return the original
6405 // mem operand 6549 // mem operand
6406 return MemOperand; 6550 return MemOperand;
6407 } 6551 }
6408 6552
6409 } // end of namespace X86Internal 6553 } // end of namespace X86Internal
6410 } // end of namespace Ice 6554 } // end of namespace Ice
6411 6555
6412 #endif // SUBZERO_SRC_ICETARGETLOWERINGX86BASEIMPL_H 6556 #endif // SUBZERO_SRC_ICETARGETLOWERINGX86BASEIMPL_H
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698