void genSetPSPSym(regNumber initReg, bool* pInitRegZeroed);
void genUpdateCurrentFunclet(BasicBlock* block);
+#if defined(_TARGET_ARM_)
+ void genInsertNopForUnwinder(BasicBlock* block);
+#endif
#else // FEATURE_EH_FUNCLETS
return;
}
+#if defined(_TARGET_ARM_)
+ void genInsertNopForUnwinder(BasicBlock* block)
+ {
+ return;
+ }
+#endif
+
#endif // FEATURE_EH_FUNCLETS
void genGeneratePrologsAndEpilogs();
// jump target using bbJumpDest - that is already used to point
// to the finally block. So just skip past the BBJ_ALWAYS unless the
// block is RETLESS.
- if (!(block->bbFlags & BBF_RETLESS_CALL))
- {
- assert(block->isBBCallAlwaysPair());
-
- lblk = block;
- block = block->bbNext;
- }
- return block;
+ assert(!(block->bbFlags & BBF_RETLESS_CALL));
+ assert(block->isBBCallAlwaysPair());
+ return block->bbNext;
}
//------------------------------------------------------------------------
}
}
}
+
+#if defined(_TARGET_ARM_)
+void CodeGen::genInsertNopForUnwinder(BasicBlock* block)
+{
+ // If this block is the target of a finally return, we need to add a preceding NOP, in the same EH region,
+ // so the unwinder doesn't get confused by our "movw lr, xxx; movt lr, xxx; b Lyyy" calling convention that
+ // calls the funclet during non-exceptional control flow.
+ if (block->bbFlags & BBF_FINALLY_TARGET)
+ {
+ assert(block->bbFlags & BBF_JMP_TARGET);
+
+#ifdef DEBUG
+ if (compiler->verbose)
+ {
+ printf("\nEmitting finally target NOP predecessor for BB%02u\n", block->bbNum);
+ }
+#endif
+ // Create a label that we'll use for computing the start of an EH region, if this block is
+ // at the beginning of such a region. If we used the existing bbEmitCookie as is for
+ // determining the EH regions, then this NOP would end up outside of the region, if this
+ // block starts an EH region. If we pointed the existing bbEmitCookie here, then the NOP
+ // would be executed, which we would prefer not to do.
+
+ block->bbUnwindNopEmitCookie =
+ getEmitter()->emitAddLabel(gcInfo.gcVarPtrSetCur, gcInfo.gcRegGCrefSetCur, gcInfo.gcRegByrefSetCur);
+
+ instGen(INS_nop);
+ }
+}
+#endif
+
#endif // FEATURE_EH_FUNCLETS
/*****************************************************************************
#if FEATURE_EH_FUNCLETS
#if defined(_TARGET_ARM_)
- // If this block is the target of a finally return, we need to add a preceding NOP, in the same EH region,
- // so the unwinder doesn't get confused by our "movw lr, xxx; movt lr, xxx; b Lyyy" calling convention that
- // calls the funclet during non-exceptional control flow.
- if (block->bbFlags & BBF_FINALLY_TARGET)
- {
- assert(block->bbFlags & BBF_JMP_TARGET);
-
-#ifdef DEBUG
- if (compiler->verbose)
- {
- printf("\nEmitting finally target NOP predecessor for BB%02u\n", block->bbNum);
- }
-#endif
- // Create a label that we'll use for computing the start of an EH region, if this block is
- // at the beginning of such a region. If we used the existing bbEmitCookie as is for
- // determining the EH regions, then this NOP would end up outside of the region, if this
- // block starts an EH region. If we pointed the existing bbEmitCookie here, then the NOP
- // would be executed, which we would prefer not to do.
-
- block->bbUnwindNopEmitCookie =
- getEmitter()->emitAddLabel(gcInfo.gcVarPtrSetCur, gcInfo.gcRegGCrefSetCur, gcInfo.gcRegByrefSetCur);
-
- instGen(INS_nop);
- }
+ genInsertNopForUnwinder(block);
#endif // defined(_TARGET_ARM_)
genUpdateCurrentFunclet(block);
}
}
+#if FEATURE_EH_FUNCLETS && defined(_TARGET_ARM_)
+ genInsertNopForUnwinder(block);
+#endif
+
/* Start a new code output block */
genUpdateCurrentFunclet(block);
inst_RV_IV(ins, reg, tree->gtIntCon.gtIconVal, emitActualTypeSize(tree->TypeGet()), flags);
break;
-#if CPU_LONG_USES_REGPAIR
case GT_CNS_LNG:
assert(size == EA_4BYTE || size == EA_8BYTE);
constVal = (ssize_t)(tree->gtLngCon.gtLconVal >> 32);
size = EA_4BYTE;
}
-#ifndef LEGACY_BACKEND
-#ifdef _TARGET_ARM_
+#if defined(_TARGET_ARM_) && CPU_LONG_USES_REGPAIR
if ((ins != INS_mov) && !arm_Valid_Imm_For_Instr(ins, constVal, flags))
{
regNumber constReg = (offs == 0) ? genRegPairLo(tree->gtRegPair) : genRegPairHi(tree->gtRegPair);
getEmitter()->emitIns_R_R(ins, size, reg, constReg, flags);
break;
}
-#endif // _TARGET_ARM_
-#endif // !LEGACY_BACKEND
+#endif // _TARGET_ARM_ && CPU_LONG_USES_REGPAIR
inst_RV_IV(ins, reg, constVal, size, flags);
break;
-#endif // CPU_LONG_USES_REGPAIR
case GT_COMMA:
tree = tree->gtOp.gtOp2;
void* cookie;
-#if FEATURE_EH_FUNCLETS && defined(_TARGET_ARM_) && defined(LEGACY_BACKEND)
+#if FEATURE_EH_FUNCLETS && defined(_TARGET_ARM_)
if (block->bbFlags & BBF_FINALLY_TARGET)
{
// Use the offset of the beginning of the NOP padding, not the main block.