Also pass current section as argument to directive handlers
MODIFY
src/assembler/assembler.h
src/assembler/assembler.h
@@ -134,21 +134,21 @@ protected:
return std::get<LineTokens>(joinedtokens);
}
- virtual HandleDirectiveRes assembleDirective(const TokenizedSrcLine& line, bool& ok,
+ virtual HandleDirectiveRes assembleDirective(const DirectiveArg& arg, bool& ok,
bool skipEarlyDirectives = true) const {
ok = false;
- if (line.directive.isEmpty()) {
+ if (arg.line.directive.isEmpty()) {
return std::nullopt;
}
ok = true;
try {
- const auto& directive = m_directivesMap.at(line.directive);
+ const auto& directive = m_directivesMap.at(arg.line.directive);
if (directive->early() && skipEarlyDirectives) {
return std::nullopt;
}
- return directive->handle(this, line);
+ return directive->handle(this, arg);
} catch (const std::out_of_range&) {
- return {Error(line.sourceLine, "Unknown directive '" + line.directive + "'")};
+ return {Error(arg.line.sourceLine, "Unknown directive '" + arg.line.directive + "'")};
}
};
/**
@@ -480,7 +480,8 @@ protected:
if (!tsl.directive.isEmpty() && m_earlyDirectives.count(tsl.directive)) {
bool wasDirective; // unused
- runOperation(directiveBytes, std::optional<QByteArray>, assembleDirective, tsl, wasDirective, false);
+ runOperation(directiveBytes, std::optional<QByteArray>, assembleDirective,
+ DirectiveArg{.line = tsl, .section = nullptr}, wasDirective, false);
}
}
if (errors.size() != 0) {
@@ -548,22 +549,23 @@ protected:
}
Errors errors;
- QByteArray* currentSection = &program.sections.at(m_currentSection).data;
+ ProgramSection* currentSection = &program.sections.at(m_currentSection);
bool wasDirective;
for (const auto& line : tokenizedLines) {
// Get offset of currently emitting position in memory relative to section position
- uint32_t addr_offset = currentSection->size();
+ uint32_t addr_offset = currentSection->data.size();
for (const auto& s : line.symbols) {
// Record symbol position as its absolute address in memory
runOperationNoRes(addSymbol, line, s, addr_offset + program.sections.at(m_currentSection).address);
}
- runOperation(directiveBytes, std::optional<QByteArray>, assembleDirective, line, wasDirective);
+ runOperation(directiveBytes, std::optional<QByteArray>, assembleDirective,
+ DirectiveArg{.line = line, .section = currentSection}, wasDirective);
// Currently emitting segment may have changed during the assembler directive; refresh state
- currentSection = &program.sections.at(m_currentSection).data;
- addr_offset = currentSection->size();
+ currentSection = &program.sections.at(m_currentSection);
+ addr_offset = currentSection->data.size();
if (!wasDirective) {
std::weak_ptr<Instruction> assembledWith;
runOperation(machineCode, InstrRes, assembleInstruction, line, assembledWith);
@@ -576,13 +578,13 @@ protected:
req.section = m_currentSection;
needsLinkage.push_back(req);
}
- currentSection->append(
+ currentSection->data.append(
QByteArray(reinterpret_cast<char*>(&machineCode.instruction), sizeof(machineCode.instruction)));
}
// This was a directive; check if any bytes needs to be appended to the segment
else if (directiveBytes) {
- currentSection->append(directiveBytes.value());
+ currentSection->data.append(directiveBytes.value());
}
}
if (errors.size() != 0) {

MODIFY
src/assembler/directive.h
src/assembler/directive.h
@@ -14,14 +14,19 @@ namespace Assembler {
class AssemblerBase;
+struct DirectiveArg {
+ const TokenizedSrcLine& line;
+ const ProgramSection* section;
+};
+
class Directive {
public:
- using DirectiveHandler = std::function<HandleDirectiveRes(const AssemblerBase*, const TokenizedSrcLine&)>;
+ using DirectiveHandler = std::function<HandleDirectiveRes(const AssemblerBase*, const DirectiveArg&)>;
Directive(const QString& directive, const DirectiveHandler& handler, bool isEarly = false)
: m_directive(directive), m_handler(handler), m_early(isEarly) {}
- HandleDirectiveRes handle(const AssemblerBase* assembler, const TokenizedSrcLine& line) {
- return m_handler(assembler, line);
+ HandleDirectiveRes handle(const AssemblerBase* assembler, const DirectiveArg& arg) {
+ return m_handler(assembler, arg);
}
const QString& name() const { return m_directive; }
bool early() const { return m_early; }

MODIFY
src/assembler/gnudirectives.cpp
src/assembler/gnudirectives.cpp
@@ -46,12 +46,12 @@ std::optional<Error> assembleData(const TokenizedSrcLine& line, QByteArray& byte
}
template <size_t width>
-HandleDirectiveRes dataFunctor(const AssemblerBase*, const TokenizedSrcLine& line) {
- if (line.tokens.length() < 1) {
- return {Error(line.sourceLine, "Invalid number of arguments (expected >1)")};
+HandleDirectiveRes dataFunctor(const AssemblerBase*, const DirectiveArg& arg) {
+ if (arg.line.tokens.length() < 1) {
+ return {Error(arg.line.sourceLine, "Invalid number of arguments (expected >1)")};
}
QByteArray bytes;
- auto err = assembleData(line, bytes, width);
+ auto err = assembleData(arg.line, bytes, width);
if (err) {
return {err.value()};
} else {
@@ -59,11 +59,11 @@ HandleDirectiveRes dataFunctor(const AssemblerBase*, const TokenizedSrcLine& lin
}
};
-HandleDirectiveRes stringFunctor(const AssemblerBase*, const TokenizedSrcLine& line) {
- if (line.tokens.length() != 1) {
- return {Error(line.sourceLine, "Invalid number of arguments (expected 1)")};
+HandleDirectiveRes stringFunctor(const AssemblerBase*, const DirectiveArg& arg) {
+ if (arg.line.tokens.length() != 1) {
+ return {Error(arg.line.sourceLine, "Invalid number of arguments (expected 1)")};
}
- QString string = line.tokens.at(0);
+ QString string = arg.line.tokens.at(0);
string.replace("\\n", "\n");
string.remove('\"');
return {string.toUtf8().append('\0')};
@@ -106,14 +106,14 @@ Directive stringDirective() {
}
Directive::DirectiveHandler genSegmentChangeFunctor(const QString& segment) {
- return [segment](const AssemblerBase* assembler, const TokenizedSrcLine& line) {
- if (line.tokens.length() != 0) {
- return HandleDirectiveRes{Error(line.sourceLine, "Invalid number of arguments (expected 0)")};
+ return [segment](const AssemblerBase* assembler, const DirectiveArg& arg) {
+ if (arg.line.tokens.length() != 0) {
+ return HandleDirectiveRes{Error(arg.line.sourceLine, "Invalid number of arguments (expected 0)")};
}
auto err = assembler->setCurrentSegment(segment);
if (err) {
// Embed source line into error message
- err.value().first = line.sourceLine;
+ err.value().first = arg.line.sourceLine;
return HandleDirectiveRes{err.value()};
}
return HandleDirectiveRes(std::nullopt);
@@ -133,14 +133,14 @@ Directive dataDirective() {
}
Directive zeroDirective() {
- auto zeroFunctor = [](const AssemblerBase*, const TokenizedSrcLine& line) -> HandleDirectiveRes {
- if (line.tokens.length() != 1) {
- return {Error(line.sourceLine, "Invalid number of arguments (expected 1)")};
+ auto zeroFunctor = [](const AssemblerBase*, const DirectiveArg& arg) -> HandleDirectiveRes {
+ if (arg.line.tokens.length() != 1) {
+ return {Error(arg.line.sourceLine, "Invalid number of arguments (expected 1)")};
}
bool ok;
- int value = getImmediate(line.tokens.at(0), ok);
+ int value = getImmediate(arg.line.tokens.at(0), ok);
if (!ok) {
- return {Error(line.sourceLine, "Invalid argument")};
+ return {Error(arg.line.sourceLine, "Invalid argument")};
}
QByteArray bytes;
for (int i = 0; i < value; i++) {
@@ -152,17 +152,17 @@ Directive zeroDirective() {
}
Directive equDirective() {
- auto equFunctor = [](const AssemblerBase* assembler, const TokenizedSrcLine& line) -> HandleDirectiveRes {
- if (line.tokens.length() != 2) {
- return {Error(line.sourceLine, "Invalid number of arguments (expected 2)")};
+ auto equFunctor = [](const AssemblerBase* assembler, const DirectiveArg& arg) -> HandleDirectiveRes {
+ if (arg.line.tokens.length() != 2) {
+ return {Error(arg.line.sourceLine, "Invalid number of arguments (expected 2)")};
}
bool ok;
- int value = getImmediate(line.tokens.at(1), ok);
+ int value = getImmediate(arg.line.tokens.at(1), ok);
if (!ok) {
- return {Error(line.sourceLine, "Invalid argument")};
+ return {Error(arg.line.sourceLine, "Invalid argument")};
}
- auto err = assembler->addSymbol(line, line.tokens.at(0), value);
+ auto err = assembler->addSymbol(arg.line, arg.line.tokens.at(0), value);
if (err) {
return err.value();
}

Also pass current section as argument to directive handlers