OLD | NEW |
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 413 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
424 if (Arg->hasReg()) { | 424 if (Arg->hasReg()) { |
425 assert(Ty != IceType_i64); | 425 assert(Ty != IceType_i64); |
426 OperandX8632Mem *Mem = OperandX8632Mem::create( | 426 OperandX8632Mem *Mem = OperandX8632Mem::create( |
427 Func, Ty, FramePtr, | 427 Func, Ty, FramePtr, |
428 Ctx->getConstantInt(IceType_i32, Arg->getStackOffset())); | 428 Ctx->getConstantInt(IceType_i32, Arg->getStackOffset())); |
429 _mov(Arg, Mem); | 429 _mov(Arg, Mem); |
430 } | 430 } |
431 InArgsSizeBytes += typeWidthInBytesOnStack(Ty); | 431 InArgsSizeBytes += typeWidthInBytesOnStack(Ty); |
432 } | 432 } |
433 | 433 |
| 434 // static |
| 435 Type TargetX8632::stackSlotType() { return IceType_i32; } |
| 436 |
434 void TargetX8632::addProlog(CfgNode *Node) { | 437 void TargetX8632::addProlog(CfgNode *Node) { |
435 // If SimpleCoalescing is false, each variable without a register | 438 // If SimpleCoalescing is false, each variable without a register |
436 // gets its own unique stack slot, which leads to large stack | 439 // gets its own unique stack slot, which leads to large stack |
437 // frames. If SimpleCoalescing is true, then each "global" variable | 440 // frames. If SimpleCoalescing is true, then each "global" variable |
438 // without a register gets its own slot, but "local" variable slots | 441 // without a register gets its own slot, but "local" variable slots |
439 // are reused across basic blocks. E.g., if A and B are local to | 442 // are reused across basic blocks. E.g., if A and B are local to |
440 // block 1 and C is local to block 2, then C may share a slot with A | 443 // block 1 and C is local to block 2, then C may share a slot with A |
441 // or B. | 444 // or B. |
442 const bool SimpleCoalescing = true; | 445 const bool SimpleCoalescing = true; |
443 size_t InArgsSizeBytes = 0; | 446 size_t InArgsSizeBytes = 0; |
(...skipping 309 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
753 split64(Var); | 756 split64(Var); |
754 return Var->getLo(); | 757 return Var->getLo(); |
755 } | 758 } |
756 if (ConstantInteger *Const = llvm::dyn_cast<ConstantInteger>(Operand)) { | 759 if (ConstantInteger *Const = llvm::dyn_cast<ConstantInteger>(Operand)) { |
757 uint64_t Mask = (1ull << 32) - 1; | 760 uint64_t Mask = (1ull << 32) - 1; |
758 return Ctx->getConstantInt(IceType_i32, Const->getValue() & Mask); | 761 return Ctx->getConstantInt(IceType_i32, Const->getValue() & Mask); |
759 } | 762 } |
760 if (OperandX8632Mem *Mem = llvm::dyn_cast<OperandX8632Mem>(Operand)) { | 763 if (OperandX8632Mem *Mem = llvm::dyn_cast<OperandX8632Mem>(Operand)) { |
761 return OperandX8632Mem::create(Func, IceType_i32, Mem->getBase(), | 764 return OperandX8632Mem::create(Func, IceType_i32, Mem->getBase(), |
762 Mem->getOffset(), Mem->getIndex(), | 765 Mem->getOffset(), Mem->getIndex(), |
763 Mem->getShift()); | 766 Mem->getShift(), Mem->getSegmentRegister()); |
764 } | 767 } |
765 llvm_unreachable("Unsupported operand type"); | 768 llvm_unreachable("Unsupported operand type"); |
766 return NULL; | 769 return NULL; |
767 } | 770 } |
768 | 771 |
769 Operand *TargetX8632::hiOperand(Operand *Operand) { | 772 Operand *TargetX8632::hiOperand(Operand *Operand) { |
770 assert(Operand->getType() == IceType_i64); | 773 assert(Operand->getType() == IceType_i64); |
771 if (Operand->getType() != IceType_i64) | 774 if (Operand->getType() != IceType_i64) |
772 return Operand; | 775 return Operand; |
773 if (Variable *Var = llvm::dyn_cast<Variable>(Operand)) { | 776 if (Variable *Var = llvm::dyn_cast<Variable>(Operand)) { |
774 split64(Var); | 777 split64(Var); |
775 return Var->getHi(); | 778 return Var->getHi(); |
776 } | 779 } |
777 if (ConstantInteger *Const = llvm::dyn_cast<ConstantInteger>(Operand)) { | 780 if (ConstantInteger *Const = llvm::dyn_cast<ConstantInteger>(Operand)) { |
778 return Ctx->getConstantInt(IceType_i32, Const->getValue() >> 32); | 781 return Ctx->getConstantInt(IceType_i32, Const->getValue() >> 32); |
779 } | 782 } |
780 if (OperandX8632Mem *Mem = llvm::dyn_cast<OperandX8632Mem>(Operand)) { | 783 if (OperandX8632Mem *Mem = llvm::dyn_cast<OperandX8632Mem>(Operand)) { |
781 Constant *Offset = Mem->getOffset(); | 784 Constant *Offset = Mem->getOffset(); |
782 if (Offset == NULL) | 785 if (Offset == NULL) |
783 Offset = Ctx->getConstantInt(IceType_i32, 4); | 786 Offset = Ctx->getConstantInt(IceType_i32, 4); |
784 else if (ConstantInteger *IntOffset = | 787 else if (ConstantInteger *IntOffset = |
785 llvm::dyn_cast<ConstantInteger>(Offset)) { | 788 llvm::dyn_cast<ConstantInteger>(Offset)) { |
786 Offset = Ctx->getConstantInt(IceType_i32, 4 + IntOffset->getValue()); | 789 Offset = Ctx->getConstantInt(IceType_i32, 4 + IntOffset->getValue()); |
787 } else if (ConstantRelocatable *SymOffset = | 790 } else if (ConstantRelocatable *SymOffset = |
788 llvm::dyn_cast<ConstantRelocatable>(Offset)) { | 791 llvm::dyn_cast<ConstantRelocatable>(Offset)) { |
789 Offset = Ctx->getConstantSym(IceType_i32, 4 + SymOffset->getOffset(), | 792 Offset = Ctx->getConstantSym(IceType_i32, 4 + SymOffset->getOffset(), |
790 SymOffset->getName()); | 793 SymOffset->getName()); |
791 } | 794 } |
792 return OperandX8632Mem::create(Func, IceType_i32, Mem->getBase(), Offset, | 795 return OperandX8632Mem::create(Func, IceType_i32, Mem->getBase(), Offset, |
793 Mem->getIndex(), Mem->getShift()); | 796 Mem->getIndex(), Mem->getShift(), |
| 797 Mem->getSegmentRegister()); |
794 } | 798 } |
795 llvm_unreachable("Unsupported operand type"); | 799 llvm_unreachable("Unsupported operand type"); |
796 return NULL; | 800 return NULL; |
797 } | 801 } |
798 | 802 |
799 llvm::SmallBitVector TargetX8632::getRegisterSet(RegSetMask Include, | 803 llvm::SmallBitVector TargetX8632::getRegisterSet(RegSetMask Include, |
800 RegSetMask Exclude) const { | 804 RegSetMask Exclude) const { |
801 llvm::SmallBitVector Registers(Reg_NUM); | 805 llvm::SmallBitVector Registers(Reg_NUM); |
802 | 806 |
803 #define X(val, init, name, name16, name8, scratch, preserved, stackptr, \ | 807 #define X(val, init, name, name16, name8, scratch, preserved, stackptr, \ |
(...skipping 963 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1767 legalize(Src0, IsSrc1ImmOrReg ? Legal_All : Legal_Reg, true); | 1771 legalize(Src0, IsSrc1ImmOrReg ? Legal_All : Legal_Reg, true); |
1768 InstX8632Label *Label = InstX8632Label::create(Func, this); | 1772 InstX8632Label *Label = InstX8632Label::create(Func, this); |
1769 _cmp(Src0New, Src1); | 1773 _cmp(Src0New, Src1); |
1770 _mov(Dest, One); | 1774 _mov(Dest, One); |
1771 _br(getIcmp32Mapping(Inst->getCondition()), Label); | 1775 _br(getIcmp32Mapping(Inst->getCondition()), Label); |
1772 Context.insert(InstFakeUse::create(Func, Dest)); | 1776 Context.insert(InstFakeUse::create(Func, Dest)); |
1773 _mov(Dest, Zero); | 1777 _mov(Dest, Zero); |
1774 Context.insert(Label); | 1778 Context.insert(Label); |
1775 } | 1779 } |
1776 | 1780 |
| 1781 void TargetX8632::lowerIntrinsicCall(const InstIntrinsicCall *Instr) { |
| 1782 switch (Instr->getIntrinsicInfo().ID) { |
| 1783 case Intrinsics::AtomicCmpxchg: |
| 1784 case Intrinsics::AtomicFence: |
| 1785 case Intrinsics::AtomicFenceAll: |
| 1786 case Intrinsics::AtomicIsLockFree: |
| 1787 case Intrinsics::AtomicLoad: |
| 1788 case Intrinsics::AtomicRMW: |
| 1789 case Intrinsics::AtomicStore: |
| 1790 case Intrinsics::Bswap: |
| 1791 case Intrinsics::Ctlz: |
| 1792 case Intrinsics::Ctpop: |
| 1793 case Intrinsics::Cttz: |
| 1794 Func->setError("Unhandled intrinsic"); |
| 1795 return; |
| 1796 case Intrinsics::Longjmp: { |
| 1797 InstCall *Call = makeHelperCall("longjmp", NULL, 2); |
| 1798 Call->addArg(Instr->getArg(0)); |
| 1799 Call->addArg(Instr->getArg(1)); |
| 1800 lowerCall(Call); |
| 1801 break; |
| 1802 } |
| 1803 case Intrinsics::Memcpy: { |
| 1804 // In the future, we could potentially emit an inline memcpy/memset, etc. |
| 1805 // for intrinsic calls w/ a known length. |
| 1806 InstCall *Call = makeHelperCall("memcpy", NULL, 3); |
| 1807 Call->addArg(Instr->getArg(0)); |
| 1808 Call->addArg(Instr->getArg(1)); |
| 1809 Call->addArg(Instr->getArg(2)); |
| 1810 lowerCall(Call); |
| 1811 break; |
| 1812 } |
| 1813 case Intrinsics::Memmove: { |
| 1814 InstCall *Call = makeHelperCall("memmove", NULL, 3); |
| 1815 Call->addArg(Instr->getArg(0)); |
| 1816 Call->addArg(Instr->getArg(1)); |
| 1817 Call->addArg(Instr->getArg(2)); |
| 1818 lowerCall(Call); |
| 1819 break; |
| 1820 } |
| 1821 case Intrinsics::Memset: { |
| 1822 // The value operand needs to be extended to a stack slot size |
| 1823 // because we "push" only works for a specific operand size. |
| 1824 Operand *ValOp = Instr->getArg(1); |
| 1825 assert(ValOp->getType() == IceType_i8); |
| 1826 Variable *ValExt = makeReg(stackSlotType()); |
| 1827 _movzx(ValExt, ValOp); |
| 1828 InstCall *Call = makeHelperCall("memset", NULL, 3); |
| 1829 Call->addArg(Instr->getArg(0)); |
| 1830 Call->addArg(ValExt); |
| 1831 Call->addArg(Instr->getArg(2)); |
| 1832 lowerCall(Call); |
| 1833 break; |
| 1834 } |
| 1835 case Intrinsics::NaClReadTP: { |
| 1836 Constant *Zero = Ctx->getConstantInt(IceType_i32, 0); |
| 1837 Operand *Src = OperandX8632Mem::create(Func, IceType_i32, NULL, Zero, NULL, |
| 1838 0, OperandX8632Mem::SegReg_GS); |
| 1839 Variable *Dest = Instr->getDest(); |
| 1840 Variable *T = NULL; |
| 1841 _mov(T, Src); |
| 1842 _mov(Dest, T); |
| 1843 break; |
| 1844 } |
| 1845 case Intrinsics::Setjmp: { |
| 1846 InstCall *Call = makeHelperCall("setjmp", Instr->getDest(), 1); |
| 1847 Call->addArg(Instr->getArg(0)); |
| 1848 lowerCall(Call); |
| 1849 break; |
| 1850 } |
| 1851 case Intrinsics::Sqrt: |
| 1852 case Intrinsics::Stacksave: |
| 1853 case Intrinsics::Stackrestore: |
| 1854 Func->setError("Unhandled intrinsic"); |
| 1855 return; |
| 1856 case Intrinsics::Trap: |
| 1857 _ud2(); |
| 1858 break; |
| 1859 case Intrinsics::UnknownIntrinsic: |
| 1860 Func->setError("Should not be lowering UnknownIntrinsic"); |
| 1861 return; |
| 1862 } |
| 1863 return; |
| 1864 } |
| 1865 |
1777 namespace { | 1866 namespace { |
1778 | 1867 |
1779 bool isAdd(const Inst *Inst) { | 1868 bool isAdd(const Inst *Inst) { |
1780 if (const InstArithmetic *Arith = | 1869 if (const InstArithmetic *Arith = |
1781 llvm::dyn_cast_or_null<const InstArithmetic>(Inst)) { | 1870 llvm::dyn_cast_or_null<const InstArithmetic>(Inst)) { |
1782 return (Arith->getOp() == InstArithmetic::Add); | 1871 return (Arith->getOp() == InstArithmetic::Add); |
1783 } | 1872 } |
1784 return false; | 1873 return false; |
1785 } | 1874 } |
1786 | 1875 |
1787 void computeAddressOpt(Variable *&Base, Variable *&Index, int32_t &Shift, | 1876 void computeAddressOpt(Variable *&Base, Variable *&Index, uint16_t &Shift, |
1788 int32_t &Offset) { | 1877 int32_t &Offset) { |
1789 (void)Offset; // TODO: pattern-match for non-zero offsets. | 1878 (void)Offset; // TODO: pattern-match for non-zero offsets. |
1790 if (Base == NULL) | 1879 if (Base == NULL) |
1791 return; | 1880 return; |
1792 // If the Base has more than one use or is live across multiple | 1881 // If the Base has more than one use or is live across multiple |
1793 // blocks, then don't go further. Alternatively (?), never consider | 1882 // blocks, then don't go further. Alternatively (?), never consider |
1794 // a transformation that would change a variable that is currently | 1883 // a transformation that would change a variable that is currently |
1795 // *not* live across basic block boundaries into one that *is*. | 1884 // *not* live across basic block boundaries into one that *is*. |
1796 if (Base->isMultiblockLife() /* || Base->getUseCount() > 1*/) | 1885 if (Base->isMultiblockLife() /* || Base->getUseCount() > 1*/) |
1797 return; | 1886 return; |
(...skipping 160 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1958 | 2047 |
1959 InstAssign *Assign = InstAssign::create(Func, Inst->getDest(), Src0); | 2048 InstAssign *Assign = InstAssign::create(Func, Inst->getDest(), Src0); |
1960 lowerAssign(Assign); | 2049 lowerAssign(Assign); |
1961 } | 2050 } |
1962 | 2051 |
1963 void TargetX8632::doAddressOptLoad() { | 2052 void TargetX8632::doAddressOptLoad() { |
1964 Inst *Inst = *Context.getCur(); | 2053 Inst *Inst = *Context.getCur(); |
1965 Variable *Dest = Inst->getDest(); | 2054 Variable *Dest = Inst->getDest(); |
1966 Operand *Addr = Inst->getSrc(0); | 2055 Operand *Addr = Inst->getSrc(0); |
1967 Variable *Index = NULL; | 2056 Variable *Index = NULL; |
1968 int32_t Shift = 0; | 2057 uint16_t Shift = 0; |
1969 int32_t Offset = 0; // TODO: make Constant | 2058 int32_t Offset = 0; // TODO: make Constant |
| 2059 // Vanilla ICE load instructions should not use the segment registers, |
| 2060 // and computeAddressOpt only works at the level of Variables and Constants, |
| 2061 // not other OperandX8632Mem, so there should be no mention of segment |
| 2062 // registers there either. |
| 2063 const OperandX8632Mem::SegmentRegisters SegmentReg = |
| 2064 OperandX8632Mem::DefaultSegment; |
1970 Variable *Base = llvm::dyn_cast<Variable>(Addr); | 2065 Variable *Base = llvm::dyn_cast<Variable>(Addr); |
1971 computeAddressOpt(Base, Index, Shift, Offset); | 2066 computeAddressOpt(Base, Index, Shift, Offset); |
1972 if (Base && Addr != Base) { | 2067 if (Base && Addr != Base) { |
1973 Constant *OffsetOp = Ctx->getConstantInt(IceType_i32, Offset); | 2068 Constant *OffsetOp = Ctx->getConstantInt(IceType_i32, Offset); |
1974 Addr = OperandX8632Mem::create(Func, Dest->getType(), Base, OffsetOp, Index, | 2069 Addr = OperandX8632Mem::create(Func, Dest->getType(), Base, OffsetOp, Index, |
1975 Shift); | 2070 Shift, SegmentReg); |
1976 Inst->setDeleted(); | 2071 Inst->setDeleted(); |
1977 Context.insert(InstLoad::create(Func, Dest, Addr)); | 2072 Context.insert(InstLoad::create(Func, Dest, Addr)); |
1978 } | 2073 } |
1979 } | 2074 } |
1980 | 2075 |
1981 void TargetX8632::lowerPhi(const InstPhi * /*Inst*/) { | 2076 void TargetX8632::lowerPhi(const InstPhi * /*Inst*/) { |
1982 Func->setError("Phi found in regular instruction list"); | 2077 Func->setError("Phi found in regular instruction list"); |
1983 } | 2078 } |
1984 | 2079 |
1985 void TargetX8632::lowerRet(const InstRet *Inst) { | 2080 void TargetX8632::lowerRet(const InstRet *Inst) { |
(...skipping 88 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2074 Value = legalize(Value, Legal_Reg | Legal_Imm, true); | 2169 Value = legalize(Value, Legal_Reg | Legal_Imm, true); |
2075 _store(Value, NewAddr); | 2170 _store(Value, NewAddr); |
2076 } | 2171 } |
2077 } | 2172 } |
2078 | 2173 |
2079 void TargetX8632::doAddressOptStore() { | 2174 void TargetX8632::doAddressOptStore() { |
2080 InstStore *Inst = llvm::cast<InstStore>(*Context.getCur()); | 2175 InstStore *Inst = llvm::cast<InstStore>(*Context.getCur()); |
2081 Operand *Data = Inst->getData(); | 2176 Operand *Data = Inst->getData(); |
2082 Operand *Addr = Inst->getAddr(); | 2177 Operand *Addr = Inst->getAddr(); |
2083 Variable *Index = NULL; | 2178 Variable *Index = NULL; |
2084 int32_t Shift = 0; | 2179 uint16_t Shift = 0; |
2085 int32_t Offset = 0; // TODO: make Constant | 2180 int32_t Offset = 0; // TODO: make Constant |
2086 Variable *Base = llvm::dyn_cast<Variable>(Addr); | 2181 Variable *Base = llvm::dyn_cast<Variable>(Addr); |
| 2182 // Vanilla ICE store instructions should not use the segment registers, |
| 2183 // and computeAddressOpt only works at the level of Variables and Constants, |
| 2184 // not other OperandX8632Mem, so there should be no mention of segment |
| 2185 // registers there either. |
| 2186 const OperandX8632Mem::SegmentRegisters SegmentReg = |
| 2187 OperandX8632Mem::DefaultSegment; |
2087 computeAddressOpt(Base, Index, Shift, Offset); | 2188 computeAddressOpt(Base, Index, Shift, Offset); |
2088 if (Base && Addr != Base) { | 2189 if (Base && Addr != Base) { |
2089 Constant *OffsetOp = Ctx->getConstantInt(IceType_i32, Offset); | 2190 Constant *OffsetOp = Ctx->getConstantInt(IceType_i32, Offset); |
2090 Addr = OperandX8632Mem::create(Func, Data->getType(), Base, OffsetOp, Index, | 2191 Addr = OperandX8632Mem::create(Func, Data->getType(), Base, OffsetOp, Index, |
2091 Shift); | 2192 Shift, SegmentReg); |
2092 Inst->setDeleted(); | 2193 Inst->setDeleted(); |
2093 Context.insert(InstStore::create(Func, Data, Addr)); | 2194 Context.insert(InstStore::create(Func, Data, Addr)); |
2094 } | 2195 } |
2095 } | 2196 } |
2096 | 2197 |
2097 void TargetX8632::lowerSwitch(const InstSwitch *Inst) { | 2198 void TargetX8632::lowerSwitch(const InstSwitch *Inst) { |
2098 // This implements the most naive possible lowering. | 2199 // This implements the most naive possible lowering. |
2099 // cmp a,val[0]; jeq label[0]; cmp a,val[1]; jeq label[1]; ... jmp default | 2200 // cmp a,val[0]; jeq label[0]; cmp a,val[1]; jeq label[1]; ... jmp default |
2100 Operand *Src0 = Inst->getComparison(); | 2201 Operand *Src0 = Inst->getComparison(); |
2101 SizeT NumCases = Inst->getNumCases(); | 2202 SizeT NumCases = Inst->getNumCases(); |
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2140 Variable *Index = Mem->getIndex(); | 2241 Variable *Index = Mem->getIndex(); |
2141 Variable *RegBase = NULL; | 2242 Variable *RegBase = NULL; |
2142 Variable *RegIndex = NULL; | 2243 Variable *RegIndex = NULL; |
2143 if (Base) { | 2244 if (Base) { |
2144 RegBase = legalizeToVar(Base, true); | 2245 RegBase = legalizeToVar(Base, true); |
2145 } | 2246 } |
2146 if (Index) { | 2247 if (Index) { |
2147 RegIndex = legalizeToVar(Index, true); | 2248 RegIndex = legalizeToVar(Index, true); |
2148 } | 2249 } |
2149 if (Base != RegBase || Index != RegIndex) { | 2250 if (Base != RegBase || Index != RegIndex) { |
2150 From = | 2251 From = OperandX8632Mem::create( |
2151 OperandX8632Mem::create(Func, Mem->getType(), RegBase, | 2252 Func, Mem->getType(), RegBase, Mem->getOffset(), RegIndex, |
2152 Mem->getOffset(), RegIndex, Mem->getShift()); | 2253 Mem->getShift(), Mem->getSegmentRegister()); |
2153 } | 2254 } |
2154 | 2255 |
2155 if (!(Allowed & Legal_Mem)) { | 2256 if (!(Allowed & Legal_Mem)) { |
2156 Variable *Reg = makeReg(From->getType(), RegNum); | 2257 Variable *Reg = makeReg(From->getType(), RegNum); |
2157 _mov(Reg, From, RegNum); | 2258 _mov(Reg, From, RegNum); |
2158 From = Reg; | 2259 From = Reg; |
2159 } | 2260 } |
2160 return From; | 2261 return From; |
2161 } | 2262 } |
2162 if (llvm::isa<Constant>(From)) { | 2263 if (llvm::isa<Constant>(From)) { |
(...skipping 124 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2287 // llvm-mc doesn't parse "dword ptr [.L$foo]". | 2388 // llvm-mc doesn't parse "dword ptr [.L$foo]". |
2288 Str << "dword ptr [L$" << IceType_f32 << "$" << getPoolEntryID() << "]"; | 2389 Str << "dword ptr [L$" << IceType_f32 << "$" << getPoolEntryID() << "]"; |
2289 } | 2390 } |
2290 | 2391 |
2291 template <> void ConstantDouble::emit(GlobalContext *Ctx) const { | 2392 template <> void ConstantDouble::emit(GlobalContext *Ctx) const { |
2292 Ostream &Str = Ctx->getStrEmit(); | 2393 Ostream &Str = Ctx->getStrEmit(); |
2293 Str << "qword ptr [L$" << IceType_f64 << "$" << getPoolEntryID() << "]"; | 2394 Str << "qword ptr [L$" << IceType_f64 << "$" << getPoolEntryID() << "]"; |
2294 } | 2395 } |
2295 | 2396 |
2296 } // end of namespace Ice | 2397 } // end of namespace Ice |
OLD | NEW |