Replace assert with assume for release build optimization (#1390)

This commit is contained in:
Sylvie
2024-04-02 11:09:31 -04:00
committed by GitHub
parent 1d39e5ed56
commit a234da42a6
26 changed files with 158 additions and 147 deletions

View File

@@ -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 &macro, 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;

View File

@@ -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 {

View File

@@ -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);

View 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);
}

View File

@@ -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)

View File

@@ -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 &sect, 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 &sect, 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

View File

@@ -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) {