aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--lib/Target/ARM/MCTargetDesc/ARMMCNaCl.cpp147
1 files changed, 73 insertions, 74 deletions
diff --git a/lib/Target/ARM/MCTargetDesc/ARMMCNaCl.cpp b/lib/Target/ARM/MCTargetDesc/ARMMCNaCl.cpp
index 98ee80c358..af2b04086a 100644
--- a/lib/Target/ARM/MCTargetDesc/ARMMCNaCl.cpp
+++ b/lib/Target/ARM/MCTargetDesc/ARMMCNaCl.cpp
@@ -66,9 +66,9 @@ static void EmitTST(MCStreamer &Out, unsigned Reg) {
// it must ensure that the two instructions are in the same bundle.
// It just so happens that the SFI_NOP_IF_AT_BUNDLE_END is always
// emitted in conjunction with a SFI_DATA_MASK
-//
+//
static void EmitDataMask(int I, MCInst Saved[], MCStreamer &Out) {
- assert(I == 3 &&
+ assert(I == 3 &&
(ARM::SFI_NOP_IF_AT_BUNDLE_END == Saved[0].getOpcode()) &&
(ARM::SFI_DATA_MASK == Saved[2].getOpcode()) &&
"Unexpected SFI Pseudo while lowering");
@@ -190,6 +190,7 @@ static void EmitGuardSpLoad(int I, MCInst Saved[], MCStreamer &Out) {
}
namespace llvm {
+
// CustomExpandInstNaClARM -
// If Inst is a NaCl pseudo instruction, emits the substitute
// expansion to the MCStreamer and returns true.
@@ -200,101 +201,99 @@ namespace llvm {
// Care must be taken to ensure that this does not result in an infinite
// loop. Also, global state must be managed carefully so that it is
// consistent during recursive calls.
-//
-// We need global state to keep track of the explicit prefix (PREFIX_*)
-// instructions. Unfortunately, the assembly parser prefers to generate
-// these instead of combined instructions. At this time, having only
-// one explicit prefix is supported.
-
-
bool CustomExpandInstNaClARM(const MCInst &Inst, MCStreamer &Out) {
+ // Logic:
+ // This is somewhat convoluted, but in the current model, the SFI
+ // guard pseudo instructions occur PRIOR to the actual instruction.
+ // So, the bundling/alignment operation has to refer to the FOLLOWING
+ // instructions.
+ //
+ // When a SFI pseudo is detected, it is saved. Then, the saved SFI
+ // pseudo and the very next instructions (their amount depending on the kind
+ // of the SFI pseudo) are used as arguments to the Emit*() functions in
+ // this file.
+ //
+ // Some static data is used to preserve state accross calls (TODO: can this
+ // be lifted into a proper state object?)
+ //
+ // Saved: the saved instructions (starting with the SFI_ pseudo).
+ // SavedCount: the amount of saved instructions required for the SFI pseudo
+ // that's being expanded.
+ // I: the index of the currently saved instruction - used to track
+ // where in Saved to insert the instruction and how many more
+ // remain.
+ //
const int MaxSaved = 4;
static MCInst Saved[MaxSaved];
static int SaveCount = 0;
static int I = 0;
- // This routine only executes if RecurseGuard == 0
- static bool RecurseGuard = false;
// If we are emitting to .s, just emit all pseudo-instructions directly.
if (Out.hasRawTextSupport()) {
return false;
}
- //No recursive calls allowed;
- if (RecurseGuard) return false;
-
- unsigned Opc = Inst.getOpcode();
+ // Protect against recursive execution. If RecurseGuard == true, it means
+ // we're already in the process of expanding a custom instruction, and we
+ // don't need to run recursively on anything generated by such an expansion.
+ static bool RecurseGuard = false;
+ if (RecurseGuard)
+ return false;
DEBUG(dbgs() << "CustomExpandInstNaClARM("; Inst.dump(); dbgs() << ")\n");
- // Note: SFI_NOP_IF_AT_BUNDLE_END is only emitted directly as part of
- // a stack guard in conjunction with a SFI_DATA_MASK
-
- // Logic:
- // This is somewhat convoluted, but in the current model, the SFI
- // guard pseudo instructions occur PRIOR to the actual instruction.
- // So, the bundling/alignment operation has to refer to the FOLLOWING
- // one or two instructions.
- //
- // When a SFI_* pseudo is detected, it is saved. Then, the saved SFI_*
- // pseudo and the very next one or two instructions are used as arguments to
- // the Emit*() functions in this file. This is the reason why we have a
- // doublely nested switch here. First, to save the SFI_* pseudo, then to
- // emit it and the next instruction
-
- // By default, we only need to save two or three instructions
-
if ((I == 0) && (SaveCount == 0)) {
- // Base State, no saved instructions.
- // If the current instruction is a SFI instruction, set the SaveCount
- // and fall through.
- switch (Opc) {
- default:
- SaveCount = 0; // Nothing to do.
- return false; // Handle this Inst elsewhere.
- case ARM::SFI_NOP_IF_AT_BUNDLE_END:
- SaveCount = 3;
- break;
- case ARM::SFI_DATA_MASK:
- SaveCount = 0; // Do nothing.
- break;
- case ARM::SFI_GUARD_CALL:
- case ARM::SFI_GUARD_INDIRECT_CALL:
- case ARM::SFI_GUARD_INDIRECT_JMP:
- case ARM::SFI_GUARD_RETURN:
- case ARM::SFI_GUARD_LOADSTORE:
- case ARM::SFI_GUARD_LOADSTORE_TST:
- SaveCount = 2;
- break;
- case ARM::SFI_GUARD_SP_LOAD:
- SaveCount = 4;
- break;
+ // Base state: no SFI guard identified yet and no saving started.
+ switch (Inst.getOpcode()) {
+ default:
+ // We don't handle non-SFI guards here
+ return false;
+ case ARM::SFI_NOP_IF_AT_BUNDLE_END:
+ // Note: SFI_NOP_IF_AT_BUNDLE_END is only emitted directly as part of
+ // a stack guard in conjunction with a SFI_DATA_MASK.
+ SaveCount = 3;
+ break;
+ case ARM::SFI_DATA_MASK:
+ assert(0 &&
+ "SFI_DATA_MASK found without preceding SFI_NOP_IF_AT_BUNDLE_END");
+ return false;
+ case ARM::SFI_GUARD_CALL:
+ case ARM::SFI_GUARD_INDIRECT_CALL:
+ case ARM::SFI_GUARD_INDIRECT_JMP:
+ case ARM::SFI_GUARD_RETURN:
+ case ARM::SFI_GUARD_LOADSTORE:
+ case ARM::SFI_GUARD_LOADSTORE_TST:
+ SaveCount = 2;
+ break;
+ case ARM::SFI_GUARD_SP_LOAD:
+ SaveCount = 4;
+ break;
}
}
+ // We're in "saving instructions" state
if (I < SaveCount) {
- // Othewise, save the current Inst and return
+ // This instruction has to be saved
+ assert(I < MaxSaved && "Trying to save too many instructions");
Saved[I++] = Inst;
if (I < SaveCount)
return true;
- // Else fall through to next stat
}
- if (SaveCount > 0) {
- assert(I == SaveCount && "Bookeeping Error");
- SaveCount = 0; // Reset for next iteration
- // The following calls may call Out.EmitInstruction()
- // which must not again call CustomExpandInst ...
- // So set RecurseGuard = 1;
- RecurseGuard = true;
+ // We're in "saved enough instructions, time to emit" state
+ assert(I == SaveCount && SaveCount > 0 && "Bookeeping Error");
- switch (Saved[0].getOpcode()) {
- default: /* No action required */ break;
+ // When calling Emit* functions, do that with RecurseGuard set (the comment
+ // at the beginning of this function explains why)
+ RecurseGuard = true;
+ switch (Saved[0].getOpcode()) {
+ default:
+ break;
case ARM::SFI_NOP_IF_AT_BUNDLE_END:
EmitDataMask(I, Saved, Out);
break;
case ARM::SFI_DATA_MASK:
- assert(0 && "Unexpected NOP_IF_AT_BUNDLE_END as a Saved Inst");
+ assert(0 && "SFI_DATA_MASK can't start a SFI sequence");
break;
case ARM::SFI_GUARD_CALL:
EmitDirectGuardCall(I, Saved, Out);
@@ -317,14 +316,14 @@ bool CustomExpandInstNaClARM(const MCInst &Inst, MCStreamer &Out) {
case ARM::SFI_GUARD_SP_LOAD:
EmitGuardSpLoad(I, Saved, Out);
break;
- }
- I = 0; // Reset I for next.
- assert(RecurseGuard && "Illegal Depth");
- RecurseGuard = false;
- return true;
}
+ assert(RecurseGuard && "Illegal Depth");
+ RecurseGuard = false;
- return false;
+ // We're done expanding a SFI guard. Reset state vars.
+ SaveCount = 0;
+ I = 0;
+ return true;
}
} // namespace llvm