Checkpoint
This commit is contained in:
parent
e84492a449
commit
99be5acb89
3 changed files with 61 additions and 32 deletions
|
|
@ -103,7 +103,6 @@ static void emitDec(int n) {
|
||||||
|
|
||||||
|
|
||||||
__attribute__((noinline))
|
__attribute__((noinline))
|
||||||
__attribute__((optnone))
|
|
||||||
static void emitULong(unsigned long n) {
|
static void emitULong(unsigned long n) {
|
||||||
char buf[11];
|
char buf[11];
|
||||||
int i = 0;
|
int i = 0;
|
||||||
|
|
@ -300,7 +299,6 @@ static int format(const char *fmt, va_list ap) {
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
__attribute__((optnone))
|
|
||||||
int snprintf(char *buf, size_t n, const char *fmt, ...) {
|
int snprintf(char *buf, size_t n, const char *fmt, ...) {
|
||||||
gCur = buf;
|
gCur = buf;
|
||||||
// n == 0 must NOT touch the buffer (C99 7.19.6.5). Setting
|
// n == 0 must NOT touch the buffer (C99 7.19.6.5). Setting
|
||||||
|
|
|
||||||
|
|
@ -93,11 +93,26 @@ void W65816InstrInfo::copyPhysReg(MachineBasicBlock &MBB,
|
||||||
BuildMI(MBB, I, DL, get(W65816::STA_DP)).addImm(dstImg);
|
BuildMI(MBB, I, DL, get(W65816::STA_DP)).addImm(dstImg);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
// IMGn → IMGm: route through A. Caller is responsible for ensuring
|
// IMGn → IMGm: route through A, but PHA-bracket so A is preserved.
|
||||||
// A is dead at this program point (regalloc usually arranges this).
|
// Without the bracket, regalloc could insert this COPY between a
|
||||||
|
// def of A and the use of A (e.g. between `$a = COPY $img10` and
|
||||||
|
// `STAfi $a, slot`, when both vregs are alive simultaneously and
|
||||||
|
// the regalloc decides to shuffle img physregs in between). The
|
||||||
|
// unbracketed lda/sta clobbers A and the subsequent STAfi spills
|
||||||
|
// garbage. Observed under ptr32 + full IMG defs in the C++ try/
|
||||||
|
// catch path: `*p = 42` after `__cxa_allocate_exception` stored
|
||||||
|
// hi-half-of-ptr at lo-half-slot, breaking the indirect-long
|
||||||
|
// address setup so 42 landed at the wrong place.
|
||||||
|
//
|
||||||
|
// PHA bracket cost: +PHA (3 cyc, 1 byte) + PLA (4 cyc, 1 byte) = +7
|
||||||
|
// cyc, +2 bytes per IMG-IMG copy. These are rare (regalloc usually
|
||||||
|
// can avoid them by picking the same physreg for COPY's src and
|
||||||
|
// dst), so the cost is small.
|
||||||
if (srcImg >= 0 && dstImg >= 0) {
|
if (srcImg >= 0 && dstImg >= 0) {
|
||||||
|
BuildMI(MBB, I, DL, get(W65816::PHA));
|
||||||
BuildMI(MBB, I, DL, get(W65816::LDA_DP)).addImm(srcImg);
|
BuildMI(MBB, I, DL, get(W65816::LDA_DP)).addImm(srcImg);
|
||||||
BuildMI(MBB, I, DL, get(W65816::STA_DP)).addImm(dstImg);
|
BuildMI(MBB, I, DL, get(W65816::STA_DP)).addImm(dstImg);
|
||||||
|
BuildMI(MBB, I, DL, get(W65816::PLA));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
// SP -> A via TSC. Used by alloca / setjmp asm machinery.
|
// SP -> A via TSC. Used by alloca / setjmp asm machinery.
|
||||||
|
|
|
||||||
|
|
@ -226,22 +226,45 @@ bool W65816SjLjFinalize::runOnFunction(Function &F) {
|
||||||
Builder.CreateCondBr(IsUnwind, DispatchBB, EHContinueBB);
|
Builder.CreateCondBr(IsUnwind, DispatchBB, EHContinueBB);
|
||||||
|
|
||||||
// The landing-pad blocks each start with a `landingpad { ptr, i32 }`
|
// The landing-pad blocks each start with a `landingpad { ptr, i32 }`
|
||||||
// instruction. After we convert invokes to plain calls, those
|
// instruction. We need its catch-clause typeinfo arguments to build
|
||||||
// blocks are no longer reached via an unwind edge — the verifier
|
// the per-function catch table further down, so capture them BEFORE
|
||||||
// requires landingpads to be reached only from invoke unwind dests.
|
// erasing — the catchtab loop below uses the saved data instead of
|
||||||
// Remove the landingpad insts (they're no-ops now; the real
|
// re-reading from the IR.
|
||||||
// exception ptr / selector come from explicit fn_ctx.data loads
|
//
|
||||||
// SjLjEHPrepare emitted right after). Replace landingpad uses with
|
// Capture: per call_site, list of (typeinfo Constant*) for each
|
||||||
// poison since downstream code reads via GEPs, not via the inst's
|
// catch clause (skipping null = catch-all). De-dup landingpads
|
||||||
// result.
|
// (multiple call_sites can share a landing pad).
|
||||||
|
struct LPadInfo {
|
||||||
|
SmallVector<Constant *, 2> CatchTypes;
|
||||||
|
};
|
||||||
|
DenseMap<BasicBlock *, LPadInfo> LPadCatches;
|
||||||
SmallVector<LandingPadInst *, 4> LPads;
|
SmallVector<LandingPadInst *, 4> LPads;
|
||||||
for (auto &KV : CSToLPad) {
|
for (auto &KV : CSToLPad) {
|
||||||
if (LandingPadInst *LP = KV.second->getLandingPadInst())
|
BasicBlock *LPadBB = KV.second;
|
||||||
LPads.push_back(LP);
|
if (LPadCatches.count(LPadBB))
|
||||||
|
continue;
|
||||||
|
LandingPadInst *LP = LPadBB->getLandingPadInst();
|
||||||
|
if (!LP)
|
||||||
|
continue;
|
||||||
|
LPadInfo Info;
|
||||||
|
for (unsigned i = 0; i < LP->getNumClauses(); i++) {
|
||||||
|
if (LP->isCatch(i)) {
|
||||||
|
Constant *TIClause = cast<Constant>(LP->getClause(i));
|
||||||
|
if (TIClause->isNullValue())
|
||||||
|
continue;
|
||||||
|
Info.CatchTypes.push_back(TIClause);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
LPadCatches[LPadBB] = std::move(Info);
|
||||||
|
LPads.push_back(LP);
|
||||||
}
|
}
|
||||||
// De-dup (multiple call_sites can share a landing pad).
|
// After we convert invokes to plain calls, landingpad blocks are no
|
||||||
std::sort(LPads.begin(), LPads.end());
|
// longer reached via an unwind edge — the verifier requires landing-
|
||||||
LPads.erase(std::unique(LPads.begin(), LPads.end()), LPads.end());
|
// pads to be reached only from invoke unwind dests. Erase them now
|
||||||
|
// (they're no-ops post-finalize; the real exception ptr / selector
|
||||||
|
// come from explicit fn_ctx.data loads SjLjEHPrepare emitted right
|
||||||
|
// after). Replace landingpad uses with poison since downstream
|
||||||
|
// code reads via GEPs, not via the inst's result.
|
||||||
for (LandingPadInst *LP : LPads) {
|
for (LandingPadInst *LP : LPads) {
|
||||||
LP->replaceAllUsesWith(PoisonValue::get(LP->getType()));
|
LP->replaceAllUsesWith(PoisonValue::get(LP->getType()));
|
||||||
LP->eraseFromParent();
|
LP->eraseFromParent();
|
||||||
|
|
@ -284,25 +307,18 @@ bool W65816SjLjFinalize::runOnFunction(Function &F) {
|
||||||
// eh.typeid.for(@TI) calls to also yield (i32)(uintptr_t)&TI. The
|
// eh.typeid.for(@TI) calls to also yield (i32)(uintptr_t)&TI. The
|
||||||
// icmp eq then succeeds for the matched catch.
|
// icmp eq then succeeds for the matched catch.
|
||||||
SmallVector<Constant *, 16> TableRows;
|
SmallVector<Constant *, 16> TableRows;
|
||||||
// Walk each invoke (now lowered to call+br); we kept its call_site
|
// Walk each invoke's call_site → unwind_dest mapping; emit a row per
|
||||||
// → unwind_dest mapping, so re-derive from CSToLPad and the lpad's
|
// (call_site, catch typeinfo) pair using the LPadCatches data we
|
||||||
// landingpad instruction's catch clauses.
|
// captured BEFORE erasing the landingpad insts above.
|
||||||
for (auto &KV : CSToLPad) {
|
for (auto &KV : CSToLPad) {
|
||||||
int CS = KV.first;
|
int CS = KV.first;
|
||||||
BasicBlock *LPadBB = KV.second;
|
BasicBlock *LPadBB = KV.second;
|
||||||
LandingPadInst *LP = LPadBB->getLandingPadInst();
|
auto It = LPadCatches.find(LPadBB);
|
||||||
if (!LP)
|
if (It == LPadCatches.end())
|
||||||
continue;
|
continue;
|
||||||
for (unsigned i = 0; i < LP->getNumClauses(); i++) {
|
for (Constant *TIClause : It->second.CatchTypes) {
|
||||||
if (LP->isCatch(i)) {
|
TableRows.push_back(ConstantInt::get(I16Ty, CS));
|
||||||
Constant *TIClause = cast<Constant>(LP->getClause(i));
|
TableRows.push_back(ConstantExpr::getPtrToInt(TIClause, I16Ty));
|
||||||
// Skip catch-all (null TI) for now — rare, and our personality
|
|
||||||
// would need to handle it specially.
|
|
||||||
if (TIClause->isNullValue())
|
|
||||||
continue;
|
|
||||||
TableRows.push_back(ConstantInt::get(I16Ty, CS));
|
|
||||||
TableRows.push_back(ConstantExpr::getPtrToInt(TIClause, I16Ty));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// Append (0, 0) sentinel.
|
// Append (0, 0) sentinel.
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue