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

Side by Side Diff: src/IceInstX8632.cpp

Issue 265703002: Add Om1 lowering with no optimizations (Closed) Base URL: https://gerrit.chromium.org/gerrit/p/native_client/pnacl-subzero.git@master
Patch Set: Created 6 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
(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
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698