MCPcopy Create free account
hub / github.com/FEX-Emu/FEX / IsBranchMonoTailcall

Method IsBranchMonoTailcall

FEXCore/Source/Interface/Core/Frontend.cpp:1148–1200  ·  view source on GitHub ↗

Source from the content-addressed store, hash-verified

1146}
1147
1148bool Decoder::IsBranchMonoTailcall(uint64_t NumInstructions) const {
1149 // While the mono call backpatching block can easily be detected due it being the only one to contain SMC-faulting
1150 // atomics, that can't be said for the tailcall jump backpatcher which has changed several times across versions and
1151 // can be partially inlined. To work around this, instead detect the tailcall site itself and force full non-signal-based
1152 // SMC detection for that single block.
1153 if (!ExecutableRangeWritable) {
1154 // We only care about jitted code
1155 return false;
1156 }
1157
1158 // See mini-{amd64,x86}.c in the mono codebase, specifically where METHOD_JUMP patches are emitted.
1159 if (GetGPROpSize() == IR::OpSize::i32Bit) {
1160 // Matches:
1161 // LEAVE
1162 // <none> / NOP / MOV EAX, EAX / LEA EBP, [EBP+0]
1163 // JMP imm32
1164 if (DecodeInst->OP != 0xE9 || NumInstructions < 2) {
1165 return false;
1166 }
1167
1168 auto PrevInst = std::prev(DecodeInst);
1169 if (PrevInst->OP == 0xC9) {
1170 return true;
1171 }
1172
1173 if (NumInstructions < 3 || std::prev(PrevInst)->OP != 0xC9) {
1174 return false;
1175 }
1176
1177 return PrevInst->OP == 0x90 || (PrevInst->OP == 0x8B && PrevInst->ModRM == 0xC0) ||
1178 (PrevInst->OP == 0x8D && PrevInst->ModRM == 0x6D && PrevInst->Src[1].IsLiteral() && PrevInst->Src[1].Literal() == 0);
1179 } else {
1180 FEXCore::X86Tables::ModRMDecoded ModRM;
1181 ModRM.Hex = DecodeInst->ModRM;
1182 if (DecodeInst->OPRaw == 0xFF && ModRM.reg == 4 && DecodeInst->Src[0].IsGPR()) {
1183 if (DecodeInst->Src[0].Data.GPR.GPR == FEXCore::X86State::REG_RAX) {
1184 // Found in versions of mono from 2024 onwards - matches:
1185 // REX.W JMP rax
1186 return (DecodeInst->Flags & (DecodeFlags::FLAG_REX_PREFIX | DecodeFlags::FLAG_REX_WIDENING | DecodeFlags::FLAG_REX_XGPR_B |
1187 DecodeFlags::FLAG_REX_XGPR_X | DecodeFlags::FLAG_REX_XGPR_R)) ==
1188 (DecodeFlags::FLAG_REX_PREFIX | DecodeFlags::FLAG_REX_WIDENING);
1189 } else if (NumInstructions > 1 && DecodeInst->Src[0].Data.GPR.GPR == FEXCore::X86State::REG_R11) {
1190 // Found in older versions of mono - match:
1191 // MOV r11, imm64
1192 // JMP r11
1193 auto PrevInst = std::prev(DecodeInst);
1194 return PrevInst->OP == 0xBB && PrevInst->Dest.IsGPR() && PrevInst->Dest.Data.GPR.GPR == FEXCore::X86State::REG_R11;
1195 }
1196 }
1197 }
1198
1199 return false;
1200}
1201
1202bool Decoder::InstCanContinue() const {
1203 if (DecodeInst->PC + DecodeInst->InstSize == NextBlockStartAddress) {

Callers

nothing calls this directly

Calls 3

IsLiteralMethod · 0.80
LiteralMethod · 0.80
IsGPRMethod · 0.45

Tested by

no test coverage detected