OLD | NEW |
(Empty) | |
| 1 //===- subzero/src/IceInstX8632.cpp - X86-32 instruction implementation ---===// |
| 2 // |
| 3 // The Subzero Code Generator |
| 4 // |
| 5 // This file is distributed under the University of Illinois Open Source |
| 6 // License. See LICENSE.TXT for details. |
| 7 // |
| 8 //===----------------------------------------------------------------------===// |
| 9 // |
| 10 // This file implements the InstX8632 and OperandX8632 classes, |
| 11 // primarily the constructors and the dump()/emit() methods. |
| 12 // |
| 13 //===----------------------------------------------------------------------===// |
| 14 |
| 15 #include "IceCfg.h" |
| 16 #include "IceCfgNode.h" |
| 17 #include "IceInst.h" |
| 18 #include "IceInstX8632.h" |
| 19 #include "IceTargetLoweringX8632.h" |
| 20 #include "IceOperand.h" |
| 21 |
| 22 namespace Ice { |
| 23 |
| 24 namespace { |
| 25 |
| 26 const struct InstX8632BrAttributes_ { |
| 27 const char *DisplayString; |
| 28 const char *EmitString; |
| 29 } InstX8632BrAttributes[] = { |
| 30 #define X(tag, dump, emit) \ |
| 31 { dump, emit } \ |
| 32 , |
| 33 ICEINSTX8632BR_TABLE |
| 34 #undef X |
| 35 }; |
| 36 const size_t InstX8632BrAttributesSize = |
| 37 llvm::array_lengthof(InstX8632BrAttributes); |
| 38 |
| 39 const struct TypeX8632Attributes_ { |
| 40 const char *CvtString; // i (integer), s (single FP), d (double FP) |
| 41 const char *SdSsString; // ss, sd, or <blank> |
| 42 const char *WidthString; // {byte,word,dword,qword} ptr |
| 43 } TypeX8632Attributes[] = { |
| 44 #define X(tag, cvt, sdss, width) \ |
| 45 { cvt, "" sdss, width } \ |
| 46 , |
| 47 ICETYPEX8632_TABLE |
| 48 #undef X |
| 49 }; |
| 50 const size_t TypeX8632AttributesSize = |
| 51 llvm::array_lengthof(TypeX8632Attributes); |
| 52 |
| 53 } // end of anonymous namespace |
| 54 |
| 55 const char *InstX8632::getWidthString(Type Ty) { |
| 56 return TypeX8632Attributes[Ty].WidthString; |
| 57 } |
| 58 |
| 59 OperandX8632Mem::OperandX8632Mem(Cfg *Func, Type Ty, Variable *Base, |
| 60 Constant *Offset, Variable *Index, |
| 61 uint32_t Shift) |
| 62 : OperandX8632(kMem, Ty), Base(Base), Offset(Offset), Index(Index), |
| 63 Shift(Shift) { |
| 64 assert(Shift <= 3); |
| 65 Vars = NULL; |
| 66 NumVars = 0; |
| 67 if (Base) |
| 68 ++NumVars; |
| 69 if (Index) |
| 70 ++NumVars; |
| 71 if (NumVars) { |
| 72 Vars = Func->allocateArrayOf<Variable *>(NumVars); |
| 73 SizeT I = 0; |
| 74 if (Base) |
| 75 Vars[I++] = Base; |
| 76 if (Index) |
| 77 Vars[I++] = Index; |
| 78 assert(I == NumVars); |
| 79 } |
| 80 } |
| 81 |
| 82 InstX8632Mul::InstX8632Mul(Cfg *Func, Variable *Dest, Variable *Source1, |
| 83 Operand *Source2) |
| 84 : InstX8632(Func, InstX8632::Mul, 2, Dest) { |
| 85 addSource(Source1); |
| 86 addSource(Source2); |
| 87 } |
| 88 |
| 89 InstX8632Shld::InstX8632Shld(Cfg *Func, Variable *Dest, Variable *Source1, |
| 90 Variable *Source2) |
| 91 : InstX8632(Func, InstX8632::Shld, 3, Dest) { |
| 92 addSource(Dest); |
| 93 addSource(Source1); |
| 94 addSource(Source2); |
| 95 } |
| 96 |
| 97 InstX8632Shrd::InstX8632Shrd(Cfg *Func, Variable *Dest, Variable *Source1, |
| 98 Variable *Source2) |
| 99 : InstX8632(Func, InstX8632::Shrd, 3, Dest) { |
| 100 addSource(Dest); |
| 101 addSource(Source1); |
| 102 addSource(Source2); |
| 103 } |
| 104 |
| 105 InstX8632Label::InstX8632Label(Cfg *Func, TargetX8632 *Target) |
| 106 : InstX8632(Func, InstX8632::Label, 0, NULL), |
| 107 Number(Target->makeNextLabelNumber()) {} |
| 108 |
| 109 IceString InstX8632Label::getName(const Cfg *Func) const { |
| 110 char buf[30]; |
| 111 snprintf(buf, llvm::array_lengthof(buf), "%u", Number); |
| 112 return ".L" + Func->getFunctionName() + "$__" + buf; |
| 113 } |
| 114 |
| 115 InstX8632Br::InstX8632Br(Cfg *Func, CfgNode *TargetTrue, CfgNode *TargetFalse, |
| 116 InstX8632Label *Label, InstX8632Br::BrCond Condition) |
| 117 : InstX8632(Func, InstX8632::Br, 0, NULL), Condition(Condition), |
| 118 TargetTrue(TargetTrue), TargetFalse(TargetFalse), Label(Label) {} |
| 119 |
| 120 InstX8632Call::InstX8632Call(Cfg *Func, Variable *Dest, Operand *CallTarget) |
| 121 : InstX8632(Func, InstX8632::Call, 1, Dest) { |
| 122 HasSideEffects = true; |
| 123 addSource(CallTarget); |
| 124 } |
| 125 |
| 126 InstX8632Cdq::InstX8632Cdq(Cfg *Func, Variable *Dest, Operand *Source) |
| 127 : InstX8632(Func, InstX8632::Cdq, 1, Dest) { |
| 128 assert(Dest->getRegNum() == TargetX8632::Reg_edx); |
| 129 assert(llvm::isa<Variable>(Source)); |
| 130 assert(llvm::dyn_cast<Variable>(Source)->getRegNum() == TargetX8632::Reg_eax); |
| 131 addSource(Source); |
| 132 } |
| 133 |
| 134 InstX8632Cvt::InstX8632Cvt(Cfg *Func, Variable *Dest, Operand *Source) |
| 135 : InstX8632(Func, InstX8632::Cvt, 1, Dest) { |
| 136 addSource(Source); |
| 137 } |
| 138 |
| 139 InstX8632Icmp::InstX8632Icmp(Cfg *Func, Operand *Src0, Operand *Src1) |
| 140 : InstX8632(Func, InstX8632::Icmp, 2, NULL) { |
| 141 addSource(Src0); |
| 142 addSource(Src1); |
| 143 } |
| 144 |
| 145 InstX8632Ucomiss::InstX8632Ucomiss(Cfg *Func, Operand *Src0, Operand *Src1) |
| 146 : InstX8632(Func, InstX8632::Ucomiss, 2, NULL) { |
| 147 addSource(Src0); |
| 148 addSource(Src1); |
| 149 } |
| 150 |
| 151 InstX8632Test::InstX8632Test(Cfg *Func, Operand *Src1, Operand *Src2) |
| 152 : InstX8632(Func, InstX8632::Test, 2, NULL) { |
| 153 addSource(Src1); |
| 154 addSource(Src2); |
| 155 } |
| 156 |
| 157 InstX8632Store::InstX8632Store(Cfg *Func, Operand *Value, OperandX8632 *Mem) |
| 158 : InstX8632(Func, InstX8632::Store, 2, NULL) { |
| 159 addSource(Value); |
| 160 addSource(Mem); |
| 161 } |
| 162 |
| 163 InstX8632Mov::InstX8632Mov(Cfg *Func, Variable *Dest, Operand *Source) |
| 164 : InstX8632(Func, InstX8632::Mov, 1, Dest) { |
| 165 addSource(Source); |
| 166 } |
| 167 |
| 168 InstX8632Movsx::InstX8632Movsx(Cfg *Func, Variable *Dest, Operand *Source) |
| 169 : InstX8632(Func, InstX8632::Movsx, 1, Dest) { |
| 170 addSource(Source); |
| 171 } |
| 172 |
| 173 InstX8632Movzx::InstX8632Movzx(Cfg *Func, Variable *Dest, Operand *Source) |
| 174 : InstX8632(Func, InstX8632::Movzx, 1, Dest) { |
| 175 addSource(Source); |
| 176 } |
| 177 |
| 178 InstX8632Fld::InstX8632Fld(Cfg *Func, Operand *Src) |
| 179 : InstX8632(Func, InstX8632::Fld, 1, NULL) { |
| 180 addSource(Src); |
| 181 } |
| 182 |
| 183 InstX8632Fstp::InstX8632Fstp(Cfg *Func, Variable *Dest) |
| 184 : InstX8632(Func, InstX8632::Fstp, 0, Dest) {} |
| 185 |
| 186 InstX8632Pop::InstX8632Pop(Cfg *Func, Variable *Dest) |
| 187 : InstX8632(Func, InstX8632::Pop, 0, Dest) {} |
| 188 |
| 189 InstX8632Push::InstX8632Push(Cfg *Func, Operand *Source, |
| 190 bool SuppressStackAdjustment) |
| 191 : InstX8632(Func, InstX8632::Push, 1, NULL), |
| 192 SuppressStackAdjustment(SuppressStackAdjustment) { |
| 193 addSource(Source); |
| 194 } |
| 195 |
| 196 bool InstX8632Mov::isRedundantAssign() const { |
| 197 Variable *Src = llvm::dyn_cast<Variable>(getSrc(0)); |
| 198 if (Src == NULL) |
| 199 return false; |
| 200 if (getDest()->hasReg() && getDest()->getRegNum() == Src->getRegNum()) { |
| 201 // TODO: On x86-64, instructions like "mov eax, eax" are used to |
| 202 // clear the upper 32 bits of rax. We need to recognize and |
| 203 // preserve these. |
| 204 return true; |
| 205 } |
| 206 if (!getDest()->hasReg() && !Src->hasReg() && |
| 207 Dest->getStackOffset() == Src->getStackOffset()) |
| 208 return true; |
| 209 return false; |
| 210 } |
| 211 |
| 212 InstX8632Ret::InstX8632Ret(Cfg *Func, Variable *Source) |
| 213 : InstX8632(Func, InstX8632::Ret, Source ? 1 : 0, NULL) { |
| 214 if (Source) |
| 215 addSource(Source); |
| 216 } |
| 217 |
| 218 // ======================== Dump routines ======================== // |
| 219 |
| 220 void InstX8632::dump(const Cfg *Func) const { |
| 221 Ostream &Str = Func->getContext()->getStrDump(); |
| 222 Str << "[X8632] "; |
| 223 Inst::dump(Func); |
| 224 } |
| 225 |
| 226 void InstX8632Label::emit(const Cfg *Func) const { |
| 227 Ostream &Str = Func->getContext()->getStrEmit(); |
| 228 Str << getName(Func) << ":\n"; |
| 229 } |
| 230 |
| 231 void InstX8632Label::dump(const Cfg *Func) const { |
| 232 Ostream &Str = Func->getContext()->getStrDump(); |
| 233 Str << getName(Func) << ":"; |
| 234 } |
| 235 |
| 236 void InstX8632Br::emit(const Cfg *Func) const { |
| 237 Ostream &Str = Func->getContext()->getStrEmit(); |
| 238 Str << "\t"; |
| 239 |
| 240 if (Condition == Br_None) { |
| 241 Str << "jmp"; |
| 242 } else { |
| 243 Str << InstX8632BrAttributes[Condition].EmitString; |
| 244 } |
| 245 |
| 246 if (Label) { |
| 247 Str << "\t" << Label->getName(Func) << "\n"; |
| 248 } else { |
| 249 if (Condition == Br_None) { |
| 250 Str << "\t" << getTargetFalse()->getAsmName() << "\n"; |
| 251 } else { |
| 252 Str << "\t" << getTargetTrue()->getAsmName() << "\n"; |
| 253 if (getTargetFalse()) { |
| 254 Str << "\tjmp\t" << getTargetFalse()->getAsmName() << "\n"; |
| 255 } |
| 256 } |
| 257 } |
| 258 } |
| 259 |
| 260 void InstX8632Br::dump(const Cfg *Func) const { |
| 261 Ostream &Str = Func->getContext()->getStrDump(); |
| 262 Str << "br "; |
| 263 |
| 264 if (Condition == Br_None) { |
| 265 Str << "label %" |
| 266 << (Label ? Label->getName(Func) : getTargetFalse()->getName()); |
| 267 return; |
| 268 } |
| 269 |
| 270 Str << InstX8632BrAttributes[Condition].DisplayString; |
| 271 if (Label) { |
| 272 Str << ", label %" << Label->getName(Func); |
| 273 } else { |
| 274 Str << ", label %" << getTargetTrue()->getName(); |
| 275 if (getTargetFalse()) { |
| 276 Str << ", label %" << getTargetFalse()->getName(); |
| 277 } |
| 278 } |
| 279 } |
| 280 |
| 281 void InstX8632Call::emit(const Cfg *Func) const { |
| 282 Ostream &Str = Func->getContext()->getStrEmit(); |
| 283 assert(getSrcSize() == 1); |
| 284 Str << "\tcall\t"; |
| 285 getCallTarget()->emit(Func); |
| 286 Str << "\n"; |
| 287 Func->getTarget()->resetStackAdjustment(); |
| 288 } |
| 289 |
| 290 void InstX8632Call::dump(const Cfg *Func) const { |
| 291 Ostream &Str = Func->getContext()->getStrDump(); |
| 292 if (getDest()) { |
| 293 dumpDest(Func); |
| 294 Str << " = "; |
| 295 } |
| 296 Str << "call "; |
| 297 getCallTarget()->dump(Func); |
| 298 } |
| 299 |
| 300 // The ShiftHack parameter is used to emit "cl" instead of "ecx" for |
| 301 // shift instructions, in order to be syntactically valid. The |
| 302 // Opcode parameter needs to be char* and not IceString because of |
| 303 // template issues. |
| 304 void emitTwoAddress(const char *Opcode, const Inst *Inst, const Cfg *Func, |
| 305 bool ShiftHack) { |
| 306 Ostream &Str = Func->getContext()->getStrEmit(); |
| 307 assert(Inst->getSrcSize() == 2); |
| 308 assert(Inst->getDest() == Inst->getSrc(0)); |
| 309 Str << "\t" << Opcode << "\t"; |
| 310 Inst->getDest()->emit(Func); |
| 311 Str << ", "; |
| 312 bool EmittedSrc1 = false; |
| 313 if (ShiftHack) { |
| 314 Variable *ShiftReg = llvm::dyn_cast<Variable>(Inst->getSrc(1)); |
| 315 if (ShiftReg && ShiftReg->getRegNum() == TargetX8632::Reg_ecx) { |
| 316 Str << "cl"; |
| 317 EmittedSrc1 = true; |
| 318 } |
| 319 } |
| 320 if (!EmittedSrc1) |
| 321 Inst->getSrc(1)->emit(Func); |
| 322 Str << "\n"; |
| 323 } |
| 324 |
| 325 template <> const char *InstX8632Add::Opcode = "add"; |
| 326 template <> const char *InstX8632Adc::Opcode = "adc"; |
| 327 template <> const char *InstX8632Addss::Opcode = "addss"; |
| 328 template <> const char *InstX8632Sub::Opcode = "sub"; |
| 329 template <> const char *InstX8632Subss::Opcode = "subss"; |
| 330 template <> const char *InstX8632Sbb::Opcode = "sbb"; |
| 331 template <> const char *InstX8632And::Opcode = "and"; |
| 332 template <> const char *InstX8632Or::Opcode = "or"; |
| 333 template <> const char *InstX8632Xor::Opcode = "xor"; |
| 334 template <> const char *InstX8632Imul::Opcode = "imul"; |
| 335 template <> const char *InstX8632Mulss::Opcode = "mulss"; |
| 336 template <> const char *InstX8632Div::Opcode = "div"; |
| 337 template <> const char *InstX8632Idiv::Opcode = "idiv"; |
| 338 template <> const char *InstX8632Divss::Opcode = "divss"; |
| 339 template <> const char *InstX8632Shl::Opcode = "shl"; |
| 340 template <> const char *InstX8632Shr::Opcode = "shr"; |
| 341 template <> const char *InstX8632Sar::Opcode = "sar"; |
| 342 |
| 343 template <> void InstX8632Addss::emit(const Cfg *Func) const { |
| 344 char buf[30]; |
| 345 snprintf(buf, llvm::array_lengthof(buf), "add%s", |
| 346 TypeX8632Attributes[getDest()->getType()].SdSsString); |
| 347 emitTwoAddress(buf, this, Func); |
| 348 } |
| 349 |
| 350 template <> void InstX8632Subss::emit(const Cfg *Func) const { |
| 351 char buf[30]; |
| 352 snprintf(buf, llvm::array_lengthof(buf), "sub%s", |
| 353 TypeX8632Attributes[getDest()->getType()].SdSsString); |
| 354 emitTwoAddress(buf, this, Func); |
| 355 } |
| 356 |
| 357 template <> void InstX8632Mulss::emit(const Cfg *Func) const { |
| 358 char buf[30]; |
| 359 snprintf(buf, llvm::array_lengthof(buf), "mul%s", |
| 360 TypeX8632Attributes[getDest()->getType()].SdSsString); |
| 361 emitTwoAddress(buf, this, Func); |
| 362 } |
| 363 |
| 364 template <> void InstX8632Divss::emit(const Cfg *Func) const { |
| 365 char buf[30]; |
| 366 snprintf(buf, llvm::array_lengthof(buf), "div%s", |
| 367 TypeX8632Attributes[getDest()->getType()].SdSsString); |
| 368 emitTwoAddress(buf, this, Func); |
| 369 } |
| 370 |
| 371 template <> void InstX8632Imul::emit(const Cfg *Func) const { |
| 372 Ostream &Str = Func->getContext()->getStrEmit(); |
| 373 assert(getSrcSize() == 2); |
| 374 if (getDest()->getType() == IceType_i8) { |
| 375 // The 8-bit version of imul only allows the form "imul r/m8". |
| 376 Variable *Src0 = llvm::dyn_cast<Variable>(getSrc(0)); |
| 377 assert(Src0 && Src0->getRegNum() == TargetX8632::Reg_eax); |
| 378 Str << "\timul\t"; |
| 379 getSrc(1)->emit(Func); |
| 380 Str << "\n"; |
| 381 } else if (llvm::isa<Constant>(getSrc(1))) { |
| 382 Str << "\timul\t"; |
| 383 getDest()->emit(Func); |
| 384 Str << ", "; |
| 385 getSrc(0)->emit(Func); |
| 386 Str << ", "; |
| 387 getSrc(1)->emit(Func); |
| 388 Str << "\n"; |
| 389 } else { |
| 390 emitTwoAddress("imul", this, Func); |
| 391 } |
| 392 } |
| 393 |
| 394 void InstX8632Mul::emit(const Cfg *Func) const { |
| 395 Ostream &Str = Func->getContext()->getStrEmit(); |
| 396 assert(getSrcSize() == 2); |
| 397 assert(llvm::isa<Variable>(getSrc(0))); |
| 398 assert(llvm::dyn_cast<Variable>(getSrc(0))->getRegNum() == |
| 399 TargetX8632::Reg_eax); |
| 400 assert(getDest()->getRegNum() == TargetX8632::Reg_eax); // TODO: allow edx? |
| 401 Str << "\tmul\t"; |
| 402 getSrc(1)->emit(Func); |
| 403 Str << "\n"; |
| 404 } |
| 405 |
| 406 void InstX8632Mul::dump(const Cfg *Func) const { |
| 407 Ostream &Str = Func->getContext()->getStrDump(); |
| 408 dumpDest(Func); |
| 409 Str << " = mul." << getDest()->getType() << " "; |
| 410 dumpSources(Func); |
| 411 } |
| 412 |
| 413 void InstX8632Shld::emit(const Cfg *Func) const { |
| 414 Ostream &Str = Func->getContext()->getStrEmit(); |
| 415 assert(getSrcSize() == 3); |
| 416 assert(getDest() == getSrc(0)); |
| 417 Str << "\tshld\t"; |
| 418 getDest()->emit(Func); |
| 419 Str << ", "; |
| 420 getSrc(1)->emit(Func); |
| 421 Str << ", "; |
| 422 if (Variable *ShiftReg = llvm::dyn_cast<Variable>(getSrc(2))) { |
| 423 assert(ShiftReg->getRegNum() == TargetX8632::Reg_ecx); |
| 424 Str << "cl"; |
| 425 } else { |
| 426 getSrc(2)->emit(Func); |
| 427 } |
| 428 Str << "\n"; |
| 429 } |
| 430 |
| 431 void InstX8632Shld::dump(const Cfg *Func) const { |
| 432 Ostream &Str = Func->getContext()->getStrDump(); |
| 433 dumpDest(Func); |
| 434 Str << " = shld." << getDest()->getType() << " "; |
| 435 dumpSources(Func); |
| 436 } |
| 437 |
| 438 void InstX8632Shrd::emit(const Cfg *Func) const { |
| 439 Ostream &Str = Func->getContext()->getStrEmit(); |
| 440 assert(getSrcSize() == 3); |
| 441 assert(getDest() == getSrc(0)); |
| 442 Str << "\tshrd\t"; |
| 443 getDest()->emit(Func); |
| 444 Str << ", "; |
| 445 getSrc(1)->emit(Func); |
| 446 Str << ", "; |
| 447 if (Variable *ShiftReg = llvm::dyn_cast<Variable>(getSrc(2))) { |
| 448 assert(ShiftReg->getRegNum() == TargetX8632::Reg_ecx); |
| 449 Str << "cl"; |
| 450 } else { |
| 451 getSrc(2)->emit(Func); |
| 452 } |
| 453 Str << "\n"; |
| 454 } |
| 455 |
| 456 void InstX8632Shrd::dump(const Cfg *Func) const { |
| 457 Ostream &Str = Func->getContext()->getStrDump(); |
| 458 dumpDest(Func); |
| 459 Str << " = shrd." << getDest()->getType() << " "; |
| 460 dumpSources(Func); |
| 461 } |
| 462 |
| 463 void InstX8632Cdq::emit(const Cfg *Func) const { |
| 464 Ostream &Str = Func->getContext()->getStrEmit(); |
| 465 assert(getSrcSize() == 1); |
| 466 Str << "\tcdq\n"; |
| 467 } |
| 468 |
| 469 void InstX8632Cdq::dump(const Cfg *Func) const { |
| 470 Ostream &Str = Func->getContext()->getStrDump(); |
| 471 dumpDest(Func); |
| 472 Str << " = cdq." << getSrc(0)->getType() << " "; |
| 473 dumpSources(Func); |
| 474 } |
| 475 |
| 476 void InstX8632Cvt::emit(const Cfg *Func) const { |
| 477 Ostream &Str = Func->getContext()->getStrEmit(); |
| 478 assert(getSrcSize() == 1); |
| 479 Str << "\tcvts" << TypeX8632Attributes[getSrc(0)->getType()].CvtString << "2s" |
| 480 << TypeX8632Attributes[getDest()->getType()].CvtString << "\t"; |
| 481 getDest()->emit(Func); |
| 482 Str << ", "; |
| 483 getSrc(0)->emit(Func); |
| 484 Str << "\n"; |
| 485 } |
| 486 |
| 487 void InstX8632Cvt::dump(const Cfg *Func) const { |
| 488 Ostream &Str = Func->getContext()->getStrDump(); |
| 489 dumpDest(Func); |
| 490 Str << " = cvts" << TypeX8632Attributes[getSrc(0)->getType()].CvtString |
| 491 << "2s" << TypeX8632Attributes[getDest()->getType()].CvtString << " "; |
| 492 dumpSources(Func); |
| 493 } |
| 494 |
| 495 void InstX8632Icmp::emit(const Cfg *Func) const { |
| 496 Ostream &Str = Func->getContext()->getStrEmit(); |
| 497 assert(getSrcSize() == 2); |
| 498 Str << "\tcmp\t"; |
| 499 getSrc(0)->emit(Func); |
| 500 Str << ", "; |
| 501 getSrc(1)->emit(Func); |
| 502 Str << "\n"; |
| 503 } |
| 504 |
| 505 void InstX8632Icmp::dump(const Cfg *Func) const { |
| 506 Ostream &Str = Func->getContext()->getStrDump(); |
| 507 Str << "cmp." << getSrc(0)->getType() << " "; |
| 508 dumpSources(Func); |
| 509 } |
| 510 |
| 511 void InstX8632Ucomiss::emit(const Cfg *Func) const { |
| 512 Ostream &Str = Func->getContext()->getStrEmit(); |
| 513 assert(getSrcSize() == 2); |
| 514 Str << "\tucomi" << TypeX8632Attributes[getSrc(0)->getType()].SdSsString |
| 515 << "\t"; |
| 516 getSrc(0)->emit(Func); |
| 517 Str << ", "; |
| 518 getSrc(1)->emit(Func); |
| 519 Str << "\n"; |
| 520 } |
| 521 |
| 522 void InstX8632Ucomiss::dump(const Cfg *Func) const { |
| 523 Ostream &Str = Func->getContext()->getStrDump(); |
| 524 Str << "ucomiss." << getSrc(0)->getType() << " "; |
| 525 dumpSources(Func); |
| 526 } |
| 527 |
| 528 void InstX8632Test::emit(const Cfg *Func) const { |
| 529 Ostream &Str = Func->getContext()->getStrEmit(); |
| 530 assert(getSrcSize() == 2); |
| 531 Str << "\ttest\t"; |
| 532 getSrc(0)->emit(Func); |
| 533 Str << ", "; |
| 534 getSrc(1)->emit(Func); |
| 535 Str << "\n"; |
| 536 } |
| 537 |
| 538 void InstX8632Test::dump(const Cfg *Func) const { |
| 539 Ostream &Str = Func->getContext()->getStrDump(); |
| 540 Str << "test." << getSrc(0)->getType() << " "; |
| 541 dumpSources(Func); |
| 542 } |
| 543 |
| 544 void InstX8632Store::emit(const Cfg *Func) const { |
| 545 Ostream &Str = Func->getContext()->getStrEmit(); |
| 546 assert(getSrcSize() == 2); |
| 547 Str << "\tmov\t"; |
| 548 getSrc(1)->emit(Func); |
| 549 Str << ", "; |
| 550 getSrc(0)->emit(Func); |
| 551 Str << "\n"; |
| 552 } |
| 553 |
| 554 void InstX8632Store::dump(const Cfg *Func) const { |
| 555 Ostream &Str = Func->getContext()->getStrDump(); |
| 556 Str << "mov." << getSrc(0)->getType() << " "; |
| 557 getSrc(1)->dump(Func); |
| 558 Str << ", "; |
| 559 getSrc(0)->dump(Func); |
| 560 } |
| 561 |
| 562 void InstX8632Mov::emit(const Cfg *Func) const { |
| 563 Ostream &Str = Func->getContext()->getStrEmit(); |
| 564 assert(getSrcSize() == 1); |
| 565 Str << "\tmov" << TypeX8632Attributes[getDest()->getType()].SdSsString |
| 566 << "\t"; |
| 567 // For an integer truncation operation, src is wider than dest. |
| 568 // Ideally, we use a mov instruction whose data width matches the |
| 569 // narrower dest. This is a problem if e.g. src is a register like |
| 570 // esi or si where there is no 8-bit version of the register. To be |
| 571 // safe, we instead widen the dest to match src. This works even |
| 572 // for stack-allocated dest variables because typeWidthOnStack() |
| 573 // pads to a 4-byte boundary even if only a lower portion is used. |
| 574 assert(Func->getTarget()->typeWidthInBytesOnStack(getDest()->getType()) == |
| 575 Func->getTarget()->typeWidthInBytesOnStack(getSrc(0)->getType())); |
| 576 getDest()->asType(getSrc(0)->getType()).emit(Func); |
| 577 Str << ", "; |
| 578 getSrc(0)->emit(Func); |
| 579 Str << "\n"; |
| 580 } |
| 581 |
| 582 void InstX8632Mov::dump(const Cfg *Func) const { |
| 583 Ostream &Str = Func->getContext()->getStrDump(); |
| 584 Str << "mov." << getDest()->getType() << " "; |
| 585 dumpDest(Func); |
| 586 Str << ", "; |
| 587 dumpSources(Func); |
| 588 } |
| 589 |
| 590 void InstX8632Movsx::emit(const Cfg *Func) const { |
| 591 Ostream &Str = Func->getContext()->getStrEmit(); |
| 592 assert(getSrcSize() == 1); |
| 593 Str << "\tmovsx\t"; |
| 594 getDest()->emit(Func); |
| 595 Str << ", "; |
| 596 getSrc(0)->emit(Func); |
| 597 Str << "\n"; |
| 598 } |
| 599 |
| 600 void InstX8632Movsx::dump(const Cfg *Func) const { |
| 601 Ostream &Str = Func->getContext()->getStrDump(); |
| 602 Str << "movsx." << getDest()->getType() << "." << getSrc(0)->getType(); |
| 603 Str << " "; |
| 604 dumpDest(Func); |
| 605 Str << ", "; |
| 606 dumpSources(Func); |
| 607 } |
| 608 |
| 609 void InstX8632Movzx::emit(const Cfg *Func) const { |
| 610 Ostream &Str = Func->getContext()->getStrEmit(); |
| 611 assert(getSrcSize() == 1); |
| 612 Str << "\tmovzx\t"; |
| 613 getDest()->emit(Func); |
| 614 Str << ", "; |
| 615 getSrc(0)->emit(Func); |
| 616 Str << "\n"; |
| 617 } |
| 618 |
| 619 void InstX8632Movzx::dump(const Cfg *Func) const { |
| 620 Ostream &Str = Func->getContext()->getStrDump(); |
| 621 Str << "movzx." << getDest()->getType() << "." << getSrc(0)->getType(); |
| 622 Str << " "; |
| 623 dumpDest(Func); |
| 624 Str << ", "; |
| 625 dumpSources(Func); |
| 626 } |
| 627 |
| 628 void InstX8632Fld::emit(const Cfg *Func) const { |
| 629 Ostream &Str = Func->getContext()->getStrEmit(); |
| 630 assert(getSrcSize() == 1); |
| 631 Type Ty = getSrc(0)->getType(); |
| 632 Variable *Var = llvm::dyn_cast<Variable>(getSrc(0)); |
| 633 if (Var && Var->hasReg()) { |
| 634 // This is a physical xmm register, so we need to spill it to a |
| 635 // temporary stack slot. |
| 636 SizeT Width = typeWidthInBytes(Ty); |
| 637 Str << "\tsub\tesp, " << Width << "\n"; |
| 638 Str << "\tmov" << TypeX8632Attributes[Ty].SdSsString << "\t" |
| 639 << TypeX8632Attributes[Ty].WidthString << " [esp], "; |
| 640 Var->emit(Func); |
| 641 Str << "\n"; |
| 642 Str << "\tfld\t" << TypeX8632Attributes[Ty].WidthString << " [esp]\n"; |
| 643 Str << "\tadd\tesp, " << Width << "\n"; |
| 644 return; |
| 645 } |
| 646 Str << "\tfld\t"; |
| 647 getSrc(0)->emit(Func); |
| 648 Str << "\n"; |
| 649 } |
| 650 |
| 651 void InstX8632Fld::dump(const Cfg *Func) const { |
| 652 Ostream &Str = Func->getContext()->getStrDump(); |
| 653 Str << "fld." << getSrc(0)->getType() << " "; |
| 654 dumpSources(Func); |
| 655 } |
| 656 |
| 657 void InstX8632Fstp::emit(const Cfg *Func) const { |
| 658 Ostream &Str = Func->getContext()->getStrEmit(); |
| 659 assert(getSrcSize() == 0); |
| 660 if (getDest() == NULL) { |
| 661 Str << "\tfstp\tst(0)\n"; |
| 662 return; |
| 663 } |
| 664 if (!getDest()->hasReg()) { |
| 665 Str << "\tfstp\t"; |
| 666 getDest()->emit(Func); |
| 667 Str << "\n"; |
| 668 return; |
| 669 } |
| 670 // Dest is a physical (xmm) register, so st(0) needs to go through |
| 671 // memory. Hack this by creating a temporary stack slot, spilling |
| 672 // st(0) there, loading it into the xmm register, and deallocating |
| 673 // the stack slot. |
| 674 Type Ty = getDest()->getType(); |
| 675 size_t Width = typeWidthInBytes(Ty); |
| 676 Str << "\tsub\tesp, " << Width << "\n"; |
| 677 Str << "\tfstp\t" << TypeX8632Attributes[Ty].WidthString << " [esp]\n"; |
| 678 Str << "\tmov" << TypeX8632Attributes[Ty].SdSsString << "\t"; |
| 679 getDest()->emit(Func); |
| 680 Str << ", " << TypeX8632Attributes[Ty].WidthString << " [esp]\n"; |
| 681 Str << "\tadd\tesp, " << Width << "\n"; |
| 682 } |
| 683 |
| 684 void InstX8632Fstp::dump(const Cfg *Func) const { |
| 685 Ostream &Str = Func->getContext()->getStrDump(); |
| 686 dumpDest(Func); |
| 687 Str << " = fstp." << getDest()->getType() << ", st(0)"; |
| 688 Str << "\n"; |
| 689 } |
| 690 |
| 691 void InstX8632Pop::emit(const Cfg *Func) const { |
| 692 Ostream &Str = Func->getContext()->getStrEmit(); |
| 693 assert(getSrcSize() == 0); |
| 694 Str << "\tpop\t"; |
| 695 getDest()->emit(Func); |
| 696 Str << "\n"; |
| 697 } |
| 698 |
| 699 void InstX8632Pop::dump(const Cfg *Func) const { |
| 700 Ostream &Str = Func->getContext()->getStrDump(); |
| 701 dumpDest(Func); |
| 702 Str << " = pop." << getDest()->getType() << " "; |
| 703 } |
| 704 |
| 705 void InstX8632Push::emit(const Cfg *Func) const { |
| 706 Ostream &Str = Func->getContext()->getStrEmit(); |
| 707 assert(getSrcSize() == 1); |
| 708 Type Ty = getSrc(0)->getType(); |
| 709 Variable *Var = llvm::dyn_cast<Variable>(getSrc(0)); |
| 710 if ((Ty == IceType_f32 || Ty == IceType_f64) && Var && Var->hasReg()) { |
| 711 // The xmm registers can't be directly pushed, so we fake it by |
| 712 // decrementing esp and then storing to [esp]. |
| 713 Str << "\tsub\tesp, " << typeWidthInBytes(Ty) << "\n"; |
| 714 if (!SuppressStackAdjustment) |
| 715 Func->getTarget()->updateStackAdjustment(typeWidthInBytes(Ty)); |
| 716 Str << "\tmov" << TypeX8632Attributes[Ty].SdSsString << "\t" |
| 717 << TypeX8632Attributes[Ty].WidthString << " [esp], "; |
| 718 getSrc(0)->emit(Func); |
| 719 Str << "\n"; |
| 720 } else if (Ty == IceType_f64 && (!Var || !Var->hasReg())) { |
| 721 // A double on the stack has to be pushed as two halves. Push the |
| 722 // upper half followed by the lower half for little-endian. TODO: |
| 723 // implement. |
| 724 llvm_unreachable("Missing support for pushing doubles from memory"); |
| 725 } else { |
| 726 Str << "\tpush\t"; |
| 727 getSrc(0)->emit(Func); |
| 728 Str << "\n"; |
| 729 if (!SuppressStackAdjustment) |
| 730 Func->getTarget()->updateStackAdjustment(4); |
| 731 } |
| 732 } |
| 733 |
| 734 void InstX8632Push::dump(const Cfg *Func) const { |
| 735 Ostream &Str = Func->getContext()->getStrDump(); |
| 736 Str << "push." << getSrc(0)->getType() << " "; |
| 737 dumpSources(Func); |
| 738 } |
| 739 |
| 740 void InstX8632Ret::emit(const Cfg *Func) const { |
| 741 Ostream &Str = Func->getContext()->getStrEmit(); |
| 742 Str << "\tret\n"; |
| 743 } |
| 744 |
| 745 void InstX8632Ret::dump(const Cfg *Func) const { |
| 746 Ostream &Str = Func->getContext()->getStrDump(); |
| 747 Type Ty = (getSrcSize() == 0 ? IceType_void : getSrc(0)->getType()); |
| 748 Str << "ret." << Ty << " "; |
| 749 dumpSources(Func); |
| 750 } |
| 751 |
| 752 void OperandX8632::dump(const Cfg *Func) const { |
| 753 Ostream &Str = Func->getContext()->getStrDump(); |
| 754 Str << "<OperandX8632>"; |
| 755 } |
| 756 |
| 757 void OperandX8632Mem::emit(const Cfg *Func) const { |
| 758 Ostream &Str = Func->getContext()->getStrEmit(); |
| 759 Str << TypeX8632Attributes[getType()].WidthString << " "; |
| 760 // TODO: The following is an almost verbatim paste of dump(). |
| 761 bool Dumped = false; |
| 762 Str << "["; |
| 763 if (Base) { |
| 764 Base->emit(Func); |
| 765 Dumped = true; |
| 766 } |
| 767 if (Index) { |
| 768 assert(Base); |
| 769 Str << "+"; |
| 770 if (Shift > 0) |
| 771 Str << (1u << Shift) << "*"; |
| 772 Index->emit(Func); |
| 773 Dumped = true; |
| 774 } |
| 775 // Pretty-print the Offset. |
| 776 bool OffsetIsZero = false; |
| 777 bool OffsetIsNegative = false; |
| 778 if (Offset == NULL) { |
| 779 OffsetIsZero = true; |
| 780 } else if (ConstantInteger *CI = llvm::dyn_cast<ConstantInteger>(Offset)) { |
| 781 OffsetIsZero = (CI->getValue() == 0); |
| 782 OffsetIsNegative = (static_cast<int64_t>(CI->getValue()) < 0); |
| 783 } |
| 784 if (!OffsetIsZero) { // Suppress if Offset is known to be 0 |
| 785 if (Dumped) { |
| 786 if (!OffsetIsNegative) // Suppress if Offset is known to be negative |
| 787 Str << "+"; |
| 788 } |
| 789 Offset->emit(Func); |
| 790 } |
| 791 Str << "]"; |
| 792 } |
| 793 |
| 794 void OperandX8632Mem::dump(const Cfg *Func) const { |
| 795 Ostream &Str = Func->getContext()->getStrDump(); |
| 796 bool Dumped = false; |
| 797 Str << "["; |
| 798 if (Base) { |
| 799 Base->dump(Func); |
| 800 Dumped = true; |
| 801 } |
| 802 if (Index) { |
| 803 assert(Base); |
| 804 Str << "+"; |
| 805 if (Shift > 0) |
| 806 Str << (1u << Shift) << "*"; |
| 807 Index->dump(Func); |
| 808 Dumped = true; |
| 809 } |
| 810 // Pretty-print the Offset. |
| 811 bool OffsetIsZero = false; |
| 812 bool OffsetIsNegative = false; |
| 813 if (Offset == NULL) { |
| 814 OffsetIsZero = true; |
| 815 } else if (ConstantInteger *CI = llvm::dyn_cast<ConstantInteger>(Offset)) { |
| 816 OffsetIsZero = (CI->getValue() == 0); |
| 817 OffsetIsNegative = (static_cast<int64_t>(CI->getValue()) < 0); |
| 818 } |
| 819 if (!OffsetIsZero) { // Suppress if Offset is known to be 0 |
| 820 if (Dumped) { |
| 821 if (!OffsetIsNegative) // Suppress if Offset is known to be negative |
| 822 Str << "+"; |
| 823 } |
| 824 Offset->dump(Func); |
| 825 } |
| 826 Str << "]"; |
| 827 } |
| 828 |
| 829 void VariableSplit::emit(const Cfg *Func) const { |
| 830 Ostream &Str = Func->getContext()->getStrEmit(); |
| 831 assert(Var->getLocalUseNode() == NULL || |
| 832 Var->getLocalUseNode() == Func->getCurrentNode()); |
| 833 assert(!Var->hasReg()); |
| 834 // The following is copied/adapted from TargetX8632::emitVariable(). |
| 835 const TargetLowering *Target = Func->getTarget(); |
| 836 const Type Ty = IceType_i32; |
| 837 Str << TypeX8632Attributes[Ty].WidthString << " [" |
| 838 << Target->getRegName(Target->getFrameOrStackReg(), Ty); |
| 839 int32_t Offset = Var->getStackOffset() + Target->getStackAdjustment(); |
| 840 if (Part == High) |
| 841 Offset += 4; |
| 842 if (Offset) { |
| 843 if (Offset > 0) |
| 844 Str << "+"; |
| 845 Str << Offset; |
| 846 } |
| 847 Str << "]"; |
| 848 } |
| 849 |
| 850 void VariableSplit::dump(const Cfg *Func) const { |
| 851 Ostream &Str = Func->getContext()->getStrDump(); |
| 852 switch (Part) { |
| 853 case Low: |
| 854 Str << "low"; |
| 855 break; |
| 856 case High: |
| 857 Str << "high"; |
| 858 break; |
| 859 default: |
| 860 Str << "???"; |
| 861 break; |
| 862 } |
| 863 Str << "("; |
| 864 Var->dump(Func); |
| 865 Str << ")"; |
| 866 } |
| 867 |
| 868 } // end of namespace Ice |
OLD | NEW |