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