mirror of
https://github.com/gbdev/rgbds.git
synced 2025-11-20 10:12:06 +00:00
Replace assert with assume for release build optimization (#1390)
This commit is contained in:
@@ -3,7 +3,6 @@
|
|||||||
#ifndef RGBDS_FILE_HPP
|
#ifndef RGBDS_FILE_HPP
|
||||||
#define RGBDS_FILE_HPP
|
#define RGBDS_FILE_HPP
|
||||||
|
|
||||||
#include <assert.h>
|
|
||||||
#include <fcntl.h>
|
#include <fcntl.h>
|
||||||
#include <fstream>
|
#include <fstream>
|
||||||
#include <ios>
|
#include <ios>
|
||||||
@@ -13,6 +12,7 @@
|
|||||||
#include <string>
|
#include <string>
|
||||||
#include <variant>
|
#include <variant>
|
||||||
|
|
||||||
|
#include "helpers.hpp" // assume
|
||||||
#include "platform.hpp"
|
#include "platform.hpp"
|
||||||
|
|
||||||
#include "gfx/main.hpp"
|
#include "gfx/main.hpp"
|
||||||
@@ -33,7 +33,7 @@ public:
|
|||||||
if (path != "-") {
|
if (path != "-") {
|
||||||
return _file.emplace<std::filebuf>().open(path, mode) ? this : nullptr;
|
return _file.emplace<std::filebuf>().open(path, mode) ? this : nullptr;
|
||||||
} else if (mode & std::ios_base::in) {
|
} else if (mode & std::ios_base::in) {
|
||||||
assert(!(mode & std::ios_base::out));
|
assume(!(mode & std::ios_base::out));
|
||||||
_file.emplace<std::streambuf *>(std::cin.rdbuf());
|
_file.emplace<std::streambuf *>(std::cin.rdbuf());
|
||||||
if (setmode(STDIN_FILENO, (mode & std::ios_base::binary) ? O_BINARY : O_TEXT) == -1) {
|
if (setmode(STDIN_FILENO, (mode & std::ios_base::binary) ? O_BINARY : O_TEXT) == -1) {
|
||||||
fatal(
|
fatal(
|
||||||
@@ -43,7 +43,7 @@ public:
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
assert(mode & std::ios_base::out);
|
assume(mode & std::ios_base::out);
|
||||||
_file.emplace<std::streambuf *>(std::cout.rdbuf());
|
_file.emplace<std::streambuf *>(std::cout.rdbuf());
|
||||||
}
|
}
|
||||||
return this;
|
return this;
|
||||||
|
|||||||
@@ -3,12 +3,12 @@
|
|||||||
#ifndef HELPERS_H
|
#ifndef HELPERS_H
|
||||||
#define HELPERS_H
|
#define HELPERS_H
|
||||||
|
|
||||||
// Ideally, we'd use `__has_attribute` and `__has_builtin`, but these were only introduced in GCC 9
|
// Ideally we'd use `std::unreachable`, but it has insufficient compiler support
|
||||||
#ifdef __GNUC__ // GCC or compatible
|
#ifdef __GNUC__ // GCC or compatible
|
||||||
// In release builds, define "unreachable" as such, but trap in debug builds
|
|
||||||
#ifdef NDEBUG
|
#ifdef NDEBUG
|
||||||
#define unreachable_ __builtin_unreachable
|
#define unreachable_ __builtin_unreachable
|
||||||
#else
|
#else
|
||||||
|
// In release builds, define "unreachable" as such, but trap in debug builds
|
||||||
#define unreachable_ __builtin_trap
|
#define unreachable_ __builtin_trap
|
||||||
#endif
|
#endif
|
||||||
#else
|
#else
|
||||||
@@ -18,32 +18,52 @@
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// Use builtins whenever possible, and shim them otherwise
|
// Ideally we'd use `[[assume()]]`, but it has insufficient compiler support
|
||||||
|
#ifdef NDEBUG
|
||||||
|
#ifdef _MSC_VER
|
||||||
|
#define assume(x) __assume(x)
|
||||||
|
#else
|
||||||
|
// `[[gnu::assume()]]` for GCC or compatible also has insufficient support (GCC 13+ only)
|
||||||
|
#define assume(x) \
|
||||||
|
do { \
|
||||||
|
if (!(x)) \
|
||||||
|
unreachable_(); \
|
||||||
|
} while (0)
|
||||||
|
#endif
|
||||||
|
#else
|
||||||
|
// In release builds, define "assume" as such, but `assert` in debug builds
|
||||||
|
#include <assert.h>
|
||||||
|
#define assume assert
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// Ideally we'd use `std::bit_width`, but it has insufficient compiler support
|
||||||
#ifdef __GNUC__ // GCC or compatible
|
#ifdef __GNUC__ // GCC or compatible
|
||||||
#define ctz __builtin_ctz
|
#define ctz __builtin_ctz
|
||||||
#define clz __builtin_clz
|
#define clz __builtin_clz
|
||||||
|
|
||||||
#elif defined(_MSC_VER)
|
#elif defined(_MSC_VER)
|
||||||
#include <assert.h>
|
|
||||||
#include <intrin.h>
|
#include <intrin.h>
|
||||||
#pragma intrinsic(_BitScanReverse, _BitScanForward)
|
#pragma intrinsic(_BitScanReverse, _BitScanForward)
|
||||||
|
|
||||||
static inline int ctz(unsigned int x) {
|
static inline int ctz(unsigned int x) {
|
||||||
unsigned long cnt;
|
unsigned long cnt;
|
||||||
|
|
||||||
assert(x != 0);
|
assume(x != 0);
|
||||||
_BitScanForward(&cnt, x);
|
_BitScanForward(&cnt, x);
|
||||||
return cnt;
|
return cnt;
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline int clz(unsigned int x) {
|
static inline int clz(unsigned int x) {
|
||||||
unsigned long cnt;
|
unsigned long cnt;
|
||||||
|
|
||||||
assert(x != 0);
|
assume(x != 0);
|
||||||
_BitScanReverse(&cnt, x);
|
_BitScanReverse(&cnt, x);
|
||||||
return 31 - cnt;
|
return 31 - cnt;
|
||||||
}
|
}
|
||||||
|
|
||||||
#else
|
#else
|
||||||
#include <limits.h>
|
#include <limits.h>
|
||||||
|
|
||||||
static inline int ctz(unsigned int x) {
|
static inline int ctz(unsigned int x) {
|
||||||
int cnt = 0;
|
int cnt = 0;
|
||||||
|
|
||||||
|
|||||||
@@ -3,10 +3,11 @@
|
|||||||
#ifndef RGBDS_LINKDEFS_H
|
#ifndef RGBDS_LINKDEFS_H
|
||||||
#define RGBDS_LINKDEFS_H
|
#define RGBDS_LINKDEFS_H
|
||||||
|
|
||||||
#include <assert.h>
|
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
#include <string>
|
#include <string>
|
||||||
|
|
||||||
|
#include "helpers.hpp" // assume
|
||||||
|
|
||||||
#define RGBDS_OBJECT_VERSION_STRING "RGBA"
|
#define RGBDS_OBJECT_VERSION_STRING "RGBA"
|
||||||
#define RGBDS_OBJECT_REV 10U
|
#define RGBDS_OBJECT_REV 10U
|
||||||
|
|
||||||
@@ -93,7 +94,7 @@ extern struct SectionTypeInfo {
|
|||||||
* @return `true` if the section's definition includes data
|
* @return `true` if the section's definition includes data
|
||||||
*/
|
*/
|
||||||
static inline bool sect_HasData(SectionType type) {
|
static inline bool sect_HasData(SectionType type) {
|
||||||
assert(type != SECTTYPE_INVALID);
|
assume(type != SECTTYPE_INVALID);
|
||||||
return type == SECTTYPE_ROM0 || type == SECTTYPE_ROMX;
|
return type == SECTTYPE_ROM0 || type == SECTTYPE_ROMX;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -3,7 +3,6 @@
|
|||||||
#include "asm/fstack.hpp"
|
#include "asm/fstack.hpp"
|
||||||
#include <sys/stat.h>
|
#include <sys/stat.h>
|
||||||
|
|
||||||
#include <assert.h>
|
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
#include <inttypes.h>
|
#include <inttypes.h>
|
||||||
#include <memory>
|
#include <memory>
|
||||||
@@ -50,28 +49,28 @@ static std::vector<std::string> includePaths = {""};
|
|||||||
static std::string preIncludeName;
|
static std::string preIncludeName;
|
||||||
|
|
||||||
std::vector<uint32_t> &FileStackNode::iters() {
|
std::vector<uint32_t> &FileStackNode::iters() {
|
||||||
assert(std::holds_alternative<std::vector<uint32_t>>(data));
|
assume(std::holds_alternative<std::vector<uint32_t>>(data));
|
||||||
return std::get<std::vector<uint32_t>>(data);
|
return std::get<std::vector<uint32_t>>(data);
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<uint32_t> const &FileStackNode::iters() const {
|
std::vector<uint32_t> const &FileStackNode::iters() const {
|
||||||
assert(std::holds_alternative<std::vector<uint32_t>>(data));
|
assume(std::holds_alternative<std::vector<uint32_t>>(data));
|
||||||
return std::get<std::vector<uint32_t>>(data);
|
return std::get<std::vector<uint32_t>>(data);
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string &FileStackNode::name() {
|
std::string &FileStackNode::name() {
|
||||||
assert(std::holds_alternative<std::string>(data));
|
assume(std::holds_alternative<std::string>(data));
|
||||||
return std::get<std::string>(data);
|
return std::get<std::string>(data);
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string const &FileStackNode::name() const {
|
std::string const &FileStackNode::name() const {
|
||||||
assert(std::holds_alternative<std::string>(data));
|
assume(std::holds_alternative<std::string>(data));
|
||||||
return std::get<std::string>(data);
|
return std::get<std::string>(data);
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string const &FileStackNode::dump(uint32_t curLineNo) const {
|
std::string const &FileStackNode::dump(uint32_t curLineNo) const {
|
||||||
if (std::holds_alternative<std::vector<uint32_t>>(data)) {
|
if (std::holds_alternative<std::vector<uint32_t>>(data)) {
|
||||||
assert(parent); // REPT nodes use their parent's name
|
assume(parent); // REPT nodes use their parent's name
|
||||||
std::string const &lastName = parent->dump(lineNo);
|
std::string const &lastName = parent->dump(lineNo);
|
||||||
fputs(" -> ", stderr);
|
fputs(" -> ", stderr);
|
||||||
fputs(lastName.c_str(), stderr);
|
fputs(lastName.c_str(), stderr);
|
||||||
@@ -270,7 +269,7 @@ static void newMacroContext(Symbol const ¯o, std::shared_ptr<MacroArgs> macr
|
|||||||
fileInfoName.append(macro.name);
|
fileInfoName.append(macro.name);
|
||||||
|
|
||||||
auto fileInfo = std::make_shared<FileStackNode>(NODE_MACRO, fileInfoName);
|
auto fileInfo = std::make_shared<FileStackNode>(NODE_MACRO, fileInfoName);
|
||||||
assert(!contextStack.empty()); // The top level context cannot be a MACRO
|
assume(!contextStack.empty()); // The top level context cannot be a MACRO
|
||||||
fileInfo->parent = oldContext.fileInfo;
|
fileInfo->parent = oldContext.fileInfo;
|
||||||
fileInfo->lineNo = lexer_GetLineNo();
|
fileInfo->lineNo = lexer_GetLineNo();
|
||||||
|
|
||||||
@@ -295,7 +294,7 @@ static Context &newReptContext(int32_t reptLineNo, ContentSpan const &span, uint
|
|||||||
}
|
}
|
||||||
|
|
||||||
auto fileInfo = std::make_shared<FileStackNode>(NODE_REPT, fileInfoIters);
|
auto fileInfo = std::make_shared<FileStackNode>(NODE_REPT, fileInfoIters);
|
||||||
assert(!contextStack.empty()); // The top level context cannot be a REPT
|
assume(!contextStack.empty()); // The top level context cannot be a REPT
|
||||||
fileInfo->parent = oldContext.fileInfo;
|
fileInfo->parent = oldContext.fileInfo;
|
||||||
fileInfo->lineNo = reptLineNo;
|
fileInfo->lineNo = reptLineNo;
|
||||||
|
|
||||||
|
|||||||
@@ -5,7 +5,6 @@
|
|||||||
#include <sys/types.h>
|
#include <sys/types.h>
|
||||||
|
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
#include <assert.h>
|
|
||||||
#include <ctype.h>
|
#include <ctype.h>
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
#include <fcntl.h>
|
#include <fcntl.h>
|
||||||
@@ -20,7 +19,7 @@
|
|||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#include "helpers.hpp" // QUOTEDSTRLEN
|
#include "helpers.hpp" // assume, QUOTEDSTRLEN
|
||||||
#include "util.hpp"
|
#include "util.hpp"
|
||||||
|
|
||||||
#include "asm/fixpoint.hpp"
|
#include "asm/fixpoint.hpp"
|
||||||
@@ -477,14 +476,14 @@ LexerState::~LexerState() {
|
|||||||
// scheduled at EOF; `lexerStateEOL` thus becomes a (weak) ref to that lexer state...
|
// scheduled at EOF; `lexerStateEOL` thus becomes a (weak) ref to that lexer state...
|
||||||
// It has been possible, due to a bug, that the corresponding fstack context gets popped
|
// It has been possible, due to a bug, that the corresponding fstack context gets popped
|
||||||
// before EOL, deleting the associated state... but it would still be switched to at EOL.
|
// before EOL, deleting the associated state... but it would still be switched to at EOL.
|
||||||
// This assertion checks that this doesn't happen again.
|
// This assumption checks that this doesn't happen again.
|
||||||
// It could be argued that deleting a state that's scheduled for EOF could simply clear
|
// It could be argued that deleting a state that's scheduled for EOF could simply clear
|
||||||
// `lexerStateEOL`, but there's currently no situation in which this should happen.
|
// `lexerStateEOL`, but there's currently no situation in which this should happen.
|
||||||
assert(this != lexerStateEOL);
|
assume(this != lexerStateEOL);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Expansion::advance() {
|
bool Expansion::advance() {
|
||||||
assert(offset <= size());
|
assume(offset <= size());
|
||||||
offset++;
|
offset++;
|
||||||
return offset > size();
|
return offset > size();
|
||||||
}
|
}
|
||||||
@@ -494,11 +493,11 @@ BufferedContent::~BufferedContent() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void BufferedContent::advance() {
|
void BufferedContent::advance() {
|
||||||
assert(offset < LEXER_BUF_SIZE);
|
assume(offset < LEXER_BUF_SIZE);
|
||||||
offset++;
|
offset++;
|
||||||
if (offset == LEXER_BUF_SIZE)
|
if (offset == LEXER_BUF_SIZE)
|
||||||
offset = 0; // Wrap around if necessary
|
offset = 0; // Wrap around if necessary
|
||||||
assert(size > 0);
|
assume(size > 0);
|
||||||
size--;
|
size--;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -528,7 +527,7 @@ void BufferedContent::refill() {
|
|||||||
|
|
||||||
size_t BufferedContent::readMore(size_t startIndex, size_t nbChars) {
|
size_t BufferedContent::readMore(size_t startIndex, size_t nbChars) {
|
||||||
// This buffer overflow made me lose WEEKS of my life. Never again.
|
// This buffer overflow made me lose WEEKS of my life. Never again.
|
||||||
assert(startIndex + nbChars <= LEXER_BUF_SIZE);
|
assume(startIndex + nbChars <= LEXER_BUF_SIZE);
|
||||||
ssize_t nbReadChars = read(fd, &buf[startIndex], nbChars);
|
ssize_t nbReadChars = read(fd, &buf[startIndex], nbChars);
|
||||||
|
|
||||||
if (nbReadChars == -1)
|
if (nbReadChars == -1)
|
||||||
@@ -671,7 +670,7 @@ static std::shared_ptr<std::string> readMacroArg(char name) {
|
|||||||
error("Invalid macro argument '\\0'\n");
|
error("Invalid macro argument '\\0'\n");
|
||||||
return nullptr;
|
return nullptr;
|
||||||
} else {
|
} else {
|
||||||
assert(name > '0' && name <= '9');
|
assume(name > '0' && name <= '9');
|
||||||
|
|
||||||
MacroArgs *macroArgs = fstk_GetCurrentMacroArgs();
|
MacroArgs *macroArgs = fstk_GetCurrentMacroArgs();
|
||||||
if (!macroArgs) {
|
if (!macroArgs) {
|
||||||
@@ -698,11 +697,11 @@ int LexerState::peekChar() {
|
|||||||
if (view->offset < view->span.size)
|
if (view->offset < view->span.size)
|
||||||
return (uint8_t)view->span.ptr[view->offset];
|
return (uint8_t)view->span.ptr[view->offset];
|
||||||
} else {
|
} else {
|
||||||
assert(std::holds_alternative<BufferedContent>(content));
|
assume(std::holds_alternative<BufferedContent>(content));
|
||||||
auto &cbuf = std::get<BufferedContent>(content);
|
auto &cbuf = std::get<BufferedContent>(content);
|
||||||
if (cbuf.size == 0)
|
if (cbuf.size == 0)
|
||||||
cbuf.refill();
|
cbuf.refill();
|
||||||
assert(cbuf.offset < LEXER_BUF_SIZE);
|
assume(cbuf.offset < LEXER_BUF_SIZE);
|
||||||
if (cbuf.size > 0)
|
if (cbuf.size > 0)
|
||||||
return (uint8_t)cbuf.buf[cbuf.offset];
|
return (uint8_t)cbuf.buf[cbuf.offset];
|
||||||
}
|
}
|
||||||
@@ -718,7 +717,7 @@ int LexerState::peekCharAhead() {
|
|||||||
for (Expansion &exp : expansions) {
|
for (Expansion &exp : expansions) {
|
||||||
// An expansion that has reached its end will have `exp.offset` == `exp.size()`,
|
// An expansion that has reached its end will have `exp.offset` == `exp.size()`,
|
||||||
// and `.peekCharAhead()` will continue with its parent
|
// and `.peekCharAhead()` will continue with its parent
|
||||||
assert(exp.offset <= exp.size());
|
assume(exp.offset <= exp.size());
|
||||||
if (exp.offset + distance < exp.size())
|
if (exp.offset + distance < exp.size())
|
||||||
return (uint8_t)(*exp.contents)[exp.offset + distance];
|
return (uint8_t)(*exp.contents)[exp.offset + distance];
|
||||||
distance -= exp.size() - exp.offset;
|
distance -= exp.size() - exp.offset;
|
||||||
@@ -728,9 +727,9 @@ int LexerState::peekCharAhead() {
|
|||||||
if (view->offset + distance < view->span.size)
|
if (view->offset + distance < view->span.size)
|
||||||
return (uint8_t)view->span.ptr[view->offset + distance];
|
return (uint8_t)view->span.ptr[view->offset + distance];
|
||||||
} else {
|
} else {
|
||||||
assert(std::holds_alternative<BufferedContent>(content));
|
assume(std::holds_alternative<BufferedContent>(content));
|
||||||
auto &cbuf = std::get<BufferedContent>(content);
|
auto &cbuf = std::get<BufferedContent>(content);
|
||||||
assert(distance < LEXER_BUF_SIZE);
|
assume(distance < LEXER_BUF_SIZE);
|
||||||
if (cbuf.size <= distance)
|
if (cbuf.size <= distance)
|
||||||
cbuf.refill();
|
cbuf.refill();
|
||||||
if (cbuf.size > distance)
|
if (cbuf.size > distance)
|
||||||
@@ -816,7 +815,7 @@ restart:
|
|||||||
if (auto *view = std::get_if<ViewedContent>(&lexerState->content); view) {
|
if (auto *view = std::get_if<ViewedContent>(&lexerState->content); view) {
|
||||||
view->offset++;
|
view->offset++;
|
||||||
} else {
|
} else {
|
||||||
assert(std::holds_alternative<BufferedContent>(lexerState->content));
|
assume(std::holds_alternative<BufferedContent>(lexerState->content));
|
||||||
auto &cbuf = std::get<BufferedContent>(lexerState->content);
|
auto &cbuf = std::get<BufferedContent>(lexerState->content);
|
||||||
cbuf.advance();
|
cbuf.advance();
|
||||||
}
|
}
|
||||||
@@ -1785,7 +1784,7 @@ static Token yylex_NORMAL() {
|
|||||||
return token;
|
return token;
|
||||||
|
|
||||||
// `token` is either an `ID` or a `LOCAL_ID`, and both have a `std::string` value.
|
// `token` is either an `ID` or a `LOCAL_ID`, and both have a `std::string` value.
|
||||||
assert(std::holds_alternative<std::string>(token.value));
|
assume(std::holds_alternative<std::string>(token.value));
|
||||||
|
|
||||||
// Local symbols cannot be string expansions
|
// Local symbols cannot be string expansions
|
||||||
if (token.type == T_(ID) && lexerState->expandStrings) {
|
if (token.type == T_(ID) && lexerState->expandStrings) {
|
||||||
@@ -1795,7 +1794,7 @@ static Token yylex_NORMAL() {
|
|||||||
if (sym && sym->type == SYM_EQUS) {
|
if (sym && sym->type == SYM_EQUS) {
|
||||||
std::shared_ptr<std::string> str = sym->getEqus();
|
std::shared_ptr<std::string> str = sym->getEqus();
|
||||||
|
|
||||||
assert(str);
|
assume(str);
|
||||||
beginExpansion(str, sym->name);
|
beginExpansion(str, sym->name);
|
||||||
continue; // Restart, reading from the new buffer
|
continue; // Restart, reading from the new buffer
|
||||||
}
|
}
|
||||||
@@ -2172,7 +2171,7 @@ yy::parser::symbol_type yylex() {
|
|||||||
} else if (auto *strValue = std::get_if<std::string>(&token.value); strValue) {
|
} else if (auto *strValue = std::get_if<std::string>(&token.value); strValue) {
|
||||||
return yy::parser::symbol_type(token.type, *strValue);
|
return yy::parser::symbol_type(token.type, *strValue);
|
||||||
} else {
|
} else {
|
||||||
assert(std::holds_alternative<std::monostate>(token.value));
|
assume(std::holds_alternative<std::monostate>(token.value));
|
||||||
return yy::parser::symbol_type(token.type);
|
return yy::parser::symbol_type(token.type);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -2180,10 +2179,10 @@ yy::parser::symbol_type yylex() {
|
|||||||
static Capture startCapture() {
|
static Capture startCapture() {
|
||||||
// Due to parser internals, it reads the EOL after the expression before calling this.
|
// Due to parser internals, it reads the EOL after the expression before calling this.
|
||||||
// Thus, we don't need to keep one in the buffer afterwards.
|
// Thus, we don't need to keep one in the buffer afterwards.
|
||||||
// The following assertion checks that.
|
// The following assumption checks that.
|
||||||
assert(lexerState->atLineStart);
|
assume(lexerState->atLineStart);
|
||||||
|
|
||||||
assert(!lexerState->capturing && lexerState->captureBuf == nullptr);
|
assume(!lexerState->capturing && lexerState->captureBuf == nullptr);
|
||||||
lexerState->capturing = true;
|
lexerState->capturing = true;
|
||||||
lexerState->captureSize = 0;
|
lexerState->captureSize = 0;
|
||||||
|
|
||||||
@@ -2194,7 +2193,7 @@ static Capture startCapture() {
|
|||||||
.lineNo = lineNo, .span = {.ptr = view->makeSharedContentPtr(), .size = 0}
|
.lineNo = lineNo, .span = {.ptr = view->makeSharedContentPtr(), .size = 0}
|
||||||
};
|
};
|
||||||
} else {
|
} else {
|
||||||
assert(lexerState->captureBuf == nullptr);
|
assume(lexerState->captureBuf == nullptr);
|
||||||
lexerState->captureBuf = std::make_shared<std::vector<char>>();
|
lexerState->captureBuf = std::make_shared<std::vector<char>>();
|
||||||
// `.span.ptr == nullptr`; indicates to retrieve the capture buffer when done capturing
|
// `.span.ptr == nullptr`; indicates to retrieve the capture buffer when done capturing
|
||||||
return {
|
return {
|
||||||
|
|||||||
@@ -2,7 +2,6 @@
|
|||||||
|
|
||||||
#include "asm/output.hpp"
|
#include "asm/output.hpp"
|
||||||
|
|
||||||
#include <assert.h>
|
|
||||||
#include <deque>
|
#include <deque>
|
||||||
#include <inttypes.h>
|
#include <inttypes.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
@@ -12,7 +11,7 @@
|
|||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
#include "error.hpp"
|
#include "error.hpp"
|
||||||
#include "helpers.hpp" // Defer
|
#include "helpers.hpp" // assume, Defer
|
||||||
|
|
||||||
#include "asm/fstack.hpp"
|
#include "asm/fstack.hpp"
|
||||||
#include "asm/lexer.hpp"
|
#include "asm/lexer.hpp"
|
||||||
@@ -75,7 +74,7 @@ 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 *file) {
|
static void writepatch(Patch const &patch, FILE *file) {
|
||||||
assert(patch.src->ID != (uint32_t)-1);
|
assume(patch.src->ID != (uint32_t)-1);
|
||||||
putlong(patch.src->ID, file);
|
putlong(patch.src->ID, file);
|
||||||
putlong(patch.lineNo, file);
|
putlong(patch.lineNo, file);
|
||||||
putlong(patch.offset, file);
|
putlong(patch.offset, file);
|
||||||
@@ -117,7 +116,7 @@ static void writesymbol(Symbol const &sym, FILE *file) {
|
|||||||
if (!sym.isDefined()) {
|
if (!sym.isDefined()) {
|
||||||
putc(SYMTYPE_IMPORT, file);
|
putc(SYMTYPE_IMPORT, file);
|
||||||
} else {
|
} else {
|
||||||
assert(sym.src->ID != (uint32_t)-1);
|
assume(sym.src->ID != (uint32_t)-1);
|
||||||
|
|
||||||
putc(sym.isExported ? SYMTYPE_EXPORT : SYMTYPE_LOCAL, file);
|
putc(sym.isExported ? SYMTYPE_EXPORT : SYMTYPE_LOCAL, file);
|
||||||
putlong(sym.src->ID, file);
|
putlong(sym.src->ID, file);
|
||||||
|
|||||||
@@ -2542,7 +2542,7 @@ static std::string strfmt(
|
|||||||
} else if (auto *n = std::get_if<uint32_t>(&args[argIndex]); n) {
|
} else if (auto *n = std::get_if<uint32_t>(&args[argIndex]); n) {
|
||||||
fmt.appendNumber(str, *n);
|
fmt.appendNumber(str, *n);
|
||||||
} else {
|
} else {
|
||||||
assert(std::holds_alternative<std::string>(args[argIndex]));
|
assume(std::holds_alternative<std::string>(args[argIndex]));
|
||||||
auto &s = std::get<std::string>(args[argIndex]);
|
auto &s = std::get<std::string>(args[argIndex]);
|
||||||
fmt.appendString(str, s);
|
fmt.appendString(str, s);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,7 +2,6 @@
|
|||||||
|
|
||||||
#include "asm/rpn.hpp"
|
#include "asm/rpn.hpp"
|
||||||
|
|
||||||
#include <assert.h>
|
|
||||||
#include <inttypes.h>
|
#include <inttypes.h>
|
||||||
#include <limits.h>
|
#include <limits.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
@@ -10,6 +9,7 @@
|
|||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <string_view>
|
#include <string_view>
|
||||||
|
|
||||||
|
#include "helpers.hpp" // assume
|
||||||
#include "opmath.hpp"
|
#include "opmath.hpp"
|
||||||
|
|
||||||
#include "asm/output.hpp"
|
#include "asm/output.hpp"
|
||||||
@@ -20,7 +20,7 @@
|
|||||||
using namespace std::literals;
|
using namespace std::literals;
|
||||||
|
|
||||||
int32_t Expression::value() const {
|
int32_t Expression::value() const {
|
||||||
assert(std::holds_alternative<int32_t>(data));
|
assume(std::holds_alternative<int32_t>(data));
|
||||||
return std::get<int32_t>(data);
|
return std::get<int32_t>(data);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -116,7 +116,7 @@ void Expression::makeBankSymbol(std::string const &symName) {
|
|||||||
data = 1;
|
data = 1;
|
||||||
} else {
|
} else {
|
||||||
sym = sym_Ref(symName);
|
sym = sym_Ref(symName);
|
||||||
assert(sym); // If the symbol didn't exist, it should have been created
|
assume(sym); // If the symbol didn't exist, it should have been created
|
||||||
|
|
||||||
if (sym->getSection() && sym->getSection()->bank != (uint32_t)-1) {
|
if (sym->getSection() && sym->getSection()->bank != (uint32_t)-1) {
|
||||||
// Symbol's section is known and bank is fixed
|
// Symbol's section is known and bank is fixed
|
||||||
@@ -217,7 +217,7 @@ static int32_t tryConstMask(Expression const &lhs, Expression const &rhs) {
|
|||||||
Symbol const &sym = lhsIsSymbol ? *lhsSymbol : *rhsSymbol;
|
Symbol const &sym = lhsIsSymbol ? *lhsSymbol : *rhsSymbol;
|
||||||
Expression const &expr = lhsIsSymbol ? rhs : lhs; // Opposite side of `sym`
|
Expression const &expr = lhsIsSymbol ? rhs : lhs; // Opposite side of `sym`
|
||||||
|
|
||||||
assert(sym.isNumeric());
|
assume(sym.isNumeric());
|
||||||
|
|
||||||
if (!expr.isKnown())
|
if (!expr.isKnown())
|
||||||
return -1;
|
return -1;
|
||||||
@@ -231,7 +231,7 @@ static int32_t tryConstMask(Expression const &lhs, Expression const &rhs) {
|
|||||||
|
|
||||||
// `sym.getValue()` attempts to add the section's address, but that's "-1"
|
// `sym.getValue()` attempts to add the section's address, but that's "-1"
|
||||||
// because the section is floating (otherwise we wouldn't be here)
|
// because the section is floating (otherwise we wouldn't be here)
|
||||||
assert(sect.org == (uint32_t)-1);
|
assume(sect.org == (uint32_t)-1);
|
||||||
int32_t symbolOfs = sym.getValue() + 1;
|
int32_t symbolOfs = sym.getValue() + 1;
|
||||||
|
|
||||||
return (symbolOfs + sect.alignOfs) & ~unknownBits;
|
return (symbolOfs + sect.alignOfs) & ~unknownBits;
|
||||||
@@ -502,8 +502,8 @@ void Expression::makeCheckRST() {
|
|||||||
|
|
||||||
// Checks that an RPN expression's value fits within N bits (signed or unsigned)
|
// Checks that an RPN expression's value fits within N bits (signed or unsigned)
|
||||||
void Expression::checkNBit(uint8_t n) const {
|
void Expression::checkNBit(uint8_t n) const {
|
||||||
assert(n != 0); // That doesn't make sense
|
assume(n != 0); // That doesn't make sense
|
||||||
assert(n < CHAR_BIT * sizeof(int)); // Otherwise `1 << n` is UB
|
assume(n < CHAR_BIT * sizeof(int)); // Otherwise `1 << n` is UB
|
||||||
|
|
||||||
if (isKnown()) {
|
if (isKnown()) {
|
||||||
if (int32_t val = value(); val < -(1 << n) || val >= 1 << n)
|
if (int32_t val = value(); val < -(1 << n) || val >= 1 << n)
|
||||||
|
|||||||
@@ -3,7 +3,6 @@
|
|||||||
#include "asm/section.hpp"
|
#include "asm/section.hpp"
|
||||||
|
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
#include <assert.h>
|
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
#include <inttypes.h>
|
#include <inttypes.h>
|
||||||
#include <optional>
|
#include <optional>
|
||||||
@@ -125,7 +124,7 @@ Section *sect_FindSectionByName(std::string const &name) {
|
|||||||
static unsigned int mergeSectUnion(
|
static unsigned int mergeSectUnion(
|
||||||
Section §, SectionType type, uint32_t org, uint8_t alignment, uint16_t alignOffset
|
Section §, SectionType type, uint32_t org, uint8_t alignment, uint16_t alignOffset
|
||||||
) {
|
) {
|
||||||
assert(alignment < 16); // Should be ensured by the caller
|
assume(alignment < 16); // Should be ensured by the caller
|
||||||
unsigned int nbSectErrors = 0;
|
unsigned int nbSectErrors = 0;
|
||||||
|
|
||||||
// Unionized sections only need "compatible" constraints, and they end up with the strictest
|
// Unionized sections only need "compatible" constraints, and they end up with the strictest
|
||||||
@@ -177,7 +176,7 @@ static unsigned int mergeSectUnion(
|
|||||||
|
|
||||||
static unsigned int
|
static unsigned int
|
||||||
mergeFragments(Section §, uint32_t org, uint8_t alignment, uint16_t alignOffset) {
|
mergeFragments(Section §, uint32_t org, uint8_t alignment, uint16_t alignOffset) {
|
||||||
assert(alignment < 16); // Should be ensured by the caller
|
assume(alignment < 16); // Should be ensured by the caller
|
||||||
unsigned int nbSectErrors = 0;
|
unsigned int nbSectErrors = 0;
|
||||||
|
|
||||||
// Fragments only need "compatible" constraints, and they end up with the strictest
|
// Fragments only need "compatible" constraints, and they end up with the strictest
|
||||||
|
|||||||
@@ -2,12 +2,12 @@
|
|||||||
|
|
||||||
#include "asm/symbol.hpp"
|
#include "asm/symbol.hpp"
|
||||||
|
|
||||||
#include <assert.h>
|
|
||||||
#include <inttypes.h>
|
#include <inttypes.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <unordered_map>
|
#include <unordered_map>
|
||||||
|
|
||||||
#include "error.hpp"
|
#include "error.hpp"
|
||||||
|
#include "helpers.hpp" // assume
|
||||||
#include "version.hpp"
|
#include "version.hpp"
|
||||||
|
|
||||||
#include "asm/fstack.hpp"
|
#include "asm/fstack.hpp"
|
||||||
@@ -55,7 +55,7 @@ static int32_t CallbackPC() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
int32_t Symbol::getValue() const {
|
int32_t Symbol::getValue() const {
|
||||||
assert(std::holds_alternative<int32_t>(data) || std::holds_alternative<int32_t (*)()>(data));
|
assume(std::holds_alternative<int32_t>(data) || std::holds_alternative<int32_t (*)()>(data));
|
||||||
if (auto *value = std::get_if<int32_t>(&data); value) {
|
if (auto *value = std::get_if<int32_t>(&data); value) {
|
||||||
return type == SYM_LABEL ? *value + getSection()->org : *value;
|
return type == SYM_LABEL ? *value + getSection()->org : *value;
|
||||||
}
|
}
|
||||||
@@ -73,12 +73,12 @@ int32_t Symbol::getOutputValue() const {
|
|||||||
}
|
}
|
||||||
|
|
||||||
ContentSpan const &Symbol::getMacro() const {
|
ContentSpan const &Symbol::getMacro() const {
|
||||||
assert((std::holds_alternative<ContentSpan>(data)));
|
assume((std::holds_alternative<ContentSpan>(data)));
|
||||||
return std::get<ContentSpan>(data);
|
return std::get<ContentSpan>(data);
|
||||||
}
|
}
|
||||||
|
|
||||||
std::shared_ptr<std::string> Symbol::getEqus() const {
|
std::shared_ptr<std::string> Symbol::getEqus() const {
|
||||||
assert(std::holds_alternative<std::shared_ptr<std::string>>(data));
|
assume(std::holds_alternative<std::shared_ptr<std::string>>(data));
|
||||||
return std::get<std::shared_ptr<std::string>>(data);
|
return std::get<std::shared_ptr<std::string>>(data);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -361,7 +361,7 @@ Symbol *sym_AddVar(std::string const &symName, int32_t value) {
|
|||||||
* @return The created symbol
|
* @return The created symbol
|
||||||
*/
|
*/
|
||||||
static Symbol *addLabel(std::string const &symName) {
|
static Symbol *addLabel(std::string const &symName) {
|
||||||
assert(!symName.starts_with('.')); // The symbol name must have been expanded prior
|
assume(!symName.starts_with('.')); // The symbol name must have been expanded prior
|
||||||
Symbol *sym = sym_FindExactSymbol(symName);
|
Symbol *sym = sym_FindExactSymbol(symName);
|
||||||
|
|
||||||
if (!sym) {
|
if (!sym) {
|
||||||
@@ -390,11 +390,11 @@ static Symbol *addLabel(std::string const &symName) {
|
|||||||
// Add a local (`.name` or `Parent.name`) relocatable symbol
|
// Add a local (`.name` or `Parent.name`) relocatable symbol
|
||||||
Symbol *sym_AddLocalLabel(std::string const &symName) {
|
Symbol *sym_AddLocalLabel(std::string const &symName) {
|
||||||
// Assuming no dots in `labelScope` if defined
|
// Assuming no dots in `labelScope` if defined
|
||||||
assert(!labelScope.has_value() || labelScope->find('.') == std::string::npos);
|
assume(!labelScope.has_value() || labelScope->find('.') == std::string::npos);
|
||||||
|
|
||||||
size_t dotPos = symName.find('.');
|
size_t dotPos = symName.find('.');
|
||||||
|
|
||||||
assert(dotPos != std::string::npos); // There should be at least one dot in `symName`
|
assume(dotPos != std::string::npos); // There should be at least one dot in `symName`
|
||||||
|
|
||||||
// Check for something after the dot
|
// Check for something after the dot
|
||||||
if (dotPos == symName.length() - 1) {
|
if (dotPos == symName.length() - 1) {
|
||||||
|
|||||||
@@ -3,7 +3,6 @@
|
|||||||
#include <sys/stat.h>
|
#include <sys/stat.h>
|
||||||
#include <sys/types.h>
|
#include <sys/types.h>
|
||||||
|
|
||||||
#include <assert.h>
|
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
#include <limits.h>
|
#include <limits.h>
|
||||||
#include <stdarg.h>
|
#include <stdarg.h>
|
||||||
@@ -774,7 +773,7 @@ static uint8_t maxTitleLen() {
|
|||||||
|
|
||||||
static ssize_t readBytes(int fd, uint8_t *buf, size_t len) {
|
static ssize_t readBytes(int fd, uint8_t *buf, size_t len) {
|
||||||
// POSIX specifies that lengths greater than SSIZE_MAX yield implementation-defined results
|
// POSIX specifies that lengths greater than SSIZE_MAX yield implementation-defined results
|
||||||
assert(len <= SSIZE_MAX);
|
assume(len <= SSIZE_MAX);
|
||||||
|
|
||||||
ssize_t total = 0;
|
ssize_t total = 0;
|
||||||
|
|
||||||
@@ -799,7 +798,7 @@ static ssize_t readBytes(int fd, uint8_t *buf, size_t len) {
|
|||||||
|
|
||||||
static ssize_t writeBytes(int fd, uint8_t *buf, size_t len) {
|
static ssize_t writeBytes(int fd, uint8_t *buf, size_t len) {
|
||||||
// POSIX specifies that lengths greater than SSIZE_MAX yield implementation-defined results
|
// POSIX specifies that lengths greater than SSIZE_MAX yield implementation-defined results
|
||||||
assert(len <= SSIZE_MAX);
|
assume(len <= SSIZE_MAX);
|
||||||
|
|
||||||
ssize_t total = 0;
|
ssize_t total = 0;
|
||||||
|
|
||||||
@@ -869,9 +868,9 @@ static void overwriteBytes(
|
|||||||
static void processFile(int input, int output, char const *name, off_t fileSize) {
|
static void processFile(int input, int output, char const *name, off_t fileSize) {
|
||||||
// Both of these should be true for seekable files, and neither otherwise
|
// Both of these should be true for seekable files, and neither otherwise
|
||||||
if (input == output)
|
if (input == output)
|
||||||
assert(fileSize != 0);
|
assume(fileSize != 0);
|
||||||
else
|
else
|
||||||
assert(fileSize == 0);
|
assume(fileSize == 0);
|
||||||
|
|
||||||
uint8_t rom0[BANK_SIZE];
|
uint8_t rom0[BANK_SIZE];
|
||||||
ssize_t rom0Len = readBytes(input, rom0, sizeof(rom0));
|
ssize_t rom0Len = readBytes(input, rom0, sizeof(rom0));
|
||||||
@@ -1037,9 +1036,9 @@ static void processFile(int input, int output, char const *name, off_t fileSize)
|
|||||||
}
|
}
|
||||||
nbBanks = 2;
|
nbBanks = 2;
|
||||||
} else {
|
} else {
|
||||||
assert(rom0Len == sizeof(rom0));
|
assume(rom0Len == sizeof(rom0));
|
||||||
}
|
}
|
||||||
assert(nbBanks >= 2);
|
assume(nbBanks >= 2);
|
||||||
// Alter number of banks to reflect required value
|
// Alter number of banks to reflect required value
|
||||||
// x&(x-1) is zero iff x is a power of 2, or 0; we know for sure it's non-zero,
|
// x&(x-1) is zero iff x is a power of 2, or 0; we know for sure it's non-zero,
|
||||||
// so this is true (non-zero) when we don't have a power of 2
|
// so this is true (non-zero) when we don't have a power of 2
|
||||||
@@ -1063,7 +1062,7 @@ static void processFile(int input, int output, char const *name, off_t fileSize)
|
|||||||
|
|
||||||
if (fixSpec & (FIX_GLOBAL_SUM | TRASH_GLOBAL_SUM)) {
|
if (fixSpec & (FIX_GLOBAL_SUM | TRASH_GLOBAL_SUM)) {
|
||||||
// Computation of the global checksum does not include the checksum bytes
|
// Computation of the global checksum does not include the checksum bytes
|
||||||
assert(rom0Len >= 0x14E);
|
assume(rom0Len >= 0x14E);
|
||||||
for (uint16_t i = 0; i < 0x14E; i++)
|
for (uint16_t i = 0; i < 0x14E; i++)
|
||||||
globalSum += rom0[i];
|
globalSum += rom0[i];
|
||||||
for (uint16_t i = 0x150; i < rom0Len; i++)
|
for (uint16_t i = 0x150; i < rom0Len; i++)
|
||||||
|
|||||||
@@ -3,7 +3,6 @@
|
|||||||
#include "gfx/main.hpp"
|
#include "gfx/main.hpp"
|
||||||
|
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
#include <assert.h>
|
|
||||||
#include <ctype.h>
|
#include <ctype.h>
|
||||||
#include <inttypes.h>
|
#include <inttypes.h>
|
||||||
#include <ios>
|
#include <ios>
|
||||||
@@ -17,6 +16,7 @@
|
|||||||
|
|
||||||
#include "extern/getopt.hpp"
|
#include "extern/getopt.hpp"
|
||||||
#include "file.hpp"
|
#include "file.hpp"
|
||||||
|
#include "helpers.hpp" // assume
|
||||||
#include "platform.hpp"
|
#include "platform.hpp"
|
||||||
#include "version.hpp"
|
#include "version.hpp"
|
||||||
|
|
||||||
@@ -633,7 +633,7 @@ int main(int argc, char *argv[]) {
|
|||||||
|
|
||||||
if (musl_optind != curArgc) {
|
if (musl_optind != curArgc) {
|
||||||
// This happens if `--` is passed, process the remaining arg(s) as positional
|
// This happens if `--` is passed, process the remaining arg(s) as positional
|
||||||
assert(musl_optind < curArgc);
|
assume(musl_optind < curArgc);
|
||||||
for (int i = musl_optind; i < curArgc; ++i) {
|
for (int i = musl_optind; i < curArgc; ++i) {
|
||||||
registerInput(argv[i]);
|
registerInput(argv[i]);
|
||||||
}
|
}
|
||||||
@@ -845,7 +845,7 @@ int main(int argc, char *argv[]) {
|
|||||||
|
|
||||||
void Palette::addColor(uint16_t color) {
|
void Palette::addColor(uint16_t color) {
|
||||||
for (size_t i = 0; true; ++i) {
|
for (size_t i = 0; true; ++i) {
|
||||||
assert(i < colors.size()); // The packing should guarantee this
|
assume(i < colors.size()); // The packing should guarantee this
|
||||||
if (colors[i] == color) { // The color is already present
|
if (colors[i] == color) { // The color is already present
|
||||||
break;
|
break;
|
||||||
} else if (colors[i] == UINT16_MAX) { // Empty slot
|
} else if (colors[i] == UINT16_MAX) { // Empty slot
|
||||||
|
|||||||
@@ -3,7 +3,6 @@
|
|||||||
#include "gfx/pal_packing.hpp"
|
#include "gfx/pal_packing.hpp"
|
||||||
|
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
#include <assert.h>
|
|
||||||
#include <deque>
|
#include <deque>
|
||||||
#include <inttypes.h>
|
#include <inttypes.h>
|
||||||
#include <optional>
|
#include <optional>
|
||||||
@@ -107,7 +106,7 @@ private:
|
|||||||
return it;
|
return it;
|
||||||
}
|
}
|
||||||
reference operator*() const {
|
reference operator*() const {
|
||||||
assert((*_iter).has_value());
|
assume((*_iter).has_value());
|
||||||
return **_iter;
|
return **_iter;
|
||||||
}
|
}
|
||||||
pointer operator->() const {
|
pointer operator->() const {
|
||||||
@@ -308,7 +307,7 @@ static void decant(
|
|||||||
// Build up the "component"...
|
// Build up the "component"...
|
||||||
colors.clear();
|
colors.clear();
|
||||||
members.clear();
|
members.clear();
|
||||||
assert(members.empty()); // Compiler optimization hint
|
assume(members.empty()); // Compiler optimization hint
|
||||||
do {
|
do {
|
||||||
ProtoPalette const &protoPal = protoPalettes[attrs->protoPalIndex];
|
ProtoPalette const &protoPal = protoPalettes[attrs->protoPalIndex];
|
||||||
// If this is the first proto-pal, or if at least one color matches, add it
|
// If this is the first proto-pal, or if at least one color matches, add it
|
||||||
|
|||||||
@@ -3,7 +3,6 @@
|
|||||||
#include "gfx/pal_sorting.hpp"
|
#include "gfx/pal_sorting.hpp"
|
||||||
|
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
#include <assert.h>
|
|
||||||
|
|
||||||
#include "helpers.hpp"
|
#include "helpers.hpp"
|
||||||
|
|
||||||
@@ -55,7 +54,7 @@ void grayscale(
|
|||||||
|
|
||||||
// This method is only applicable if there are at most as many colors as colors per palette, so
|
// This method is only applicable if there are at most as many colors as colors per palette, so
|
||||||
// we should only have a single palette.
|
// we should only have a single palette.
|
||||||
assert(palettes.size() == 1);
|
assume(palettes.size() == 1);
|
||||||
|
|
||||||
Palette &palette = palettes[0];
|
Palette &palette = palettes[0];
|
||||||
std::fill(RANGE(palette.colors), Rgba::transparent);
|
std::fill(RANGE(palette.colors), Rgba::transparent);
|
||||||
|
|||||||
@@ -3,7 +3,6 @@
|
|||||||
#include "gfx/pal_spec.hpp"
|
#include "gfx/pal_spec.hpp"
|
||||||
|
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
#include <assert.h>
|
|
||||||
#include <charconv>
|
#include <charconv>
|
||||||
#include <fstream>
|
#include <fstream>
|
||||||
#include <inttypes.h>
|
#include <inttypes.h>
|
||||||
@@ -26,13 +25,13 @@ using namespace std::string_view_literals;
|
|||||||
|
|
||||||
constexpr uint8_t nibble(char c) {
|
constexpr uint8_t nibble(char c) {
|
||||||
if (c >= 'a') {
|
if (c >= 'a') {
|
||||||
assert(c <= 'f');
|
assume(c <= 'f');
|
||||||
return c - 'a' + 10;
|
return c - 'a' + 10;
|
||||||
} else if (c >= 'A') {
|
} else if (c >= 'A') {
|
||||||
assert(c <= 'F');
|
assume(c <= 'F');
|
||||||
return c - 'A' + 10;
|
return c - 'A' + 10;
|
||||||
} else {
|
} else {
|
||||||
assert(c >= '0' && c <= '9');
|
assume(c >= '0' && c <= '9');
|
||||||
return c - '0';
|
return c - '0';
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -59,8 +58,8 @@ void parseInlinePalSpec(char const * const rawArg) {
|
|||||||
|
|
||||||
auto parseError = [&rawArg, &arg](size_type ofs, size_type len, char const *msg) {
|
auto parseError = [&rawArg, &arg](size_type ofs, size_type len, char const *msg) {
|
||||||
(void)arg; // With NDEBUG, `arg` is otherwise not used
|
(void)arg; // With NDEBUG, `arg` is otherwise not used
|
||||||
assert(ofs <= arg.length());
|
assume(ofs <= arg.length());
|
||||||
assert(len <= arg.length());
|
assume(len <= arg.length());
|
||||||
|
|
||||||
errorMessage(msg);
|
errorMessage(msg);
|
||||||
fprintf(
|
fprintf(
|
||||||
@@ -178,7 +177,7 @@ void parseInlinePalSpec(char const * const rawArg) {
|
|||||||
*/
|
*/
|
||||||
template<size_t n>
|
template<size_t n>
|
||||||
static bool readMagic(std::filebuf &file, char const *magic) {
|
static bool readMagic(std::filebuf &file, char const *magic) {
|
||||||
assert(strlen(magic) == n);
|
assume(strlen(magic) == n);
|
||||||
|
|
||||||
char magicBuf[n];
|
char magicBuf[n];
|
||||||
return file.sgetn(magicBuf, n) == n && memcmp(magicBuf, magic, n);
|
return file.sgetn(magicBuf, n) == n && memcmp(magicBuf, magic, n);
|
||||||
|
|||||||
@@ -3,7 +3,6 @@
|
|||||||
#include "gfx/process.hpp"
|
#include "gfx/process.hpp"
|
||||||
|
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
#include <assert.h>
|
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
#include <inttypes.h>
|
#include <inttypes.h>
|
||||||
#include <optional>
|
#include <optional>
|
||||||
@@ -48,7 +47,7 @@ public:
|
|||||||
if (!slot.has_value()) {
|
if (!slot.has_value()) {
|
||||||
slot.emplace(rgba);
|
slot.emplace(rgba);
|
||||||
} else if (*slot != rgba) {
|
} else if (*slot != rgba) {
|
||||||
assert(slot->cgbColor() != UINT16_MAX);
|
assume(slot->cgbColor() != UINT16_MAX);
|
||||||
return &*slot;
|
return &*slot;
|
||||||
}
|
}
|
||||||
return nullptr;
|
return nullptr;
|
||||||
@@ -270,7 +269,7 @@ public:
|
|||||||
|
|
||||||
if (png_get_PLTE(png, info, &embeddedPal, &nbColors) != 0) {
|
if (png_get_PLTE(png, info, &embeddedPal, &nbColors) != 0) {
|
||||||
if (png_get_tRNS(png, info, &transparencyPal, &nbTransparentEntries, nullptr)) {
|
if (png_get_tRNS(png, info, &transparencyPal, &nbTransparentEntries, nullptr)) {
|
||||||
assert(nbTransparentEntries <= nbColors);
|
assume(nbTransparentEntries <= nbColors);
|
||||||
}
|
}
|
||||||
|
|
||||||
options.verbosePrint(
|
options.verbosePrint(
|
||||||
@@ -326,16 +325,16 @@ public:
|
|||||||
// Update `info` with the transformations
|
// Update `info` with the transformations
|
||||||
png_read_update_info(png, info);
|
png_read_update_info(png, info);
|
||||||
// These shouldn't have changed
|
// These shouldn't have changed
|
||||||
assert(png_get_image_width(png, info) == width);
|
assume(png_get_image_width(png, info) == width);
|
||||||
assert(png_get_image_height(png, info) == height);
|
assume(png_get_image_height(png, info) == height);
|
||||||
// These should have changed, however
|
// These should have changed, however
|
||||||
assert(png_get_color_type(png, info) == PNG_COLOR_TYPE_RGBA);
|
assume(png_get_color_type(png, info) == PNG_COLOR_TYPE_RGBA);
|
||||||
assert(png_get_bit_depth(png, info) == 8);
|
assume(png_get_bit_depth(png, info) == 8);
|
||||||
|
|
||||||
// Now that metadata has been read, we can process the image data
|
// Now that metadata has been read, we can process the image data
|
||||||
|
|
||||||
size_t nbRowBytes = png_get_rowbytes(png, info);
|
size_t nbRowBytes = png_get_rowbytes(png, info);
|
||||||
assert(nbRowBytes != 0);
|
assume(nbRowBytes != 0);
|
||||||
DefaultInitVec<png_byte> row(nbRowBytes);
|
DefaultInitVec<png_byte> row(nbRowBytes);
|
||||||
// Holds known-conflicting color pairs to avoid warning about them twice.
|
// Holds known-conflicting color pairs to avoid warning about them twice.
|
||||||
// We don't need to worry about transitivity, as ImagePalette slots are immutable once
|
// We don't need to worry about transitivity, as ImagePalette slots are immutable once
|
||||||
@@ -394,7 +393,7 @@ public:
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
assert(interlaceType == PNG_INTERLACE_ADAM7);
|
assume(interlaceType == PNG_INTERLACE_ADAM7);
|
||||||
|
|
||||||
// For interlace to work properly, we must read the image `nbPasses` times
|
// For interlace to work properly, we must read the image `nbPasses` times
|
||||||
for (int pass = 0; pass < PNG_INTERLACE_ADAM7_PASSES; ++pass) {
|
for (int pass = 0; pass < PNG_INTERLACE_ADAM7_PASSES; ++pass) {
|
||||||
@@ -549,7 +548,7 @@ static void generatePalSpec(Png const &png) {
|
|||||||
|
|
||||||
// Fill in the palette spec
|
// Fill in the palette spec
|
||||||
options.palSpec.emplace_back(); // A single palette, with `#00000000`s (transparent)
|
options.palSpec.emplace_back(); // A single palette, with `#00000000`s (transparent)
|
||||||
assert(options.palSpec.size() == 1);
|
assume(options.palSpec.size() == 1);
|
||||||
if (embPalSize > options.maxOpaqueColors()) { // Ignore extraneous colors if they are unused
|
if (embPalSize > options.maxOpaqueColors()) { // Ignore extraneous colors if they are unused
|
||||||
embPalSize = options.maxOpaqueColors();
|
embPalSize = options.maxOpaqueColors();
|
||||||
}
|
}
|
||||||
@@ -568,7 +567,7 @@ static std::tuple<DefaultInitVec<size_t>, std::vector<Palette>>
|
|||||||
// Run a "pagination" problem solver
|
// Run a "pagination" problem solver
|
||||||
// TODO: allow picking one of several solvers?
|
// TODO: allow picking one of several solvers?
|
||||||
auto [mappings, nbPalettes] = packing::overloadAndRemove(protoPalettes);
|
auto [mappings, nbPalettes] = packing::overloadAndRemove(protoPalettes);
|
||||||
assert(mappings.size() == protoPalettes.size());
|
assume(mappings.size() == protoPalettes.size());
|
||||||
|
|
||||||
if (options.verbosity >= Options::VERB_INTERM) {
|
if (options.verbosity >= Options::VERB_INTERM) {
|
||||||
fprintf(
|
fprintf(
|
||||||
@@ -647,7 +646,7 @@ static std::tuple<DefaultInitVec<size_t>, std::vector<Palette>>
|
|||||||
});
|
});
|
||||||
|
|
||||||
if (iter == palettes.end()) {
|
if (iter == palettes.end()) {
|
||||||
assert(!protoPal.empty());
|
assume(!protoPal.empty());
|
||||||
error("Failed to fit tile colors [%s] in specified palettes", listColors(protoPal));
|
error("Failed to fit tile colors [%s] in specified palettes", listColors(protoPal));
|
||||||
bad = true;
|
bad = true;
|
||||||
}
|
}
|
||||||
@@ -725,7 +724,7 @@ public:
|
|||||||
for (uint32_t x = 0; x < 8; ++x) {
|
for (uint32_t x = 0; x < 8; ++x) {
|
||||||
row <<= 1;
|
row <<= 1;
|
||||||
uint8_t index = palette.indexOf(tile.pixel(x, y).cgbColor());
|
uint8_t index = palette.indexOf(tile.pixel(x, y).cgbColor());
|
||||||
assert(index < palette.size()); // The color should be in the palette
|
assume(index < palette.size()); // The color should be in the palette
|
||||||
if (index & 1) {
|
if (index & 1) {
|
||||||
row |= 1;
|
row |= 1;
|
||||||
}
|
}
|
||||||
@@ -803,7 +802,7 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
// If we have both (i.e. we have symmetry), default to vflip only
|
// If we have both (i.e. we have symmetry), default to vflip only
|
||||||
assert(hasVFlip || hasVHFlip);
|
assume(hasVFlip || hasVHFlip);
|
||||||
return hasVFlip ? MatchType::VFLIP : MatchType::VHFLIP;
|
return hasVFlip ? MatchType::VFLIP : MatchType::VHFLIP;
|
||||||
}
|
}
|
||||||
friend bool operator==(TileData const &lhs, TileData const &rhs) {
|
friend bool operator==(TileData const &lhs, TileData const &rhs) {
|
||||||
@@ -854,7 +853,7 @@ static void outputTileData(
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
assert(remainingTiles == 0);
|
assume(remainingTiles == 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void outputMaps(
|
static void outputMaps(
|
||||||
@@ -877,7 +876,7 @@ static void outputMaps(
|
|||||||
uint8_t bank = 0;
|
uint8_t bank = 0;
|
||||||
for (auto attr : attrmap) {
|
for (auto attr : attrmap) {
|
||||||
if (tileID == options.maxNbTiles[bank]) {
|
if (tileID == options.maxNbTiles[bank]) {
|
||||||
assert(bank == 0);
|
assume(bank == 0);
|
||||||
bank = 1;
|
bank = 1;
|
||||||
tileID = 0;
|
tileID = 0;
|
||||||
}
|
}
|
||||||
@@ -976,7 +975,7 @@ static void outputTileData(UniqueTiles const &tiles) {
|
|||||||
uint16_t tileID = 0;
|
uint16_t tileID = 0;
|
||||||
for (auto iter = tiles.begin(), end = tiles.end() - options.trim; iter != end; ++iter) {
|
for (auto iter = tiles.begin(), end = tiles.end() - options.trim; iter != end; ++iter) {
|
||||||
TileData const *tile = *iter;
|
TileData const *tile = *iter;
|
||||||
assert(tile->tileID == tileID);
|
assume(tile->tileID == tileID);
|
||||||
++tileID;
|
++tileID;
|
||||||
output->sputn(reinterpret_cast<char const *>(tile->data().data()), options.bitDepth * 8);
|
output->sputn(reinterpret_cast<char const *>(tile->data().data()), options.bitDepth * 8);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,7 +3,6 @@
|
|||||||
#include "gfx/proto_palette.hpp"
|
#include "gfx/proto_palette.hpp"
|
||||||
|
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
#include <assert.h>
|
|
||||||
|
|
||||||
#include "helpers.hpp"
|
#include "helpers.hpp"
|
||||||
|
|
||||||
@@ -41,8 +40,8 @@ bool ProtoPalette::add(uint16_t color) {
|
|||||||
|
|
||||||
ProtoPalette::ComparisonResult ProtoPalette::compare(ProtoPalette const &other) const {
|
ProtoPalette::ComparisonResult ProtoPalette::compare(ProtoPalette const &other) const {
|
||||||
// This works because the sets are sorted numerically
|
// This works because the sets are sorted numerically
|
||||||
assert(std::is_sorted(RANGE(_colorIndices)));
|
assume(std::is_sorted(RANGE(_colorIndices)));
|
||||||
assert(std::is_sorted(RANGE(other._colorIndices)));
|
assume(std::is_sorted(RANGE(other._colorIndices)));
|
||||||
|
|
||||||
auto ours = _colorIndices.begin(), theirs = other._colorIndices.begin();
|
auto ours = _colorIndices.begin(), theirs = other._colorIndices.begin();
|
||||||
bool weBigger = true, theyBigger = true;
|
bool weBigger = true, theyBigger = true;
|
||||||
|
|||||||
@@ -4,7 +4,6 @@
|
|||||||
|
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
#include <array>
|
#include <array>
|
||||||
#include <assert.h>
|
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
#include <inttypes.h>
|
#include <inttypes.h>
|
||||||
#include <optional>
|
#include <optional>
|
||||||
@@ -14,6 +13,7 @@
|
|||||||
|
|
||||||
#include "defaultinitalloc.hpp"
|
#include "defaultinitalloc.hpp"
|
||||||
#include "file.hpp"
|
#include "file.hpp"
|
||||||
|
#include "helpers.hpp" // assume
|
||||||
#include "itertools.hpp"
|
#include "itertools.hpp"
|
||||||
|
|
||||||
#include "gfx/main.hpp"
|
#include "gfx/main.hpp"
|
||||||
@@ -42,7 +42,7 @@ static DefaultInitVec<uint8_t> readInto(std::string const &path) {
|
|||||||
|
|
||||||
// Arbitrary, but if you got a better idea...
|
// Arbitrary, but if you got a better idea...
|
||||||
size_t newSize = oldSize != data.capacity() ? data.capacity() : oldSize * 2;
|
size_t newSize = oldSize != data.capacity() ? data.capacity() : oldSize * 2;
|
||||||
assert(oldSize != newSize);
|
assume(oldSize != newSize);
|
||||||
data.resize(newSize);
|
data.resize(newSize);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -343,9 +343,9 @@ void reverse() {
|
|||||||
tileID =
|
tileID =
|
||||||
(*tilemap)[index] - options.baseTileIDs[bank] + bank * options.maxNbTiles[0];
|
(*tilemap)[index] - options.baseTileIDs[bank] + bank * options.maxNbTiles[0];
|
||||||
}
|
}
|
||||||
assert(tileID < nbTileInstances); // Should have been checked earlier
|
assume(tileID < nbTileInstances); // Should have been checked earlier
|
||||||
size_t palID = palmap ? (*palmap)[index] : attribute & 0b111;
|
size_t palID = palmap ? (*palmap)[index] : attribute & 0b111;
|
||||||
assert(palID < palettes.size()); // Should be ensured on data read
|
assume(palID < palettes.size()); // Should be ensured on data read
|
||||||
|
|
||||||
// We do not have data for tiles trimmed with `-x`, so assume they are "blank"
|
// We do not have data for tiles trimmed with `-x`, so assume they are "blank"
|
||||||
static std::array<uint8_t, 16> const trimmedTile{
|
static std::array<uint8_t, 16> const trimmedTile{
|
||||||
|
|||||||
@@ -3,10 +3,11 @@
|
|||||||
#include "gfx/rgba.hpp"
|
#include "gfx/rgba.hpp"
|
||||||
|
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
#include <assert.h>
|
|
||||||
#include <math.h>
|
#include <math.h>
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
|
|
||||||
|
#include "helpers.hpp" // assume
|
||||||
|
|
||||||
#include "gfx/main.hpp" // options
|
#include "gfx/main.hpp" // options
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -37,7 +38,7 @@ uint16_t Rgba::cgbColor() const {
|
|||||||
if (isTransparent()) {
|
if (isTransparent()) {
|
||||||
return transparent;
|
return transparent;
|
||||||
}
|
}
|
||||||
assert(isOpaque());
|
assume(isOpaque());
|
||||||
|
|
||||||
uint8_t r = red, g = green, b = blue;
|
uint8_t r = red, g = green, b = blue;
|
||||||
if (options.useColorCurve) {
|
if (options.useColorCurve) {
|
||||||
@@ -56,7 +57,7 @@ uint16_t Rgba::cgbColor() const {
|
|||||||
}
|
}
|
||||||
|
|
||||||
uint8_t Rgba::grayIndex() const {
|
uint8_t Rgba::grayIndex() const {
|
||||||
assert(isGray());
|
assume(isGray());
|
||||||
// Convert from [0; 256[ to [0; maxOpaqueColors[
|
// Convert from [0; 256[ to [0; maxOpaqueColors[
|
||||||
return static_cast<uint16_t>(255 - red) * options.maxOpaqueColors() / 256;
|
return static_cast<uint16_t>(255 - red) * options.maxOpaqueColors() / 256;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,7 +3,6 @@
|
|||||||
#include <sys/stat.h>
|
#include <sys/stat.h>
|
||||||
#include <sys/types.h>
|
#include <sys/types.h>
|
||||||
|
|
||||||
#include <assert.h>
|
|
||||||
#include <inttypes.h>
|
#include <inttypes.h>
|
||||||
#include <limits.h>
|
#include <limits.h>
|
||||||
#include <stdarg.h>
|
#include <stdarg.h>
|
||||||
@@ -12,6 +11,7 @@
|
|||||||
|
|
||||||
#include "error.hpp"
|
#include "error.hpp"
|
||||||
#include "extern/getopt.hpp"
|
#include "extern/getopt.hpp"
|
||||||
|
#include "helpers.hpp" // assume
|
||||||
#include "itertools.hpp"
|
#include "itertools.hpp"
|
||||||
#include "platform.hpp"
|
#include "platform.hpp"
|
||||||
#include "script.hpp"
|
#include "script.hpp"
|
||||||
@@ -46,28 +46,28 @@ FILE *linkerScript;
|
|||||||
static uint32_t nbErrors = 0;
|
static uint32_t nbErrors = 0;
|
||||||
|
|
||||||
std::vector<uint32_t> &FileStackNode::iters() {
|
std::vector<uint32_t> &FileStackNode::iters() {
|
||||||
assert(std::holds_alternative<std::vector<uint32_t>>(data));
|
assume(std::holds_alternative<std::vector<uint32_t>>(data));
|
||||||
return std::get<std::vector<uint32_t>>(data);
|
return std::get<std::vector<uint32_t>>(data);
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<uint32_t> const &FileStackNode::iters() const {
|
std::vector<uint32_t> const &FileStackNode::iters() const {
|
||||||
assert(std::holds_alternative<std::vector<uint32_t>>(data));
|
assume(std::holds_alternative<std::vector<uint32_t>>(data));
|
||||||
return std::get<std::vector<uint32_t>>(data);
|
return std::get<std::vector<uint32_t>>(data);
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string &FileStackNode::name() {
|
std::string &FileStackNode::name() {
|
||||||
assert(std::holds_alternative<std::string>(data));
|
assume(std::holds_alternative<std::string>(data));
|
||||||
return std::get<std::string>(data);
|
return std::get<std::string>(data);
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string const &FileStackNode::name() const {
|
std::string const &FileStackNode::name() const {
|
||||||
assert(std::holds_alternative<std::string>(data));
|
assume(std::holds_alternative<std::string>(data));
|
||||||
return std::get<std::string>(data);
|
return std::get<std::string>(data);
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string const &FileStackNode::dump(uint32_t curLineNo) const {
|
std::string const &FileStackNode::dump(uint32_t curLineNo) const {
|
||||||
if (std::holds_alternative<std::vector<uint32_t>>(data)) {
|
if (std::holds_alternative<std::vector<uint32_t>>(data)) {
|
||||||
assert(parent); // REPT nodes use their parent's name
|
assume(parent); // REPT nodes use their parent's name
|
||||||
std::string const &lastName = parent->dump(lineNo);
|
std::string const &lastName = parent->dump(lineNo);
|
||||||
fputs(" -> ", stderr);
|
fputs(" -> ", stderr);
|
||||||
fputs(lastName.c_str(), stderr);
|
fputs(lastName.c_str(), stderr);
|
||||||
@@ -223,7 +223,7 @@ static void parseScrambleSpec(char const *spec) {
|
|||||||
// indicating their scramble limit.
|
// indicating their scramble limit.
|
||||||
while (spec) {
|
while (spec) {
|
||||||
// Invariant: we should not be pointing at whitespace at this point
|
// Invariant: we should not be pointing at whitespace at this point
|
||||||
assert(*spec != ' ' && *spec != '\t');
|
assume(*spec != ' ' && *spec != '\t');
|
||||||
|
|
||||||
// Remember where the region's name begins and ends
|
// Remember where the region's name begins and ends
|
||||||
char const *regionName = spec;
|
char const *regionName = spec;
|
||||||
@@ -232,7 +232,7 @@ static void parseScrambleSpec(char const *spec) {
|
|||||||
int regionNamePrintLen = regionNameLen > INT_MAX ? INT_MAX : (int)regionNameLen;
|
int regionNamePrintLen = regionNameLen > INT_MAX ? INT_MAX : (int)regionNameLen;
|
||||||
ScrambledRegion region = SCRAMBLE_UNK;
|
ScrambledRegion region = SCRAMBLE_UNK;
|
||||||
|
|
||||||
// If this trips, `spec` must be pointing at a ',' or '=' (or NUL) due to the assert
|
// If this trips, `spec` must be pointing at a ',' or '=' (or NUL) due to the assumption
|
||||||
if (regionNameLen == 0) {
|
if (regionNameLen == 0) {
|
||||||
argErr('S', "Missing region name");
|
argErr('S', "Missing region name");
|
||||||
|
|
||||||
@@ -322,7 +322,7 @@ static void parseScrambleSpec(char const *spec) {
|
|||||||
|
|
||||||
next: // Can't `continue` a `for` loop with this nontrivial iteration logic
|
next: // Can't `continue` a `for` loop with this nontrivial iteration logic
|
||||||
if (spec) {
|
if (spec) {
|
||||||
assert(*spec == ',' || *spec == '\0');
|
assume(*spec == ',' || *spec == '\0');
|
||||||
if (*spec == ',')
|
if (*spec == ',')
|
||||||
spec += 1 + strspn(&spec[1], " \t");
|
spec += 1 + strspn(&spec[1], " \t");
|
||||||
if (*spec == '\0')
|
if (*spec == '\0')
|
||||||
|
|||||||
@@ -3,7 +3,6 @@
|
|||||||
#include "link/output.hpp"
|
#include "link/output.hpp"
|
||||||
|
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
#include <assert.h>
|
|
||||||
#include <deque>
|
#include <deque>
|
||||||
#include <inttypes.h>
|
#include <inttypes.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
@@ -162,7 +161,7 @@ static void
|
|||||||
|
|
||||||
if (bankSections) {
|
if (bankSections) {
|
||||||
for (Section const *section : *bankSections) {
|
for (Section const *section : *bankSections) {
|
||||||
assert(section->offset == 0);
|
assume(section->offset == 0);
|
||||||
// Output padding up to the next SECTION
|
// Output padding up to the next SECTION
|
||||||
while (offset + baseOffset < section->org) {
|
while (offset + baseOffset < section->org) {
|
||||||
putc(overlayFile ? getc(overlayFile) : padValue, outputFile);
|
putc(overlayFile ? getc(overlayFile) : padValue, outputFile);
|
||||||
@@ -407,7 +406,7 @@ static void writeMapBank(SortedSections const §List, SectionType type, uint3
|
|||||||
Section const *sect = *pickedSection;
|
Section const *sect = *pickedSection;
|
||||||
|
|
||||||
used += sect->size;
|
used += sect->size;
|
||||||
assert(sect->offset == 0);
|
assume(sect->offset == 0);
|
||||||
|
|
||||||
writeEmptySpace(prevEndAddr, sect->org);
|
writeEmptySpace(prevEndAddr, sect->org);
|
||||||
|
|
||||||
|
|||||||
@@ -2,13 +2,13 @@
|
|||||||
|
|
||||||
#include "link/patch.hpp"
|
#include "link/patch.hpp"
|
||||||
|
|
||||||
#include <assert.h>
|
|
||||||
#include <deque>
|
#include <deque>
|
||||||
#include <inttypes.h>
|
#include <inttypes.h>
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
#include <variant>
|
#include <variant>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
|
#include "helpers.hpp" // assume
|
||||||
#include "linkdefs.hpp"
|
#include "linkdefs.hpp"
|
||||||
#include "opmath.hpp"
|
#include "opmath.hpp"
|
||||||
|
|
||||||
@@ -54,7 +54,7 @@ static uint32_t getRPNByte(uint8_t const *&expression, int32_t &size, Patch cons
|
|||||||
}
|
}
|
||||||
|
|
||||||
static Symbol const *getSymbol(std::vector<Symbol> const &symbolList, uint32_t index) {
|
static Symbol const *getSymbol(std::vector<Symbol> const &symbolList, uint32_t index) {
|
||||||
assert(index != (uint32_t)-1); // PC needs to be handled specially, not here
|
assume(index != (uint32_t)-1); // PC needs to be handled specially, not here
|
||||||
Symbol const &symbol = symbolList[index];
|
Symbol const &symbol = symbolList[index];
|
||||||
|
|
||||||
// If the symbol is defined elsewhere...
|
// If the symbol is defined elsewhere...
|
||||||
@@ -297,7 +297,7 @@ static int32_t computeRPNExpr(Patch const &patch, std::vector<Symbol> const &fil
|
|||||||
isError = true;
|
isError = true;
|
||||||
value = 1;
|
value = 1;
|
||||||
} else {
|
} else {
|
||||||
assert(sect->offset == 0);
|
assume(sect->offset == 0);
|
||||||
value = sect->org;
|
value = sect->org;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
@@ -377,7 +377,7 @@ static int32_t computeRPNExpr(Patch const &patch, std::vector<Symbol> const &fil
|
|||||||
} else if (auto *label = std::get_if<Label>(&symbol->data); label) {
|
} else if (auto *label = std::get_if<Label>(&symbol->data); label) {
|
||||||
value = label->section->org + label->offset;
|
value = label->section->org + label->offset;
|
||||||
} else {
|
} else {
|
||||||
assert(std::holds_alternative<int32_t>(symbol->data));
|
assume(std::holds_alternative<int32_t>(symbol->data));
|
||||||
value = std::get<int32_t>(symbol->data);
|
value = std::get<int32_t>(symbol->data);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -15,7 +15,6 @@
|
|||||||
%code {
|
%code {
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
#include <array>
|
#include <array>
|
||||||
#include <assert.h>
|
|
||||||
#include <bit>
|
#include <bit>
|
||||||
#include <fstream>
|
#include <fstream>
|
||||||
#include <inttypes.h>
|
#include <inttypes.h>
|
||||||
@@ -329,7 +328,7 @@ yy::parser::symbol_type yylex() {
|
|||||||
std::string ident;
|
std::string ident;
|
||||||
auto strUpperCmp = [](char cmp, char ref) {
|
auto strUpperCmp = [](char cmp, char ref) {
|
||||||
// `locale::classic()` yields the "C" locale.
|
// `locale::classic()` yields the "C" locale.
|
||||||
assert(!std::use_facet<std::ctype<char>>(std::locale::classic())
|
assume(!std::use_facet<std::ctype<char>>(std::locale::classic())
|
||||||
.is(std::ctype_base::lower, ref));
|
.is(std::ctype_base::lower, ref));
|
||||||
return std::use_facet<std::ctype<char>>(std::locale::classic()).toupper(cmp) == ref;
|
return std::use_facet<std::ctype<char>>(std::locale::classic()).toupper(cmp) == ref;
|
||||||
};
|
};
|
||||||
@@ -522,7 +521,7 @@ static void alignTo(uint32_t alignment, uint32_t alignOfs) {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
assert(pc >= typeInfo.startAddr);
|
assume(pc >= typeInfo.startAddr);
|
||||||
length %= alignSize;
|
length %= alignSize;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -556,7 +555,7 @@ static void pad(uint32_t length) {
|
|||||||
auto const &typeInfo = sectionTypeInfo[activeType];
|
auto const &typeInfo = sectionTypeInfo[activeType];
|
||||||
auto &pc = curAddr[activeType][activeBankIdx];
|
auto &pc = curAddr[activeType][activeBankIdx];
|
||||||
|
|
||||||
assert(pc >= typeInfo.startAddr);
|
assume(pc >= typeInfo.startAddr);
|
||||||
if (uint16_t offset = pc - typeInfo.startAddr; length + offset > typeInfo.size) {
|
if (uint16_t offset = pc - typeInfo.startAddr; length + offset > typeInfo.size) {
|
||||||
scriptError(
|
scriptError(
|
||||||
context,
|
context,
|
||||||
@@ -588,7 +587,7 @@ static void placeSection(std::string const &name, bool isOptional) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
auto const &typeInfo = sectionTypeInfo[activeType];
|
auto const &typeInfo = sectionTypeInfo[activeType];
|
||||||
assert(section->offset == 0);
|
assume(section->offset == 0);
|
||||||
// Check that the linker script doesn't contradict what the code says.
|
// Check that the linker script doesn't contradict what the code says.
|
||||||
if (section->type == SECTTYPE_INVALID) {
|
if (section->type == SECTTYPE_INVALID) {
|
||||||
// SDCC areas don't have a type assigned yet, so the linker script is used to give them one.
|
// SDCC areas don't have a type assigned yet, so the linker script is used to give them one.
|
||||||
|
|||||||
@@ -2,7 +2,6 @@
|
|||||||
|
|
||||||
#include "link/sdas_obj.hpp"
|
#include "link/sdas_obj.hpp"
|
||||||
|
|
||||||
#include <assert.h>
|
|
||||||
#include <ctype.h>
|
#include <ctype.h>
|
||||||
#include <inttypes.h>
|
#include <inttypes.h>
|
||||||
#include <memory>
|
#include <memory>
|
||||||
@@ -11,6 +10,7 @@
|
|||||||
#include <tuple>
|
#include <tuple>
|
||||||
#include <variant>
|
#include <variant>
|
||||||
|
|
||||||
|
#include "helpers.hpp" // assume
|
||||||
#include "linkdefs.hpp"
|
#include "linkdefs.hpp"
|
||||||
#include "platform.hpp"
|
#include "platform.hpp"
|
||||||
|
|
||||||
@@ -255,7 +255,7 @@ void sdobj_ReadFile(FileStackNode const &where, FILE *file, std::vector<Symbol>
|
|||||||
std::unique_ptr<Section> curSection = std::make_unique<Section>();
|
std::unique_ptr<Section> curSection = std::make_unique<Section>();
|
||||||
|
|
||||||
getToken(line.data(), "'A' line is too short");
|
getToken(line.data(), "'A' line is too short");
|
||||||
assert(strlen(token) != 0); // This should be impossible, tokens are non-empty
|
assume(strlen(token) != 0); // This should be impossible, tokens are non-empty
|
||||||
// The following is required for fragment offsets to be reliably predicted
|
// The following is required for fragment offsets to be reliably predicted
|
||||||
for (FileSection &entry : fileSections) {
|
for (FileSection &entry : fileSections) {
|
||||||
if (!strcmp(token, entry.section->name.c_str()))
|
if (!strcmp(token, entry.section->name.c_str()))
|
||||||
@@ -365,7 +365,7 @@ void sdobj_ReadFile(FileStackNode const &where, FILE *file, std::vector<Symbol>
|
|||||||
// Symbols in sections are labels; their value is an offset
|
// Symbols in sections are labels; their value is an offset
|
||||||
Section *section = fileSections.back().section.get();
|
Section *section = fileSections.back().section.get();
|
||||||
if (section->isAddressFixed) {
|
if (section->isAddressFixed) {
|
||||||
assert(value >= section->org && value <= section->org + section->size);
|
assume(value >= section->org && value <= section->org + section->size);
|
||||||
value -= section->org;
|
value -= section->org;
|
||||||
}
|
}
|
||||||
// No need to set the `sectionID`, since we set the pointer
|
// No need to set the `sectionID`, since we set the pointer
|
||||||
@@ -392,7 +392,7 @@ void sdobj_ReadFile(FileStackNode const &where, FILE *file, std::vector<Symbol>
|
|||||||
auto checkSymbol = [](Symbol const &sym) -> std::tuple<Section *, int32_t> {
|
auto checkSymbol = [](Symbol const &sym) -> std::tuple<Section *, int32_t> {
|
||||||
if (auto *label = std::get_if<Label>(&sym.data); label)
|
if (auto *label = std::get_if<Label>(&sym.data); label)
|
||||||
return {label->section, label->offset};
|
return {label->section, label->offset};
|
||||||
assert(std::holds_alternative<int32_t>(sym.data));
|
assume(std::holds_alternative<int32_t>(sym.data));
|
||||||
return {nullptr, std::get<int32_t>(sym.data)};
|
return {nullptr, std::get<int32_t>(sym.data)};
|
||||||
};
|
};
|
||||||
auto [symbolSection, symbolValue] = checkSymbol(symbol);
|
auto [symbolSection, symbolValue] = checkSymbol(symbol);
|
||||||
@@ -468,7 +468,7 @@ void sdobj_ReadFile(FileStackNode const &where, FILE *file, std::vector<Symbol>
|
|||||||
areaIdx,
|
areaIdx,
|
||||||
fileSections.size()
|
fileSections.size()
|
||||||
);
|
);
|
||||||
assert(!fileSections.empty()); // There should be at least one, from the above check
|
assume(!fileSections.empty()); // There should be at least one, from the above check
|
||||||
Section *section = fileSections[areaIdx].section.get();
|
Section *section = fileSections[areaIdx].section.get();
|
||||||
uint16_t *writeIndex = &fileSections[areaIdx].writeIndex;
|
uint16_t *writeIndex = &fileSections[areaIdx].writeIndex;
|
||||||
uint8_t writtenOfs = ADDR_SIZE; // Bytes before this have been written to `->data`
|
uint8_t writtenOfs = ADDR_SIZE; // Bytes before this have been written to `->data`
|
||||||
@@ -500,7 +500,7 @@ void sdobj_ReadFile(FileStackNode const &where, FILE *file, std::vector<Symbol>
|
|||||||
*writeIndex
|
*writeIndex
|
||||||
);
|
);
|
||||||
if (section->data.empty()) {
|
if (section->data.empty()) {
|
||||||
assert(section->size != 0);
|
assume(section->size != 0);
|
||||||
section->data.resize(section->size);
|
section->data.resize(section->size);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -584,7 +584,7 @@ void sdobj_ReadFile(FileStackNode const &where, FILE *file, std::vector<Symbol>
|
|||||||
uint8_t nbBaseBytes = patch.type == PATCHTYPE_BYTE ? ADDR_SIZE : 2;
|
uint8_t nbBaseBytes = patch.type == PATCHTYPE_BYTE ? ADDR_SIZE : 2;
|
||||||
uint32_t baseValue = 0;
|
uint32_t baseValue = 0;
|
||||||
|
|
||||||
assert(offset < data.size());
|
assume(offset < data.size());
|
||||||
if (data.size() - offset < nbBaseBytes)
|
if (data.size() - offset < nbBaseBytes)
|
||||||
fatal(
|
fatal(
|
||||||
&where,
|
&where,
|
||||||
@@ -755,7 +755,7 @@ void sdobj_ReadFile(FileStackNode const &where, FILE *file, std::vector<Symbol>
|
|||||||
patch.rpnExpression.push_back(RPN_AND);
|
patch.rpnExpression.push_back(RPN_AND);
|
||||||
}
|
}
|
||||||
} else if (flags & 1 << RELOC_ISPCREL) {
|
} else if (flags & 1 << RELOC_ISPCREL) {
|
||||||
assert(patch.type == PATCHTYPE_WORD);
|
assume(patch.type == PATCHTYPE_WORD);
|
||||||
fatal(&where, lineNo, "16-bit PC-relative relocations are not supported");
|
fatal(&where, lineNo, "16-bit PC-relative relocations are not supported");
|
||||||
} else if (flags & (1 << RELOC_EXPR16 | 1 << RELOC_EXPR24)) {
|
} else if (flags & (1 << RELOC_EXPR16 | 1 << RELOC_EXPR24)) {
|
||||||
fatal(
|
fatal(
|
||||||
@@ -769,7 +769,7 @@ void sdobj_ReadFile(FileStackNode const &where, FILE *file, std::vector<Symbol>
|
|||||||
|
|
||||||
// If there is some data left to append, do so
|
// If there is some data left to append, do so
|
||||||
if (writtenOfs != data.size()) {
|
if (writtenOfs != data.size()) {
|
||||||
assert(data.size() > writtenOfs);
|
assume(data.size() > writtenOfs);
|
||||||
if (*writeIndex + (data.size() - writtenOfs) > section->size)
|
if (*writeIndex + (data.size() - writtenOfs) > section->size)
|
||||||
fatal(
|
fatal(
|
||||||
&where,
|
&where,
|
||||||
|
|||||||
@@ -2,7 +2,6 @@
|
|||||||
|
|
||||||
#include "link/section.hpp"
|
#include "link/section.hpp"
|
||||||
|
|
||||||
#include <assert.h>
|
|
||||||
#include <inttypes.h>
|
#include <inttypes.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
@@ -183,7 +182,7 @@ static void mergeSections(Section &target, std::unique_ptr<Section> &&other, Sec
|
|||||||
for (Patch &patch : other->patches)
|
for (Patch &patch : other->patches)
|
||||||
patch.pcOffset += other->offset;
|
patch.pcOffset += other->offset;
|
||||||
} else if (!target.data.empty()) {
|
} else if (!target.data.empty()) {
|
||||||
assert(other->size == 0);
|
assume(other->size == 0);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
|||||||
@@ -5,18 +5,20 @@
|
|||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <unordered_map>
|
#include <unordered_map>
|
||||||
|
|
||||||
|
#include "helpers.hpp" // assume
|
||||||
|
|
||||||
#include "link/main.hpp"
|
#include "link/main.hpp"
|
||||||
#include "link/section.hpp"
|
#include "link/section.hpp"
|
||||||
|
|
||||||
std::unordered_map<std::string, Symbol *> symbols;
|
std::unordered_map<std::string, Symbol *> symbols;
|
||||||
|
|
||||||
Label &Symbol::label() {
|
Label &Symbol::label() {
|
||||||
assert(std::holds_alternative<Label>(data));
|
assume(std::holds_alternative<Label>(data));
|
||||||
return std::get<Label>(data);
|
return std::get<Label>(data);
|
||||||
}
|
}
|
||||||
|
|
||||||
Label const &Symbol::label() const {
|
Label const &Symbol::label() const {
|
||||||
assert(std::holds_alternative<Label>(data));
|
assume(std::holds_alternative<Label>(data));
|
||||||
return std::get<Label>(data);
|
return std::get<Label>(data);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user