summaryrefslogtreecommitdiff
path: root/src/con_.c
diff options
context:
space:
mode:
authorGravatar Michael Smith <mikesmiffy128@gmail.com> 2025-12-27 03:05:05 +0000
committerGravatar Michael Smith <mikesmiffy128@gmail.com> 2026-02-16 19:11:24 +0000
commit8d4b47298b6c9eeb9a3f79a5b80d894f80ed4a45 (patch)
tree63a8ea6f645b997fd7943a58a002e66244fa49ac /src/con_.c
parente7943fb834cbcaec585ed68e67b5f17ceda504f7 (diff)
downloadsst-8d4b47298b6c9eeb9a3f79a5b80d894f80ed4a45.tar.gz
sst-8d4b47298b6c9eeb9a3f79a5b80d894f80ed4a45.zip
Do away with memcpy/memset/memcmp
Now everything is either explicitly a rep thing, or explicitly some other small run of reasonably efficient instructions. No library calls or function call overhead of any kind. Code size remains nice and small. Ban a few other bad libc functions while we're at it. More can be added later if we decide that's a useful idea. This will require some discipline and workarounds to cope with Clang's tendency to shove mem* calls in places you don't want them even when you tell it not to. Well, c'est la vie. I'm a little nervous that the __builtin_memmove() usage in shuntvars() could still one day emit actual library calls. It appears we're not importing memmove() from anywhere at the moment, though. So I guess it's good enough for now. Also I had to get rid of alloca() in con_.c but that was kind of bad anyway, so that's fine.
Diffstat (limited to 'src/con_.c')
-rw-r--r--src/con_.c16
1 files changed, 10 insertions, 6 deletions
diff --git a/src/con_.c b/src/con_.c
index 6d5ce03..56ab57f 100644
--- a/src/con_.c
+++ b/src/con_.c
@@ -201,13 +201,13 @@ void VCALLCONV Dispatch_OE(struct con_cmd *this) {
static void ChangeStringValue_common(struct con_var *this,
struct con_var_common *common, char *old, const char *s) {
- memcpy(old, common->strval, common->strlen);
+ mem_copy(old, common->strval, common->strlen);
int len = strlen(s) + 1;
if (len > common->strlen) {
common->strval = extrealloc(common->strval, len);
common->strlen = len;
}
- memcpy(common->strval, s, len);
+ mem_copy(common->strval, s, len);
// callbacks don't matter as far as ABI compat goes (and thank goodness
// because e.g. portal2 randomly adds a *list* of callbacks!?). however we
// do need callbacks for at least one feature, so do our own minimal thing
@@ -215,15 +215,19 @@ static void ChangeStringValue_common(struct con_var *this,
}
static void VCALLCONV ChangeStringValue(struct con_var *this, const char *s,
float oldf) {
- char *old = alloca(this->v2.strlen);
+ char oldbuf[128], *old = oldbuf;
+ if_cold (this->v2.strlen > sizeof(oldbuf)) old = extmalloc(this->v2.strlen);
ChangeStringValue_common(this, &this->v2, old, s);
CallGlobalChangeCallbacks(_con_iface, this, old, oldf);
+ if_cold (old != oldbuf) extfree(old);
}
#ifdef _WIN32
static void VCALLCONV ChangeStringValue_OE(struct con_var *this, const char *s) {
- char *old = alloca(this->v1.strlen);
+ char oldbuf[128], *old = oldbuf;
+ if_cold (this->v1.strlen > sizeof(oldbuf)) old = extmalloc(this->v1.strlen);
ChangeStringValue_common(this, &this->v1, old, s);
CallGlobalChangeCallbacks_OE(_con_iface, this, old);
+ extfree(old);
}
#endif
@@ -418,7 +422,7 @@ void con_regvar(struct con_var *v) {
fudgeflags(&v->base);
struct con_var_common *c = con_getvarcommon(v);
c->strval = extmalloc(c->strlen); // note: _DEF_CVAR() sets strlen member
- memcpy(c->strval, c->defaultval, c->strlen);
+ mem_copy(c->strval, c->defaultval, c->strlen);
RegisterConCommand(_con_iface, v);
}
@@ -578,7 +582,7 @@ bool con_detect(int pluginver) {
if (!find_argcargv()) return false;
if (!find_Con_ColorPrintf()) return false;
// note: _con_colourmsg is already RWX, just overwrite it.
- memcpy((void *)&_con_colourmsg, (void *)&_con_colourmsg_OE,
+ mem_copy((void *)&_con_colourmsg, (void *)&_con_colourmsg_OE,
SELFMOD_LEN);
// NOTE: the default static struct layout is for NE; immediately after
// engineapi init finishes, the generated glue code will shunt