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

Side by Side Diff: src/IceTargetLoweringX8632.cpp

Issue 870653002: Subzero: Initial implementation of multithreaded translation. (Closed) Base URL: https://chromium.googlesource.com/native_client/pnacl-subzero.git@master
Patch Set: Rebase Created 5 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
« no previous file with comments | « src/IceTargetLoweringX8632.h ('k') | src/IceTranslator.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 //===- subzero/src/IceTargetLoweringX8632.cpp - x86-32 lowering -----------===// 1 //===- subzero/src/IceTargetLoweringX8632.cpp - x86-32 lowering -----------===//
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 // This file implements the TargetLoweringX8632 class, which 10 // This file implements the TargetLoweringX8632 class, which
(...skipping 879 matching lines...) Expand 10 before | Expand all | Expand 10 after
890 this->FrameSizeLocals = NextStackOffset - SpillAreaPaddingBytes; 890 this->FrameSizeLocals = NextStackOffset - SpillAreaPaddingBytes;
891 this->HasComputedFrame = true; 891 this->HasComputedFrame = true;
892 892
893 // Assign stack offsets to variables that have been linked to spilled 893 // Assign stack offsets to variables that have been linked to spilled
894 // variables. 894 // variables.
895 for (Variable *Var : VariablesLinkedToSpillSlots) { 895 for (Variable *Var : VariablesLinkedToSpillSlots) {
896 Variable *Linked = (llvm::cast<SpillVariable>(Var))->getLinkedTo(); 896 Variable *Linked = (llvm::cast<SpillVariable>(Var))->getLinkedTo();
897 Var->setStackOffset(Linked->getStackOffset()); 897 Var->setStackOffset(Linked->getStackOffset());
898 } 898 }
899 899
900 if (ALLOW_DUMP && Func->getContext()->isVerbose(IceV_Frame)) { 900 if (ALLOW_DUMP && Func->isVerbose(IceV_Frame)) {
901 OstreamLocker L(Func->getContext()); 901 OstreamLocker L(Func->getContext());
902 Ostream &Str = Func->getContext()->getStrDump(); 902 Ostream &Str = Func->getContext()->getStrDump();
903 903
904 Str << "Stack layout:\n"; 904 Str << "Stack layout:\n";
905 uint32_t EspAdjustmentPaddingSize = 905 uint32_t EspAdjustmentPaddingSize =
906 SpillAreaSizeBytes - LocalsSpillAreaSize - 906 SpillAreaSizeBytes - LocalsSpillAreaSize -
907 GlobalsAndSubsequentPaddingSize - SpillAreaPaddingBytes; 907 GlobalsAndSubsequentPaddingSize - SpillAreaPaddingBytes;
908 Str << " in-args = " << InArgsSizeBytes << " bytes\n" 908 Str << " in-args = " << InArgsSizeBytes << " bytes\n"
909 << " return address = " << X86_RET_IP_SIZE_BYTES << " bytes\n" 909 << " return address = " << X86_RET_IP_SIZE_BYTES << " bytes\n"
910 << " preserved registers = " << PreservedRegsSizeBytes << " bytes\n" 910 << " preserved registers = " << PreservedRegsSizeBytes << " bytes\n"
(...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after
959 for (SizeT i = 0; i < CalleeSaves.size(); ++i) { 959 for (SizeT i = 0; i < CalleeSaves.size(); ++i) {
960 SizeT j = CalleeSaves.size() - i - 1; 960 SizeT j = CalleeSaves.size() - i - 1;
961 if (j == RegX8632::Reg_ebp && IsEbpBasedFrame) 961 if (j == RegX8632::Reg_ebp && IsEbpBasedFrame)
962 continue; 962 continue;
963 if (CalleeSaves[j] && RegsUsed[j]) { 963 if (CalleeSaves[j] && RegsUsed[j]) {
964 _pop(getPhysicalRegister(j)); 964 _pop(getPhysicalRegister(j));
965 } 965 }
966 } 966 }
967 } 967 }
968 968
969 template <typename T> struct PoolTypeConverter {};
970
971 template <> struct PoolTypeConverter<float> {
972 typedef uint32_t PrimitiveIntType;
973 typedef ConstantFloat IceType;
974 static const Type Ty = IceType_f32;
975 static const char *TypeName;
976 static const char *AsmTag;
977 static const char *PrintfString;
978 };
979 const char *PoolTypeConverter<float>::TypeName = "float";
980 const char *PoolTypeConverter<float>::AsmTag = ".long";
981 const char *PoolTypeConverter<float>::PrintfString = "0x%x";
982
983 template <> struct PoolTypeConverter<double> {
984 typedef uint64_t PrimitiveIntType;
985 typedef ConstantDouble IceType;
986 static const Type Ty = IceType_f64;
987 static const char *TypeName;
988 static const char *AsmTag;
989 static const char *PrintfString;
990 };
991 const char *PoolTypeConverter<double>::TypeName = "double";
992 const char *PoolTypeConverter<double>::AsmTag = ".quad";
993 const char *PoolTypeConverter<double>::PrintfString = "0x%llx";
994
995 template <typename T> void TargetX8632::emitConstantPool() const {
996 // Note: Still used by emit IAS.
997 Ostream &Str = Ctx->getStrEmit();
998 Type Ty = T::Ty;
999 SizeT Align = typeAlignInBytes(Ty);
1000 ConstantList Pool = Ctx->getConstantPool(Ty);
1001
1002 Str << "\t.section\t.rodata.cst" << Align << ",\"aM\",@progbits," << Align
1003 << "\n";
1004 Str << "\t.align\t" << Align << "\n";
1005 for (Constant *C : Pool) {
1006 typename T::IceType *Const = llvm::cast<typename T::IceType>(C);
1007 typename T::IceType::PrimType Value = Const->getValue();
1008 // Use memcpy() to copy bits from Value into RawValue in a way
1009 // that avoids breaking strict-aliasing rules.
1010 typename T::PrimitiveIntType RawValue;
1011 memcpy(&RawValue, &Value, sizeof(Value));
1012 char buf[30];
1013 int CharsPrinted =
1014 snprintf(buf, llvm::array_lengthof(buf), T::PrintfString, RawValue);
1015 assert(CharsPrinted >= 0 &&
1016 (size_t)CharsPrinted < llvm::array_lengthof(buf));
1017 (void)CharsPrinted; // avoid warnings if asserts are disabled
1018 Const->emitPoolLabel(Str);
1019 Str << ":\n\t" << T::AsmTag << "\t" << buf << "\t# " << T::TypeName << " "
1020 << Value << "\n";
1021 }
1022 }
1023
1024 void TargetX8632::emitConstants() const {
1025 // No need to emit constants from the int pool since (for x86) they
1026 // are embedded as immediates in the instructions, just emit float/double.
1027 if (Ctx->getFlags().UseELFWriter) {
1028 ELFObjectWriter *Writer = Ctx->getObjectWriter();
1029 Writer->writeConstantPool<ConstantFloat>(IceType_f32);
1030 Writer->writeConstantPool<ConstantDouble>(IceType_f64);
1031 } else {
1032 OstreamLocker L(Ctx);
1033 emitConstantPool<PoolTypeConverter<float>>();
1034 emitConstantPool<PoolTypeConverter<double>>();
1035 }
1036 }
1037
1038 void TargetX8632::split64(Variable *Var) { 969 void TargetX8632::split64(Variable *Var) {
1039 switch (Var->getType()) { 970 switch (Var->getType()) {
1040 default: 971 default:
1041 return; 972 return;
1042 case IceType_i64: 973 case IceType_i64:
1043 // TODO: Only consider F64 if we need to push each half when 974 // TODO: Only consider F64 if we need to push each half when
1044 // passing as an argument to a function call. Note that each half 975 // passing as an argument to a function call. Note that each half
1045 // is still typed as I32. 976 // is still typed as I32.
1046 case IceType_f64: 977 case IceType_f64:
1047 break; 978 break;
(...skipping 2512 matching lines...) Expand 10 before | Expand all | Expand 10 after
3560 return (Arith->getOp() == InstArithmetic::Add); 3491 return (Arith->getOp() == InstArithmetic::Add);
3561 } 3492 }
3562 return false; 3493 return false;
3563 } 3494 }
3564 3495
3565 void dumpAddressOpt(const Cfg *Func, const Variable *Base, 3496 void dumpAddressOpt(const Cfg *Func, const Variable *Base,
3566 const Variable *Index, uint16_t Shift, int32_t Offset, 3497 const Variable *Index, uint16_t Shift, int32_t Offset,
3567 const Inst *Reason) { 3498 const Inst *Reason) {
3568 if (!ALLOW_DUMP) 3499 if (!ALLOW_DUMP)
3569 return; 3500 return;
3570 if (!Func->getContext()->isVerbose(IceV_AddrOpt)) 3501 if (!Func->isVerbose(IceV_AddrOpt))
3571 return; 3502 return;
3572 OstreamLocker L(Func->getContext()); 3503 OstreamLocker L(Func->getContext());
3573 Ostream &Str = Func->getContext()->getStrDump(); 3504 Ostream &Str = Func->getContext()->getStrDump();
3574 Str << "Instruction: "; 3505 Str << "Instruction: ";
3575 Reason->dumpDecorated(Func); 3506 Reason->dumpDecorated(Func);
3576 Str << " results in Base="; 3507 Str << " results in Base=";
3577 if (Base) 3508 if (Base)
3578 Base->dump(Func); 3509 Base->dump(Func);
3579 else 3510 else
3580 Str << "<null>"; 3511 Str << "<null>";
(...skipping 152 matching lines...) Expand 10 before | Expand all | Expand 10 after
3733 Offset += MoreOffset; 3664 Offset += MoreOffset;
3734 Reason = BaseInst; 3665 Reason = BaseInst;
3735 return true; 3666 return true;
3736 } 3667 }
3737 return false; 3668 return false;
3738 } 3669 }
3739 3670
3740 void computeAddressOpt(Cfg *Func, const Inst *Instr, Variable *&Base, 3671 void computeAddressOpt(Cfg *Func, const Inst *Instr, Variable *&Base,
3741 Variable *&Index, uint16_t &Shift, int32_t &Offset) { 3672 Variable *&Index, uint16_t &Shift, int32_t &Offset) {
3742 Func->resetCurrentNode(); 3673 Func->resetCurrentNode();
3743 if (Func->getContext()->isVerbose(IceV_AddrOpt)) { 3674 if (Func->isVerbose(IceV_AddrOpt)) {
3744 OstreamLocker L(Func->getContext()); 3675 OstreamLocker L(Func->getContext());
3745 Ostream &Str = Func->getContext()->getStrDump(); 3676 Ostream &Str = Func->getContext()->getStrDump();
3746 Str << "\nStarting computeAddressOpt for instruction:\n "; 3677 Str << "\nStarting computeAddressOpt for instruction:\n ";
3747 Instr->dumpDecorated(Func); 3678 Instr->dumpDecorated(Func);
3748 } 3679 }
3749 (void)Offset; // TODO: pattern-match for non-zero offsets. 3680 (void)Offset; // TODO: pattern-match for non-zero offsets.
3750 if (Base == nullptr) 3681 if (Base == nullptr)
3751 return; 3682 return;
3752 // If the Base has more than one use or is live across multiple 3683 // If the Base has more than one use or is live across multiple
3753 // blocks, then don't go further. Alternatively (?), never consider 3684 // blocks, then don't go further. Alternatively (?), never consider
(...skipping 821 matching lines...) Expand 10 before | Expand all | Expand 10 after
4575 RegisterList Shuffled(List); 4506 RegisterList Shuffled(List);
4576 std::random_shuffle(Shuffled.begin(), Shuffled.end(), RNG); 4507 std::random_shuffle(Shuffled.begin(), Shuffled.end(), RNG);
4577 for (size_t SI = 0, SE = Shuffled.size(); SI < SE; ++SI) { 4508 for (size_t SI = 0, SE = Shuffled.size(); SI < SE; ++SI) {
4578 Permutation[List[SI]] = Shuffled[SI]; 4509 Permutation[List[SI]] = Shuffled[SI];
4579 ++NumShuffled; 4510 ++NumShuffled;
4580 } 4511 }
4581 } 4512 }
4582 4513
4583 assert(NumShuffled + NumPreserved == RegX8632::Reg_NUM); 4514 assert(NumShuffled + NumPreserved == RegX8632::Reg_NUM);
4584 4515
4585 if (Func->getContext()->isVerbose(IceV_Random)) { 4516 if (Func->isVerbose(IceV_Random)) {
4586 OstreamLocker L(Func->getContext()); 4517 OstreamLocker L(Func->getContext());
4587 Ostream &Str = Func->getContext()->getStrDump(); 4518 Ostream &Str = Func->getContext()->getStrDump();
4588 Str << "Register equivalence classes:\n"; 4519 Str << "Register equivalence classes:\n";
4589 for (auto I : EquivalenceClasses) { 4520 for (auto I : EquivalenceClasses) {
4590 Str << "{"; 4521 Str << "{";
4591 const RegisterList &List = I.second; 4522 const RegisterList &List = I.second;
4592 bool First = true; 4523 bool First = true;
4593 for (int32_t Register : List) { 4524 for (int32_t Register : List) {
4594 if (!First) 4525 if (!First)
4595 Str << " "; 4526 Str << " ";
(...skipping 27 matching lines...) Expand all
4623 if (!ALLOW_DUMP) 4554 if (!ALLOW_DUMP)
4624 return; 4555 return;
4625 Ostream &Str = Ctx->getStrEmit(); 4556 Ostream &Str = Ctx->getStrEmit();
4626 emitPoolLabel(Str); 4557 emitPoolLabel(Str);
4627 } 4558 }
4628 4559
4629 void ConstantUndef::emit(GlobalContext *) const { 4560 void ConstantUndef::emit(GlobalContext *) const {
4630 llvm_unreachable("undef value encountered by emitter."); 4561 llvm_unreachable("undef value encountered by emitter.");
4631 } 4562 }
4632 4563
4633 TargetGlobalInitX8632::TargetGlobalInitX8632(GlobalContext *Ctx) 4564 TargetGlobalX8632::TargetGlobalX8632(GlobalContext *Ctx)
4634 : TargetGlobalInitLowering(Ctx) {} 4565 : TargetGlobalLowering(Ctx) {}
4635 4566
4636 void TargetGlobalInitX8632::lower(const VariableDeclaration &Var) { 4567 void TargetGlobalX8632::lowerInit(const VariableDeclaration &Var) const {
4637 // TODO(jvoung): handle this without text. 4568 // TODO(jvoung): handle this without text.
4638 if (Ctx->getFlags().UseELFWriter) 4569 if (Ctx->getFlags().UseELFWriter)
4639 return; 4570 return;
4640 4571
4641 Ostream &Str = Ctx->getStrEmit(); 4572 Ostream &Str = Ctx->getStrEmit();
4642 4573
4643 const VariableDeclaration::InitializerListType &Initializers = 4574 const VariableDeclaration::InitializerListType &Initializers =
4644 Var.getInitializers(); 4575 Var.getInitializers();
4645 4576
4646 // If external and not initialized, this must be a cross test. 4577 // If external and not initialized, this must be a cross test.
(...skipping 60 matching lines...) Expand 10 before | Expand all | Expand 10 after
4707 } else 4638 } else
4708 // NOTE: for non-constant zero initializers, this is BSS (no bits), 4639 // NOTE: for non-constant zero initializers, this is BSS (no bits),
4709 // so an ELF writer would not write to the file, and only track 4640 // so an ELF writer would not write to the file, and only track
4710 // virtual offsets, but the .s writer still needs this .zero and 4641 // virtual offsets, but the .s writer still needs this .zero and
4711 // cannot simply use the .size to advance offsets. 4642 // cannot simply use the .size to advance offsets.
4712 Str << "\t.zero\t" << Size << "\n"; 4643 Str << "\t.zero\t" << Size << "\n";
4713 4644
4714 Str << "\t.size\t" << MangledName << ", " << Size << "\n"; 4645 Str << "\t.size\t" << MangledName << ", " << Size << "\n";
4715 } 4646 }
4716 4647
4648 template <typename T> struct PoolTypeConverter {};
4649
4650 template <> struct PoolTypeConverter<float> {
4651 typedef uint32_t PrimitiveIntType;
4652 typedef ConstantFloat IceType;
4653 static const Type Ty = IceType_f32;
4654 static const char *TypeName;
4655 static const char *AsmTag;
4656 static const char *PrintfString;
4657 };
4658 const char *PoolTypeConverter<float>::TypeName = "float";
4659 const char *PoolTypeConverter<float>::AsmTag = ".long";
4660 const char *PoolTypeConverter<float>::PrintfString = "0x%x";
4661
4662 template <> struct PoolTypeConverter<double> {
4663 typedef uint64_t PrimitiveIntType;
4664 typedef ConstantDouble IceType;
4665 static const Type Ty = IceType_f64;
4666 static const char *TypeName;
4667 static const char *AsmTag;
4668 static const char *PrintfString;
4669 };
4670 const char *PoolTypeConverter<double>::TypeName = "double";
4671 const char *PoolTypeConverter<double>::AsmTag = ".quad";
4672 const char *PoolTypeConverter<double>::PrintfString = "0x%llx";
4673
4674 template <typename T>
4675 void TargetGlobalX8632::emitConstantPool(GlobalContext *Ctx) {
4676 // Note: Still used by emit IAS.
4677 Ostream &Str = Ctx->getStrEmit();
4678 Type Ty = T::Ty;
4679 SizeT Align = typeAlignInBytes(Ty);
4680 ConstantList Pool = Ctx->getConstantPool(Ty);
4681
4682 Str << "\t.section\t.rodata.cst" << Align << ",\"aM\",@progbits," << Align
4683 << "\n";
4684 Str << "\t.align\t" << Align << "\n";
4685 for (Constant *C : Pool) {
4686 typename T::IceType *Const = llvm::cast<typename T::IceType>(C);
4687 typename T::IceType::PrimType Value = Const->getValue();
4688 // Use memcpy() to copy bits from Value into RawValue in a way
4689 // that avoids breaking strict-aliasing rules.
4690 typename T::PrimitiveIntType RawValue;
4691 memcpy(&RawValue, &Value, sizeof(Value));
4692 char buf[30];
4693 int CharsPrinted =
4694 snprintf(buf, llvm::array_lengthof(buf), T::PrintfString, RawValue);
4695 assert(CharsPrinted >= 0 &&
4696 (size_t)CharsPrinted < llvm::array_lengthof(buf));
4697 (void)CharsPrinted; // avoid warnings if asserts are disabled
4698 Const->emitPoolLabel(Str);
4699 Str << ":\n\t" << T::AsmTag << "\t" << buf << "\t# " << T::TypeName << " "
4700 << Value << "\n";
4701 }
4702 }
4703
4704 void TargetGlobalX8632::lowerConstants(GlobalContext *Ctx) const {
4705 if (Ctx->getFlags().DisableTranslation)
4706 return;
4707 // No need to emit constants from the int pool since (for x86) they
4708 // are embedded as immediates in the instructions, just emit float/double.
4709 if (Ctx->getFlags().UseELFWriter) {
4710 ELFObjectWriter *Writer = Ctx->getObjectWriter();
4711 Writer->writeConstantPool<ConstantFloat>(IceType_f32);
4712 Writer->writeConstantPool<ConstantDouble>(IceType_f64);
4713 } else {
4714 OstreamLocker L(Ctx);
4715 emitConstantPool<PoolTypeConverter<float>>(Ctx);
4716 emitConstantPool<PoolTypeConverter<double>>(Ctx);
4717 }
4718 }
4719
4717 } // end of namespace Ice 4720 } // end of namespace Ice
OLDNEW
« no previous file with comments | « src/IceTargetLoweringX8632.h ('k') | src/IceTranslator.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698