mirror of
https://github.com/gbdev/rgbds.git
synced 2025-11-27 13:32:08 +00:00
Replace assert with assume for release build optimization (#1390)
This commit is contained in:
@@ -3,7 +3,6 @@
|
||||
#include "asm/fstack.hpp"
|
||||
#include <sys/stat.h>
|
||||
|
||||
#include <assert.h>
|
||||
#include <errno.h>
|
||||
#include <inttypes.h>
|
||||
#include <memory>
|
||||
@@ -50,28 +49,28 @@ static std::vector<std::string> includePaths = {""};
|
||||
static std::string preIncludeName;
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
std::string &FileStackNode::name() {
|
||||
assert(std::holds_alternative<std::string>(data));
|
||||
assume(std::holds_alternative<std::string>(data));
|
||||
return std::get<std::string>(data);
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
std::string const &FileStackNode::dump(uint32_t curLineNo) const {
|
||||
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);
|
||||
fputs(" -> ", 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);
|
||||
|
||||
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->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);
|
||||
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->lineNo = reptLineNo;
|
||||
|
||||
|
||||
@@ -5,7 +5,6 @@
|
||||
#include <sys/types.h>
|
||||
|
||||
#include <algorithm>
|
||||
#include <assert.h>
|
||||
#include <ctype.h>
|
||||
#include <errno.h>
|
||||
#include <fcntl.h>
|
||||
@@ -20,7 +19,7 @@
|
||||
#include <unistd.h>
|
||||
#endif
|
||||
|
||||
#include "helpers.hpp" // QUOTEDSTRLEN
|
||||
#include "helpers.hpp" // assume, QUOTEDSTRLEN
|
||||
#include "util.hpp"
|
||||
|
||||
#include "asm/fixpoint.hpp"
|
||||
@@ -477,14 +476,14 @@ LexerState::~LexerState() {
|
||||
// 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
|
||||
// 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
|
||||
// `lexerStateEOL`, but there's currently no situation in which this should happen.
|
||||
assert(this != lexerStateEOL);
|
||||
assume(this != lexerStateEOL);
|
||||
}
|
||||
|
||||
bool Expansion::advance() {
|
||||
assert(offset <= size());
|
||||
assume(offset <= size());
|
||||
offset++;
|
||||
return offset > size();
|
||||
}
|
||||
@@ -494,11 +493,11 @@ BufferedContent::~BufferedContent() {
|
||||
}
|
||||
|
||||
void BufferedContent::advance() {
|
||||
assert(offset < LEXER_BUF_SIZE);
|
||||
assume(offset < LEXER_BUF_SIZE);
|
||||
offset++;
|
||||
if (offset == LEXER_BUF_SIZE)
|
||||
offset = 0; // Wrap around if necessary
|
||||
assert(size > 0);
|
||||
assume(size > 0);
|
||||
size--;
|
||||
}
|
||||
|
||||
@@ -528,7 +527,7 @@ void BufferedContent::refill() {
|
||||
|
||||
size_t BufferedContent::readMore(size_t startIndex, size_t nbChars) {
|
||||
// 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);
|
||||
|
||||
if (nbReadChars == -1)
|
||||
@@ -671,7 +670,7 @@ static std::shared_ptr<std::string> readMacroArg(char name) {
|
||||
error("Invalid macro argument '\\0'\n");
|
||||
return nullptr;
|
||||
} else {
|
||||
assert(name > '0' && name <= '9');
|
||||
assume(name > '0' && name <= '9');
|
||||
|
||||
MacroArgs *macroArgs = fstk_GetCurrentMacroArgs();
|
||||
if (!macroArgs) {
|
||||
@@ -698,11 +697,11 @@ int LexerState::peekChar() {
|
||||
if (view->offset < view->span.size)
|
||||
return (uint8_t)view->span.ptr[view->offset];
|
||||
} else {
|
||||
assert(std::holds_alternative<BufferedContent>(content));
|
||||
assume(std::holds_alternative<BufferedContent>(content));
|
||||
auto &cbuf = std::get<BufferedContent>(content);
|
||||
if (cbuf.size == 0)
|
||||
cbuf.refill();
|
||||
assert(cbuf.offset < LEXER_BUF_SIZE);
|
||||
assume(cbuf.offset < LEXER_BUF_SIZE);
|
||||
if (cbuf.size > 0)
|
||||
return (uint8_t)cbuf.buf[cbuf.offset];
|
||||
}
|
||||
@@ -718,7 +717,7 @@ int LexerState::peekCharAhead() {
|
||||
for (Expansion &exp : expansions) {
|
||||
// An expansion that has reached its end will have `exp.offset` == `exp.size()`,
|
||||
// and `.peekCharAhead()` will continue with its parent
|
||||
assert(exp.offset <= exp.size());
|
||||
assume(exp.offset <= exp.size());
|
||||
if (exp.offset + distance < exp.size())
|
||||
return (uint8_t)(*exp.contents)[exp.offset + distance];
|
||||
distance -= exp.size() - exp.offset;
|
||||
@@ -728,9 +727,9 @@ int LexerState::peekCharAhead() {
|
||||
if (view->offset + distance < view->span.size)
|
||||
return (uint8_t)view->span.ptr[view->offset + distance];
|
||||
} else {
|
||||
assert(std::holds_alternative<BufferedContent>(content));
|
||||
assume(std::holds_alternative<BufferedContent>(content));
|
||||
auto &cbuf = std::get<BufferedContent>(content);
|
||||
assert(distance < LEXER_BUF_SIZE);
|
||||
assume(distance < LEXER_BUF_SIZE);
|
||||
if (cbuf.size <= distance)
|
||||
cbuf.refill();
|
||||
if (cbuf.size > distance)
|
||||
@@ -816,7 +815,7 @@ restart:
|
||||
if (auto *view = std::get_if<ViewedContent>(&lexerState->content); view) {
|
||||
view->offset++;
|
||||
} else {
|
||||
assert(std::holds_alternative<BufferedContent>(lexerState->content));
|
||||
assume(std::holds_alternative<BufferedContent>(lexerState->content));
|
||||
auto &cbuf = std::get<BufferedContent>(lexerState->content);
|
||||
cbuf.advance();
|
||||
}
|
||||
@@ -1785,7 +1784,7 @@ static Token yylex_NORMAL() {
|
||||
return token;
|
||||
|
||||
// `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
|
||||
if (token.type == T_(ID) && lexerState->expandStrings) {
|
||||
@@ -1795,7 +1794,7 @@ static Token yylex_NORMAL() {
|
||||
if (sym && sym->type == SYM_EQUS) {
|
||||
std::shared_ptr<std::string> str = sym->getEqus();
|
||||
|
||||
assert(str);
|
||||
assume(str);
|
||||
beginExpansion(str, sym->name);
|
||||
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) {
|
||||
return yy::parser::symbol_type(token.type, *strValue);
|
||||
} else {
|
||||
assert(std::holds_alternative<std::monostate>(token.value));
|
||||
assume(std::holds_alternative<std::monostate>(token.value));
|
||||
return yy::parser::symbol_type(token.type);
|
||||
}
|
||||
}
|
||||
@@ -2180,10 +2179,10 @@ yy::parser::symbol_type yylex() {
|
||||
static Capture startCapture() {
|
||||
// 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.
|
||||
// The following assertion checks that.
|
||||
assert(lexerState->atLineStart);
|
||||
// The following assumption checks that.
|
||||
assume(lexerState->atLineStart);
|
||||
|
||||
assert(!lexerState->capturing && lexerState->captureBuf == nullptr);
|
||||
assume(!lexerState->capturing && lexerState->captureBuf == nullptr);
|
||||
lexerState->capturing = true;
|
||||
lexerState->captureSize = 0;
|
||||
|
||||
@@ -2194,7 +2193,7 @@ static Capture startCapture() {
|
||||
.lineNo = lineNo, .span = {.ptr = view->makeSharedContentPtr(), .size = 0}
|
||||
};
|
||||
} else {
|
||||
assert(lexerState->captureBuf == nullptr);
|
||||
assume(lexerState->captureBuf == nullptr);
|
||||
lexerState->captureBuf = std::make_shared<std::vector<char>>();
|
||||
// `.span.ptr == nullptr`; indicates to retrieve the capture buffer when done capturing
|
||||
return {
|
||||
|
||||
@@ -2,7 +2,6 @@
|
||||
|
||||
#include "asm/output.hpp"
|
||||
|
||||
#include <assert.h>
|
||||
#include <deque>
|
||||
#include <inttypes.h>
|
||||
#include <stdio.h>
|
||||
@@ -12,7 +11,7 @@
|
||||
#include <vector>
|
||||
|
||||
#include "error.hpp"
|
||||
#include "helpers.hpp" // Defer
|
||||
#include "helpers.hpp" // assume, Defer
|
||||
|
||||
#include "asm/fstack.hpp"
|
||||
#include "asm/lexer.hpp"
|
||||
@@ -75,7 +74,7 @@ static uint32_t getSectIDIfAny(Section *sect) {
|
||||
|
||||
// Write a patch to a 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.lineNo, file);
|
||||
putlong(patch.offset, file);
|
||||
@@ -117,7 +116,7 @@ static void writesymbol(Symbol const &sym, FILE *file) {
|
||||
if (!sym.isDefined()) {
|
||||
putc(SYMTYPE_IMPORT, file);
|
||||
} else {
|
||||
assert(sym.src->ID != (uint32_t)-1);
|
||||
assume(sym.src->ID != (uint32_t)-1);
|
||||
|
||||
putc(sym.isExported ? SYMTYPE_EXPORT : SYMTYPE_LOCAL, 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) {
|
||||
fmt.appendNumber(str, *n);
|
||||
} 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]);
|
||||
fmt.appendString(str, s);
|
||||
}
|
||||
|
||||
@@ -2,7 +2,6 @@
|
||||
|
||||
#include "asm/rpn.hpp"
|
||||
|
||||
#include <assert.h>
|
||||
#include <inttypes.h>
|
||||
#include <limits.h>
|
||||
#include <stdio.h>
|
||||
@@ -10,6 +9,7 @@
|
||||
#include <string.h>
|
||||
#include <string_view>
|
||||
|
||||
#include "helpers.hpp" // assume
|
||||
#include "opmath.hpp"
|
||||
|
||||
#include "asm/output.hpp"
|
||||
@@ -20,7 +20,7 @@
|
||||
using namespace std::literals;
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
@@ -116,7 +116,7 @@ void Expression::makeBankSymbol(std::string const &symName) {
|
||||
data = 1;
|
||||
} else {
|
||||
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) {
|
||||
// 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;
|
||||
Expression const &expr = lhsIsSymbol ? rhs : lhs; // Opposite side of `sym`
|
||||
|
||||
assert(sym.isNumeric());
|
||||
assume(sym.isNumeric());
|
||||
|
||||
if (!expr.isKnown())
|
||||
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"
|
||||
// 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;
|
||||
|
||||
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)
|
||||
void Expression::checkNBit(uint8_t n) const {
|
||||
assert(n != 0); // That doesn't make sense
|
||||
assert(n < CHAR_BIT * sizeof(int)); // Otherwise `1 << n` is UB
|
||||
assume(n != 0); // That doesn't make sense
|
||||
assume(n < CHAR_BIT * sizeof(int)); // Otherwise `1 << n` is UB
|
||||
|
||||
if (isKnown()) {
|
||||
if (int32_t val = value(); val < -(1 << n) || val >= 1 << n)
|
||||
|
||||
@@ -3,7 +3,6 @@
|
||||
#include "asm/section.hpp"
|
||||
|
||||
#include <algorithm>
|
||||
#include <assert.h>
|
||||
#include <errno.h>
|
||||
#include <inttypes.h>
|
||||
#include <optional>
|
||||
@@ -125,7 +124,7 @@ Section *sect_FindSectionByName(std::string const &name) {
|
||||
static unsigned int mergeSectUnion(
|
||||
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;
|
||||
|
||||
// Unionized sections only need "compatible" constraints, and they end up with the strictest
|
||||
@@ -177,7 +176,7 @@ static unsigned int mergeSectUnion(
|
||||
|
||||
static unsigned int
|
||||
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;
|
||||
|
||||
// Fragments only need "compatible" constraints, and they end up with the strictest
|
||||
|
||||
@@ -2,12 +2,12 @@
|
||||
|
||||
#include "asm/symbol.hpp"
|
||||
|
||||
#include <assert.h>
|
||||
#include <inttypes.h>
|
||||
#include <stdio.h>
|
||||
#include <unordered_map>
|
||||
|
||||
#include "error.hpp"
|
||||
#include "helpers.hpp" // assume
|
||||
#include "version.hpp"
|
||||
|
||||
#include "asm/fstack.hpp"
|
||||
@@ -55,7 +55,7 @@ static int32_t CallbackPC() {
|
||||
}
|
||||
|
||||
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) {
|
||||
return type == SYM_LABEL ? *value + getSection()->org : *value;
|
||||
}
|
||||
@@ -73,12 +73,12 @@ int32_t Symbol::getOutputValue() const {
|
||||
}
|
||||
|
||||
ContentSpan const &Symbol::getMacro() const {
|
||||
assert((std::holds_alternative<ContentSpan>(data)));
|
||||
assume((std::holds_alternative<ContentSpan>(data)));
|
||||
return std::get<ContentSpan>(data);
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
@@ -361,7 +361,7 @@ Symbol *sym_AddVar(std::string const &symName, int32_t value) {
|
||||
* @return The created symbol
|
||||
*/
|
||||
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);
|
||||
|
||||
if (!sym) {
|
||||
@@ -390,11 +390,11 @@ static Symbol *addLabel(std::string const &symName) {
|
||||
// Add a local (`.name` or `Parent.name`) relocatable symbol
|
||||
Symbol *sym_AddLocalLabel(std::string const &symName) {
|
||||
// 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('.');
|
||||
|
||||
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
|
||||
if (dotPos == symName.length() - 1) {
|
||||
|
||||
Reference in New Issue
Block a user