Vauto::~Vauto() { for (auto& b : unit().blocks) { if (!b.code.empty()) { // Found at least one nonempty block. Finish up. if (!main().closed()) main() << fallthru{}; if (!cold().closed()) cold() << fallthru{}; // Prevent spurious printir traces. Trace::Bump bumper{Trace::printir, 10}; auto const abi = jit::abi(m_kind); switch (arch()) { case Arch::X64: optimizeX64(unit(), abi, true /* regalloc */); emitX64(unit(), m_text, m_fixups, nullptr); break; case Arch::ARM: optimizeARM(unit(), abi, true /* regalloc */); emitARM(unit(), m_text, m_fixups, nullptr); break; case Arch::PPC64: optimizePPC64(unit(), abi, true /* regalloc */); emitPPC64(unit(), m_text, m_fixups, nullptr); break; } return; } } }
Vauto::~Vauto() { auto& areas = this->areas(); for (auto& b : unit().blocks) { if (!b.code.empty()) { // Found at least one nonempty block. Finish up. if (!main().closed()) { main() << fallthru{}; } assertx(areas.size() < 2 || cold().empty() || cold().closed()); assertx(areas.size() < 3 || frozen().empty() || frozen().closed()); Trace::Bump bumper{Trace::printir, 10}; // prevent spurious printir switch (arch()) { case Arch::X64: optimizeX64(unit(), vauto_abi); emitX64(unit(), areas, nullptr); break; case Arch::ARM: finishARM(unit(), areas, vauto_abi, nullptr); break; } return; } } }
template<class T> uint64_t test_const(T val) { using testfunc = double (*)(); static const Abi test_abi = { .gpUnreserved = RegSet{}, .gpReserved = x64::abi().gp(), .simdUnreserved = RegSet{xmm0}, .simdReserved = x64::abi().simd() - RegSet{xmm0}, .calleeSaved = x64::abi().calleeSaved, .sf = x64::abi().sf }; static uint8_t code[1000]; // None of these tests should use any data. static uint8_t data_buffer[0]; CodeBlock main; main.init(code, sizeof(code), "test"); DataBlock data; data.init(data_buffer, sizeof(data), "data"); Vunit unit; Vasm vasm{unit}; Vtext text { main, data }; auto& v = vasm.main(); unit.entry = v; v << copy{v.cns(val), Vreg{xmm0}}; v << ret{RegSet{xmm0}}; optimizeX64(vasm.unit(), test_abi, true /* regalloc */); CGMeta fixups; LeaseHolder writer{Translator::WriteLease()}; EXPECT_TRUE(writer.canWrite()); emitX64(unit, text, fixups, nullptr); // The above code might use fixups.literals but shouldn't use anything else. fixups.literals.clear(); EXPECT_TRUE(fixups.empty()); union { double d; uint64_t c; } u; u.d = ((testfunc)code)(); return u.c; }
Vauto::~Vauto() { for (auto& b : unit().blocks) { if (!b.code.empty()) { // Found at least one nonempty block. Finish up. if (!main().closed()) main() << fallthru{}; // Prevent spurious printir traces. Trace::Bump bumper{Trace::printir, 10}; switch (arch()) { case Arch::X64: optimizeX64(unit(), abi(m_kind)); emitX64(unit(), m_text, nullptr); break; case Arch::ARM: finishARM(unit(), m_text, abi(m_kind), nullptr); break; } return; } } }
template<class T> uint64_t test_const(T val) { using testfunc = double (*)(); static const Abi test_abi = { .gpUnreserved = RegSet{}, .gpReserved = x64::abi().gp(), .simdUnreserved = RegSet{xmm0}, .simdReserved = x64::abi().simd() - RegSet{xmm0}, .calleeSaved = x64::abi().calleeSaved, .sf = x64::abi().sf }; static uint8_t code[1000]; CodeBlock main; main.init(code, sizeof(code), "test"); Vasm vasm; Vtext text { main }; auto& unit = vasm.unit(); auto& v = vasm.main(); unit.entry = v; v << copy{v.cns(val), Vreg{xmm0}}; v << ret{RegSet{xmm0}}; optimizeX64(vasm.unit(), test_abi); CGMeta fixups; emitX64(unit, text, fixups, nullptr); // The above code might use fixups.literals but shouldn't use anything else. fixups.literals.clear(); EXPECT_TRUE(fixups.empty()); union { double d; uint64_t c; } u; u.d = ((testfunc)code)(); return u.c; }