Skip to content
Merged
Show file tree
Hide file tree
Changes from 15 commits
Commits
Show all changes
18 commits
Select commit Hold shift + click to select a range
aab77fb
[rocjitsu] Return scalar builder failures as results
IanWood1 Oct 29, 2026
1b33498
[rocjitsu] Merge develop and check new scalar builder consumers
IanWood1 Oct 29, 2026
9ec6ce7
[rocjitsu] Check scalar builder results in migrated tests
IanWood1 Oct 29, 2026
43b4648
[rocjitsu] Merge develop and reconcile checked builder tests
IanWood1 Oct 29, 2026
6d1cba5
[rocjitsu] Check newly merged boundary drain test encodings
IanWood1 Oct 29, 2026
bb9f2f5
[rocjitsu] Merge develop for new probe contract tests
IanWood1 Oct 29, 2026
3af8a7d
[rocjitsu] Check scalar encodings in new wave-size tests
IanWood1 Oct 29, 2026
21dbe6b
[rocjitsu] Address scalar builder review feedback
IanWood1 Oct 29, 2026
c3ddd13
[rocjitsu] Merge develop and adapt new scalar builder callers
IanWood1 Oct 30, 2026
cfba0f6
Forward scalar builder diagnostics through patching boundaries
IanWood1 Oct 30, 2026
675503c
Unwrap reused trampoline test NOP words once
IanWood1 Oct 30, 2026
99b2ad5
[rocjitsu] Preserve scalar encoding and diagnostic boundaries
IanWood1 Nov 2, 2026
9cd08a5
[rocjitsu] Merge develop into scalar builder errors
IanWood1 Nov 2, 2026
1c8ca86
Preserve scalar builder diagnostics in relocation sequences
IanWood1 Nov 2, 2026
494bc89
[rocjitsu] Preserve branch relocation diagnostic context
IanWood1 Nov 3, 2026
1c3c0cb
Preserve scalar builder diagnostics through layout growth
IanWood1 Nov 3, 2026
9a30b93
Clarify scalar builder diagnostics and test exact errors
IanWood1 Nov 3, 2026
e7b7978
Merge develop and adapt the new CFG test to scalar results
IanWood1 Nov 3, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -74,47 +74,76 @@ enum class ScalarSop2Op {
return std::nullopt;
}

void report_unsupported_pc_delta_builder(const util::DiagnosticEmitter *error) {
if (error != nullptr)
error->emit() << "Unimplemented instruction: scalar PC delta builder for target architecture";
}

/// @brief Build an encoded scalar `s_add_u32` instruction.
///
/// @details Used only for final static-PC recovery fixup emission, after the
/// recovery pass has proven that the old address-recovery region can be
/// overwritten. The operands are already scalar operand encoding values.
[[nodiscard]] std::optional<uint32_t> build_s_add_u32(rj_code_arch_t arch, uint16_t sdst,
uint16_t ssrc0, uint16_t ssrc1) {
uint16_t ssrc0, uint16_t ssrc1,
const util::DiagnosticEmitter *error) {
auto opcode = scalar_sop2_opcode(arch, ScalarSop2Op::AddU32);
if (!opcode)
if (!opcode) {
report_unsupported_pc_delta_builder(error);
return std::nullopt;
}
util::FailureOr<uint32_t> word = build_sop2_encoding(arch, *opcode, sdst, ssrc0, ssrc1, error);
if (word.failed())
return std::nullopt;
return build_sop2_encoding(arch, *opcode, sdst, ssrc0, ssrc1);
return word.value();
}

/// @brief Build an encoded scalar `s_sub_u32` instruction.
/// @copydetails build_s_add_u32
[[nodiscard]] std::optional<uint32_t> build_s_sub_u32(rj_code_arch_t arch, uint16_t sdst,
uint16_t ssrc0, uint16_t ssrc1) {
uint16_t ssrc0, uint16_t ssrc1,
const util::DiagnosticEmitter *error) {
auto opcode = scalar_sop2_opcode(arch, ScalarSop2Op::SubU32);
if (!opcode)
if (!opcode) {
report_unsupported_pc_delta_builder(error);
return std::nullopt;
return build_sop2_encoding(arch, *opcode, sdst, ssrc0, ssrc1);
}
util::FailureOr<uint32_t> word = build_sop2_encoding(arch, *opcode, sdst, ssrc0, ssrc1, error);
if (word.failed())
return std::nullopt;
return word.value();
}

/// @brief Build an encoded scalar `s_addc_u32` instruction.
/// @copydetails build_s_add_u32
[[nodiscard]] std::optional<uint32_t> build_s_addc_u32(rj_code_arch_t arch, uint16_t sdst,
uint16_t ssrc0, uint16_t ssrc1) {
uint16_t ssrc0, uint16_t ssrc1,
const util::DiagnosticEmitter *error) {
auto opcode = scalar_sop2_opcode(arch, ScalarSop2Op::AddcU32);
if (!opcode)
if (!opcode) {
report_unsupported_pc_delta_builder(error);
return std::nullopt;
}
util::FailureOr<uint32_t> word = build_sop2_encoding(arch, *opcode, sdst, ssrc0, ssrc1, error);
if (word.failed())
return std::nullopt;
return build_sop2_encoding(arch, *opcode, sdst, ssrc0, ssrc1);
return word.value();
}

/// @brief Build an encoded scalar `s_subb_u32` instruction.
/// @copydetails build_s_add_u32
[[nodiscard]] std::optional<uint32_t> build_s_subb_u32(rj_code_arch_t arch, uint16_t sdst,
uint16_t ssrc0, uint16_t ssrc1) {
uint16_t ssrc0, uint16_t ssrc1,
const util::DiagnosticEmitter *error) {
auto opcode = scalar_sop2_opcode(arch, ScalarSop2Op::SubbU32);
if (!opcode)
if (!opcode) {
report_unsupported_pc_delta_builder(error);
return std::nullopt;
}
util::FailureOr<uint32_t> word = build_sop2_encoding(arch, *opcode, sdst, ssrc0, ssrc1, error);
if (word.failed())
return std::nullopt;
return build_sop2_encoding(arch, *opcode, sdst, ssrc0, ssrc1);
return word.value();
}

} // namespace
Expand Down Expand Up @@ -143,7 +172,8 @@ bool patch_pcrel_branch_offset(const Instruction &inst, std::span<uint32_t> word
}

bool append_pc_delta_builder(std::vector<uint32_t> &words, rj_code_arch_t arch, uint16_t pc_sreg,
int64_t delta, bool prefer_literal64) {
int64_t delta, bool prefer_literal64,
const util::DiagnosticEmitter *error) {
constexpr uint16_t kLiteralOperand = 255;
constexpr uint16_t kLiteral64Operand = 254;
constexpr uint16_t kInlineInt0 = 128;
Expand All @@ -157,10 +187,16 @@ bool append_pc_delta_builder(std::vector<uint32_t> &words, rj_code_arch_t arch,
const bool use_literal32 =
!prefer_literal64 && delta >= 0 && raw_delta <= std::numeric_limits<uint32_t>::max();
auto opcode = scalar_sop2_opcode(arch, ScalarSop2Op::AddNcU64);
if (!opcode)
if (!opcode) {
report_unsupported_pc_delta_builder(error);
return false;
words.push_back(build_sop2_encoding(arch, *opcode, pc_sreg, pc_sreg,
use_literal32 ? kLiteralOperand : kLiteral64Operand));
}
util::FailureOr<uint32_t> word =
build_sop2_encoding(arch, *opcode, pc_sreg, pc_sreg,
use_literal32 ? kLiteralOperand : kLiteral64Operand, error);
if (word.failed())
return false;
words.push_back(word.value());
words.push_back(static_cast<uint32_t>(raw_delta));
if (!use_literal32)
words.push_back(static_cast<uint32_t>(raw_delta >> 32));
Expand All @@ -179,17 +215,25 @@ bool append_pc_delta_builder(std::vector<uint32_t> &words, rj_code_arch_t arch,
// uses a literal; the high half uses inline zero when possible to keep the
// replacement smaller than the original builder sequence.
if (negative) {
auto sub = build_s_sub_u32(arch, pc_sreg, pc_sreg, kLiteralOperand);
auto subb = build_s_subb_u32(arch, pc_hi, pc_hi, hi == 0 ? kInlineInt0 : kLiteralOperand);
if (!sub || !subb)
const std::optional<uint32_t> sub =
build_s_sub_u32(arch, pc_sreg, pc_sreg, kLiteralOperand, error);
if (!sub)
return false;
const std::optional<uint32_t> subb =
build_s_subb_u32(arch, pc_hi, pc_hi, hi == 0 ? kInlineInt0 : kLiteralOperand, error);
if (!subb)
return false;
words.push_back(*sub);
words.push_back(lo);
words.push_back(*subb);
} else {
auto add = build_s_add_u32(arch, pc_sreg, pc_sreg, kLiteralOperand);
auto addc = build_s_addc_u32(arch, pc_hi, pc_hi, hi == 0 ? kInlineInt0 : kLiteralOperand);
if (!add || !addc)
const std::optional<uint32_t> add =
build_s_add_u32(arch, pc_sreg, pc_sreg, kLiteralOperand, error);
if (!add)
return false;
const std::optional<uint32_t> addc =
build_s_addc_u32(arch, pc_hi, pc_hi, hi == 0 ? kInlineInt0 : kLiteralOperand, error);
if (!addc)
return false;
words.push_back(*add);
words.push_back(lo);
Expand Down
Loading
Loading