mirror of
https://github.com/gbdev/rgbds.git
synced 2025-11-20 18:22:07 +00:00
Pass std::string references to output functions
This commit is contained in:
@@ -4,20 +4,21 @@
|
|||||||
#define RGBDS_ASM_OUTPUT_H
|
#define RGBDS_ASM_OUTPUT_H
|
||||||
|
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
|
#include <string>
|
||||||
|
|
||||||
#include "linkdefs.hpp"
|
#include "linkdefs.hpp"
|
||||||
|
|
||||||
struct Expression;
|
struct Expression;
|
||||||
struct FileStackNode;
|
struct FileStackNode;
|
||||||
|
|
||||||
extern char const *objectName;
|
extern std::string objectName;
|
||||||
|
|
||||||
void out_RegisterNode(FileStackNode *node);
|
void out_RegisterNode(FileStackNode *node);
|
||||||
void out_ReplaceNode(FileStackNode *node);
|
void out_ReplaceNode(FileStackNode *node);
|
||||||
void out_SetFileName(char *s);
|
void out_SetFileName(std::string const &name);
|
||||||
void out_CreatePatch(uint32_t type, Expression const &expr, uint32_t ofs, uint32_t pcShift);
|
void out_CreatePatch(uint32_t type, Expression const &expr, uint32_t ofs, uint32_t pcShift);
|
||||||
void out_CreateAssert(
|
void out_CreateAssert(
|
||||||
AssertionType type, Expression const &expr, char const *message, uint32_t ofs
|
AssertionType type, Expression const &expr, std::string const &message, uint32_t ofs
|
||||||
);
|
);
|
||||||
void out_WriteObject();
|
void out_WriteObject();
|
||||||
|
|
||||||
|
|||||||
@@ -362,7 +362,7 @@ int main(int argc, char *argv[]) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (targetFileName.empty() && objectName)
|
if (targetFileName.empty() && !objectName.empty())
|
||||||
targetFileName = objectName;
|
targetFileName = objectName;
|
||||||
|
|
||||||
if (argc == musl_optind) {
|
if (argc == musl_optind) {
|
||||||
@@ -413,7 +413,7 @@ int main(int argc, char *argv[]) {
|
|||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
// If no path specified, don't write file
|
// If no path specified, don't write file
|
||||||
if (objectName != nullptr)
|
if (!objectName.empty())
|
||||||
out_WriteObject();
|
out_WriteObject();
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -29,7 +29,7 @@ struct Assertion {
|
|||||||
std::string message;
|
std::string message;
|
||||||
};
|
};
|
||||||
|
|
||||||
char const *objectName;
|
std::string objectName;
|
||||||
|
|
||||||
// List of symbols to put in the object file
|
// List of symbols to put in the object file
|
||||||
static std::vector<Symbol *> objectSymbols;
|
static std::vector<Symbol *> objectSymbols;
|
||||||
@@ -39,20 +39,20 @@ static std::deque<Assertion> assertions;
|
|||||||
static std::deque<FileStackNode *> fileStackNodes;
|
static std::deque<FileStackNode *> fileStackNodes;
|
||||||
|
|
||||||
// Write a long to a file (little-endian)
|
// Write a long to a file (little-endian)
|
||||||
static void putlong(uint32_t n, FILE *f) {
|
static void putlong(uint32_t n, FILE *file) {
|
||||||
uint8_t bytes[] = {
|
uint8_t bytes[] = {
|
||||||
(uint8_t)n,
|
(uint8_t)n,
|
||||||
(uint8_t)(n >> 8),
|
(uint8_t)(n >> 8),
|
||||||
(uint8_t)(n >> 16),
|
(uint8_t)(n >> 16),
|
||||||
(uint8_t)(n >> 24),
|
(uint8_t)(n >> 24),
|
||||||
};
|
};
|
||||||
fwrite(bytes, 1, sizeof(bytes), f);
|
fwrite(bytes, 1, sizeof(bytes), file);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Write a NUL-terminated string to a file
|
// Write a NUL-terminated string to a file
|
||||||
static void putstring(std::string const &s, FILE *f) {
|
static void putstring(std::string const &s, FILE *file) {
|
||||||
fputs(s.c_str(), f);
|
fputs(s.c_str(), file);
|
||||||
putc('\0', f);
|
putc('\0', file);
|
||||||
}
|
}
|
||||||
|
|
||||||
void out_RegisterNode(FileStackNode *node) {
|
void out_RegisterNode(FileStackNode *node) {
|
||||||
@@ -90,56 +90,56 @@ static uint32_t getSectIDIfAny(Section *sect) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Write a patch to a file
|
// Write a patch to a file
|
||||||
static void writepatch(Patch const &patch, FILE *f) {
|
static void writepatch(Patch const &patch, FILE *file) {
|
||||||
assert(patch.src->ID != (uint32_t)-1);
|
assert(patch.src->ID != (uint32_t)-1);
|
||||||
putlong(patch.src->ID, f);
|
putlong(patch.src->ID, file);
|
||||||
putlong(patch.lineNo, f);
|
putlong(patch.lineNo, file);
|
||||||
putlong(patch.offset, f);
|
putlong(patch.offset, file);
|
||||||
putlong(getSectIDIfAny(patch.pcSection), f);
|
putlong(getSectIDIfAny(patch.pcSection), file);
|
||||||
putlong(patch.pcOffset, f);
|
putlong(patch.pcOffset, file);
|
||||||
putc(patch.type, f);
|
putc(patch.type, file);
|
||||||
putlong(patch.rpn.size(), f);
|
putlong(patch.rpn.size(), file);
|
||||||
fwrite(patch.rpn.data(), 1, patch.rpn.size(), f);
|
fwrite(patch.rpn.data(), 1, patch.rpn.size(), file);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Write a section to a file
|
// Write a section to a file
|
||||||
static void writesection(Section const §, FILE *f) {
|
static void writesection(Section const §, FILE *file) {
|
||||||
putstring(sect.name, f);
|
putstring(sect.name, file);
|
||||||
|
|
||||||
putlong(sect.size, f);
|
putlong(sect.size, file);
|
||||||
|
|
||||||
bool isUnion = sect.modifier == SECTION_UNION;
|
bool isUnion = sect.modifier == SECTION_UNION;
|
||||||
bool isFragment = sect.modifier == SECTION_FRAGMENT;
|
bool isFragment = sect.modifier == SECTION_FRAGMENT;
|
||||||
|
|
||||||
putc(sect.type | isUnion << 7 | isFragment << 6, f);
|
putc(sect.type | isUnion << 7 | isFragment << 6, file);
|
||||||
|
|
||||||
putlong(sect.org, f);
|
putlong(sect.org, file);
|
||||||
putlong(sect.bank, f);
|
putlong(sect.bank, file);
|
||||||
putc(sect.align, f);
|
putc(sect.align, file);
|
||||||
putlong(sect.alignOfs, f);
|
putlong(sect.alignOfs, file);
|
||||||
|
|
||||||
if (sect_HasData(sect.type)) {
|
if (sect_HasData(sect.type)) {
|
||||||
fwrite(sect.data.data(), 1, sect.size, f);
|
fwrite(sect.data.data(), 1, sect.size, file);
|
||||||
putlong(sect.patches.size(), f);
|
putlong(sect.patches.size(), file);
|
||||||
|
|
||||||
for (Patch const &patch : sect.patches)
|
for (Patch const &patch : sect.patches)
|
||||||
writepatch(patch, f);
|
writepatch(patch, file);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Write a symbol to a file
|
// Write a symbol to a file
|
||||||
static void writesymbol(Symbol const &sym, FILE *f) {
|
static void writesymbol(Symbol const &sym, FILE *file) {
|
||||||
putstring(sym.name, f);
|
putstring(sym.name, file);
|
||||||
if (!sym.isDefined()) {
|
if (!sym.isDefined()) {
|
||||||
putc(SYMTYPE_IMPORT, f);
|
putc(SYMTYPE_IMPORT, file);
|
||||||
} else {
|
} else {
|
||||||
assert(sym.src->ID != (uint32_t)-1);
|
assert(sym.src->ID != (uint32_t)-1);
|
||||||
|
|
||||||
putc(sym.isExported ? SYMTYPE_EXPORT : SYMTYPE_LOCAL, f);
|
putc(sym.isExported ? SYMTYPE_EXPORT : SYMTYPE_LOCAL, file);
|
||||||
putlong(sym.src->ID, f);
|
putlong(sym.src->ID, file);
|
||||||
putlong(sym.fileLine, f);
|
putlong(sym.fileLine, file);
|
||||||
putlong(getSectIDIfAny(sym.getSection()), f);
|
putlong(getSectIDIfAny(sym.getSection()), file);
|
||||||
putlong(sym.getOutputValue(), f);
|
putlong(sym.getOutputValue(), file);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -294,7 +294,7 @@ void out_CreatePatch(uint32_t type, Expression const &expr, uint32_t ofs, uint32
|
|||||||
|
|
||||||
// Creates an assert that will be written to the object file
|
// Creates an assert that will be written to the object file
|
||||||
void out_CreateAssert(
|
void out_CreateAssert(
|
||||||
AssertionType type, Expression const &expr, char const *message, uint32_t ofs
|
AssertionType type, Expression const &expr, std::string const &message, uint32_t ofs
|
||||||
) {
|
) {
|
||||||
Assertion &assertion = assertions.emplace_front();
|
Assertion &assertion = assertions.emplace_front();
|
||||||
|
|
||||||
@@ -302,24 +302,24 @@ void out_CreateAssert(
|
|||||||
assertion.message = message;
|
assertion.message = message;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void writeassert(Assertion &assert, FILE *f) {
|
static void writeassert(Assertion &assert, FILE *file) {
|
||||||
writepatch(assert.patch, f);
|
writepatch(assert.patch, file);
|
||||||
putstring(assert.message, f);
|
putstring(assert.message, file);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void writeFileStackNode(FileStackNode const &node, FILE *f) {
|
static void writeFileStackNode(FileStackNode const &node, FILE *file) {
|
||||||
putlong(node.parent ? node.parent->ID : (uint32_t)-1, f);
|
putlong(node.parent ? node.parent->ID : (uint32_t)-1, file);
|
||||||
putlong(node.lineNo, f);
|
putlong(node.lineNo, file);
|
||||||
putc(node.type, f);
|
putc(node.type, file);
|
||||||
if (node.type != NODE_REPT) {
|
if (node.type != NODE_REPT) {
|
||||||
putstring(node.name(), f);
|
putstring(node.name(), file);
|
||||||
} else {
|
} else {
|
||||||
std::vector<uint32_t> const &nodeIters = node.iters();
|
std::vector<uint32_t> const &nodeIters = node.iters();
|
||||||
|
|
||||||
putlong(nodeIters.size(), f);
|
putlong(nodeIters.size(), file);
|
||||||
// Iters are stored by decreasing depth, so reverse the order for output
|
// Iters are stored by decreasing depth, so reverse the order for output
|
||||||
for (uint32_t i = nodeIters.size(); i--;)
|
for (uint32_t i = nodeIters.size(); i--;)
|
||||||
putlong(nodeIters[i], f);
|
putlong(nodeIters[i], file);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -332,31 +332,31 @@ static void registerUnregisteredSymbol(Symbol &sym) {
|
|||||||
|
|
||||||
// Write an objectfile
|
// Write an objectfile
|
||||||
void out_WriteObject() {
|
void out_WriteObject() {
|
||||||
FILE *f;
|
FILE *file;
|
||||||
|
|
||||||
if (strcmp(objectName, "-")) {
|
if (objectName != "-") {
|
||||||
f = fopen(objectName, "wb");
|
file = fopen(objectName.c_str(), "wb");
|
||||||
} else {
|
} else {
|
||||||
objectName = "<stdout>";
|
objectName = "<stdout>";
|
||||||
f = fdopen(STDOUT_FILENO, "wb");
|
file = fdopen(STDOUT_FILENO, "wb");
|
||||||
}
|
}
|
||||||
if (!f)
|
if (!file)
|
||||||
err("Failed to open object file '%s'", objectName);
|
err("Failed to open object file '%s'", objectName.c_str());
|
||||||
|
|
||||||
// Also write symbols that weren't written above
|
// Also write symbols that weren't written above
|
||||||
sym_ForEach(registerUnregisteredSymbol);
|
sym_ForEach(registerUnregisteredSymbol);
|
||||||
|
|
||||||
fprintf(f, RGBDS_OBJECT_VERSION_STRING);
|
fprintf(file, RGBDS_OBJECT_VERSION_STRING);
|
||||||
putlong(RGBDS_OBJECT_REV, f);
|
putlong(RGBDS_OBJECT_REV, file);
|
||||||
|
|
||||||
putlong(objectSymbols.size(), f);
|
putlong(objectSymbols.size(), file);
|
||||||
putlong(sectionList.size(), f);
|
putlong(sectionList.size(), file);
|
||||||
|
|
||||||
putlong(fileStackNodes.size(), f);
|
putlong(fileStackNodes.size(), file);
|
||||||
for (auto it = fileStackNodes.begin(); it != fileStackNodes.end(); it++) {
|
for (auto it = fileStackNodes.begin(); it != fileStackNodes.end(); it++) {
|
||||||
FileStackNode const *node = *it;
|
FileStackNode const *node = *it;
|
||||||
|
|
||||||
writeFileStackNode(*node, f);
|
writeFileStackNode(*node, file);
|
||||||
|
|
||||||
// The list is supposed to have decrementing IDs
|
// The list is supposed to have decrementing IDs
|
||||||
if (it + 1 != fileStackNodes.end() && it[1]->ID != node->ID - 1)
|
if (it + 1 != fileStackNodes.end() && it[1]->ID != node->ID - 1)
|
||||||
@@ -369,24 +369,24 @@ void out_WriteObject() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
for (Symbol const *sym : objectSymbols)
|
for (Symbol const *sym : objectSymbols)
|
||||||
writesymbol(*sym, f);
|
writesymbol(*sym, file);
|
||||||
|
|
||||||
for (auto it = sectionList.rbegin(); it != sectionList.rend(); it++)
|
for (auto it = sectionList.rbegin(); it != sectionList.rend(); it++)
|
||||||
writesection(*it, f);
|
writesection(*it, file);
|
||||||
|
|
||||||
putlong(assertions.size(), f);
|
putlong(assertions.size(), file);
|
||||||
|
|
||||||
for (Assertion &assert : assertions)
|
for (Assertion &assert : assertions)
|
||||||
writeassert(assert, f);
|
writeassert(assert, file);
|
||||||
|
|
||||||
fclose(f);
|
fclose(file);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Set the objectfilename
|
// Set the objectfilename
|
||||||
void out_SetFileName(char *s) {
|
void out_SetFileName(std::string const &name) {
|
||||||
if (objectName)
|
if (!objectName.empty())
|
||||||
warnx("Overriding output filename %s", objectName);
|
warnx("Overriding output filename %s", objectName.c_str());
|
||||||
objectName = s;
|
objectName = name;
|
||||||
if (verbose)
|
if (verbose)
|
||||||
printf("Output filename %s\n", objectName);
|
printf("Output filename %s\n", objectName.c_str());
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -88,7 +88,7 @@
|
|||||||
);
|
);
|
||||||
static void compoundAssignment(std::string const &symName, RPNCommand op, int32_t constValue);
|
static void compoundAssignment(std::string const &symName, RPNCommand op, int32_t constValue);
|
||||||
static void failAssert(AssertionType type);
|
static void failAssert(AssertionType type);
|
||||||
static void failAssertMsg(AssertionType type, char const *msg);
|
static void failAssertMsg(AssertionType type, std::string const &message);
|
||||||
|
|
||||||
// The CPU encodes instructions in a logical way, so most instructions actually follow patterns.
|
// The CPU encodes instructions in a logical way, so most instructions actually follow patterns.
|
||||||
// These enums thus help with bit twiddling to compute opcodes.
|
// These enums thus help with bit twiddling to compute opcodes.
|
||||||
@@ -824,9 +824,9 @@ assert:
|
|||||||
}
|
}
|
||||||
| POP_ASSERT assert_type relocexpr COMMA string {
|
| POP_ASSERT assert_type relocexpr COMMA string {
|
||||||
if (!$3.isKnown) {
|
if (!$3.isKnown) {
|
||||||
out_CreateAssert($2, $3, $5.c_str(), sect_GetOutputOffset());
|
out_CreateAssert($2, $3, $5, sect_GetOutputOffset());
|
||||||
} else if ($3.val == 0) {
|
} else if ($3.val == 0) {
|
||||||
failAssertMsg($2, $5.c_str());
|
failAssertMsg($2, $5);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
| POP_STATIC_ASSERT assert_type const {
|
| POP_STATIC_ASSERT assert_type const {
|
||||||
@@ -835,7 +835,7 @@ assert:
|
|||||||
}
|
}
|
||||||
| POP_STATIC_ASSERT assert_type const COMMA string {
|
| POP_STATIC_ASSERT assert_type const COMMA string {
|
||||||
if ($3 == 0)
|
if ($3 == 0)
|
||||||
failAssertMsg($2, $5.c_str());
|
failAssertMsg($2, $5);
|
||||||
}
|
}
|
||||||
;
|
;
|
||||||
|
|
||||||
@@ -2736,15 +2736,15 @@ static void failAssert(AssertionType type) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void failAssertMsg(AssertionType type, char const *msg) {
|
static void failAssertMsg(AssertionType type, std::string const &message) {
|
||||||
switch (type) {
|
switch (type) {
|
||||||
case ASSERT_FATAL:
|
case ASSERT_FATAL:
|
||||||
fatalerror("Assertion failed: %s\n", msg);
|
fatalerror("Assertion failed: %s\n", message.c_str());
|
||||||
case ASSERT_ERROR:
|
case ASSERT_ERROR:
|
||||||
error("Assertion failed: %s\n", msg);
|
error("Assertion failed: %s\n", message.c_str());
|
||||||
break;
|
break;
|
||||||
case ASSERT_WARN:
|
case ASSERT_WARN:
|
||||||
warning(WARNING_ASSERT, "Assertion failed: %s\n", msg);
|
warning(WARNING_ASSERT, "Assertion failed: %s\n", message.c_str());
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user