Chromium Code Reviews| Index: src/IceInstX8632.cpp |
| diff --git a/src/IceInstX8632.cpp b/src/IceInstX8632.cpp |
| index dbacd58a87bdcb65a911de3849a96ea7c20692c6..f9bb382d4f9280f8bac4e5f84c74c29dec15dec5 100644 |
| --- a/src/IceInstX8632.cpp |
| +++ b/src/IceInstX8632.cpp |
| @@ -375,6 +375,33 @@ void emitIASBytes(const Cfg *Func, const x86::AssemblerX86 *Asm, |
| } |
| } |
| +void emitIASBytesBranch(const Cfg *Func, const x86::AssemblerX86 *Asm, |
| + intptr_t StartPosition, const x86::Label *Label, |
| + const IceString &LabelName, bool Near) { |
| + // If this is a backward branch (label is bound), we're good and know |
| + // the offset. If this is a forward branch, then we can't actually emit |
| + // the thing as text in a streaming manner, because the fixup hasn't |
| + // happened yet. Instead, emit .long ($BranchLabel) - (. + 4), in that |
| + // case and let the external assembler take care of that fixup. |
| + if (Label->IsBound()) { |
| + emitIASBytes(Func, Asm, StartPosition); |
| + return; |
| + } |
| + const intptr_t FwdBranchSize = Near ? 1 : 4; |
|
Jim Stichnoth
2014/10/22 18:01:14
Should this be size_t or ptrdiff_t or something si
jvoung (off chromium)
2014/10/22 20:43:58
Hmm, it could be a ptrdiff_t too, but I had it as
|
| + const IceString FwdBranchDirective = Near ? ".byte" : ".long"; |
| + Ostream &Str = Func->getContext()->getStrEmit(); |
| + intptr_t EndPosition = Asm->GetPosition(); |
| + assert(EndPosition - StartPosition > FwdBranchSize); |
| + for (intptr_t i = StartPosition; i < EndPosition - FwdBranchSize; ++i) { |
| + Str << "\t.byte 0x"; |
| + Str.write_hex(Asm->LoadBuffer<uint8_t>(i)); |
| + Str << "\n"; |
| + } |
| + Str << "\t" << FwdBranchDirective << " " << LabelName << " - (. + " |
| + << FwdBranchSize << ")\n"; |
| + return; |
| +} |
| + |
| } // end of anonymous namespace |
| void InstX8632::dump(const Cfg *Func) const { |
| @@ -388,6 +415,15 @@ void InstX8632Label::emit(const Cfg *Func) const { |
| Str << getName(Func) << ":\n"; |
| } |
| +void InstX8632Label::emitIAS(const Cfg *Func) const { |
| + x86::AssemblerX86 *Asm = Func->getAssembler<x86::AssemblerX86>(); |
| + Asm->Bind(&AsmLabel); |
| + // TODO(jvoung): remove the the textual label once forward branch |
| + // fixups are used (and text assembler is not used). |
| + Ostream &Str = Func->getContext()->getStrEmit(); |
| + Str << getName(Func) << ":\n"; |
| +} |
| + |
| void InstX8632Label::dump(const Cfg *Func) const { |
| Ostream &Str = Func->getContext()->getStrDump(); |
| Str << getName(Func) << ":"; |
| @@ -417,6 +453,47 @@ void InstX8632Br::emit(const Cfg *Func) const { |
| } |
| } |
| +void InstX8632Br::emitIAS(const Cfg *Func) const { |
| + x86::AssemblerX86 *Asm = Func->getAssembler<x86::AssemblerX86>(); |
| + intptr_t StartPosition = Asm->GetPosition(); |
| + if (Label) { |
| + x86::Label *L = Label->getAsmLabel(); |
| + // In all these cases, local Labels should only be used for Near. |
|
Jim Stichnoth
2014/10/22 18:01:14
Is there any validation of this assumption? Stric
jvoung (off chromium)
2014/10/22 20:43:58
Yes, it's a bit roundabout, but when the forward-r
jvoung (off chromium)
2014/10/23 18:19:51
As far as stats, so far on GCC, eon, perlbmk, and
|
| + const bool Near = true; |
| + if (Condition == CondX86::Br_None) { |
| + Asm->jmp(L, Near); |
| + } else { |
| + Asm->j(Condition, L, Near); |
| + } |
| + emitIASBytesBranch(Func, Asm, StartPosition, L, Label->getName(Func), Near); |
| + } else { |
| + // Pessimistically assume it's far. This only affects Labels that |
| + // are not Bound. |
| + const bool Near = false; |
| + if (Condition == CondX86::Br_None) { |
| + x86::Label *L = |
| + Asm->GetOrCreateCfgNodeLabel(getTargetFalse()->getIndex()); |
| + assert(!getTargetTrue()); |
| + Asm->jmp(L, Near); |
| + emitIASBytesBranch(Func, Asm, StartPosition, L, |
| + getTargetFalse()->getAsmName(), Near); |
| + } else { |
| + x86::Label *L = Asm->GetOrCreateCfgNodeLabel(getTargetTrue()->getIndex()); |
| + Asm->j(Condition, L, Near); |
| + emitIASBytesBranch(Func, Asm, StartPosition, L, |
| + getTargetTrue()->getAsmName(), Near); |
| + StartPosition = Asm->GetPosition(); |
| + if (getTargetFalse()) { |
| + x86::Label *L2 = |
| + Asm->GetOrCreateCfgNodeLabel(getTargetFalse()->getIndex()); |
| + Asm->jmp(L2, Near); |
| + emitIASBytesBranch(Func, Asm, StartPosition, L2, |
| + getTargetFalse()->getAsmName(), Near); |
| + } |
| + } |
| + } |
| +} |
| + |
| void InstX8632Br::dump(const Cfg *Func) const { |
| Ostream &Str = Func->getContext()->getStrDump(); |
| Str << "br "; |