Also perform immediate field-width check during symbol resolution
MODIFY
src/assembler/assembler.h
src/assembler/assembler.h
@@ -572,7 +572,11 @@ protected:
// Re-apply immediate resolution using the value acquired from the symbol map
if (auto* immField = dynamic_cast<const Imm*>(linkRequest.fieldRequest.field)) {
- immField->applySymbolResolution(symbolValue, instr, linkReqAddress(linkRequest));
+ if (auto err = immField->applySymbolResolution(symbolValue, instr, linkReqAddress(linkRequest),
+ linkRequest.sourceLine)) {
+ errors.push_back(err.value());
+ continue;
+ }
} else {
assert(false && "Something other than an immediate field has requested linkage?");
}

MODIFY
src/assembler/instruction.h
src/assembler/instruction.h
@@ -111,7 +111,8 @@ struct Reg : public Field {
Reg(const ISAInfoBase* isa, unsigned tokenIndex, BitRange range) : Field(tokenIndex), m_range(range), m_isa(isa) {}
Reg(const ISAInfoBase* isa, unsigned tokenIndex, unsigned _start, unsigned _stop)
: Field(tokenIndex), m_range({_start, _stop}), m_isa(isa) {}
- Reg(const ISAInfoBase* isa, unsigned tokenIndex, BitRange range, QString _regsd) : Field(tokenIndex), m_range(range), m_isa(isa), regsd(_regsd) {}
+ Reg(const ISAInfoBase* isa, unsigned tokenIndex, BitRange range, QString _regsd)
+ : Field(tokenIndex), m_range(range), m_isa(isa), regsd(_regsd) {}
Reg(const ISAInfoBase* isa, unsigned tokenIndex, unsigned _start, unsigned _stop, QString _regsd)
: Field(tokenIndex), m_range({_start, _stop}), m_isa(isa), regsd(_regsd) {}
std::optional<Assembler::Error> apply(const Assembler::TokenizedSrcLine& line, uint32_t& instruction,
@@ -201,9 +202,8 @@ struct Imm : public Field {
return {};
}
- if (!((repr == Repr::Signed && isInt(width, svalue)) || (isUInt(width, uvalue)))) {
- return Assembler::Error(line.sourceLine, "Immediate value '" + immToken + "' does not fit in " +
- QString::number(width) + " bits");
+ if (auto err = checkFitsInWidth(svalue, uvalue, line.sourceLine)) {
+ return err;
}
for (const auto& part : parts) {
@@ -212,8 +212,17 @@ struct Imm : public Field {
return std::nullopt;
}
+ std::optional<Assembler::Error> checkFitsInWidth(int32_t svalue, uint32_t uvalue, unsigned sourceLine) const {
+ if (!(repr == Repr::Signed ? isInt(width, svalue) : (isUInt(width, uvalue)))) {
+ const QString v = repr == Repr::Signed ? QString::number(svalue) : QString::number(uvalue);
+ return Assembler::Error(sourceLine,
+ "Immediate value '" + v + "' does not fit in " + QString::number(width) + " bits");
+ }
+ return std::nullopt;
+ }
+
std::optional<Assembler::Error> applySymbolResolution(uint32_t symbolValue, uint32_t& instruction,
- const uint32_t address) const {
+ const uint32_t address, unsigned sourceLine) const {
long adjustedValue = symbolValue;
if (symbolType == SymbolType::Relative) {
adjustedValue -= address;
@@ -223,6 +232,10 @@ struct Imm : public Field {
adjustedValue = symbolTransformer(adjustedValue);
}
+ if (auto err = checkFitsInWidth(adjustedValue, adjustedValue, sourceLine)) {
+ return err;
+ }
+
for (const auto& part : parts) {
part.apply(adjustedValue, instruction);
}
@@ -315,8 +328,6 @@ public:
return m_assembler(this, line);
}
-
-
DisassembleRes disassemble(const uint32_t instruction, const uint32_t address,
const ReverseSymbolMap& symbolMap) const {
return m_disassembler(this, instruction, address, symbolMap);

Also perform immediate field-width check during symbol resolution