emit_x64: Make EmitTerminal type-safe

Avoid the use of boost::variant::which, which tends to produce code which
is not verifiable at compile-time.
This commit is contained in:
MerryMage 2017-02-16 19:40:51 +00:00
parent e197b10b96
commit 058f7b5de6
2 changed files with 19 additions and 41 deletions

View file

@ -14,6 +14,7 @@
#include "backend_x64/jitstate.h" #include "backend_x64/jitstate.h"
#include "common/assert.h" #include "common/assert.h"
#include "common/bit_util.h" #include "common/bit_util.h"
#include "common/variant_util.h"
#include "frontend/arm/types.h" #include "frontend/arm/types.h"
#include "frontend/ir/basic_block.h" #include "frontend/ir/basic_block.h"
#include "frontend/ir/location_descriptor.h" #include "frontend/ir/location_descriptor.h"
@ -3351,40 +3352,17 @@ void EmitX64::EmitCondPrelude(const IR::Block& block) {
Xbyak::Label pass = EmitCond(code, block.GetCondition()); Xbyak::Label pass = EmitCond(code, block.GetCondition());
EmitAddCycles(block.ConditionFailedCycleCount()); EmitAddCycles(block.ConditionFailedCycleCount());
EmitTerminalLinkBlock(IR::Term::LinkBlock{block.ConditionFailedLocation()}, block.Location()); EmitTerminal(IR::Term::LinkBlock{block.ConditionFailedLocation()}, block.Location());
code->L(pass); code->L(pass);
} }
void EmitX64::EmitTerminal(IR::Terminal terminal, IR::LocationDescriptor initial_location) { void EmitX64::EmitTerminal(IR::Terminal terminal, IR::LocationDescriptor initial_location) {
switch (terminal.which()) { Common::VisitVariant<void>(terminal, [this, &initial_location](auto x) {
case 1: this->EmitTerminal(x, initial_location);
EmitTerminalInterpret(boost::get<IR::Term::Interpret>(terminal), initial_location); });
return;
case 2:
EmitTerminalReturnToDispatch(boost::get<IR::Term::ReturnToDispatch>(terminal), initial_location);
return;
case 3:
EmitTerminalLinkBlock(boost::get<IR::Term::LinkBlock>(terminal), initial_location);
return;
case 4:
EmitTerminalLinkBlockFast(boost::get<IR::Term::LinkBlockFast>(terminal), initial_location);
return;
case 5:
EmitTerminalPopRSBHint(boost::get<IR::Term::PopRSBHint>(terminal), initial_location);
return;
case 6:
EmitTerminalIf(boost::get<IR::Term::If>(terminal), initial_location);
return;
case 7:
EmitTerminalCheckHalt(boost::get<IR::Term::CheckHalt>(terminal), initial_location);
return;
default:
ASSERT_MSG(false, "Invalid Terminal. Bad programmer.");
return;
}
} }
void EmitX64::EmitTerminalInterpret(IR::Term::Interpret terminal, IR::LocationDescriptor initial_location) { void EmitX64::EmitTerminal(IR::Term::Interpret terminal, IR::LocationDescriptor initial_location) {
ASSERT_MSG(terminal.next.TFlag() == initial_location.TFlag(), "Unimplemented"); ASSERT_MSG(terminal.next.TFlag() == initial_location.TFlag(), "Unimplemented");
ASSERT_MSG(terminal.next.EFlag() == initial_location.EFlag(), "Unimplemented"); ASSERT_MSG(terminal.next.EFlag() == initial_location.EFlag(), "Unimplemented");
@ -3397,11 +3375,11 @@ void EmitX64::EmitTerminalInterpret(IR::Term::Interpret terminal, IR::LocationDe
code->ReturnFromRunCode(false); // TODO: Check cycles code->ReturnFromRunCode(false); // TODO: Check cycles
} }
void EmitX64::EmitTerminalReturnToDispatch(IR::Term::ReturnToDispatch, IR::LocationDescriptor) { void EmitX64::EmitTerminal(IR::Term::ReturnToDispatch, IR::LocationDescriptor) {
code->ReturnFromRunCode(); code->ReturnFromRunCode();
} }
void EmitX64::EmitTerminalLinkBlock(IR::Term::LinkBlock terminal, IR::LocationDescriptor initial_location) { void EmitX64::EmitTerminal(IR::Term::LinkBlock terminal, IR::LocationDescriptor initial_location) {
using namespace Xbyak::util; using namespace Xbyak::util;
if (terminal.next.TFlag() != initial_location.TFlag()) { if (terminal.next.TFlag() != initial_location.TFlag()) {
@ -3432,7 +3410,7 @@ void EmitX64::EmitTerminalLinkBlock(IR::Term::LinkBlock terminal, IR::LocationDe
code->ReturnFromRunCode(); // TODO: Check cycles, Properly do a link code->ReturnFromRunCode(); // TODO: Check cycles, Properly do a link
} }
void EmitX64::EmitTerminalLinkBlockFast(IR::Term::LinkBlockFast terminal, IR::LocationDescriptor initial_location) { void EmitX64::EmitTerminal(IR::Term::LinkBlockFast terminal, IR::LocationDescriptor initial_location) {
using namespace Xbyak::util; using namespace Xbyak::util;
if (terminal.next.TFlag() != initial_location.TFlag()) { if (terminal.next.TFlag() != initial_location.TFlag()) {
@ -3458,7 +3436,7 @@ void EmitX64::EmitTerminalLinkBlockFast(IR::Term::LinkBlockFast terminal, IR::Lo
} }
} }
void EmitX64::EmitTerminalPopRSBHint(IR::Term::PopRSBHint, IR::LocationDescriptor) { void EmitX64::EmitTerminal(IR::Term::PopRSBHint, IR::LocationDescriptor) {
using namespace Xbyak::util; using namespace Xbyak::util;
// This calculation has to match up with IREmitter::PushRSB // This calculation has to match up with IREmitter::PushRSB
@ -3479,14 +3457,14 @@ void EmitX64::EmitTerminalPopRSBHint(IR::Term::PopRSBHint, IR::LocationDescripto
code->jmp(rax); code->jmp(rax);
} }
void EmitX64::EmitTerminalIf(IR::Term::If terminal, IR::LocationDescriptor initial_location) { void EmitX64::EmitTerminal(IR::Term::If terminal, IR::LocationDescriptor initial_location) {
Xbyak::Label pass = EmitCond(code, terminal.if_); Xbyak::Label pass = EmitCond(code, terminal.if_);
EmitTerminal(terminal.else_, initial_location); EmitTerminal(terminal.else_, initial_location);
code->L(pass); code->L(pass);
EmitTerminal(terminal.then_, initial_location); EmitTerminal(terminal.then_, initial_location);
} }
void EmitX64::EmitTerminalCheckHalt(IR::Term::CheckHalt terminal, IR::LocationDescriptor initial_location) { void EmitX64::EmitTerminal(IR::Term::CheckHalt terminal, IR::LocationDescriptor initial_location) {
using namespace Xbyak::util; using namespace Xbyak::util;
code->cmp(code->byte[r15 + offsetof(JitState, halt_requested)], u8(0)); code->cmp(code->byte[r15 + offsetof(JitState, halt_requested)], u8(0));

View file

@ -64,13 +64,13 @@ private:
// Terminal instruction emitters // Terminal instruction emitters
void EmitTerminal(IR::Terminal terminal, IR::LocationDescriptor initial_location); void EmitTerminal(IR::Terminal terminal, IR::LocationDescriptor initial_location);
void EmitTerminalInterpret(IR::Term::Interpret terminal, IR::LocationDescriptor initial_location); void EmitTerminal(IR::Term::Interpret terminal, IR::LocationDescriptor initial_location);
void EmitTerminalReturnToDispatch(IR::Term::ReturnToDispatch terminal, IR::LocationDescriptor initial_location); void EmitTerminal(IR::Term::ReturnToDispatch terminal, IR::LocationDescriptor initial_location);
void EmitTerminalLinkBlock(IR::Term::LinkBlock terminal, IR::LocationDescriptor initial_location); void EmitTerminal(IR::Term::LinkBlock terminal, IR::LocationDescriptor initial_location);
void EmitTerminalLinkBlockFast(IR::Term::LinkBlockFast terminal, IR::LocationDescriptor initial_location); void EmitTerminal(IR::Term::LinkBlockFast terminal, IR::LocationDescriptor initial_location);
void EmitTerminalPopRSBHint(IR::Term::PopRSBHint terminal, IR::LocationDescriptor initial_location); void EmitTerminal(IR::Term::PopRSBHint terminal, IR::LocationDescriptor initial_location);
void EmitTerminalIf(IR::Term::If terminal, IR::LocationDescriptor initial_location); void EmitTerminal(IR::Term::If terminal, IR::LocationDescriptor initial_location);
void EmitTerminalCheckHalt(IR::Term::CheckHalt terminal, IR::LocationDescriptor initial_location); void EmitTerminal(IR::Term::CheckHalt terminal, IR::LocationDescriptor initial_location);
// Patching // Patching
struct PatchInformation { struct PatchInformation {