uint64_t Addr,
const MCDisassembler *Decoder);
-static bool Check(DecodeStatus &Out, DecodeStatus In) {
- switch (In) {
- case MCDisassembler::Success:
- // Out stays the same.
- return true;
- case MCDisassembler::SoftFail:
- Out = In;
- return true;
- case MCDisassembler::Fail:
- Out = In;
- return false;
- }
- llvm_unreachable("Invalid DecodeStatus!");
-}
-
#include "AArch64GenDisassemblerTables.inc"
#include "AArch64GenInstrInfo.inc"
} // end anonymous namespace
-static bool Check(DecodeStatus &Out, DecodeStatus In) {
- switch (In) {
- case MCDisassembler::Success:
- // Out stays the same.
- return true;
- case MCDisassembler::SoftFail:
- Out = In;
- return true;
- case MCDisassembler::Fail:
- Out = In;
- return false;
- }
- llvm_unreachable("Invalid DecodeStatus!");
-}
-
// Forward declare these because the autogenerated code will reference them.
// Definitions are further down.
static DecodeStatus DecodeGPRRegisterClass(MCInst &Inst, unsigned RegNo,
// CHECK: case 0:
// CHECK-NEXT: tmp = fieldFromInstruction(insn, 8, 3);
-// CHECK-NEXT: if (DecodeRegClassRegisterClass(MI, tmp, Address, Decoder) == MCDisassembler::Fail) { return MCDisassembler::Fail; }
+// CHECK-NEXT: if (!Check(S, DecodeRegClassRegisterClass(MI, tmp, Address, Decoder))) { return MCDisassembler::Fail; }
// CHECK-NEXT: tmp = fieldFromInstruction(insn, 0, 3);
-// CHECK-NEXT: if (DecodeRegClassRegisterClass(MI, tmp, Address, Decoder) == MCDisassembler::Fail) { return MCDisassembler::Fail; }
+// CHECK-NEXT: if (!Check(S, DecodeRegClassRegisterClass(MI, tmp, Address, Decoder))) { return MCDisassembler::Fail; }
// CHECK-NEXT: tmp = fieldFromInstruction(insn, 11, 16);
// CHECK-NEXT: MI.addOperand(MCOperand::createImm(tmp));
// CHECK-NEXT: return S;
// CHECK-NEXT: case 1:
// CHECK-NEXT: tmp = fieldFromInstruction(insn, 8, 3);
-// CHECK-NEXT: if (DecodeRegClassRegisterClass(MI, tmp, Address, Decoder) == MCDisassembler::Fail) { return MCDisassembler::Fail; }
+// CHECK-NEXT: if (!Check(S, DecodeRegClassRegisterClass(MI, tmp, Address, Decoder))) { return MCDisassembler::Fail; }
// CHECK-NEXT: tmp = fieldFromInstruction(insn, 0, 3);
-// CHECK-NEXT: if (DecodeRegClassRegisterClass(MI, tmp, Address, Decoder) == MCDisassembler::Fail) { return MCDisassembler::Fail; }
+// CHECK-NEXT: if (!Check(S, DecodeRegClassRegisterClass(MI, tmp, Address, Decoder))) { return MCDisassembler::Fail; }
// CHECK-NEXT: tmp = 0x0;
// CHECK-NEXT: insertBits(tmp, fieldFromInstruction(insn, 11, 16), 16, 16);
// CHECK-NEXT: insertBits(tmp, fieldFromInstruction(insn, 27, 16), 0, 16);
// CHECK-NEXT: /* 22 */ MCD::OPC_Decode, {{[0-9]+}}, 1, 1, // Opcode: InstA
// CHECK-NEXT: /* 26 */ MCD::OPC_Fail,
-// CHECK: if (DecodeInstB(MI, insn, Address, Decoder) == MCDisassembler::Fail) { DecodeComplete = false; return MCDisassembler::Fail; }
+// CHECK: if (!Check(S, DecodeInstB(MI, insn, Address, Decoder))) { DecodeComplete = false; return MCDisassembler::Fail; }
// CHECK-NEXT: /* 37 */ MCD::OPC_TryDecode, {{[0-9]+}}, 1, 1, 0, 0, 0, // Opcode: InstA, skip to: 44
// CHECK-NEXT: /* 44 */ MCD::OPC_Fail,
-// CHECK: if (DecodeInstB(MI, insn, Address, Decoder) == MCDisassembler::Fail) { DecodeComplete = false; return MCDisassembler::Fail; }
-// CHECK: if (DecodeInstA(MI, insn, Address, Decoder) == MCDisassembler::Fail) { DecodeComplete = false; return MCDisassembler::Fail; }
+// CHECK: if (!Check(S, DecodeInstB(MI, insn, Address, Decoder))) { DecodeComplete = false; return MCDisassembler::Fail; }
+// CHECK: if (!Check(S, DecodeInstA(MI, insn, Address, Decoder))) { DecodeComplete = false; return MCDisassembler::Fail; }
// CHECK-NEXT: /* 22 */ MCD::OPC_Decode, {{[0-9]+}}, 1, 1, // Opcode: InstA
// CHECK-NEXT: /* 26 */ MCD::OPC_Fail,
-// CHECK: if (DecodeInstBOp(MI, tmp, Address, Decoder) == MCDisassembler::Fail) { DecodeComplete = false; return MCDisassembler::Fail; }
+// CHECK: if (!Check(S, DecodeInstBOp(MI, tmp, Address, Decoder))) { DecodeComplete = false; return MCDisassembler::Fail; }
std::vector<EncodingAndInst> NumberedEncodings;
public:
- // Defaults preserved here for documentation, even though they aren't
- // strictly necessary given the way that this is currently being called.
- DecoderEmitter(RecordKeeper &R, std::string PredicateNamespace,
- std::string GPrefix = "if (",
- std::string GPostfix = " == MCDisassembler::Fail)",
- std::string ROK = "MCDisassembler::Success",
- std::string RFail = "MCDisassembler::Fail", std::string L = "")
- : RK(R), Target(R), PredicateNamespace(std::move(PredicateNamespace)),
- GuardPrefix(std::move(GPrefix)), GuardPostfix(std::move(GPostfix)),
- ReturnOK(std::move(ROK)), ReturnFail(std::move(RFail)),
- Locals(std::move(L)) {}
+ DecoderEmitter(RecordKeeper &R, std::string PredicateNamespace)
+ : RK(R), Target(R), PredicateNamespace(std::move(PredicateNamespace)) {}
// Emit the decoder state machine table.
void emitTable(formatted_raw_ostream &o, DecoderTable &Table,
public:
std::string PredicateNamespace;
- std::string GuardPrefix, GuardPostfix;
- std::string ReturnOK, ReturnFail;
- std::string Locals;
};
} // end anonymous namespace
if (Decoder != "") {
OpHasCompleteDecoder = OpInfo.HasCompleteDecoder;
- o.indent(Indentation) << Emitter->GuardPrefix << Decoder
- << "(MI, tmp, Address, Decoder)"
- << Emitter->GuardPostfix
- << " { " << (OpHasCompleteDecoder ? "" : "DecodeComplete = false; ")
- << "return MCDisassembler::Fail; }\n";
+ o.indent(Indentation) << "if (!Check(S, " << Decoder
+ << "(MI, tmp, Address, Decoder))) { "
+ << (OpHasCompleteDecoder ? ""
+ : "DecodeComplete = false; ")
+ << "return MCDisassembler::Fail; }\n";
} else {
OpHasCompleteDecoder = true;
o.indent(Indentation) << "MI.addOperand(MCOperand::createImm(tmp));\n";
// If a custom instruction decoder was specified, use that.
if (Op.numFields() == 0 && !Op.Decoder.empty()) {
HasCompleteDecoder = Op.HasCompleteDecoder;
- OS.indent(Indentation) << Emitter->GuardPrefix << Op.Decoder
- << "(MI, insn, Address, Decoder)"
- << Emitter->GuardPostfix
- << " { " << (HasCompleteDecoder ? "" : "DecodeComplete = false; ")
- << "return MCDisassembler::Fail; }\n";
+ OS.indent(Indentation)
+ << "if (!Check(S, " << Op.Decoder
+ << "(MI, insn, Address, Decoder))) { "
+ << (HasCompleteDecoder ? "" : "DecodeComplete = false; ")
+ << "return MCDisassembler::Fail; }\n";
break;
}
<< "}\n\n";
}
+// Helper to propagate SoftFail status. Returns false if the status is Fail;
+// callers are expected to early-exit in that condition. (Note, the '&' operator
+// is correct to propagate the values of this enum; see comment on 'enum
+// DecodeStatus'.)
+static void emitCheck(formatted_raw_ostream &OS) {
+ OS << "static bool Check(DecodeStatus &Out, DecodeStatus In) {\n"
+ << " Out = static_cast<DecodeStatus>(Out & In);"
+ << " return Out != MCDisassembler::Fail;\n"
+ << "}\n\n";
+}
+
// Emits disassembler code for instruction decoding.
void DecoderEmitter::run(raw_ostream &o) {
formatted_raw_ostream OS(o);
emitFieldFromInstruction(OS);
emitInsertBits(OS);
+ emitCheck(OS);
Target.reverseBitsForLittleEndianEncoding();
namespace llvm {
void EmitDecoder(RecordKeeper &RK, raw_ostream &OS,
- const std::string &PredicateNamespace,
- const std::string &GPrefix, const std::string &GPostfix,
- const std::string &ROK, const std::string &RFail,
- const std::string &L) {
- DecoderEmitter(RK, PredicateNamespace, GPrefix, GPostfix, ROK, RFail, L)
- .run(OS);
+ const std::string &PredicateNamespace) {
+ DecoderEmitter(RK, PredicateNamespace).run(OS);
}
} // end namespace llvm
namespace llvm {
extern void EmitDecoder(RecordKeeper &RK, raw_ostream &OS,
- const std::string &PredicateNamespace,
- const std::string &GPrefix, const std::string &GPostfix,
- const std::string &ROK, const std::string &RFail,
- const std::string &L);
+ const std::string &PredicateNamespace);
void EmitDisassembler(RecordKeeper &Records, raw_ostream &OS) {
CodeGenTarget Target(Records);
return;
}
- // ARM and Thumb have a CHECK() macro to deal with DecodeStatuses.
- if (Target.getName() == "ARM" || Target.getName() == "Thumb" ||
- Target.getName() == "AArch64" || Target.getName() == "ARM64") {
- std::string PredicateNamespace = std::string(Target.getName());
- if (PredicateNamespace == "Thumb")
- PredicateNamespace = "ARM";
-
- EmitDecoder(Records, OS, PredicateNamespace, "if (!Check(S, ", "))", "S",
- "MCDisassembler::Fail",
- " MCDisassembler::DecodeStatus S = "
- "MCDisassembler::Success;\n(void)S;");
- return;
- }
-
- EmitDecoder(Records, OS, std::string(Target.getName()), "if (",
- " == MCDisassembler::Fail)", "MCDisassembler::Success",
- "MCDisassembler::Fail", "");
+ std::string PredicateNamespace = std::string(Target.getName());
+ if (PredicateNamespace == "Thumb")
+ PredicateNamespace = "ARM";
+ EmitDecoder(Records, OS, PredicateNamespace);
}
} // end namespace llvm