Chromium Code Reviews| OLD | NEW |
|---|---|
| 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 /// This file implements the TargetLoweringX8664 class, which | 11 /// This file implements the TargetLoweringX8664 class, which |
| 12 /// consists almost entirely of the lowering sequence for each | 12 /// consists almost entirely of the lowering sequence for each |
| 13 /// high-level instruction. | 13 /// high-level instruction. |
| 14 /// | 14 /// |
| 15 //===----------------------------------------------------------------------===// | 15 //===----------------------------------------------------------------------===// |
| 16 | 16 |
| 17 #include "IceTargetLoweringX8664.h" | 17 #include "IceTargetLoweringX8664.h" |
| 18 | 18 |
| 19 #include "IceTargetLoweringX8664Traits.h" | 19 #include "IceTargetLoweringX8664Traits.h" |
| 20 #include "IceTargetLoweringX86Base.h" | 20 #include "IceTargetLoweringX86Base.h" |
| 21 | 21 |
| 22 namespace Ice { | 22 namespace Ice { |
| 23 | 23 |
| 24 //------------------------------------------------------------------------------ | |
| 25 // ______ ______ ______ __ ______ ______ | |
| 26 // /\__ _\ /\ == \ /\ __ \ /\ \ /\__ _\ /\ ___\ | |
| 27 // \/_/\ \/ \ \ __< \ \ __ \ \ \ \ \/_/\ \/ \ \___ \ | |
| 28 // \ \_\ \ \_\ \_\ \ \_\ \_\ \ \_\ \ \_\ \/\_____\ | |
| 29 // \/_/ \/_/ /_/ \/_/\/_/ \/_/ \/_/ \/_____/ | |
| 30 // | |
| 31 //------------------------------------------------------------------------------ | |
| 24 namespace X86Internal { | 32 namespace X86Internal { |
| 25 const MachineTraits<TargetX8664>::TableFcmpType | 33 const MachineTraits<TargetX8664>::TableFcmpType |
| 26 MachineTraits<TargetX8664>::TableFcmp[] = { | 34 MachineTraits<TargetX8664>::TableFcmp[] = { |
| 27 #define X(val, dflt, swapS, C1, C2, swapV, pred) \ | 35 #define X(val, dflt, swapS, C1, C2, swapV, pred) \ |
| 28 { \ | 36 { \ |
| 29 dflt, swapS, X8664::Traits::Cond::C1, X8664::Traits::Cond::C2, swapV, \ | 37 dflt, swapS, X8664::Traits::Cond::C1, X8664::Traits::Cond::C2, swapV, \ |
| 30 X8664::Traits::Cond::pred \ | 38 X8664::Traits::Cond::pred \ |
| 31 } \ | 39 } \ |
| 32 , | 40 , |
| 33 FCMPX8664_TABLE | 41 FCMPX8664_TABLE |
| (...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 74 }; | 82 }; |
| 75 | 83 |
| 76 const size_t MachineTraits<TargetX8664>::TableTypeX8664AttributesSize = | 84 const size_t MachineTraits<TargetX8664>::TableTypeX8664AttributesSize = |
| 77 llvm::array_lengthof(TableTypeX8664Attributes); | 85 llvm::array_lengthof(TableTypeX8664Attributes); |
| 78 | 86 |
| 79 const uint32_t MachineTraits<TargetX8664>::X86_STACK_ALIGNMENT_BYTES = 16; | 87 const uint32_t MachineTraits<TargetX8664>::X86_STACK_ALIGNMENT_BYTES = 16; |
| 80 const char *MachineTraits<TargetX8664>::TargetName = "X8664"; | 88 const char *MachineTraits<TargetX8664>::TargetName = "X8664"; |
| 81 | 89 |
| 82 } // end of namespace X86Internal | 90 } // end of namespace X86Internal |
| 83 | 91 |
| 92 //------------------------------------------------------------------------------ | |
| 93 // __ ______ __ __ ______ ______ __ __ __ ______ | |
| 94 // /\ \ /\ __ \/\ \ _ \ \/\ ___\/\ == \/\ \/\ "-.\ \/\ ___\ | |
| 95 // \ \ \___\ \ \/\ \ \ \/ ".\ \ \ __\\ \ __<\ \ \ \ \-. \ \ \__ \ | |
| 96 // \ \_____\ \_____\ \__/".~\_\ \_____\ \_\ \_\ \_\ \_\\"\_\ \_____\ | |
| 97 // \/_____/\/_____/\/_/ \/_/\/_____/\/_/ /_/\/_/\/_/ \/_/\/_____/ | |
| 98 // | |
| 99 //------------------------------------------------------------------------------ | |
| 100 namespace { | |
| 101 static inline TargetX8664::Traits::RegisterSet::AllRegisters | |
| 102 getRegisterForXmmArgNum(uint32_t ArgNum) { | |
| 103 assert(ArgNum < TargetX8664::Traits::X86_MAX_XMM_ARGS); | |
| 104 return static_cast<TargetX8664::Traits::RegisterSet::AllRegisters>( | |
| 105 TargetX8664::Traits::RegisterSet::Reg_xmm0 + ArgNum); | |
| 106 } | |
| 107 | |
| 108 static inline TargetX8664::Traits::RegisterSet::AllRegisters | |
| 109 getRegisterForGprArgNum(uint32_t ArgNum) { | |
| 110 assert(ArgNum < TargetX8664::Traits::X86_MAX_GPR_ARGS); | |
| 111 static const TargetX8664::Traits::RegisterSet::AllRegisters GprForArgNum[] = { | |
| 112 TargetX8664::Traits::RegisterSet::Reg_edi, | |
| 113 TargetX8664::Traits::RegisterSet::Reg_esi, | |
| 114 TargetX8664::Traits::RegisterSet::Reg_edx, | |
| 115 TargetX8664::Traits::RegisterSet::Reg_ecx, | |
| 116 TargetX8664::Traits::RegisterSet::Reg_r8d, | |
| 117 TargetX8664::Traits::RegisterSet::Reg_r9d, | |
| 118 }; | |
| 119 static_assert(llvm::array_lengthof(GprForArgNum) == | |
| 120 TargetX8664::TargetX8664::Traits::X86_MAX_GPR_ARGS, | |
| 121 "Mismtach between MAX_GPR_ARGS and GprForArgNum."); | |
|
jvoung (off chromium)
2015/07/31 23:53:49
"Mismatch"
John
2015/08/01 15:49:55
"Doen." :)
| |
| 122 return GprForArgNum[ArgNum]; | |
| 123 } | |
| 124 } | |
| 125 | |
| 126 void TargetX8664::lowerCall(const InstCall *Instr) { | |
| 127 // x86-64 calling convention: | |
| 128 // | |
| 129 // * At the point before the call, the stack must be aligned to 16 | |
| 130 // bytes. | |
| 131 // | |
| 132 // * The first eight arguments of vector/fp type, regardless of their | |
| 133 // position relative to the other arguments in the argument list, are | |
| 134 // placed in registers %xmm0 - %xmm7. | |
| 135 // | |
| 136 // * The first six arguments of integer types, regardless of their | |
| 137 // position relative to the other arguments in the argument list, are | |
| 138 // placed in registers %rdi, %rsi, %rdx, %rcx, %r8, and %r9. | |
| 139 // | |
| 140 // * Other arguments are pushed onto the stack in right-to-left order, | |
| 141 // such that the left-most argument ends up on the top of the stack at | |
| 142 // the lowest memory address. | |
| 143 // | |
| 144 // * Stack arguments of vector type are aligned to start at the next | |
| 145 // highest multiple of 16 bytes. Other stack arguments are aligned to | |
| 146 // 8 bytes. | |
| 147 // | |
| 148 // This intends to match the section "Function Calling Sequence" of the | |
| 149 // document "System V Application Binary Interface." | |
| 150 NeedsStackAlignment = true; | |
| 151 | |
| 152 using OperandList = std::vector<Operand *>; | |
|
jvoung (off chromium)
2015/08/03 17:04:55
Might be able to use "llvm::SmallVector<Operand *,
John
2015/08/05 16:53:03
Done.
| |
| 153 OperandList XmmArgs; | |
| 154 OperandList GprArgs; | |
| 155 OperandList StackArgs, StackArgLocations; | |
| 156 uint32_t ParameterAreaSizeBytes = 0; | |
| 157 | |
| 158 // Classify each argument operand according to the location where the | |
| 159 // argument is passed. | |
| 160 for (SizeT i = 0, NumArgs = Instr->getNumArgs(); i < NumArgs; ++i) { | |
| 161 Operand *Arg = Instr->getArg(i); | |
| 162 Type Ty = Arg->getType(); | |
| 163 // The PNaCl ABI requires the width of arguments to be at least 32 bits. | |
| 164 assert(typeWidthInBytes(Ty) >= 4); | |
| 165 if (isVectorType(Ty) && XmmArgs.size() < Traits::X86_MAX_XMM_ARGS) { | |
| 166 XmmArgs.push_back(Arg); | |
| 167 } else if (isScalarFloatingType(Ty) && | |
| 168 XmmArgs.size() < Traits::X86_MAX_XMM_ARGS) { | |
| 169 XmmArgs.push_back(Arg); | |
| 170 } else if (isScalarIntegerType(Ty) && | |
| 171 GprArgs.size() < Traits::X86_MAX_GPR_ARGS) { | |
| 172 GprArgs.push_back(Arg); | |
| 173 } else { | |
| 174 StackArgs.push_back(Arg); | |
| 175 if (isVectorType(Arg->getType())) { | |
| 176 ParameterAreaSizeBytes = | |
| 177 Traits::applyStackAlignment(ParameterAreaSizeBytes); | |
| 178 } | |
| 179 Variable *esp = getPhysicalRegister(Traits::RegisterSet::Reg_esp); | |
| 180 Constant *Loc = Ctx->getConstantInt32(ParameterAreaSizeBytes); | |
| 181 StackArgLocations.push_back( | |
| 182 Traits::X86OperandMem::create(Func, Ty, esp, Loc)); | |
| 183 ParameterAreaSizeBytes += typeWidthInBytesOnStack(Arg->getType()); | |
|
jvoung (off chromium)
2015/07/31 23:53:49
Is typeWidthInBytesOnStack defined differently for
John
2015/08/01 15:49:55
We could avoid the overhead, but if we want to be
jvoung (off chromium)
2015/08/03 17:04:55
Yes, my understanding is that the calling conventi
John
2015/08/05 16:53:03
Oh, now I see what you mean. :)
I added a TODO in
| |
| 184 } | |
| 185 } | |
| 186 | |
| 187 // Adjust the parameter area so that the stack is aligned. It is | |
| 188 // assumed that the stack is already aligned at the start of the | |
| 189 // calling sequence. | |
| 190 ParameterAreaSizeBytes = Traits::applyStackAlignment(ParameterAreaSizeBytes); | |
| 191 | |
| 192 // Subtract the appropriate amount for the argument area. This also | |
| 193 // takes care of setting the stack adjustment during emission. | |
| 194 // | |
| 195 // TODO: If for some reason the call instruction gets dead-code | |
| 196 // eliminated after lowering, we would need to ensure that the | |
| 197 // pre-call and the post-call esp adjustment get eliminated as well. | |
| 198 if (ParameterAreaSizeBytes) { | |
| 199 _adjust_stack(ParameterAreaSizeBytes); | |
| 200 } | |
| 201 | |
| 202 // Copy arguments that are passed on the stack to the appropriate | |
| 203 // stack locations. | |
| 204 for (SizeT i = 0, e = StackArgs.size(); i < e; ++i) { | |
| 205 lowerStore(InstStore::create(Func, StackArgs[i], StackArgLocations[i])); | |
| 206 } | |
| 207 | |
| 208 // Copy arguments to be passed in registers to the appropriate | |
| 209 // registers. | |
| 210 // TODO: Investigate the impact of lowering arguments passed in | |
| 211 // registers after lowering stack arguments as opposed to the other | |
| 212 // way around. Lowering register arguments after stack arguments may | |
| 213 // reduce register pressure. On the other hand, lowering register | |
| 214 // arguments first (before stack arguments) may result in more compact | |
| 215 // code, as the memory operand displacements may end up being smaller | |
| 216 // before any stack adjustment is done. | |
| 217 for (SizeT i = 0, NumXmmArgs = XmmArgs.size(); i < NumXmmArgs; ++i) { | |
| 218 Variable *Reg = legalizeToReg(XmmArgs[i], getRegisterForXmmArgNum(i)); | |
| 219 // Generate a FakeUse of register arguments so that they do not get | |
| 220 // dead code eliminated as a result of the FakeKill of scratch | |
| 221 // registers after the call. | |
| 222 Context.insert(InstFakeUse::create(Func, Reg)); | |
| 223 } | |
| 224 | |
| 225 for (SizeT i = 0, NumGprArgs = GprArgs.size(); i < NumGprArgs; ++i) { | |
| 226 Variable *Reg = legalizeToReg(GprArgs[i], getRegisterForGprArgNum(i)); | |
| 227 Context.insert(InstFakeUse::create(Func, Reg)); | |
| 228 } | |
| 229 | |
| 230 // Generate the call instruction. Assign its result to a temporary | |
| 231 // with high register allocation weight. | |
| 232 Variable *Dest = Instr->getDest(); | |
| 233 // ReturnReg doubles as ReturnRegLo as necessary. | |
| 234 Variable *ReturnReg = nullptr; | |
| 235 Variable *ReturnRegHi = nullptr; | |
| 236 if (Dest) { | |
| 237 switch (Dest->getType()) { | |
| 238 case IceType_NUM: | |
| 239 llvm_unreachable("Invalid Call dest type"); | |
| 240 break; | |
| 241 case IceType_void: | |
|
jvoung (off chromium)
2015/07/31 23:53:49
This is the same in the other targets, but it seem
Jim Stichnoth
2015/08/05 04:43:51
Yeah, I don't remember why it ended up this way, b
| |
| 242 break; | |
| 243 case IceType_i1: | |
| 244 case IceType_i8: | |
| 245 case IceType_i16: | |
| 246 case IceType_i32: | |
| 247 ReturnReg = makeReg(Dest->getType(), Traits::RegisterSet::Reg_eax); | |
| 248 break; | |
| 249 case IceType_i64: | |
| 250 // TODO(jpp): return i64 in a GPR. | |
| 251 ReturnReg = makeReg(IceType_i32, Traits::RegisterSet::Reg_eax); | |
| 252 ReturnRegHi = makeReg(IceType_i32, Traits::RegisterSet::Reg_edx); | |
| 253 break; | |
| 254 case IceType_f32: | |
| 255 case IceType_f64: | |
| 256 case IceType_v4i1: | |
| 257 case IceType_v8i1: | |
| 258 case IceType_v16i1: | |
| 259 case IceType_v16i8: | |
| 260 case IceType_v8i16: | |
| 261 case IceType_v4i32: | |
| 262 case IceType_v4f32: | |
| 263 ReturnReg = makeReg(Dest->getType(), Traits::RegisterSet::Reg_xmm0); | |
| 264 break; | |
| 265 } | |
| 266 } | |
| 267 | |
| 268 Operand *CallTarget = legalize(Instr->getCallTarget()); | |
| 269 const bool NeedSandboxing = Ctx->getFlags().getUseSandboxing(); | |
| 270 if (NeedSandboxing) { | |
| 271 if (llvm::isa<Constant>(CallTarget)) { | |
| 272 _bundle_lock(InstBundleLock::Opt_AlignToEnd); | |
| 273 } else { | |
| 274 Variable *CallTargetVar = nullptr; | |
| 275 _mov(CallTargetVar, CallTarget); | |
| 276 _bundle_lock(InstBundleLock::Opt_AlignToEnd); | |
| 277 const SizeT BundleSize = | |
| 278 1 << Func->getAssembler<>()->getBundleAlignLog2Bytes(); | |
| 279 _and(CallTargetVar, Ctx->getConstantInt32(~(BundleSize - 1))); | |
| 280 CallTarget = CallTargetVar; | |
| 281 } | |
| 282 } | |
| 283 Inst *NewCall = Traits::Insts::Call::create(Func, ReturnReg, CallTarget); | |
| 284 Context.insert(NewCall); | |
| 285 if (NeedSandboxing) | |
| 286 _bundle_unlock(); | |
| 287 if (ReturnRegHi) | |
| 288 Context.insert(InstFakeDef::create(Func, ReturnRegHi)); | |
| 289 | |
| 290 // Add the appropriate offset to esp. The call instruction takes care | |
| 291 // of resetting the stack offset during emission. | |
| 292 if (ParameterAreaSizeBytes) { | |
| 293 Variable *Esp = | |
| 294 Func->getTarget()->getPhysicalRegister(Traits::RegisterSet::Reg_esp); | |
| 295 _add(Esp, Ctx->getConstantInt32(ParameterAreaSizeBytes)); | |
| 296 } | |
| 297 | |
| 298 // Insert a register-kill pseudo instruction. | |
| 299 Context.insert(InstFakeKill::create(Func, NewCall)); | |
| 300 | |
| 301 // Generate a FakeUse to keep the call live if necessary. | |
| 302 if (Instr->hasSideEffects() && ReturnReg) { | |
| 303 Inst *FakeUse = InstFakeUse::create(Func, ReturnReg); | |
| 304 Context.insert(FakeUse); | |
| 305 } | |
| 306 | |
| 307 if (!Dest) | |
| 308 return; | |
| 309 | |
| 310 if (!ReturnReg) | |
|
jvoung (off chromium)
2015/07/31 23:53:49
Seems a bit odd to have a Dest, but no ReturnReg.
John
2015/08/01 15:49:55
Yes, indeed. This became an assert(ReturnReg);
jvoung (off chromium)
2015/08/03 17:04:55
New patch upload?
John
2015/08/05 16:53:03
Done.
| |
| 311 return; | |
| 312 | |
| 313 // Assign the result of the call to Dest. | |
| 314 if (ReturnRegHi) { | |
| 315 assert(Dest->getType() == IceType_i64); | |
| 316 split64(Dest); | |
| 317 Variable *DestLo = Dest->getLo(); | |
| 318 Variable *DestHi = Dest->getHi(); | |
| 319 _mov(DestLo, ReturnReg); | |
| 320 _mov(DestHi, ReturnRegHi); | |
| 321 return; | |
| 322 } | |
| 323 | |
| 324 assert(Dest->getType() == IceType_f32 || Dest->getType() == IceType_f64 || | |
| 325 Dest->getType() == IceType_i32 || Dest->getType() == IceType_i16 || | |
| 326 Dest->getType() == IceType_i8 || Dest->getType() == IceType_i1 || | |
| 327 isVectorType(Dest->getType())); | |
| 328 | |
| 329 if (isScalarFloatingType(Dest->getType()) || isVectorType(Dest->getType())) { | |
| 330 _movp(Dest, ReturnReg); | |
| 331 } else { | |
| 332 _mov(Dest, ReturnReg); | |
| 333 } | |
| 334 } | |
| 335 | |
| 336 void TargetX8664::emitJumpTable(const Cfg *Func, | |
| 337 const InstJumpTable *JumpTable) const { | |
| 338 if (!BuildDefs::dump()) | |
| 339 return; | |
| 340 Ostream &Str = Ctx->getStrEmit(); | |
| 341 IceString MangledName = Ctx->mangleName(Func->getFunctionName()); | |
| 342 Str << "\t.section\t.rodata." << MangledName | |
| 343 << "$jumptable,\"a\",@progbits\n"; | |
| 344 Str << "\t.align\t" << typeWidthInBytes(getPointerType()) << "\n"; | |
| 345 Str << InstJumpTable::makeName(MangledName, JumpTable->getId()) << ":"; | |
| 346 | |
| 347 // On X8664 ILP32 pointers are 32-bit hence the use of .long | |
| 348 for (SizeT I = 0; I < JumpTable->getNumTargets(); ++I) | |
| 349 Str << "\n\t.long\t" << JumpTable->getTarget(I)->getAsmName(); | |
| 350 Str << "\n"; | |
| 351 } | |
| 352 | |
| 353 void TargetDataX8664::lowerJumpTables() { | |
| 354 switch (Ctx->getFlags().getOutFileType()) { | |
| 355 case FT_Elf: { | |
| 356 ELFObjectWriter *Writer = Ctx->getObjectWriter(); | |
| 357 for (const JumpTableData &JumpTable : *Ctx->getJumpTables()) | |
| 358 // TODO(jpp): not 386. | |
| 359 Writer->writeJumpTable(JumpTable, llvm::ELF::R_386_32); | |
| 360 } break; | |
| 361 case FT_Asm: | |
| 362 // Already emitted from Cfg | |
| 363 break; | |
| 364 case FT_Iasm: { | |
| 365 if (!BuildDefs::dump()) | |
| 366 return; | |
| 367 Ostream &Str = Ctx->getStrEmit(); | |
| 368 for (const JumpTableData &JT : *Ctx->getJumpTables()) { | |
| 369 Str << "\t.section\t.rodata." << JT.getFunctionName() | |
| 370 << "$jumptable,\"a\",@progbits\n"; | |
| 371 Str << "\t.align\t" << typeWidthInBytes(getPointerType()) << "\n"; | |
| 372 Str << InstJumpTable::makeName(JT.getFunctionName(), JT.getId()) << ":"; | |
| 373 | |
| 374 // On X8664 ILP32 pointers are 32-bit hence the use of .long | |
| 375 for (intptr_t TargetOffset : JT.getTargetOffsets()) | |
| 376 Str << "\n\t.long\t" << JT.getFunctionName() << "+" << TargetOffset; | |
| 377 Str << "\n"; | |
| 378 } | |
| 379 } break; | |
| 380 } | |
| 381 } | |
| 382 | |
| 84 namespace { | 383 namespace { |
| 85 template <typename T> struct PoolTypeConverter {}; | 384 template <typename T> struct PoolTypeConverter {}; |
| 86 | 385 |
| 87 template <> struct PoolTypeConverter<float> { | 386 template <> struct PoolTypeConverter<float> { |
| 88 typedef uint32_t PrimitiveIntType; | 387 typedef uint32_t PrimitiveIntType; |
| 89 typedef ConstantFloat IceType; | 388 typedef ConstantFloat IceType; |
| 90 static const Type Ty = IceType_f32; | 389 static const Type Ty = IceType_f32; |
| 91 static const char *TypeName; | 390 static const char *TypeName; |
| 92 static const char *AsmTag; | 391 static const char *AsmTag; |
| 93 static const char *PrintfString; | 392 static const char *PrintfString; |
| (...skipping 118 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 212 emitConstantPool<PoolTypeConverter<uint8_t>>(Ctx); | 511 emitConstantPool<PoolTypeConverter<uint8_t>>(Ctx); |
| 213 emitConstantPool<PoolTypeConverter<uint16_t>>(Ctx); | 512 emitConstantPool<PoolTypeConverter<uint16_t>>(Ctx); |
| 214 emitConstantPool<PoolTypeConverter<uint32_t>>(Ctx); | 513 emitConstantPool<PoolTypeConverter<uint32_t>>(Ctx); |
| 215 | 514 |
| 216 emitConstantPool<PoolTypeConverter<float>>(Ctx); | 515 emitConstantPool<PoolTypeConverter<float>>(Ctx); |
| 217 emitConstantPool<PoolTypeConverter<double>>(Ctx); | 516 emitConstantPool<PoolTypeConverter<double>>(Ctx); |
| 218 } break; | 517 } break; |
| 219 } | 518 } |
| 220 } | 519 } |
| 221 | 520 |
| 222 void TargetX8664::emitJumpTable(const Cfg *Func, | |
| 223 const InstJumpTable *JumpTable) const { | |
| 224 if (!BuildDefs::dump()) | |
| 225 return; | |
| 226 Ostream &Str = Ctx->getStrEmit(); | |
| 227 IceString MangledName = Ctx->mangleName(Func->getFunctionName()); | |
| 228 Str << "\t.section\t.rodata." << MangledName | |
| 229 << "$jumptable,\"a\",@progbits\n"; | |
| 230 Str << "\t.align\t" << typeWidthInBytes(getPointerType()) << "\n"; | |
| 231 Str << InstJumpTable::makeName(MangledName, JumpTable->getId()) << ":"; | |
| 232 | |
| 233 // On X8664 ILP32 pointers are 32-bit hence the use of .long | |
| 234 for (SizeT I = 0; I < JumpTable->getNumTargets(); ++I) | |
| 235 Str << "\n\t.long\t" << JumpTable->getTarget(I)->getAsmName(); | |
| 236 Str << "\n"; | |
| 237 } | |
| 238 | |
| 239 void TargetDataX8664::lowerJumpTables() { | |
| 240 switch (Ctx->getFlags().getOutFileType()) { | |
| 241 case FT_Elf: { | |
| 242 ELFObjectWriter *Writer = Ctx->getObjectWriter(); | |
| 243 for (const JumpTableData &JumpTable : *Ctx->getJumpTables()) | |
| 244 // TODO(jpp): not 386. | |
| 245 Writer->writeJumpTable(JumpTable, llvm::ELF::R_386_32); | |
| 246 } break; | |
| 247 case FT_Asm: | |
| 248 // Already emitted from Cfg | |
| 249 break; | |
| 250 case FT_Iasm: { | |
| 251 if (!BuildDefs::dump()) | |
| 252 return; | |
| 253 Ostream &Str = Ctx->getStrEmit(); | |
| 254 for (const JumpTableData &JT : *Ctx->getJumpTables()) { | |
| 255 Str << "\t.section\t.rodata." << JT.getFunctionName() | |
| 256 << "$jumptable,\"a\",@progbits\n"; | |
| 257 Str << "\t.align\t" << typeWidthInBytes(getPointerType()) << "\n"; | |
| 258 Str << InstJumpTable::makeName(JT.getFunctionName(), JT.getId()) << ":"; | |
| 259 | |
| 260 // On X8664 ILP32 pointers are 32-bit hence the use of .long | |
| 261 for (intptr_t TargetOffset : JT.getTargetOffsets()) | |
| 262 Str << "\n\t.long\t" << JT.getFunctionName() << "+" << TargetOffset; | |
| 263 Str << "\n"; | |
| 264 } | |
| 265 } break; | |
| 266 } | |
| 267 } | |
| 268 | |
| 269 void TargetDataX8664::lowerGlobals(const VariableDeclarationList &Vars, | 521 void TargetDataX8664::lowerGlobals(const VariableDeclarationList &Vars, |
| 270 const IceString &SectionSuffix) { | 522 const IceString &SectionSuffix) { |
| 271 switch (Ctx->getFlags().getOutFileType()) { | 523 switch (Ctx->getFlags().getOutFileType()) { |
| 272 case FT_Elf: { | 524 case FT_Elf: { |
| 273 ELFObjectWriter *Writer = Ctx->getObjectWriter(); | 525 ELFObjectWriter *Writer = Ctx->getObjectWriter(); |
| 274 // TODO(jpp): not 386. | 526 // TODO(jpp): not 386. |
| 275 Writer->writeDataSection(Vars, llvm::ELF::R_386_32, SectionSuffix); | 527 Writer->writeDataSection(Vars, llvm::ELF::R_386_32, SectionSuffix); |
| 276 } break; | 528 } break; |
| 277 case FT_Asm: | 529 case FT_Asm: |
| 278 case FT_Iasm: { | 530 case FT_Iasm: { |
| (...skipping 110 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 389 // entries in case the high-level table has extra entries. | 641 // entries in case the high-level table has extra entries. |
| 390 #define X(tag, sizeLog2, align, elts, elty, str) \ | 642 #define X(tag, sizeLog2, align, elts, elty, str) \ |
| 391 static_assert(_table1_##tag == _table2_##tag, \ | 643 static_assert(_table1_##tag == _table2_##tag, \ |
| 392 "Inconsistency between ICETYPEX8664_TABLE and ICETYPE_TABLE"); | 644 "Inconsistency between ICETYPEX8664_TABLE and ICETYPE_TABLE"); |
| 393 ICETYPE_TABLE | 645 ICETYPE_TABLE |
| 394 #undef X | 646 #undef X |
| 395 } // end of namespace dummy3 | 647 } // end of namespace dummy3 |
| 396 } // end of anonymous namespace | 648 } // end of anonymous namespace |
| 397 | 649 |
| 398 } // end of namespace Ice | 650 } // end of namespace Ice |
| OLD | NEW |