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

Side by Side Diff: src/IceTargetLoweringX8664.cpp

Issue 1616673004: Merge x86 data and header lowering (Closed) Base URL: https://chromium.googlesource.com/native_client/pnacl-subzero.git@master
Patch Set: Small syntactic commonality. 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/IceTargetLoweringX8664.cpp - x86-64 lowering -----------===// 1 //===- subzero/src/IceTargetLoweringX8664.cpp - x86-64 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 /// \file 10 /// \file
11 /// \brief Implements the TargetLoweringX8664 class, which consists almost 11 /// \brief Implements the TargetLoweringX8664 class, which consists almost
12 /// entirely of the lowering sequence for each high-level instruction. 12 /// entirely of the lowering sequence for each high-level instruction.
13 /// 13 ///
14 //===----------------------------------------------------------------------===// 14 //===----------------------------------------------------------------------===//
15 #include "IceTargetLoweringX8664.h" 15 #include "IceTargetLoweringX8664.h"
16 16
17 #include "IceDefs.h" 17 #include "IceDefs.h"
18 #include "IceTargetLoweringX8664Traits.h" 18 #include "IceTargetLoweringX8664Traits.h"
19 19
20 namespace X8664 { 20 namespace X8664 {
21 std::unique_ptr<::Ice::TargetLowering> createTargetLowering(::Ice::Cfg *Func) { 21 std::unique_ptr<::Ice::TargetLowering> createTargetLowering(::Ice::Cfg *Func) {
22 return ::Ice::X8664::TargetX8664::create(Func); 22 return ::Ice::X8664::TargetX8664::create(Func);
23 } 23 }
24 24
25 std::unique_ptr<::Ice::TargetDataLowering> 25 std::unique_ptr<::Ice::TargetDataLowering>
26 createTargetDataLowering(::Ice::GlobalContext *Ctx) { 26 createTargetDataLowering(::Ice::GlobalContext *Ctx) {
27 return ::Ice::X8664::TargetDataX8664::create(Ctx); 27 return ::Ice::X8664::TargetDataX86<::Ice::X8664::TargetX8664Traits>::create(
28 Ctx);
28 } 29 }
29 30
30 std::unique_ptr<::Ice::TargetHeaderLowering> 31 std::unique_ptr<::Ice::TargetHeaderLowering>
31 createTargetHeaderLowering(::Ice::GlobalContext *Ctx) { 32 createTargetHeaderLowering(::Ice::GlobalContext *Ctx) {
32 return ::Ice::X8664::TargetHeaderX8664::create(Ctx); 33 return ::Ice::X8664::TargetHeaderX86::create(Ctx);
33 } 34 }
34 35
35 void staticInit(::Ice::GlobalContext *Ctx) { 36 void staticInit(::Ice::GlobalContext *Ctx) {
36 ::Ice::X8664::TargetX8664::staticInit(Ctx); 37 ::Ice::X8664::TargetX8664::staticInit(Ctx);
37 } 38 }
38 } // end of namespace X8664 39 } // end of namespace X8664
39 40
40 namespace Ice { 41 namespace Ice {
41 namespace X8664 { 42 namespace X8664 {
42 43
(...skipping 497 matching lines...) Expand 10 before | Expand all | Expand 10 after
540 const SizeT BundleSize = 541 const SizeT BundleSize =
541 1 << Func->getAssembler<>()->getBundleAlignLog2Bytes(); 542 1 << Func->getAssembler<>()->getBundleAlignLog2Bytes();
542 _and(T_ecx, Ctx->getConstantInt32(~(BundleSize - 1))); 543 _and(T_ecx, Ctx->getConstantInt32(~(BundleSize - 1)));
543 Context.insert<InstFakeDef>(T_rcx, T_ecx); 544 Context.insert<InstFakeDef>(T_rcx, T_ecx);
544 _add(T_rcx, r15); 545 _add(T_rcx, r15);
545 546
546 _jmp(T_rcx); 547 _jmp(T_rcx);
547 } 548 }
548 } 549 }
549 550
550 void TargetX8664::emitJumpTable(const Cfg *Func,
551 const InstJumpTable *JumpTable) const {
552 if (!BuildDefs::dump())
553 return;
554 Ostream &Str = Ctx->getStrEmit();
555 IceString MangledName = Ctx->mangleName(Func->getFunctionName());
556 Str << "\t.section\t.rodata." << MangledName
557 << "$jumptable,\"a\",@progbits\n";
558 Str << "\t.align\t" << typeWidthInBytes(getPointerType()) << "\n";
559 Str << InstJumpTable::makeName(MangledName, JumpTable->getId()) << ":";
560
561 // On X8664 ILP32 pointers are 32-bit hence the use of .long
562 for (SizeT I = 0; I < JumpTable->getNumTargets(); ++I)
563 Str << "\n\t.long\t" << JumpTable->getTarget(I)->getAsmName();
564 Str << "\n";
565 }
566
567 namespace {
568 template <typename T> struct PoolTypeConverter {};
569
570 template <> struct PoolTypeConverter<float> {
571 using PrimitiveIntType = uint32_t;
572 using IceType = ConstantFloat;
573 static const Type Ty = IceType_f32;
574 static const char *TypeName;
575 static const char *AsmTag;
576 static const char *PrintfString;
577 };
578 const char *PoolTypeConverter<float>::TypeName = "float";
579 const char *PoolTypeConverter<float>::AsmTag = ".long";
580 const char *PoolTypeConverter<float>::PrintfString = "0x%x";
581
582 template <> struct PoolTypeConverter<double> {
583 using PrimitiveIntType = uint64_t;
584 using IceType = ConstantDouble;
585 static const Type Ty = IceType_f64;
586 static const char *TypeName;
587 static const char *AsmTag;
588 static const char *PrintfString;
589 };
590 const char *PoolTypeConverter<double>::TypeName = "double";
591 const char *PoolTypeConverter<double>::AsmTag = ".quad";
592 const char *PoolTypeConverter<double>::PrintfString = "0x%llx";
593
594 // Add converter for int type constant pooling
595 template <> struct PoolTypeConverter<uint32_t> {
596 using PrimitiveIntType = uint32_t;
597 using IceType = ConstantInteger32;
598 static const Type Ty = IceType_i32;
599 static const char *TypeName;
600 static const char *AsmTag;
601 static const char *PrintfString;
602 };
603 const char *PoolTypeConverter<uint32_t>::TypeName = "i32";
604 const char *PoolTypeConverter<uint32_t>::AsmTag = ".long";
605 const char *PoolTypeConverter<uint32_t>::PrintfString = "0x%x";
606
607 // Add converter for int type constant pooling
608 template <> struct PoolTypeConverter<uint16_t> {
609 using PrimitiveIntType = uint32_t;
610 using IceType = ConstantInteger32;
611 static const Type Ty = IceType_i16;
612 static const char *TypeName;
613 static const char *AsmTag;
614 static const char *PrintfString;
615 };
616 const char *PoolTypeConverter<uint16_t>::TypeName = "i16";
617 const char *PoolTypeConverter<uint16_t>::AsmTag = ".short";
618 const char *PoolTypeConverter<uint16_t>::PrintfString = "0x%x";
619
620 // Add converter for int type constant pooling
621 template <> struct PoolTypeConverter<uint8_t> {
622 using PrimitiveIntType = uint32_t;
623 using IceType = ConstantInteger32;
624 static const Type Ty = IceType_i8;
625 static const char *TypeName;
626 static const char *AsmTag;
627 static const char *PrintfString;
628 };
629 const char *PoolTypeConverter<uint8_t>::TypeName = "i8";
630 const char *PoolTypeConverter<uint8_t>::AsmTag = ".byte";
631 const char *PoolTypeConverter<uint8_t>::PrintfString = "0x%x";
632 } // end of anonymous namespace
633
634 template <typename T>
635 void TargetDataX8664::emitConstantPool(GlobalContext *Ctx) {
636 if (!BuildDefs::dump())
637 return;
638 Ostream &Str = Ctx->getStrEmit();
639 Type Ty = T::Ty;
640 SizeT Align = typeAlignInBytes(Ty);
641 ConstantList Pool = Ctx->getConstantPool(Ty);
642
643 Str << "\t.section\t.rodata.cst" << Align << ",\"aM\",@progbits," << Align
644 << "\n";
645 Str << "\t.align\t" << Align << "\n";
646
647 // If reorder-pooled-constants option is set to true, we need to shuffle the
648 // constant pool before emitting it.
649 if (Ctx->getFlags().shouldReorderPooledConstants()) {
650 // Use the constant's kind value as the salt for creating random number
651 // generator.
652 Operand::OperandKind K = (*Pool.begin())->getKind();
653 RandomNumberGenerator RNG(Ctx->getFlags().getRandomSeed(),
654 RPE_PooledConstantReordering, K);
655 RandomShuffle(Pool.begin(), Pool.end(),
656 [&RNG](uint64_t N) { return (uint32_t)RNG.next(N); });
657 }
658
659 for (Constant *C : Pool) {
660 if (!C->getShouldBePooled())
661 continue;
662 auto *Const = llvm::cast<typename T::IceType>(C);
663 typename T::IceType::PrimType Value = Const->getValue();
664 // Use memcpy() to copy bits from Value into RawValue in a way that avoids
665 // breaking strict-aliasing rules.
666 typename T::PrimitiveIntType RawValue;
667 memcpy(&RawValue, &Value, sizeof(Value));
668 char buf[30];
669 int CharsPrinted =
670 snprintf(buf, llvm::array_lengthof(buf), T::PrintfString, RawValue);
671 assert(CharsPrinted >= 0 &&
672 (size_t)CharsPrinted < llvm::array_lengthof(buf));
673 (void)CharsPrinted; // avoid warnings if asserts are disabled
674 Const->emitPoolLabel(Str, Ctx);
675 Str << ":\n\t" << T::AsmTag << "\t" << buf << "\t/* " << T::TypeName << " "
676 << Value << " */\n";
677 }
678 }
679
680 void TargetDataX8664::lowerConstants() {
681 if (Ctx->getFlags().getDisableTranslation())
682 return;
683 // No need to emit constants from the int pool since (for x86) they are
684 // embedded as immediates in the instructions, just emit float/double.
685 switch (Ctx->getFlags().getOutFileType()) {
686 case FT_Elf: {
687 ELFObjectWriter *Writer = Ctx->getObjectWriter();
688
689 Writer->writeConstantPool<ConstantInteger32>(IceType_i8);
690 Writer->writeConstantPool<ConstantInteger32>(IceType_i16);
691 Writer->writeConstantPool<ConstantInteger32>(IceType_i32);
692
693 Writer->writeConstantPool<ConstantFloat>(IceType_f32);
694 Writer->writeConstantPool<ConstantDouble>(IceType_f64);
695 } break;
696 case FT_Asm:
697 case FT_Iasm: {
698 OstreamLocker L(Ctx);
699
700 emitConstantPool<PoolTypeConverter<uint8_t>>(Ctx);
701 emitConstantPool<PoolTypeConverter<uint16_t>>(Ctx);
702 emitConstantPool<PoolTypeConverter<uint32_t>>(Ctx);
703
704 emitConstantPool<PoolTypeConverter<float>>(Ctx);
705 emitConstantPool<PoolTypeConverter<double>>(Ctx);
706 } break;
707 }
708 }
709
710 void TargetDataX8664::lowerJumpTables() {
711 const bool IsPIC = Ctx->getFlags().getUseNonsfi();
712 switch (Ctx->getFlags().getOutFileType()) {
713 case FT_Elf: {
714 ELFObjectWriter *Writer = Ctx->getObjectWriter();
715 for (const JumpTableData &JumpTable : Ctx->getJumpTables())
716 Writer->writeJumpTable(JumpTable, TargetX8664::Traits::FK_Abs, IsPIC);
717 } break;
718 case FT_Asm:
719 // Already emitted from Cfg
720 break;
721 case FT_Iasm: {
722 if (!BuildDefs::dump())
723 return;
724 Ostream &Str = Ctx->getStrEmit();
725 for (const JumpTableData &JT : Ctx->getJumpTables()) {
726 Str << "\t.section\t.rodata." << JT.getFunctionName()
727 << "$jumptable,\"a\",@progbits\n";
728 Str << "\t.align\t" << typeWidthInBytes(getPointerType()) << "\n";
729 Str << InstJumpTable::makeName(JT.getFunctionName(), JT.getId()) << ":";
730
731 // On X8664 ILP32 pointers are 32-bit hence the use of .long
732 for (intptr_t TargetOffset : JT.getTargetOffsets())
733 Str << "\n\t.long\t" << JT.getFunctionName() << "+" << TargetOffset;
734 Str << "\n";
735 }
736 } break;
737 }
738 }
739
740 void TargetDataX8664::lowerGlobals(const VariableDeclarationList &Vars,
741 const IceString &SectionSuffix) {
742 const bool IsPIC = Ctx->getFlags().getUseNonsfi();
743 switch (Ctx->getFlags().getOutFileType()) {
744 case FT_Elf: {
745 ELFObjectWriter *Writer = Ctx->getObjectWriter();
746 Writer->writeDataSection(Vars, TargetX8664::Traits::FK_Abs, SectionSuffix,
747 IsPIC);
748 } break;
749 case FT_Asm:
750 case FT_Iasm: {
751 const IceString &TranslateOnly = Ctx->getFlags().getTranslateOnly();
752 OstreamLocker L(Ctx);
753 for (const VariableDeclaration *Var : Vars) {
754 if (GlobalContext::matchSymbolName(Var->getName(), TranslateOnly)) {
755 emitGlobal(*Var, SectionSuffix);
756 }
757 }
758 } break;
759 }
760 }
761
762 // In some cases, there are x-macros tables for both high-level and low-level 551 // In some cases, there are x-macros tables for both high-level and low-level
763 // instructions/operands that use the same enum key value. The tables are kept 552 // instructions/operands that use the same enum key value. The tables are kept
764 // separate to maintain a proper separation between abstraction layers. There 553 // separate to maintain a proper separation between abstraction layers. There
765 // is a risk that the tables could get out of sync if enum values are reordered 554 // is a risk that the tables could get out of sync if enum values are reordered
766 // or if entries are added or deleted. The following dummy namespaces use 555 // or if entries are added or deleted. The following dummy namespaces use
767 // static_asserts to ensure everything is kept in sync. 556 // static_asserts to ensure everything is kept in sync.
768 557
769 namespace { 558 namespace {
770 // Validate the enum values in FCMPX8664_TABLE. 559 // Validate the enum values in FCMPX8664_TABLE.
771 namespace dummy1 { 560 namespace dummy1 {
(...skipping 86 matching lines...) Expand 10 before | Expand all | Expand 10 after
858 #define X(tag, sizeLog2, align, elts, elty, str) \ 647 #define X(tag, sizeLog2, align, elts, elty, str) \
859 static_assert(_table1_##tag == _table2_##tag, \ 648 static_assert(_table1_##tag == _table2_##tag, \
860 "Inconsistency between ICETYPEX8664_TABLE and ICETYPE_TABLE"); 649 "Inconsistency between ICETYPEX8664_TABLE and ICETYPE_TABLE");
861 ICETYPE_TABLE 650 ICETYPE_TABLE
862 #undef X 651 #undef X
863 } // end of namespace dummy3 652 } // end of namespace dummy3
864 } // end of anonymous namespace 653 } // end of anonymous namespace
865 654
866 } // end of namespace X8664 655 } // end of namespace X8664
867 } // end of namespace Ice 656 } // end of namespace Ice
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698