commit 1237b5860034481d9e40836011e4e781f6a47ad4
parent 6405d2b7504c93c0c3b41a7ac8180c45691fc0f8
Author: Ryan Sepassi <rsepassi@gmail.com>
Date: Sun, 24 May 2026 05:19:07 -0700
slice: replace NUL-terminated strings with fat-pointer CfreeSlice
Eliminate NUL-terminated C strings across the first-party tree in favor of one
fat-pointer type carrying an explicit length, and type the whole public API in
terms of it. Strings retain a trailing NUL only where they cross an OS/format
boundary, and that NUL is never counted in the length.
Type & helpers
- CfreeSlice { union { const char* s; const uint8_t* data; }; size_t len; }
(public) / Slice (internal), replacing CfreeBytes. Public CFREE_SLICE_LIT/
_NULL/_ARG, cfree_slice_cstr/_eq/_eq_cstr; internal core/slice.{h,c} adds
slice_from_cstr/slice_eq/slice_eq_cstr/slice_dup; strbuf gains put_slice/slice.
Interning & printing
- Interning is slice-valued: pool_slice/pool_intern_slice replace
pool_str/pool_intern/pool_intern_cstr; public cfree_sym_str returns CfreeSlice
and cfree_sym_intern takes one (cfree_sym_intern_len removed).
- Printing is length-explicit: every printf-family %s becomes %.*s + slice args;
src/opt sprintf/snprintf moves to StrBuf.
- Comparisons: strcmp/strncmp on names/sections/registers/mnemonics/attributes
become slice_eq/slice_eq_cstr (or Sym equality); arch mnemonic tables carry
Slice. Ordering compares (stable sorts) are kept and annotated.
Public API typed on CfreeSlice
- disasm (CfreeInsn mnemonic/operands/annotation), object (sec/sym/reloc names,
by_name lookups, group name), dwarf (names/files), jit (lookup/CfreeJitSym),
arch (register name/index), link (script + session options: entry/soname/
interp/rpaths/exports/patterns + CfreeExternResolver), compile (repl_entry_name,
dep names), cg (file_scope_asm), archive (CfreeArMember.name + member symbols),
source (add_memory/_builtin), preprocess (CfreeDefine/undefines), frontend
extensions vtable, cfree_compiler_file_name.
Frontends & runtime
- lang/wasm interns names as CfreeSym instead of strdup; lang/c and lang/cpp call
the public sym API directly (no local pool shims).
Boundaries kept as char*
- printf fmt, char[N] buffers, argv/envp, byte cursors in parsers/lexers, raw
ELF/COFF readers, Mach-O fixed-name fields, static literal-table returns
(op_name/register tables), host-callback vtable strings (metrics/diag), and
file paths handed to CfreeFileIO/open()/host I/O. Driver/lang build with
-Iinclude (driver also -Ilang) and never -Isrc.
- scripts/check_no_cstr.sh gates the tree: zero banned string functions and zero
bare %s in src/lang/driver. The sole sanctioned NUL scan is slice_from_cstr in
src/core/slice.c (plus the public inline cfree_slice_cstr at the argv boundary).
Build (lib/bin/rt) and gate clean; full suite green (isa, asm, parse, pp, toy,
opt, cg-api, link, elf, macho, dwarf, ar, debug, aa64-inline, wasm-front, coff,
x64 smoke; objdump rv64 8/8). Pre-existing, unrelated: test-parse-err
6_7_file_scope_register and the wine-dependent Windows/COFF smoke.
Diffstat:
197 files changed, 4234 insertions(+), 3331 deletions(-)
diff --git a/Makefile b/Makefile
@@ -16,8 +16,11 @@ DEPFLAGS = -MMD -MP
LIB_CFLAGS = $(CFLAGS_COMMON) -ffreestanding -Iinclude -Isrc
# Driver: hosted CLI binary. Sees only the public include/ tree — that's
-# what makes the driver the first consumer of libcfree.
-DRIVER_CFLAGS = $(CFLAGS_COMMON) -Iinclude -I.
+# what makes the driver the first consumer of libcfree. -Ilang lets `cc` reach
+# the C frontend's public header ("c/c.h") for the JIT REPL; it deliberately
+# does NOT get -Isrc, so internal headers ("core/...", "link/...") are
+# unreachable from the driver.
+DRIVER_CFLAGS = $(CFLAGS_COMMON) -Iinclude -Ilang
include mk/config.mk
diff --git a/driver/ar.c b/driver/ar.c
@@ -47,14 +47,16 @@
#define AR_TOOL "ar"
static void ar_usage(void) {
- driver_errf(AR_TOOL, "%s",
+ driver_errf(AR_TOOL, "%.*s",
+ CFREE_SLICE_ARG(CFREE_SLICE_LIT(
"usage: cfree ar {rc|r|c|t|x|p}[s] archive.a [members...]\n"
- " cfree ar --help for full operation reference");
+ " cfree ar --help for full operation reference")));
}
void driver_help_ar(void) {
driver_printf(
- "%s",
+ "%.*s",
+ CFREE_SLICE_ARG(CFREE_SLICE_LIT(
"cfree ar — POSIX `ar` archive front-end\n"
"\n"
"USAGE\n"
@@ -109,7 +111,7 @@ void driver_help_ar(void) {
"\n"
"EXIT CODES\n"
" 0 success 1 archive I/O error 2 bad "
- "usage\n");
+ "usage\n")));
}
/* Parse SOURCE_DATE_EPOCH into a u64; 0 (or unset/invalid) means "no epoch". */
@@ -126,13 +128,13 @@ static uint64_t ar_epoch_from_env(void) {
/* Return 1 iff `name` matches any of the names in argv[start..argc) — or if
* there are no filters, in which case every member matches. */
-static int ar_name_selected(const char* name, int argc, char** argv,
+static int ar_name_selected(CfreeSlice name, int argc, char** argv,
int start) {
int i;
if (start >= argc) return 1;
for (i = start; i < argc; ++i) {
const char* base = driver_basename(argv[i]);
- if (driver_streq(name, base)) return 1;
+ if (cfree_slice_eq_cstr(name, base)) return 1;
}
return 0;
}
@@ -140,14 +142,15 @@ static int ar_name_selected(const char* name, int argc, char** argv,
/* Open the archive bytes via file_io. Caller releases fd via ctx. */
static int ar_open_for_read(DriverEnv* env, const char* path,
CfreeContext* ctx_out, CfreeFileData* fd_out,
- CfreeBytes* input_out) {
+ CfreeSlice* input_out) {
*ctx_out = driver_env_to_context(env);
if (ctx_out->file_io->read_all(ctx_out->file_io->user, path, fd_out) !=
CFREE_OK) {
- driver_errf(AR_TOOL, "failed to read: %s", path);
+ driver_errf(AR_TOOL, "failed to read: %.*s",
+ CFREE_SLICE_ARG(cfree_slice_cstr(path)));
return 0;
}
- input_out->name = path;
+ (void)path;
input_out->data = fd_out->data;
input_out->len = fd_out->size;
return 1;
@@ -156,7 +159,7 @@ static int ar_open_for_read(DriverEnv* env, const char* path,
static int ar_do_list(DriverEnv* env, const char* archive_path, int verbose) {
CfreeContext ctx;
CfreeFileData fd = {0};
- CfreeBytes input;
+ CfreeSlice input;
CfreeWriter* out;
int rc;
@@ -173,7 +176,8 @@ static int ar_do_list(DriverEnv* env, const char* archive_path, int verbose) {
CfreeArIter* it = NULL;
CfreeArMember m;
if (cfree_ar_iter_new(&ctx, &input, &it) != CFREE_OK) {
- driver_errf(AR_TOOL, "not an archive: %s", archive_path);
+ driver_errf(AR_TOOL, "not an archive: %.*s",
+ CFREE_SLICE_ARG(cfree_slice_cstr(archive_path)));
cfree_writer_close(out);
ctx.file_io->release(ctx.file_io->user, &fd);
return 1;
@@ -181,13 +185,16 @@ static int ar_do_list(DriverEnv* env, const char* archive_path, int verbose) {
for (;;) {
CfreeIterResult r = cfree_ar_iter_next(it, &m);
if (r != CFREE_ITER_ITEM) break;
- driver_printf("%zu\t%s\n", m.size, m.name);
+ driver_printf("%zu\t%.*s\n", m.size,
+ CFREE_SLICE_ARG(m.name));
}
cfree_ar_iter_free(it);
rc = cfree_writer_status(out) == CFREE_OK ? 0 : 1;
} else {
rc = cfree_ar_list(&input, out) == CFREE_OK ? 0 : 1;
- if (rc) driver_errf(AR_TOOL, "failed to read archive: %s", archive_path);
+ if (rc)
+ driver_errf(AR_TOOL, "failed to read archive: %.*s",
+ CFREE_SLICE_ARG(cfree_slice_cstr(archive_path)));
}
cfree_writer_close(out);
ctx.file_io->release(ctx.file_io->user, &fd);
@@ -198,14 +205,15 @@ static int ar_do_extract(DriverEnv* env, const char* archive_path, int argc,
char** argv, int start, int verbose) {
CfreeContext ctx;
CfreeFileData fd = {0};
- CfreeBytes input;
+ CfreeSlice input;
CfreeArIter* it = NULL;
CfreeArMember m;
int rc = 0;
if (!ar_open_for_read(env, archive_path, &ctx, &fd, &input)) return 1;
if (cfree_ar_iter_new(&ctx, &input, &it) != CFREE_OK) {
- driver_errf(AR_TOOL, "not an archive: %s", archive_path);
+ driver_errf(AR_TOOL, "not an archive: %.*s",
+ CFREE_SLICE_ARG(cfree_slice_cstr(archive_path)));
ctx.file_io->release(ctx.file_io->user, &fd);
return 1;
}
@@ -216,18 +224,22 @@ static int ar_do_extract(DriverEnv* env, const char* archive_path, int argc,
if (r != CFREE_ITER_ITEM) break;
if (!ar_name_selected(m.name, argc, argv, start)) continue;
- if (ctx.file_io->open_writer(ctx.file_io->user, m.name, &out) != CFREE_OK) {
- driver_errf(AR_TOOL, "failed to open: %s", m.name);
+ if (ctx.file_io->open_writer(ctx.file_io->user, m.name.s, &out) !=
+ CFREE_OK) {
+ driver_errf(AR_TOOL, "failed to open: %.*s",
+ CFREE_SLICE_ARG(m.name));
rc = 1;
continue;
}
if (m.size) cfree_writer_write(out, m.data, m.size);
if (cfree_writer_status(out) != CFREE_OK) {
- driver_errf(AR_TOOL, "write failed: %s", m.name);
+ driver_errf(AR_TOOL, "write failed: %.*s",
+ CFREE_SLICE_ARG(m.name));
rc = 1;
}
cfree_writer_close(out);
- if (verbose) driver_printf("x - %s\n", m.name);
+ if (verbose)
+ driver_printf("x - %.*s\n", CFREE_SLICE_ARG(m.name));
}
cfree_ar_iter_free(it);
@@ -239,7 +251,7 @@ static int ar_do_print(DriverEnv* env, const char* archive_path, int argc,
char** argv, int start, int verbose) {
CfreeContext ctx;
CfreeFileData fd = {0};
- CfreeBytes input;
+ CfreeSlice input;
CfreeArIter* it = NULL;
CfreeArMember m;
CfreeWriter* out;
@@ -249,7 +261,8 @@ static int ar_do_print(DriverEnv* env, const char* archive_path, int argc,
if (!ar_open_for_read(env, archive_path, &ctx, &fd, &input)) return 1;
if (cfree_ar_iter_new(&ctx, &input, &it) != CFREE_OK) {
- driver_errf(AR_TOOL, "not an archive: %s", archive_path);
+ driver_errf(AR_TOOL, "not an archive: %.*s",
+ CFREE_SLICE_ARG(cfree_slice_cstr(archive_path)));
ctx.file_io->release(ctx.file_io->user, &fd);
return 1;
}
@@ -266,7 +279,10 @@ static int ar_do_print(DriverEnv* env, const char* archive_path, int argc,
CfreeIterResult r = cfree_ar_iter_next(it, &m);
if (r != CFREE_ITER_ITEM) break;
if (!ar_name_selected(m.name, argc, argv, start)) continue;
- if (header) driver_printf("%s(%s):\n", archive_path, m.name);
+ if (header)
+ driver_printf("%.*s(%.*s):\n",
+ CFREE_SLICE_ARG(cfree_slice_cstr(archive_path)),
+ CFREE_SLICE_ARG(m.name));
if (m.size) cfree_writer_write(out, m.data, m.size);
}
if (cfree_writer_status(out) != CFREE_OK) rc = 1;
@@ -290,7 +306,7 @@ static int ar_do_write(DriverEnv* env, const char* archive_path, int nmembers,
char** member_paths, int has_r, int has_c, int has_s,
int has_v) {
uint32_t nnew = nmembers > 0 ? (uint32_t)nmembers : 0u;
- CfreeBytes* members = NULL;
+ CfreeArInput* members = NULL;
CfreeFileData* new_fds = NULL;
size_t members_cap = 0;
uint32_t nm = 0; /* count of entries in `members` */
@@ -320,7 +336,7 @@ static int ar_do_write(DriverEnv* env, const char* archive_path, int nmembers,
/* `r`: read existing archive (if any) and seed `members` with it. */
if (has_r) {
- CfreeBytes input;
+ CfreeSlice input;
CfreeArIter* it = NULL;
CfreeArMember m;
uint32_t nold = 0;
@@ -328,11 +344,11 @@ static int ar_do_write(DriverEnv* env, const char* archive_path, int nmembers,
if (ctx.file_io->read_all(ctx.file_io->user, archive_path, &old_fd) ==
CFREE_OK) {
have_old = 1;
- input.name = archive_path;
input.data = old_fd.data;
input.len = old_fd.size;
if (cfree_ar_iter_new(&ctx, &input, &it) != CFREE_OK) {
- driver_errf(AR_TOOL, "not an archive: %s", archive_path);
+ driver_errf(AR_TOOL, "not an archive: %.*s",
+ CFREE_SLICE_ARG(cfree_slice_cstr(archive_path)));
rc = 1;
goto done;
}
@@ -342,18 +358,19 @@ static int ar_do_write(DriverEnv* env, const char* archive_path, int nmembers,
CfreeIterResult r = cfree_ar_iter_next(it, &m);
if (r != CFREE_ITER_ITEM) break;
nold++;
- old_name_bytes += driver_strlen(m.name) + 1;
+ old_name_bytes += m.name.len + 1;
}
cfree_ar_iter_free(it);
it = NULL;
} else if (!has_c) {
/* POSIX: warn (not an error) when `r` creates a new archive. */
- driver_errf(AR_TOOL, "creating %s", archive_path);
+ driver_errf(AR_TOOL, "creating %.*s",
+ CFREE_SLICE_ARG(cfree_slice_cstr(archive_path)));
}
members_cap = (size_t)nold + (size_t)nnew;
if (members_cap > 0) {
- members = (CfreeBytes*)driver_alloc_zeroed(
+ members = (CfreeArInput*)driver_alloc_zeroed(
env, members_cap * sizeof(*members));
if (!members) {
driver_errf(AR_TOOL, "out of memory");
@@ -380,14 +397,15 @@ static int ar_do_write(DriverEnv* env, const char* archive_path, int nmembers,
while (nm < nold) {
CfreeIterResult r = cfree_ar_iter_next(it, &m);
char* dst;
- const char* p;
+ size_t j;
if (r != CFREE_ITER_ITEM) break;
dst = old_name_storage + cursor;
- for (p = m.name; *p; ++p) *dst++ = *p;
+ for (j = 0; j < m.name.len; ++j) *dst++ = m.name.s[j];
*dst++ = '\0';
- members[nm].name = old_name_storage + cursor;
- members[nm].data = m.data;
- members[nm].len = m.size;
+ members[nm].name.s = old_name_storage + cursor;
+ members[nm].name.len = m.name.len;
+ members[nm].bytes.data = m.data;
+ members[nm].bytes.len = m.size;
cursor = (size_t)(dst - old_name_storage);
nm++;
}
@@ -397,7 +415,7 @@ static int ar_do_write(DriverEnv* env, const char* archive_path, int nmembers,
/* `c`: overwrite. */
members_cap = (size_t)nnew;
if (members_cap > 0) {
- members = (CfreeBytes*)driver_alloc_zeroed(
+ members = (CfreeArInput*)driver_alloc_zeroed(
env, members_cap * sizeof(*members));
if (!members) {
driver_errf(AR_TOOL, "out of memory");
@@ -420,7 +438,8 @@ static int ar_do_write(DriverEnv* env, const char* archive_path, int nmembers,
const char* base = driver_basename(path);
if (ctx.file_io->read_all(ctx.file_io->user, path, &new_fds[i]) !=
CFREE_OK) {
- driver_errf(AR_TOOL, "failed to read: %s", path);
+ driver_errf(AR_TOOL, "failed to read: %.*s",
+ CFREE_SLICE_ARG(cfree_slice_cstr(path)));
rc = 1;
goto done;
}
@@ -430,27 +449,30 @@ static int ar_do_write(DriverEnv* env, const char* archive_path, int nmembers,
uint32_t j;
int replaced = 0;
for (j = 0; j < nm; ++j) {
- if (driver_streq(members[j].name, base)) {
- members[j].name = base;
- members[j].data = new_fds[i].data;
- members[j].len = new_fds[i].size;
+ if (driver_streq(members[j].name.s, base)) {
+ members[j].name = cfree_slice_cstr(base);
+ members[j].bytes.data = new_fds[i].data;
+ members[j].bytes.len = new_fds[i].size;
replaced = 1;
break;
}
}
if (!replaced) {
- members[nm].name = base;
- members[nm].data = new_fds[i].data;
- members[nm].len = new_fds[i].size;
+ members[nm].name = cfree_slice_cstr(base);
+ members[nm].bytes.data = new_fds[i].data;
+ members[nm].bytes.len = new_fds[i].size;
nm++;
}
- if (has_v) driver_printf("%c - %s\n", replaced ? 'r' : 'a', base);
+ if (has_v)
+ driver_printf("%c - %.*s\n", replaced ? 'r' : 'a',
+ CFREE_SLICE_ARG(cfree_slice_cstr(base)));
} else {
- members[nm].name = base;
- members[nm].data = new_fds[i].data;
- members[nm].len = new_fds[i].size;
+ members[nm].name = cfree_slice_cstr(base);
+ members[nm].bytes.data = new_fds[i].data;
+ members[nm].bytes.len = new_fds[i].size;
nm++;
- if (has_v) driver_printf("a - %s\n", base);
+ if (has_v)
+ driver_printf("a - %.*s\n", CFREE_SLICE_ARG(cfree_slice_cstr(base)));
}
}
}
@@ -468,16 +490,12 @@ static int ar_do_write(DriverEnv* env, const char* archive_path, int nmembers,
goto done;
}
for (i = 0; i < nm; ++i) {
- CfreeBytes in;
+ CfreeSlice in = members[i].bytes;
void* blob = NULL;
size_t blob_size = 0;
- const char** names = NULL;
+ const CfreeSlice* names = NULL;
uint32_t count = 0;
- in.name = members[i].name;
- in.data = members[i].data;
- in.len = members[i].len;
-
if (driver_collect_obj_global_syms(env, &ctx, AR_TOOL, &in, &blob,
&blob_size, &names, &count) != 0) {
rc = 1;
@@ -496,7 +514,8 @@ static int ar_do_write(DriverEnv* env, const char* archive_path, int nmembers,
if (ctx.file_io->open_writer(ctx.file_io->user, archive_path, &out) !=
CFREE_OK) {
- driver_errf(AR_TOOL, "failed to open: %s", archive_path);
+ driver_errf(AR_TOOL, "failed to open: %.*s",
+ CFREE_SLICE_ARG(cfree_slice_cstr(archive_path)));
rc = 1;
} else {
rc = cfree_ar_write(out, members, nm, &opts) == CFREE_OK ? 0 : 1;
@@ -598,12 +617,14 @@ int driver_ar(int argc, char** argv) {
{
int kinds = !!do_write + !!do_list + !!do_extract + !!do_print;
if (kinds == 0) {
- driver_errf(AR_TOOL, "no operation in mode: %s", mode);
+ driver_errf(AR_TOOL, "no operation in mode: %.*s",
+ CFREE_SLICE_ARG(cfree_slice_cstr(mode)));
ar_usage();
return 2;
}
if (kinds > 1) {
- driver_errf(AR_TOOL, "conflicting operations: %s", mode);
+ driver_errf(AR_TOOL, "conflicting operations: %.*s",
+ CFREE_SLICE_ARG(cfree_slice_cstr(mode)));
return 2;
}
}
diff --git a/driver/as.c b/driver/as.c
@@ -22,14 +22,16 @@ typedef struct AsOptions {
} AsOptions;
static void as_usage(void) {
- driver_errf(AS_TOOL, "%s",
+ driver_errf(AS_TOOL, "%.*s",
+ CFREE_SLICE_ARG(CFREE_SLICE_LIT(
"usage: cfree as [-g] [-target TRIPLE] -o out.o input.{s,S}\n"
- " cfree as --help for full option reference");
+ " cfree as --help for full option reference")));
}
void driver_help_as(void) {
driver_printf(
- "%s",
+ "%.*s",
+ CFREE_SLICE_ARG(CFREE_SLICE_LIT(
"cfree as — standalone assembler\n"
"\n"
"USAGE\n"
@@ -57,7 +59,7 @@ void driver_help_as(void) {
" -h, --help Show this help and exit\n"
"\n"
"EXIT CODES\n"
- " 0 success 1 assemble error 2 bad usage\n");
+ " 0 success 1 assemble error 2 bad usage\n")));
}
/* Returns 0 on success; non-zero on bad args (already reported). */
@@ -95,14 +97,16 @@ static int as_parse(int argc, char** argv, AsOptions* o, DriverEnv* env,
return 1;
}
if (driver_target_from_triple(argv[i], &o->target) != 0) {
- driver_errf(AS_TOOL, "unrecognized target: %s", argv[i]);
+ driver_errf(AS_TOOL, "unrecognized target: %.*s",
+ CFREE_SLICE_ARG(cfree_slice_cstr(argv[i])));
return 1;
}
continue;
}
if (a[0] == '-' && a[1] != '\0') {
- driver_errf(AS_TOOL, "unknown flag: %s", a);
+ driver_errf(AS_TOOL, "unknown flag: %.*s",
+ CFREE_SLICE_ARG(cfree_slice_cstr(a)));
return 1;
}
@@ -135,8 +139,8 @@ int driver_as(int argc, char** argv) {
CfreeWriter* writer = NULL;
CfreeWriter* pp_writer = NULL;
CfreeFileData src = {0};
- CfreeBytes input;
- CfreeBytes asm_input;
+ CfreeSlice input;
+ CfreeSlice asm_input;
CfreeAsmCompileOptions copts;
CfreeAsmCompileOptions zero = {0};
const uint8_t* pp_data;
@@ -167,14 +171,16 @@ int driver_as(int argc, char** argv) {
ctx = driver_env_to_context(&env);
if (ctx.file_io->read_all(ctx.file_io->user, o.source, &src) != CFREE_OK) {
- driver_errf(AS_TOOL, "failed to read: %s", o.source);
+ driver_errf(AS_TOOL, "failed to read: %.*s",
+ CFREE_SLICE_ARG(cfree_slice_cstr(o.source)));
goto out;
}
loaded = 1;
if (ctx.file_io->open_writer(ctx.file_io->user, o.output_path, &writer) !=
CFREE_OK) {
- driver_errf(AS_TOOL, "failed to open output: %s", o.output_path);
+ driver_errf(AS_TOOL, "failed to open output: %.*s",
+ CFREE_SLICE_ARG(cfree_slice_cstr(o.output_path)));
goto out;
}
@@ -186,7 +192,6 @@ int driver_as(int argc, char** argv) {
copts = zero;
copts.code.debug_info = o.debug_info;
- input.name = o.source;
input.data = src.data;
input.len = src.size;
asm_input = input;
@@ -196,10 +201,12 @@ int driver_as(int argc, char** argv) {
driver_errf(AS_TOOL, "out of memory");
goto out;
}
- if (cfree_cpp_preprocess(compiler, &pp, &input, pp_writer) != CFREE_OK)
+ if (cfree_cpp_preprocess(compiler, &pp, cfree_slice_cstr(o.source), &input,
+ pp_writer) != CFREE_OK)
goto out;
if (cfree_writer_status(pp_writer) != CFREE_OK) {
- driver_errf(AS_TOOL, "failed to preprocess: %s", o.source);
+ driver_errf(AS_TOOL, "failed to preprocess: %.*s",
+ CFREE_SLICE_ARG(cfree_slice_cstr(o.source)));
goto out;
}
pp_data = cfree_writer_mem_bytes(pp_writer, &pp_len);
@@ -219,6 +226,7 @@ int driver_as(int argc, char** argv) {
sopts.compile.diagnostics = copts.diagnostics;
sopts.compile.language_options = &copts;
memset(&sin, 0, sizeof(sin));
+ sin.name = cfree_slice_cstr(o.source);
sin.bytes = asm_input;
sin.lang = CFREE_LANG_ASM;
st = cfree_compile_session_new(compiler, &sopts, &session);
diff --git a/driver/cc.c b/driver/cc.c
@@ -1,4 +1,4 @@
-#include "lang/c/c.h"
+#include "c/c.h"
#include <cfree/compile.h>
#include <cfree/core.h>
@@ -209,15 +209,17 @@ typedef struct CcOptions {
} CcOptions;
static void cc_usage(void) {
- driver_errf(CC_TOOL, "%s",
+ driver_errf(CC_TOOL, "%.*s",
+ CFREE_SLICE_ARG(CFREE_SLICE_LIT(
"usage: cfree cc [-c|-E|-shared] [-o out] "
"[options...] inputs...\n"
- " cfree cc --help for full option reference");
+ " cfree cc --help for full option reference")));
}
void driver_help_cc(void) {
driver_printf(
- "%s",
+ "%.*s",
+ CFREE_SLICE_ARG(CFREE_SLICE_LIT(
"cfree cc — C compiler driver\n"
"\n"
"USAGE\n"
@@ -232,7 +234,7 @@ void driver_help_cc(void) {
" --sysroot DIR / -isysroot DIR hosted SDK/sysroot\n"
" --support-dir DIR cfree support root\n"
"\n"
- "(see source for the full GCC-subset flag reference)\n");
+ "(see source for the full GCC-subset flag reference)\n")));
}
static int cc_alloc_arrays(CcOptions* o, int argc) {
@@ -685,7 +687,8 @@ static int cc_record_build_id(CcOptions* o, const char* val) {
o->build_id_mode = CFREE_BUILDID_USER;
return 0;
}
- driver_errf(CC_TOOL, "unknown --build-id value: %s", val);
+ driver_errf(CC_TOOL, "unknown --build-id value: %.*s",
+ CFREE_SLICE_ARG(cfree_slice_cstr(val)));
return 1;
}
@@ -702,12 +705,14 @@ static int cc_record_mcmodel(CcOptions* o, const char* val) {
o->target.code_model = CFREE_CM_LARGE;
return 0;
}
- driver_errf(CC_TOOL, "unknown -mcmodel value: %s", val);
+ driver_errf(CC_TOOL, "unknown -mcmodel value: %.*s",
+ CFREE_SLICE_ARG(cfree_slice_cstr(val)));
return 1;
}
static void cc_log_ignored(const char* arg) {
- driver_errf(CC_TOOL, "ignoring accepted compatibility flag: %s", arg);
+ driver_errf(CC_TOOL, "ignoring accepted compatibility flag: %.*s",
+ CFREE_SLICE_ARG(cfree_slice_cstr(arg)));
}
static int cc_set_probe(CcOptions* o, int kind, const char* arg) {
@@ -729,17 +734,21 @@ static int cc_run_probe(CcOptions* o) {
switch (o->probe_kind) {
case CC_PROBE_PRINT_SEARCH_DIRS:
- driver_printf("install: %s\n", o->support_dir ? o->support_dir : "");
+ driver_printf("install: %.*s\n", CFREE_SLICE_ARG(cfree_slice_cstr(
+ o->support_dir ? o->support_dir : "")));
driver_printf("programs: =\n");
driver_printf("libraries: =");
- if (o->sysroot) driver_printf("%s/lib", o->sysroot);
+ if (o->sysroot)
+ driver_printf("%.*s/lib", CFREE_SLICE_ARG(cfree_slice_cstr(o->sysroot)));
driver_printf("\n");
return 0;
case CC_PROBE_PRINT_FILE_NAME:
- driver_printf("%s\n", o->probe_arg ? o->probe_arg : "");
+ driver_printf("%.*s\n", CFREE_SLICE_ARG(cfree_slice_cstr(
+ o->probe_arg ? o->probe_arg : "")));
return 0;
case CC_PROBE_PRINT_PROG_NAME:
- driver_printf("%s\n", o->probe_arg ? o->probe_arg : "");
+ driver_printf("%.*s\n", CFREE_SLICE_ARG(cfree_slice_cstr(
+ o->probe_arg ? o->probe_arg : "")));
return 0;
case CC_PROBE_PRINT_LIBGCC_FILE_NAME:
driver_printf("libcfree_rt.a\n");
@@ -748,10 +757,11 @@ static int cc_run_probe(CcOptions* o) {
driver_printf(".\n");
return 0;
case CC_PROBE_PRINT_RESOURCE_DIR:
- driver_printf("%s\n", o->support_dir ? o->support_dir : "");
+ driver_printf("%.*s\n", CFREE_SLICE_ARG(cfree_slice_cstr(
+ o->support_dir ? o->support_dir : "")));
return 0;
case CC_PROBE_DUMPMACHINE:
- driver_printf("%s\n", triple);
+ driver_printf("%.*s\n", CFREE_SLICE_ARG(cfree_slice_cstr(triple)));
return 0;
case CC_PROBE_DUMPVERSION:
driver_printf("0\n");
@@ -778,7 +788,7 @@ static int cc_record_stdin(CcOptions* o) {
return 1;
}
in = &o->source_memory[o->nsource_memory++];
- in->bytes.name = "<stdin>";
+ in->name = CFREE_SLICE_LIT("<stdin>");
in->bytes.data = o->stdin_buf;
in->bytes.len = o->stdin_size;
in->lang = CFREE_LANG_C;
@@ -827,7 +837,8 @@ static int cc_classify_positional(CcOptions* o, const char* a,
cc_push_link_item(o, CC_LINK_DSO, o->ndsos - 1u);
return 0;
}
- driver_errf(CC_TOOL, "input does not have a recognized suffix: %s", a);
+ driver_errf(CC_TOOL, "input does not have a recognized suffix: %.*s",
+ CFREE_SLICE_ARG(cfree_slice_cstr(a)));
return 1;
}
@@ -847,7 +858,8 @@ static int cc_resolve_pending_libs(CcOptions* o) {
if (driver_lib_resolve_for_os(o->env, pl->name, mode, resolve_os,
o->lib_search_paths, o->nlib_search_paths,
&p, &sz, &kind) != 0) {
- driver_errf(CC_TOOL, "library not found: -l%s", pl->name);
+ driver_errf(CC_TOOL, "library not found: -l%.*s",
+ CFREE_SLICE_ARG(cfree_slice_cstr(pl->name)));
return 1;
}
if (kind == LIB_RESOLVE_KIND_SHARED || kind == LIB_RESOLVE_KIND_TBD) {
@@ -924,7 +936,8 @@ static int cc_apply_hosted_profile(CcOptions* o) {
static int cc_apply_env(CcOptions* o) {
const char* sde = driver_getenv("SOURCE_DATE_EPOCH");
if (sde && cc_parse_u64(sde, &o->epoch) != 0) {
- driver_errf(CC_TOOL, "invalid SOURCE_DATE_EPOCH: %s", sde);
+ driver_errf(CC_TOOL, "invalid SOURCE_DATE_EPOCH: %.*s",
+ CFREE_SLICE_ARG(cfree_slice_cstr(sde)));
return 1;
}
return 0;
@@ -1115,7 +1128,8 @@ static int cc_parse(int argc, char** argv, CcOptions* o) {
}
if (driver_streq(a, "-isysroot") || driver_streq(a, "--sysroot")) {
if (++i >= argc) {
- driver_errf(CC_TOOL, "%s requires an argument", a);
+ driver_errf(CC_TOOL, "%.*s requires an argument",
+ CFREE_SLICE_ARG(cfree_slice_cstr(a)));
return 1;
}
o->sysroot = argv[i];
@@ -1176,7 +1190,8 @@ static int cc_parse(int argc, char** argv, CcOptions* o) {
}
if (driver_streq(a, "-include")) {
if (++i >= argc) {
- driver_errf(CC_TOOL, "%s requires an argument", a);
+ driver_errf(CC_TOOL, "%.*s requires an argument",
+ CFREE_SLICE_ARG(cfree_slice_cstr(a)));
return 1;
}
cc_log_ignored(a);
@@ -1332,7 +1347,8 @@ static int cc_parse(int argc, char** argv, CcOptions* o) {
return 1;
}
if (driver_target_from_triple(argv[i], &o->target) != 0) {
- driver_errf(CC_TOOL, "unrecognized target triple: %s", argv[i]);
+ driver_errf(CC_TOOL, "unrecognized target triple: %.*s",
+ CFREE_SLICE_ARG(cfree_slice_cstr(argv[i])));
return 1;
}
o->target_set = 1;
@@ -1340,7 +1356,8 @@ static int cc_parse(int argc, char** argv, CcOptions* o) {
}
if (driver_strneq(a, "--target=", 9)) {
if (driver_target_from_triple(a + 9, &o->target) != 0) {
- driver_errf(CC_TOOL, "unrecognized target triple: %s", a + 9);
+ driver_errf(CC_TOOL, "unrecognized target triple: %.*s",
+ CFREE_SLICE_ARG(cfree_slice_cstr(a + 9)));
return 1;
}
o->target_set = 1;
@@ -1352,7 +1369,8 @@ static int cc_parse(int argc, char** argv, CcOptions* o) {
return 1;
}
if (driver_target_from_triple(argv[i], &o->target) != 0) {
- driver_errf(CC_TOOL, "unrecognized target triple: %s", argv[i]);
+ driver_errf(CC_TOOL, "unrecognized target triple: %.*s",
+ CFREE_SLICE_ARG(cfree_slice_cstr(argv[i])));
return 1;
}
o->target_set = 1;
@@ -1385,7 +1403,8 @@ static int cc_parse(int argc, char** argv, CcOptions* o) {
continue;
}
{
- driver_errf(CC_TOOL, "unsupported -x language: %s", argv[i]);
+ driver_errf(CC_TOOL, "unsupported -x language: %.*s",
+ CFREE_SLICE_ARG(cfree_slice_cstr(argv[i])));
return 1;
}
}
@@ -1449,7 +1468,8 @@ static int cc_parse(int argc, char** argv, CcOptions* o) {
}
if (driver_streq(a, "-MT") || driver_streq(a, "-MQ")) {
if (++i >= argc) {
- driver_errf(CC_TOOL, "%s requires an argument", a);
+ driver_errf(CC_TOOL, "%.*s requires an argument",
+ CFREE_SLICE_ARG(cfree_slice_cstr(a)));
return 1;
}
o->dep_targets[o->ndep_targets++] = argv[i];
@@ -1467,7 +1487,8 @@ static int cc_parse(int argc, char** argv, CcOptions* o) {
continue;
}
if (a[0] == '-' && a[1] != '\0') {
- driver_errf(CC_TOOL, "unknown flag: %s", a);
+ driver_errf(CC_TOOL, "unknown flag: %.*s",
+ CFREE_SLICE_ARG(cfree_slice_cstr(a)));
return 1;
}
@@ -1568,10 +1589,12 @@ static int cc_parse(int argc, char** argv, CcOptions* o) {
return 0;
}
-/* Borrow the single source as a CfreeBytes. `*loaded` is set nonzero only
+static const char* cc_primary_source_name(const CcOptions* o);
+
+/* Borrow the single source as a CfreeSlice. `*loaded` is set nonzero only
* when the file was opened via file_io and must be released. */
static int cc_load_single_source(const CfreeContext* ctx, const CcOptions* o,
- CfreeBytes* in, CfreeFileData* fd,
+ CfreeSlice* in, CfreeFileData* fd,
int* loaded) {
*loaded = 0;
if (o->nsource_memory == 1) {
@@ -1580,11 +1603,11 @@ static int cc_load_single_source(const CfreeContext* ctx, const CcOptions* o,
}
if (ctx->file_io->read_all(ctx->file_io->user, o->source_files[0], fd) !=
CFREE_OK) {
- driver_errf(CC_TOOL, "failed to read: %s", o->source_files[0]);
+ driver_errf(CC_TOOL, "failed to read: %.*s",
+ CFREE_SLICE_ARG(cfree_slice_cstr(o->source_files[0])));
return 1;
}
*loaded = 1;
- in->name = o->source_files[0];
in->data = fd->data;
in->len = fd->size;
return 0;
@@ -1596,7 +1619,7 @@ static int cc_preprocess(DriverEnv* env, const CcOptions* o,
CfreeCompiler* compiler = NULL;
CfreeWriter* writer = NULL;
CfreeFileData fd = {0};
- CfreeBytes input = {0};
+ CfreeSlice input = {0};
int rc = 1;
int loaded = 0;
@@ -1605,7 +1628,8 @@ static int cc_preprocess(DriverEnv* env, const CcOptions* o,
if (o->output_path) {
if (ctx.file_io->open_writer(ctx.file_io->user, o->output_path, &writer) !=
CFREE_OK) {
- driver_errf(CC_TOOL, "failed to open output: %s", o->output_path);
+ driver_errf(CC_TOOL, "failed to open output: %.*s",
+ CFREE_SLICE_ARG(cfree_slice_cstr(o->output_path)));
goto out;
}
} else {
@@ -1621,7 +1645,9 @@ static int cc_preprocess(DriverEnv* env, const CcOptions* o,
goto out;
}
- rc = cfree_cpp_preprocess(compiler, pp_opts, &input, writer) == CFREE_OK
+ rc = cfree_cpp_preprocess(compiler, pp_opts,
+ cfree_slice_cstr(cc_primary_source_name(o)), &input,
+ writer) == CFREE_OK
? 0
: 1;
@@ -1849,7 +1875,7 @@ static int cc_dep_collect(DriverEnv* env, CfreeCompiler* compiler,
CfreeIterResult r = cfree_dep_iter_next(it, &e);
if (r != CFREE_ITER_ITEM) break;
if (system_filter && e.from_system_path) continue;
- if (cc_dep_list_push(env, list, e.included_name) != 0) {
+ if (cc_dep_list_push(env, list, e.included_name.s) != 0) {
cfree_dep_iter_free(it);
return 1;
}
@@ -1911,7 +1937,7 @@ static CfreeWriter* cc_dep_open_writer(DriverEnv* env, const CfreeContext* ctx,
}
static const char* cc_primary_source_name(const CcOptions* o) {
- if (o->nsource_memory == 1) return o->source_memory[0].bytes.name;
+ if (o->nsource_memory == 1) return o->source_memory[0].name.s;
return o->source_files[0];
}
@@ -1950,8 +1976,9 @@ static int cc_dep_finish(DriverEnv* env, const CfreeContext* ctx,
dep_w = cc_dep_open_writer(env, ctx, o, &owned_path, &owned_size);
if (!dep_w) {
driver_errf(
- CC_TOOL, "failed to open dep output: %s",
- o->dep_file ? o->dep_file : (owned_path ? owned_path : "<stdout>"));
+ CC_TOOL, "failed to open dep output: %.*s",
+ CFREE_SLICE_ARG(cfree_slice_cstr(
+ o->dep_file ? o->dep_file : (owned_path ? owned_path : "<stdout>"))));
goto out;
}
@@ -1988,7 +2015,7 @@ static int cc_run_deps_only(DriverEnv* env, const CcOptions* o,
CfreeCompiler* compiler = NULL;
CfreeWriter* discard = NULL;
CfreeFileData fd = {0};
- CfreeBytes input = {0};
+ CfreeSlice input = {0};
int loaded = 0;
int rc = 1;
@@ -2005,7 +2032,10 @@ static int cc_run_deps_only(DriverEnv* env, const CcOptions* o,
goto out;
}
- if (cfree_cpp_preprocess(compiler, pp, &input, discard) != CFREE_OK) goto out;
+ if (cfree_cpp_preprocess(compiler, pp,
+ cfree_slice_cstr(cc_primary_source_name(o)), &input,
+ discard) != CFREE_OK)
+ goto out;
rc = cc_dep_finish(env, &ctx, compiler, o);
@@ -2019,7 +2049,8 @@ out:
static CfreeStatus cc_compile_source_obj(CfreeCompiler* compiler,
CfreeLanguage lang,
const CfreeCCompileOptions* copts,
- const CfreeBytes* input,
+ CfreeSlice name,
+ const CfreeSlice* input,
CfreeObjBuilder** out) {
CfreeCompileSessionOptions sopts;
CfreeCompileSession* session = NULL;
@@ -2040,6 +2071,7 @@ static CfreeStatus cc_compile_source_obj(CfreeCompiler* compiler,
sopts.compile.language_options = copts;
}
memset(&sin, 0, sizeof(sin));
+ sin.name = name;
sin.bytes = *input;
sin.lang = lang;
st = cfree_compile_session_new(compiler, &sopts, &session);
@@ -2051,10 +2083,12 @@ static CfreeStatus cc_compile_source_obj(CfreeCompiler* compiler,
static CfreeStatus cc_compile_source_emit(CfreeCompiler* compiler,
CfreeLanguage lang,
const CfreeCCompileOptions* copts,
- const CfreeBytes* input,
+ CfreeSlice name,
+ const CfreeSlice* input,
CfreeWriter* out) {
CfreeObjBuilder* ob = NULL;
- CfreeStatus st = cc_compile_source_obj(compiler, lang, copts, input, &ob);
+ CfreeStatus st =
+ cc_compile_source_obj(compiler, lang, copts, name, input, &ob);
if (st == CFREE_OK && !copts->code.emit_c_source)
st = cfree_obj_builder_emit(ob, out);
cfree_obj_builder_free(ob);
@@ -2068,7 +2102,7 @@ static int cc_run_compile_one(DriverEnv* env, const CcOptions* o,
CfreeCompiler* compiler = NULL;
CfreeWriter* obj_w = NULL;
CfreeFileData fd = {0};
- CfreeBytes input = {0};
+ CfreeSlice input = {0};
CfreeCCompileOptions copts;
int loaded = 0;
int rc = 1;
@@ -2078,18 +2112,19 @@ static int cc_run_compile_one(DriverEnv* env, const CcOptions* o,
} else {
if (ctx.file_io->read_all(ctx.file_io->user, o->source_files[index], &fd) !=
CFREE_OK) {
- driver_errf(CC_TOOL, "failed to read: %s", o->source_files[index]);
+ driver_errf(CC_TOOL, "failed to read: %.*s",
+ CFREE_SLICE_ARG(cfree_slice_cstr(o->source_files[index])));
goto out;
}
loaded = 1;
- input.name = o->source_files[index];
input.data = fd.data;
input.len = fd.size;
}
if (ctx.file_io->open_writer(ctx.file_io->user, out_path, &obj_w) !=
CFREE_OK) {
- driver_errf(CC_TOOL, "failed to open output: %s", out_path);
+ driver_errf(CC_TOOL, "failed to open output: %.*s",
+ CFREE_SLICE_ARG(cfree_slice_cstr(out_path)));
goto out;
}
@@ -2111,8 +2146,10 @@ static int cc_run_compile_one(DriverEnv* env, const CcOptions* o,
? o->source_memory[index].lang
: cc_resolve_lang(compiler, o->source_files[index],
o->source_langs[index]);
+ CfreeSlice in_name = is_memory ? o->source_memory[index].name
+ : cfree_slice_cstr(o->source_files[index]);
CfreeStatus st;
- st = cc_compile_source_emit(compiler, lang, &copts, &input, obj_w);
+ st = cc_compile_source_emit(compiler, lang, &copts, in_name, &input, obj_w);
if (st != CFREE_OK) goto out;
}
@@ -2172,10 +2209,10 @@ static int cc_run_link_exe(DriverEnv* env, const CcOptions* o,
DriverLoad* arch_lf = NULL;
DriverLoad script_lf = {0};
DriverLoad* dso_lf = NULL;
- CfreeBytes* src_bytes = NULL;
- CfreeBytes* obj_in = NULL;
+ CfreeSlice* src_bytes = NULL;
+ CfreeSlice* obj_in = NULL;
CfreeLinkArchiveInput* arch_in = NULL;
- CfreeBytes* dso_in = NULL;
+ CfreeSlice* dso_in = NULL;
CfreeLinkInputOrder* order = NULL;
CfreeObjBuilder** objs = NULL;
CfreeLinkScript* script = NULL;
@@ -2263,7 +2300,7 @@ static int cc_run_link_exe(DriverEnv* env, const CcOptions* o,
}
if (o->linker_script) {
- CfreeBytes dummy;
+ CfreeSlice dummy;
if (driver_load_bytes(io, CC_TOOL, o->linker_script, &script_lf, &dummy) !=
0)
goto out;
@@ -2275,8 +2312,9 @@ static int cc_run_link_exe(DriverEnv* env, const CcOptions* o,
}
if (script_lf.loaded) {
- if (cfree_link_script_parse(&ctx, (const char*)script_lf.fd.data,
- script_lf.fd.size, &script) != CFREE_OK)
+ CfreeSlice script_text = {.s = (const char*)script_lf.fd.data,
+ .len = script_lf.fd.size};
+ if (cfree_link_script_parse(&ctx, script_text, &script) != CFREE_OK)
goto out;
}
@@ -2285,29 +2323,43 @@ static int cc_run_link_exe(DriverEnv* env, const CcOptions* o,
CfreeLanguage lang =
cc_resolve_lang(compiler, o->source_files[i], o->source_langs[i]);
CfreeStatus st;
- st = cc_compile_source_obj(compiler, lang, &copts, &src_bytes[i], &objs[i]);
+ st = cc_compile_source_obj(compiler, lang, &copts,
+ cfree_slice_cstr(o->source_files[i]),
+ &src_bytes[i], &objs[i]);
if (st != CFREE_OK) goto out;
}
for (i = 0; i < o->nsource_memory; ++i) {
CfreeStatus st;
st = cc_compile_source_obj(compiler, o->source_memory[i].lang, &copts,
+ o->source_memory[i].name,
&o->source_memory[i].bytes,
&objs[o->nsource_files + i]);
if (st != CFREE_OK) goto out;
}
if (io->open_writer(io->user, o->output_path, &out_w) != CFREE_OK) {
- driver_errf(CC_TOOL, "failed to open output: %s", o->output_path);
+ driver_errf(CC_TOOL, "failed to open output: %.*s",
+ CFREE_SLICE_ARG(cfree_slice_cstr(o->output_path)));
goto out;
}
{
CfreeLinkSessionOptions lopts;
CfreeStatus st;
+ CfreeSlice* rpath_slices = NULL;
+ if (o->nrpaths) {
+ rpath_slices = driver_alloc_zeroed(env, o->nrpaths * sizeof(*rpath_slices));
+ if (!rpath_slices) {
+ driver_errf(CC_TOOL, "out of memory");
+ goto out;
+ }
+ for (i = 0; i < o->nrpaths; ++i)
+ rpath_slices[i] = cfree_slice_cstr(o->rpaths[i]);
+ }
memset(&lopts, 0, sizeof(lopts));
lopts.output_kind =
o->shared ? CFREE_LINK_OUTPUT_SHARED : CFREE_LINK_OUTPUT_EXE;
- lopts.entry = o->entry;
+ lopts.entry = cfree_slice_cstr(o->entry);
lopts.linker_script = script;
lopts.build_id_mode = o->build_id_mode;
lopts.build_id_bytes = o->build_id_bytes;
@@ -2315,13 +2367,13 @@ static int cc_run_link_exe(DriverEnv* env, const CcOptions* o,
lopts.gc_sections = o->gc_sections;
lopts.pie = o->pie;
lopts.pe_subsystem = o->pe_subsystem;
- lopts.interp_path = o->interp_path;
- lopts.soname = o->soname;
+ lopts.interp_path = cfree_slice_cstr(o->interp_path);
+ lopts.soname = cfree_slice_cstr(o->soname);
if (o->new_dtags) {
- lopts.runpaths = o->rpaths;
+ lopts.runpaths = rpath_slices;
lopts.nrunpaths = o->nrpaths;
} else {
- lopts.rpaths = o->rpaths;
+ lopts.rpaths = rpath_slices;
lopts.nrpaths = o->nrpaths;
}
lopts.allow_undefined = 1;
@@ -2340,20 +2392,25 @@ static int cc_run_link_exe(DriverEnv* env, const CcOptions* o,
link, objs[o->nsource_files + item->index]);
break;
case CC_LINK_OBJECT:
- st = cfree_link_session_add_obj_bytes(link, &obj_in[item->index]);
+ st = cfree_link_session_add_obj_bytes(
+ link, cfree_slice_cstr(o->object_files[item->index]),
+ &obj_in[item->index]);
break;
case CC_LINK_ARCHIVE:
st = cfree_link_session_add_archive_bytes(link,
&arch_in[item->index]);
break;
case CC_LINK_DSO:
- st = cfree_link_session_add_dso_bytes(link, &dso_in[item->index]);
+ st = cfree_link_session_add_dso_bytes(
+ link, cfree_slice_cstr(o->dsos[item->index].path),
+ &dso_in[item->index]);
break;
case CC_LINK_LIB: {
const CcPendingLib* pl = &o->pending_libs[item->index];
if (pl->resolved_kind == CC_LINK_DSO) {
st = cfree_link_session_add_dso_bytes(
- link, &dso_in[pl->resolved_index]);
+ link, cfree_slice_cstr(o->dsos[pl->resolved_index].path),
+ &dso_in[pl->resolved_index]);
} else {
st = cfree_link_session_add_archive_bytes(
link, &arch_in[pl->resolved_index]);
@@ -2366,11 +2423,13 @@ static int cc_run_link_exe(DriverEnv* env, const CcOptions* o,
for (i = 0; i < nsrc && st == CFREE_OK; ++i)
st = cfree_link_session_add_obj(link, objs[i]);
for (i = 0; i < o->nobject_files && st == CFREE_OK; ++i)
- st = cfree_link_session_add_obj_bytes(link, &obj_in[i]);
+ st = cfree_link_session_add_obj_bytes(
+ link, cfree_slice_cstr(o->object_files[i]), &obj_in[i]);
for (i = 0; i < o->narchives && st == CFREE_OK; ++i)
st = cfree_link_session_add_archive_bytes(link, &arch_in[i]);
for (i = 0; i < o->ndsos && st == CFREE_OK; ++i)
- st = cfree_link_session_add_dso_bytes(link, &dso_in[i]);
+ st = cfree_link_session_add_dso_bytes(
+ link, cfree_slice_cstr(o->dsos[i].path), &dso_in[i]);
}
if (st == CFREE_OK) st = cfree_link_session_emit(link, out_w);
rc = st == CFREE_OK ? 0 : 1;
@@ -2381,7 +2440,8 @@ out:
cfree_link_session_free(link);
if (rc == 0 && o->output_path) {
if (driver_mark_executable_output(o->output_path) != 0) {
- driver_errf(CC_TOOL, "failed to set executable mode: %s", o->output_path);
+ driver_errf(CC_TOOL, "failed to set executable mode: %.*s",
+ CFREE_SLICE_ARG(cfree_slice_cstr(o->output_path)));
rc = 1;
}
}
diff --git a/driver/cflags.c b/driver/cflags.c
@@ -62,11 +62,11 @@ static int cflags_record_define(DriverCflags* cf, DriverEnv* env,
name[n] = '\0';
cf->_owned_define_names[cf->ndefines] = name;
cf->_owned_define_name_sizes[cf->ndefines] = bytes;
- d->name = name;
- d->body = eq + 1;
+ d->name = (CfreeSlice){ .s = name, .len = n };
+ d->body = cfree_slice_cstr(eq + 1);
} else {
- d->name = arg;
- d->body = NULL;
+ d->name = cfree_slice_cstr(arg);
+ d->body = CFREE_SLICE_NULL;
}
cf->ndefines++;
return 0;
@@ -84,7 +84,8 @@ static const char* cflags_pull_value(const char* tool, int argc, char** argv,
const char* a = argv[*i];
if (a[prefix_len]) return a + prefix_len;
if (++(*i) >= argc) {
- driver_errf(tool, "%s requires an argument", flag_label);
+ driver_errf(tool, "%.*s requires an argument",
+ CFREE_SLICE_ARG(cfree_slice_cstr(flag_label)));
return NULL;
}
return argv[*i];
@@ -138,7 +139,7 @@ int driver_cflags_try_consume(DriverCflags* cf, DriverEnv* env,
if (driver_strneq(a, "-U", 2)) {
const char* arg = cflags_pull_value(tool, argc, argv, i, 2, "-U");
if (!arg) return -1;
- cf->undefines[cf->nundefines++] = arg;
+ cf->undefines[cf->nundefines++] = cfree_slice_cstr(arg);
return 1;
}
diff --git a/driver/cflags.h b/driver/cflags.h
@@ -33,7 +33,7 @@ typedef struct DriverCflags {
uint32_t nsystem_include_dirs;
CfreeDefine* defines;
uint32_t ndefines;
- const char** undefines;
+ CfreeSlice* undefines;
uint32_t nundefines;
/* Internal storage for the names of `-Dname=body` defines we had to
diff --git a/driver/cpp.c b/driver/cpp.c
@@ -35,7 +35,8 @@ typedef struct CppOptions {
void driver_help_cpp(void) {
driver_printf(
- "%s",
+ "%.*s",
+ CFREE_SLICE_ARG(CFREE_SLICE_LIT(
"cfree cpp — standalone C preprocessor\n"
"\n"
"USAGE\n"
@@ -60,13 +61,14 @@ void driver_help_cpp(void) {
"\n"
"EXIT CODES\n"
" 0 success 1 preprocess / I/O error 2 bad "
- "usage\n");
+ "usage\n")));
}
static void cpp_usage(void) {
- driver_errf(CPP_TOOL, "%s",
+ driver_errf(CPP_TOOL, "%.*s",
+ CFREE_SLICE_ARG(CFREE_SLICE_LIT(
"usage: cfree cpp [options] INPUT.c\n"
- " cfree cpp --help for full option reference");
+ " cfree cpp --help for full option reference")));
}
static int cpp_parse(int argc, char** argv, CppOptions* o, DriverEnv* env,
@@ -98,7 +100,8 @@ static int cpp_parse(int argc, char** argv, CppOptions* o, DriverEnv* env,
return 1;
}
if (driver_target_from_triple(argv[i], &o->target) != 0) {
- driver_errf(CPP_TOOL, "unrecognized target: %s", argv[i]);
+ driver_errf(CPP_TOOL, "unrecognized target: %.*s",
+ CFREE_SLICE_ARG(cfree_slice_cstr(argv[i])));
return 1;
}
continue;
@@ -114,7 +117,8 @@ static int cpp_parse(int argc, char** argv, CppOptions* o, DriverEnv* env,
}
if (a[0] == '-' && a[1] != '\0') {
- driver_errf(CPP_TOOL, "unknown flag: %s", a);
+ driver_errf(CPP_TOOL, "unknown flag: %.*s",
+ CFREE_SLICE_ARG(cfree_slice_cstr(a)));
return 1;
}
@@ -142,7 +146,8 @@ int driver_cpp(int argc, char** argv) {
CfreeCompiler* compiler = NULL;
CfreeWriter* writer = NULL;
CfreeFileData src = {0};
- CfreeBytes input;
+ CfreeSlice input;
+ CfreeSlice input_name = CFREE_SLICE_NULL;
uint8_t* stdin_buf = NULL;
size_t stdin_size = 0;
int rc = 1;
@@ -175,17 +180,18 @@ int driver_cpp(int argc, char** argv) {
driver_errf(CPP_TOOL, "failed to read stdin");
goto out;
}
- input.name = "<stdin>";
+ input_name = CFREE_SLICE_LIT("<stdin>");
input.data = stdin_buf;
input.len = stdin_size;
} else {
if (ctx.file_io->read_all(ctx.file_io->user, o.source_path, &src) !=
CFREE_OK) {
- driver_errf(CPP_TOOL, "failed to read: %s", o.source_path);
+ driver_errf(CPP_TOOL, "failed to read: %.*s",
+ CFREE_SLICE_ARG(cfree_slice_cstr(o.source_path)));
goto out;
}
loaded = 1;
- input.name = o.source_path;
+ input_name = cfree_slice_cstr(o.source_path);
input.data = src.data;
input.len = src.size;
}
@@ -193,7 +199,8 @@ int driver_cpp(int argc, char** argv) {
if (o.output_path) {
if (ctx.file_io->open_writer(ctx.file_io->user, o.output_path, &writer) !=
CFREE_OK) {
- driver_errf(CPP_TOOL, "failed to open output: %s", o.output_path);
+ driver_errf(CPP_TOOL, "failed to open output: %.*s",
+ CFREE_SLICE_ARG(cfree_slice_cstr(o.output_path)));
goto out;
}
} else {
@@ -210,7 +217,10 @@ int driver_cpp(int argc, char** argv) {
}
rc =
- cfree_cpp_preprocess(compiler, &pp, &input, writer) == CFREE_OK ? 0 : 1;
+ cfree_cpp_preprocess(compiler, &pp, input_name, &input, writer) ==
+ CFREE_OK
+ ? 0
+ : 1;
out:
if (compiler) driver_compiler_free(compiler);
diff --git a/driver/dbg.c b/driver/dbg.c
@@ -66,7 +66,8 @@ typedef struct DbgOpts {
void driver_help_dbg(void) {
driver_printf(
- "%s",
+ "%.*s",
+ CFREE_SLICE_ARG(CFREE_SLICE_LIT(
"cfree dbg — interactive JIT debugger\n"
"\n"
"USAGE\n"
@@ -139,7 +140,7 @@ void driver_help_dbg(void) {
"\n"
"EXIT CODES\n"
" 0 clean exit 1 compile/link or session error 2 bad "
- "usage\n");
+ "usage\n")));
}
static int dbg_alloc_arrays(DbgOpts* o, int argc) {
@@ -182,7 +183,8 @@ static int dbg_parse_language_name(const char* name, CfreeLanguage* out) {
static int dbg_set_default_language(DbgOpts* o, const char* name) {
CfreeLanguage lang = CFREE_LANG_COUNT;
if (!dbg_parse_language_name(name, &lang)) {
- driver_errf(DBG_TOOL, "unsupported language: %s", name ? name : "");
+ driver_errf(DBG_TOOL, "unsupported language: %.*s",
+ CFREE_SLICE_ARG(cfree_slice_cstr(name)));
return 1;
}
o->default_lang = lang;
@@ -243,7 +245,8 @@ static int dbg_parse(int argc, char** argv, DbgOpts* o) {
if (driver_streq(a, "-x") || driver_streq(a, "--language") ||
driver_streq(a, "--lang")) {
if (++i >= argc) {
- driver_errf(DBG_TOOL, "%s requires an argument", a);
+ driver_errf(DBG_TOOL, "%.*s requires an argument",
+ CFREE_SLICE_ARG(cfree_slice_cstr(a)));
return 1;
}
if (dbg_set_default_language(o, argv[i]) != 0) return 1;
@@ -259,7 +262,8 @@ static int dbg_parse(int argc, char** argv, DbgOpts* o) {
}
if (a[0] == '-' && a[1] != '\0') {
- driver_errf(DBG_TOOL, "unknown flag: %s", a);
+ driver_errf(DBG_TOOL, "unknown flag: %.*s",
+ CFREE_SLICE_ARG(cfree_slice_cstr(a)));
return 1;
}
@@ -267,7 +271,8 @@ static int dbg_parse(int argc, char** argv, DbgOpts* o) {
int r = driver_inputs_classify(&o->inputs, a);
if (r < 0) return 1;
if (r == 0) {
- driver_errf(DBG_TOOL, "input does not have a recognized suffix: %s", a);
+ driver_errf(DBG_TOOL, "input does not have a recognized suffix: %.*s",
+ CFREE_SLICE_ARG(cfree_slice_cstr(a)));
return 1;
}
}
@@ -599,7 +604,8 @@ static int dbg_resolve_loc(DbgState* s, const char* spec, BpKind* kind_out,
uint64_t pc;
if (file_n == 0) {
- driver_errf(DBG_TOOL, "empty file in '%s'", spec);
+ driver_errf(DBG_TOOL, "empty file in '%.*s'",
+ CFREE_SLICE_ARG(cfree_slice_cstr(spec)));
return 1;
}
file = dbg_dup(s->env, spec, file_n, &file_size);
@@ -609,20 +615,23 @@ static int dbg_resolve_loc(DbgState* s, const char* spec, BpKind* kind_out,
}
used = dbg_parse_uint(colon + 1, &line64);
if (!used || colon[1 + used] != '\0') {
- driver_errf(DBG_TOOL, "expected file.c:LINE, got '%s'", spec);
+ driver_errf(DBG_TOOL, "expected file.c:LINE, got '%.*s'",
+ CFREE_SLICE_ARG(cfree_slice_cstr(spec)));
driver_free(s->env, file, file_size);
return 1;
}
if (!s->dwarf) {
- driver_errf(DBG_TOOL, "no DWARF: cannot resolve %s", spec);
+ driver_errf(DBG_TOOL, "no DWARF: cannot resolve %.*s",
+ CFREE_SLICE_ARG(cfree_slice_cstr(spec)));
driver_free(s->env, file, file_size);
return 1;
}
{
- CfreeStatus rc =
- cfree_dwarf_line_to_addr(s->dwarf, file, (uint32_t)line64, &pc);
+ CfreeStatus rc = cfree_dwarf_line_to_addr(
+ s->dwarf, cfree_slice_cstr(file), (uint32_t)line64, &pc);
if (rc == CFREE_NOT_FOUND) {
- driver_errf(DBG_TOOL, "no line %u in %s", (uint32_t)line64, file);
+ driver_errf(DBG_TOOL, "no line %u in %.*s", (uint32_t)line64,
+ CFREE_SLICE_ARG(cfree_slice_cstr(file)));
driver_free(s->env, file, file_size);
return 1;
}
@@ -630,22 +639,25 @@ static int dbg_resolve_loc(DbgState* s, const char* spec, BpKind* kind_out,
CfreeDwarfLineMatch cands[8];
uint32_t n = 0;
uint32_t k;
- cfree_dwarf_line_to_addr_all(s->dwarf, file, (uint32_t)line64, cands,
- 8u, &n);
- driver_errf(DBG_TOOL, "ambiguous: %s:%u matches %u files", file,
- (uint32_t)line64, (unsigned)n);
+ cfree_dwarf_line_to_addr_all(s->dwarf, cfree_slice_cstr(file),
+ (uint32_t)line64, cands, 8u, &n);
+ driver_errf(DBG_TOOL, "ambiguous: %.*s:%u matches %u files",
+ CFREE_SLICE_ARG(cfree_slice_cstr(file)), (uint32_t)line64,
+ (unsigned)n);
for (k = 0; k < n && k < 8u; ++k) {
- driver_errf(DBG_TOOL, " %s (0x%llx)", cands[k].file,
+ driver_errf(DBG_TOOL, " %.*s (0x%llx)",
+ CFREE_SLICE_ARG(cands[k].file),
(unsigned long long)cands[k].pc);
}
if (n > 8u) driver_errf(DBG_TOOL, " ... and %u more", n - 8u);
- driver_errf(DBG_TOOL, "use a longer path suffix (e.g. b dir/%s:%u)",
- file, (uint32_t)line64);
+ driver_errf(DBG_TOOL, "use a longer path suffix (e.g. b dir/%.*s:%u)",
+ CFREE_SLICE_ARG(cfree_slice_cstr(file)), (uint32_t)line64);
driver_free(s->env, file, file_size);
return 1;
}
if (rc != CFREE_OK) {
- driver_errf(DBG_TOOL, "no line entry for %s", spec);
+ driver_errf(DBG_TOOL, "no line entry for %.*s",
+ CFREE_SLICE_ARG(cfree_slice_cstr(spec)));
driver_free(s->env, file, file_size);
return 1;
}
@@ -662,7 +674,8 @@ static int dbg_resolve_loc(DbgState* s, const char* spec, BpKind* kind_out,
uint64_t v;
size_t used = dbg_parse_uint(spec, &v);
if (!used || spec[used] != '\0') {
- driver_errf(DBG_TOOL, "trailing junk in address '%s'", spec);
+ driver_errf(DBG_TOOL, "trailing junk in address '%.*s'",
+ CFREE_SLICE_ARG(cfree_slice_cstr(spec)));
return 1;
}
*kind_out = BP_ADDR;
@@ -680,7 +693,8 @@ static int dbg_resolve_loc(DbgState* s, const char* spec, BpKind* kind_out,
uint64_t off = 0;
if (name_n == 0) {
- driver_errf(DBG_TOOL, "empty symbol in '%s'", spec);
+ driver_errf(DBG_TOOL, "empty symbol in '%.*s'",
+ CFREE_SLICE_ARG(cfree_slice_cstr(spec)));
return 1;
}
name = dbg_dup(s->env, spec, name_n, &name_size);
@@ -688,9 +702,10 @@ static int dbg_resolve_loc(DbgState* s, const char* spec, BpKind* kind_out,
driver_errf(DBG_TOOL, "out of memory");
return 1;
}
- resolved = cfree_jit_lookup(s->jit, name);
+ resolved = cfree_jit_lookup(s->jit, cfree_slice_cstr(name));
if (!resolved) {
- driver_errf(DBG_TOOL, "symbol not found: %s", name);
+ driver_errf(DBG_TOOL, "symbol not found: %.*s",
+ CFREE_SLICE_ARG(cfree_slice_cstr(name)));
driver_free(s->env, name, name_size);
return 1;
}
@@ -699,7 +714,8 @@ static int dbg_resolve_loc(DbgState* s, const char* spec, BpKind* kind_out,
if (plus) {
size_t used = dbg_parse_uint(plus + 1, &off);
if (!used || plus[1 + used] != '\0') {
- driver_errf(DBG_TOOL, "bad offset in '%s'", spec);
+ driver_errf(DBG_TOOL, "bad offset in '%.*s'",
+ CFREE_SLICE_ARG(cfree_slice_cstr(spec)));
return 1;
}
}
@@ -725,24 +741,25 @@ static int dbg_resolve_loc(DbgState* s, const char* spec, BpKind* kind_out,
* ============================================================ */
static void dbg_print_pc(DbgState* s, uint64_t pc) {
- const char* sym = NULL;
+ CfreeSlice sym = CFREE_SLICE_NULL;
uint64_t off = 0;
- const char* file = NULL;
+ CfreeSlice file = CFREE_SLICE_NULL;
uint32_t line = 0;
uint32_t col = 0;
driver_printf("0x%llx", (unsigned long long)pc);
- if (cfree_jit_addr_to_sym(s->jit, pc, &sym, &off) == CFREE_OK && sym) {
+ if (cfree_jit_addr_to_sym(s->jit, pc, &sym, &off) == CFREE_OK && sym.s) {
if (off)
- driver_printf(" <%s+0x%llx>", sym, (unsigned long long)off);
+ driver_printf(" <%.*s+0x%llx>", CFREE_SLICE_ARG(sym),
+ (unsigned long long)off);
else
- driver_printf(" <%s>", sym);
+ driver_printf(" <%.*s>", CFREE_SLICE_ARG(sym));
}
if (s->dwarf &&
cfree_dwarf_addr_to_line(s->dwarf, dbg_pc_rt_to_img(s, pc), &file, &line,
&col) == CFREE_OK &&
- file) {
- driver_printf(" at %s:%u", file, line);
+ file.s) {
+ driver_printf(" at %.*s:%u", CFREE_SLICE_ARG(file), line);
if (col) driver_printf(":%u", col);
}
}
@@ -759,7 +776,8 @@ static void dbg_render_stop(DbgState* s, const CfreeStopInfo* st) {
}
}
if (b)
- driver_printf("Breakpoint %d (%s) hit at ", b->id, b->spec);
+ driver_printf("Breakpoint %d (%.*s) hit at ", b->id,
+ CFREE_SLICE_ARG(cfree_slice_cstr(b->spec)));
else
driver_printf("Breakpoint hit at ");
dbg_print_pc(s, st->regs.pc);
@@ -819,9 +837,10 @@ static int dbg_drive(DbgState* s, DbgRunMode mode) {
driver_errf(DBG_TOOL, "no entry symbol configured");
return 1;
}
- s->entry_addr = cfree_jit_lookup(s->jit, s->entry_name);
+ s->entry_addr = cfree_jit_lookup(s->jit, cfree_slice_cstr(s->entry_name));
if (!s->entry_addr) {
- driver_errf(DBG_TOOL, "entry symbol not found: %s", s->entry_name);
+ driver_errf(DBG_TOOL, "entry symbol not found: %.*s",
+ CFREE_SLICE_ARG(cfree_slice_cstr(s->entry_name)));
return 1;
}
}
@@ -862,9 +881,11 @@ static int dbg_drive(DbgState* s, DbgRunMode mode) {
if (rc != CFREE_OK) {
driver_errf(DBG_TOOL,
- "session %s failed (st=%d) — "
+ "session %.*s failed (st=%d) — "
"JIT session implementation pending",
- mode == RUN_FRESH ? "call" : "resume", (int)rc);
+ CFREE_SLICE_ARG(cfree_slice_cstr(mode == RUN_FRESH ? "call"
+ : "resume")),
+ (int)rc);
return 1;
}
@@ -917,25 +938,28 @@ static void dbg_cmd_bt(DbgState* s) {
driver_printf("0x%llx", (unsigned long long)frame.pc);
{
- const char* sym = NULL;
+ CfreeSlice sym = CFREE_SLICE_NULL;
uint64_t off = 0;
if (cfree_jit_addr_to_sym(s->jit, frame.pc, &sym, &off) == CFREE_OK &&
- sym) {
+ sym.s) {
if (off)
- driver_printf(" <%s+0x%llx>", sym, (unsigned long long)off);
+ driver_printf(" <%.*s+0x%llx>", CFREE_SLICE_ARG(sym),
+ (unsigned long long)off);
else
- driver_printf(" <%s>", sym);
+ driver_printf(" <%.*s>", CFREE_SLICE_ARG(sym));
}
}
img_frame = dbg_frame_for_dwarf(s, &frame);
have_sp =
(cfree_dwarf_subprogram_at(s->dwarf, img_frame.pc, &sp) == CFREE_OK);
- if (have_sp && sp.name) {
+ if (have_sp && sp.name.s) {
CfreeDwarfParamIter* it = NULL;
CfreeDwarfVar p;
int first = 1;
- driver_printf(" in %s%s (", sp.name, sp.inlined ? " [inlined]" : "");
+ driver_printf(" in %.*s%.*s (", CFREE_SLICE_ARG(sp.name),
+ CFREE_SLICE_ARG(sp.inlined ? CFREE_SLICE_LIT(" [inlined]")
+ : CFREE_SLICE_NULL));
if (cfree_dwarf_param_iter_new(s->dwarf, img_frame.pc, &it) == CFREE_OK) {
for (;;) {
CfreeIterResult r;
@@ -946,7 +970,8 @@ static void dbg_cmd_bt(DbgState* s) {
r = cfree_dwarf_param_iter_next(it, &p);
if (r != CFREE_ITER_ITEM) break;
if (!first) driver_printf(", ");
- driver_printf("%s=", p.name ? p.name : "?");
+ driver_printf("%.*s=", CFREE_SLICE_ARG(p.name.s ? p.name
+ : CFREE_SLICE_LIT("?")));
dbg_translate_loc(s, &p.loc);
if (dbg_read_value(s, &p.loc, &frame, stack_buf, sizeof(stack_buf),
&buf, &alloc, &got) == 0) {
@@ -963,13 +988,13 @@ static void dbg_cmd_bt(DbgState* s) {
}
{
- const char* file = NULL;
+ CfreeSlice file = CFREE_SLICE_NULL;
uint32_t line = 0;
uint32_t col = 0;
CfreeStatus rc =
cfree_dwarf_addr_to_line(s->dwarf, img_frame.pc, &file, &line, &col);
- if (rc == CFREE_OK && file) {
- driver_printf(" at %s:%u", file, line);
+ if (rc == CFREE_OK && file.s) {
+ driver_printf(" at %.*s:%u", CFREE_SLICE_ARG(file), line);
if (col) driver_printf(":%u", col);
} else if (rc == CFREE_NOT_FOUND) {
driver_printf(" [no debug info for this frame]");
@@ -1095,7 +1120,7 @@ static void dbg_print_value(DbgState* s, const CfreeDwarfType* type,
int64_t v = dbg_load_le_s(buf, got);
CfreeDwarfEnumIter* it = NULL;
CfreeDwarfEnumVal ev;
- const char* match = NULL;
+ CfreeSlice match = CFREE_SLICE_NULL;
if (cfree_dwarf_enum_iter_new(s->dwarf, type, &it) == CFREE_OK) {
for (;;) {
CfreeIterResult r = cfree_dwarf_enum_iter_next(it, &ev);
@@ -1107,8 +1132,8 @@ static void dbg_print_value(DbgState* s, const CfreeDwarfType* type,
}
cfree_dwarf_enum_iter_free(it);
}
- if (match)
- driver_printf("%s (%lld)", match, (long long)v);
+ if (match.s)
+ driver_printf("%.*s (%lld)", CFREE_SLICE_ARG(match), (long long)v);
else
driver_printf("%lld", (long long)v);
return;
@@ -1153,7 +1178,9 @@ static void dbg_print_value(DbgState* s, const CfreeDwarfType* type,
if (r != CFREE_ITER_ITEM) break;
size_t fsz = 0;
dbg_indent(depth + 1);
- driver_printf(".%s = ", (f.name && *f.name) ? f.name : "<anon>");
+ driver_printf(".%.*s = ",
+ CFREE_SLICE_ARG(f.name.len ? f.name
+ : CFREE_SLICE_LIT("<anon>")));
if (f.bit_size) {
/* Bitfield: read up to 8 bytes spanning the storage
* unit at byte_offset, shift, mask. */
@@ -1256,16 +1283,17 @@ static void dbg_cmd_print(DbgState* s, const char* name) {
CfreeStatus rc =
s->dwarf ? cfree_dwarf_var_at(s->dwarf,
dbg_pc_rt_to_img(s, s->last_stop.regs.pc),
- name, &loc)
+ cfree_slice_cstr(name), &loc)
: CFREE_NOT_FOUND;
if (rc == CFREE_OK) {
dbg_translate_loc(s, &loc);
if (dbg_read_value(s, &loc, &s->last_stop.regs, stack_buf,
sizeof(stack_buf), &buf, &alloc, &got) != 0) {
- driver_errf(DBG_TOOL, "could not read %s", name);
+ driver_errf(DBG_TOOL, "could not read %.*s",
+ CFREE_SLICE_ARG(cfree_slice_cstr(name)));
return;
}
- driver_printf("%s = ", name);
+ driver_printf("%.*s = ", CFREE_SLICE_ARG(cfree_slice_cstr(name)));
dbg_print_value(s, loc.type, buf, got, 0);
driver_printf("\n");
dbg_release_value_buf(s, buf, alloc);
@@ -1274,19 +1302,21 @@ static void dbg_cmd_print(DbgState* s, const char* name) {
/* DWARF didn't know about it — try a global symbol. */
{
- void* p = cfree_jit_lookup(s->jit, name);
+ void* p = cfree_jit_lookup(s->jit, cfree_slice_cstr(name));
if (p) {
union {
void* p;
uint64_t u;
} cv;
cv.p = p;
- driver_printf("%s = 0x%llx (no DWARF type info)\n", name,
+ driver_printf("%.*s = 0x%llx (no DWARF type info)\n",
+ CFREE_SLICE_ARG(cfree_slice_cstr(name)),
(unsigned long long)cv.u);
return;
}
}
- driver_errf(DBG_TOOL, "no variable or symbol named '%s'", name);
+ driver_errf(DBG_TOOL, "no variable or symbol named '%.*s'",
+ CFREE_SLICE_ARG(cfree_slice_cstr(name)));
}
}
@@ -1312,10 +1342,11 @@ static void dbg_cmd_set(DbgState* s, const char* name, uint64_t value) {
CfreeStatus rc =
s->dwarf ? cfree_dwarf_var_at(s->dwarf,
dbg_pc_rt_to_img(s, s->last_stop.regs.pc),
- name, &loc)
+ cfree_slice_cstr(name), &loc)
: CFREE_NOT_FOUND;
if (rc != CFREE_OK) {
- driver_errf(DBG_TOOL, "no variable named '%s'", name);
+ driver_errf(DBG_TOOL, "no variable named '%.*s'",
+ CFREE_SLICE_ARG(cfree_slice_cstr(name)));
return;
}
}
@@ -1355,8 +1386,8 @@ static void dbg_cmd_set(DbgState* s, const char* name, uint64_t value) {
return;
}
case CFREE_DLOC_EXPR:
- driver_errf(DBG_TOOL, "cannot set '%s': location is a DWARF expression",
- name);
+ driver_errf(DBG_TOOL, "cannot set '%.*s': location is a DWARF expression",
+ CFREE_SLICE_ARG(cfree_slice_cstr(name)));
return;
}
}
@@ -1398,14 +1429,15 @@ static void dbg_cmd_info_vars(DbgState* s, uint32_t mask, const char* label) {
return;
}
if (!s->dwarf) {
- driver_errf(DBG_TOOL, "no DWARF: %s unavailable", label);
+ driver_errf(DBG_TOOL, "no DWARF: %.*s unavailable",
+ CFREE_SLICE_ARG(cfree_slice_cstr(label)));
return;
}
if (cfree_dwarf_vars_at_new(s->dwarf,
dbg_pc_rt_to_img(s, s->last_stop.regs.pc), mask,
&it) != CFREE_OK) {
- driver_printf("No %s.\n", label);
+ driver_printf("No %.*s.\n", CFREE_SLICE_ARG(cfree_slice_cstr(label)));
return;
}
for (;;) {
@@ -1419,16 +1451,17 @@ static void dbg_cmd_info_vars(DbgState* s, uint32_t mask, const char* label) {
dbg_translate_loc(s, &v.loc);
if (dbg_read_value(s, &v.loc, &s->last_stop.regs, stack_buf,
sizeof(stack_buf), &buf, &alloc, &got) != 0) {
- driver_printf(" %s = <unreadable>\n", v.name);
+ driver_printf(" %.*s = <unreadable>\n", CFREE_SLICE_ARG(v.name));
continue;
}
- driver_printf(" %s = ", v.name);
+ driver_printf(" %.*s = ", CFREE_SLICE_ARG(v.name));
dbg_print_value(s, v.loc.type, buf, got, 1);
driver_printf("\n");
dbg_release_value_buf(s, buf, alloc);
}
cfree_dwarf_vars_at_free(it);
- if (!printed) driver_printf("No %s.\n", label);
+ if (!printed)
+ driver_printf("No %.*s.\n", CFREE_SLICE_ARG(cfree_slice_cstr(label)));
}
static void dbg_cmd_info_reg(DbgState* s) {
@@ -1451,7 +1484,7 @@ static void dbg_cmd_info_reg(DbgState* s) {
CfreeArchReg r;
if (cfree_arch_register_at(arch, i, &r) != CFREE_OK) continue;
if (r.dwarf_idx >= 32) continue; /* outside CfreeUnwindFrame.regs */
- driver_printf("%-6s 0x%016llx\n", r.name,
+ driver_printf("%-6.*s 0x%016llx\n", CFREE_SLICE_ARG(r.name),
(unsigned long long)s->last_stop.regs.regs[r.dwarf_idx]);
}
}
@@ -1495,8 +1528,9 @@ static void dbg_cmd_info_syms(DbgState* s, CfreeSymKind want,
CfreeIterResult r = cfree_jit_sym_iter_next(it, &sym);
if (r != CFREE_ITER_ITEM) break;
if (sym.kind != want) continue;
- if (pattern && !dbg_glob(pattern, sym.name)) continue;
- driver_printf("0x%016llx %s\n", (unsigned long long)sym.addr, sym.name);
+ if (pattern && !dbg_glob(pattern, sym.name.s)) continue;
+ driver_printf("0x%016llx %.*s\n", (unsigned long long)sym.addr,
+ CFREE_SLICE_ARG(sym.name));
printed = 1;
}
cfree_jit_sym_iter_free(it);
@@ -1660,12 +1694,13 @@ static int dbg_jit_compile_append_ex(DbgState* s, CfreeLanguage lang,
s->jit_counter++;
memset(&sin, 0, sizeof(sin));
- sin.bytes.name = input_name ? input_name : dbg_jit_default_name(lang);
+ sin.name = cfree_slice_cstr(input_name ? input_name
+ : dbg_jit_default_name(lang));
sin.bytes.data = (const uint8_t*)src;
sin.bytes.len = len;
sin.lang = lang;
sin.input_kind = input_kind;
- sin.repl_entry_name = repl_entry_name;
+ sin.repl_entry_name = cfree_slice_cstr(repl_entry_name);
st = dbg_compile_session_for(s, lang, &session);
if (st == CFREE_OK) st = cfree_compile_session_compile(session, &sin, &ob);
if (st != CFREE_OK || !ob) {
@@ -1691,9 +1726,9 @@ static int dbg_jit_compile_append_ex(DbgState* s, CfreeLanguage lang,
return 1;
}
dbg_refresh_dwarf(s);
- driver_printf("JIT generation %llu (%s)\n",
+ driver_printf("JIT generation %llu (%.*s)\n",
(unsigned long long)cfree_jit_generation(s->jit),
- dbg_jit_language_name(lang));
+ CFREE_SLICE_ARG(cfree_slice_cstr(dbg_jit_language_name(lang))));
return 0;
}
@@ -1834,15 +1869,21 @@ static void dbg_cmd_language(DbgState* s, const char* rest) {
while (p[n] && !dbg_isspace((unsigned char)p[n])) ++n;
if (n == 0) {
const CfreePreprocessOptions* pp = &s->copts.preprocess;
- driver_printf("Language: %s\n", dbg_jit_language_name(s->default_jit_lang));
+ driver_printf("Language: %.*s\n",
+ CFREE_SLICE_ARG(cfree_slice_cstr(
+ dbg_jit_language_name(s->default_jit_lang))));
driver_printf(
- "Language options: input=%s opt=-O%d debug=%s includes=%u "
- "system-includes=%u defines=%u undefines=%u session=%s\n",
- s->default_jit_name ? s->default_jit_name : "", s->copts.code.opt_level,
- s->copts.code.debug_info ? "on" : "off", (unsigned)pp->ninclude_dirs,
- (unsigned)pp->nsystem_include_dirs, (unsigned)pp->ndefines,
- (unsigned)pp->nundefines,
- s->compile_sessions[s->default_jit_lang] ? "cached" : "not-created");
+ "Language options: input=%.*s opt=-O%d debug=%.*s includes=%u "
+ "system-includes=%u defines=%u undefines=%u session=%.*s\n",
+ CFREE_SLICE_ARG(cfree_slice_cstr(s->default_jit_name)),
+ s->copts.code.opt_level,
+ CFREE_SLICE_ARG(
+ cfree_slice_cstr(s->copts.code.debug_info ? "on" : "off")),
+ (unsigned)pp->ninclude_dirs, (unsigned)pp->nsystem_include_dirs,
+ (unsigned)pp->ndefines, (unsigned)pp->nundefines,
+ CFREE_SLICE_ARG(cfree_slice_cstr(
+ s->compile_sessions[s->default_jit_lang] ? "cached"
+ : "not-created")));
return;
}
if (n >= sizeof(tmp)) {
@@ -1854,12 +1895,14 @@ static void dbg_cmd_language(DbgState* s, const char* rest) {
lang = dbg_jit_language_for_tag(s, tmp, &name);
(void)name;
if (lang == CFREE_LANG_COUNT) {
- driver_errf(DBG_TOOL, "unsupported language: %s", tmp);
+ driver_errf(DBG_TOOL, "unsupported language: %.*s",
+ CFREE_SLICE_ARG(cfree_slice_cstr(tmp)));
return;
}
s->default_jit_lang = lang;
s->default_jit_name = dbg_jit_default_name(lang);
- driver_printf("Language: %s\n", dbg_jit_language_name(lang));
+ driver_printf("Language: %.*s\n",
+ CFREE_SLICE_ARG(cfree_slice_cstr(dbg_jit_language_name(lang))));
}
static size_t dbg_u64_dec(char* dst, size_t cap, uint64_t v) {
@@ -1996,9 +2039,10 @@ static void dbg_cmd_expr(DbgState* s, const char* expr) {
}
}
- entry = cfree_jit_lookup(s->jit, name);
+ entry = cfree_jit_lookup(s->jit, cfree_slice_cstr(name));
if (!entry) {
- driver_errf(DBG_TOOL, "expression thunk not found: %s", name);
+ driver_errf(DBG_TOOL, "expression thunk not found: %.*s",
+ CFREE_SLICE_ARG(cfree_slice_cstr(name)));
goto out;
}
if (dbg_call_u64_entry(s, entry, NULL, 0, &ret) == 0) {
@@ -2033,9 +2077,10 @@ static void dbg_cmd_call(DbgState* s, const char* rest) {
driver_errf(DBG_TOOL, "usage: call SYMBOL [INT_OR_ADDR ...]");
goto out;
}
- entry = cfree_jit_lookup(s->jit, sym);
+ entry = cfree_jit_lookup(s->jit, cfree_slice_cstr(sym));
if (!entry) {
- driver_errf(DBG_TOOL, "symbol not found: %s", sym);
+ driver_errf(DBG_TOOL, "symbol not found: %.*s",
+ CFREE_SLICE_ARG(cfree_slice_cstr(sym)));
goto out;
}
while (*p) {
@@ -2050,7 +2095,8 @@ static void dbg_cmd_call(DbgState* s, const char* rest) {
}
used = dbg_parse_uint(a, &v);
if (!used || a[used] != '\0') {
- driver_errf(DBG_TOOL, "expected integer/address argument, got '%s'", a);
+ driver_errf(DBG_TOOL, "expected integer/address argument, got '%.*s'",
+ CFREE_SLICE_ARG(cfree_slice_cstr(a)));
goto out;
}
args[nargs++] = v;
@@ -2121,7 +2167,8 @@ static void dbg_cmd_list(DbgState* s, const char* spec) {
const CfreeFileIO* io;
if (!s->dwarf) {
- driver_errf(DBG_TOOL, "no DWARF: cannot resolve %s", spec);
+ driver_errf(DBG_TOOL, "no DWARF: cannot resolve %.*s",
+ CFREE_SLICE_ARG(cfree_slice_cstr(spec)));
return;
}
@@ -2132,7 +2179,8 @@ static void dbg_cmd_list(DbgState* s, const char* spec) {
}
flen = (size_t)(colon - spec);
if (flen == 0 || flen >= sizeof(path)) {
- driver_errf(DBG_TOOL, "bad file in '%s'", spec);
+ driver_errf(DBG_TOOL, "bad file in '%.*s'",
+ CFREE_SLICE_ARG(cfree_slice_cstr(spec)));
return;
}
driver_memcpy(path, spec, flen);
@@ -2145,21 +2193,23 @@ static void dbg_cmd_list(DbgState* s, const char* spec) {
/* Validate via DWARF first. */
{
- CfreeStatus st =
- cfree_dwarf_line_to_addr(s->dwarf, path, (uint32_t)line_u, &pc);
+ CfreeStatus st = cfree_dwarf_line_to_addr(
+ s->dwarf, cfree_slice_cstr(path), (uint32_t)line_u, &pc);
if (st == CFREE_NOT_FOUND) {
- driver_errf(DBG_TOOL, "no line %u in %s", (uint32_t)line_u, path);
+ driver_errf(DBG_TOOL, "no line %u in %.*s", (uint32_t)line_u,
+ CFREE_SLICE_ARG(cfree_slice_cstr(path)));
return;
}
if (st == CFREE_AMBIGUOUS) {
driver_errf(DBG_TOOL,
- "ambiguous: %s:%u matches multiple files; "
+ "ambiguous: %.*s:%u matches multiple files; "
"use a longer path suffix",
- path, (uint32_t)line_u);
+ CFREE_SLICE_ARG(cfree_slice_cstr(path)), (uint32_t)line_u);
return;
}
if (st != CFREE_OK) {
- driver_errf(DBG_TOOL, "no line entry for %s", spec);
+ driver_errf(DBG_TOOL, "no line entry for %.*s",
+ CFREE_SLICE_ARG(cfree_slice_cstr(spec)));
return;
}
rc = 0;
@@ -2170,8 +2220,9 @@ static void dbg_cmd_list(DbgState* s, const char* spec) {
* DWARF-only summary line per doc/DBG.md §10. */
io = s->env && s->env->file_io.read_all ? &s->env->file_io : NULL;
if (!io || io->read_all(io->user, path, &fd) != CFREE_OK) {
- driver_printf("%s:%u [source not available; pc=0x%llx]\n", path,
- (uint32_t)line_u, (unsigned long long)pc);
+ driver_printf("%.*s:%u [source not available; pc=0x%llx]\n",
+ CFREE_SLICE_ARG(cfree_slice_cstr(path)), (uint32_t)line_u,
+ (unsigned long long)pc);
return;
}
@@ -2190,7 +2241,9 @@ static void dbg_cmd_list(DbgState* s, const char* spec) {
if (eol) {
if (cur >= lo && cur <= hi) {
size_t len = (size_t)(p - line_start);
- driver_printf("%6u%s %.*s\n", cur, cur == target ? " >" : " ",
+ driver_printf("%6u%.*s %.*s\n", cur,
+ CFREE_SLICE_ARG(
+ cfree_slice_cstr(cur == target ? " >" : " ")),
(int)len, (const char*)line_start);
}
++cur;
@@ -2269,9 +2322,11 @@ static void dbg_cmd_break(DbgState* s, const char* spec) {
}
s->nbps++;
- driver_printf("Breakpoint %d at 0x%llx (%s)%s\n", b->id,
- (unsigned long long)addr, spec,
- b->session_id ? "" : " [disarmed]");
+ driver_printf("Breakpoint %d at 0x%llx (%.*s)%.*s\n", b->id,
+ (unsigned long long)addr,
+ CFREE_SLICE_ARG(cfree_slice_cstr(spec)),
+ CFREE_SLICE_ARG(
+ cfree_slice_cstr(b->session_id ? "" : " [disarmed]")));
}
static void dbg_cmd_info_b(DbgState* s) {
@@ -2283,11 +2338,13 @@ static void dbg_cmd_info_b(DbgState* s) {
driver_printf("Num Enb Address Skip Max Spec\n");
for (i = 0; i < s->nbps; ++i) {
Bp* b = &s->bps[i];
- driver_printf("%-4d %-4s 0x%-18llx %-6llu %-6llu %s%s\n", b->id,
+ driver_printf("%-4d %-4s 0x%-18llx %-6llu %-6llu %.*s%.*s\n", b->id,
b->enabled ? "y" : "n", (unsigned long long)b->addr,
(unsigned long long)b->skip_count,
- (unsigned long long)b->max_hits, b->spec ? b->spec : "",
- b->session_id ? "" : " [disarmed]");
+ (unsigned long long)b->max_hits,
+ CFREE_SLICE_ARG(cfree_slice_cstr(b->spec)),
+ CFREE_SLICE_ARG(
+ cfree_slice_cstr(b->session_id ? "" : " [disarmed]")));
}
}
@@ -2345,7 +2402,8 @@ static void dbg_cmd_set_enabled(DbgState* s, int id, int enable) {
static void dbg_cmd_help(void) {
driver_printf(
- "%s",
+ "%.*s",
+ CFREE_SLICE_ARG(CFREE_SLICE_LIT(
"Commands (abbrev. shown):\n"
" h, help show this help\n"
" q, quit exit (Ctrl-D also works)\n"
@@ -2379,7 +2437,7 @@ static void dbg_cmd_help(void) {
" info locals list locals at current PC\n"
" info args list args at current PC\n"
" info functions [PATTERN] list JIT functions matching PATTERN\n"
- " info variables [PATTERN] list JIT globals matching PATTERN\n");
+ " info variables [PATTERN] list JIT globals matching PATTERN\n")));
}
static CfreeLanguage dbg_default_language_from_inputs(CfreeCompiler* c,
@@ -2539,7 +2597,8 @@ static int dbg_dispatch(DbgState* s, char* line) {
dbg_take_word(rest, &pat);
dbg_cmd_info_syms(s, CFREE_SK_OBJ, *pat ? pat : NULL);
} else {
- driver_errf(DBG_TOOL, "unknown 'info' subcommand: %s", what);
+ driver_errf(DBG_TOOL, "unknown 'info' subcommand: %.*s",
+ CFREE_SLICE_ARG(cfree_slice_cstr(what)));
}
return 0;
}
@@ -2568,7 +2627,8 @@ static int dbg_dispatch(DbgState* s, char* line) {
}
used = dbg_parse_uint(val_s, &v);
if (!used || val_s[used] != '\0') {
- driver_errf(DBG_TOOL, "expected integer value, got '%s'", val_s);
+ driver_errf(DBG_TOOL, "expected integer value, got '%.*s'",
+ CFREE_SLICE_ARG(cfree_slice_cstr(val_s)));
return 0;
}
dbg_cmd_set(s, name, v);
@@ -2585,7 +2645,8 @@ static int dbg_dispatch(DbgState* s, char* line) {
}
used = dbg_parse_uint(addr_s, &addr);
if (!used || addr_s[used] != '\0') {
- driver_errf(DBG_TOOL, "bad address '%s'", addr_s);
+ driver_errf(DBG_TOOL, "bad address '%.*s'",
+ CFREE_SLICE_ARG(cfree_slice_cstr(addr_s)));
return 0;
}
dbg_cmd_jump(s, addr);
@@ -2679,14 +2740,16 @@ static int dbg_dispatch(DbgState* s, char* line) {
}
used = dbg_parse_uint(addr_s, &addr);
if (!used || addr_s[used] != '\0') {
- driver_errf(DBG_TOOL, "bad address '%s'", addr_s);
+ driver_errf(DBG_TOOL, "bad address '%.*s'",
+ CFREE_SLICE_ARG(cfree_slice_cstr(addr_s)));
return 0;
}
dbg_take_word(rest, &count_s);
if (*count_s) {
used = dbg_parse_uint(count_s, &count);
if (!used || count_s[used] != '\0') {
- driver_errf(DBG_TOOL, "bad count '%s'", count_s);
+ driver_errf(DBG_TOOL, "bad count '%.*s'",
+ CFREE_SLICE_ARG(cfree_slice_cstr(count_s)));
return 0;
}
}
@@ -2702,7 +2765,8 @@ static int dbg_dispatch(DbgState* s, char* line) {
if (s->session) {
dbg_cmd_expr(s, raw);
} else {
- driver_errf(DBG_TOOL, "unknown command: %s (try 'h')", cmd);
+ driver_errf(DBG_TOOL, "unknown command: %.*s (try 'h')",
+ CFREE_SLICE_ARG(cfree_slice_cstr(cmd)));
}
return 0;
}
@@ -2796,9 +2860,10 @@ int driver_dbg(int argc, char** argv) {
st.entry_name = o.entry;
if (driver_inputs_count(&o.inputs) != 0) {
- st.entry_addr = cfree_jit_lookup(jit, o.entry);
+ st.entry_addr = cfree_jit_lookup(jit, cfree_slice_cstr(o.entry));
if (!st.entry_addr) {
- driver_errf(DBG_TOOL, "entry symbol not found: %s", o.entry);
+ driver_errf(DBG_TOOL, "entry symbol not found: %.*s",
+ CFREE_SLICE_ARG(cfree_slice_cstr(o.entry)));
cfree_jit_free(jit);
driver_compiler_free(compiler);
dbg_options_release(&o);
diff --git a/driver/driver.h b/driver/driver.h
@@ -227,7 +227,7 @@ int driver_edit_temp(DriverEnv *, const char *suffix, const uint8_t *initial,
size_t initial_size, uint8_t **out_data, size_t *out_size);
/* Path-shaped input loader. Wraps env.file_io.read_all so each tool can
- * convert a list of paths to a list of CfreeBytes without re-implementing
+ * convert a list of paths to a list of CfreeSlice without re-implementing
* load/release/error bookkeeping. `loaded` is set to 1 on success; release is
* idempotent and does nothing when loaded is already 0. driver_load_bytes
* fills `in.name = path` plus the loaded data/len; driver_release_bytes hands
@@ -239,7 +239,7 @@ typedef struct DriverLoad {
} DriverLoad;
int driver_load_bytes(const CfreeFileIO *, const char *tool, const char *path,
- DriverLoad *out, CfreeBytes *in);
+ DriverLoad *out, CfreeSlice *in);
void driver_release_bytes(const CfreeFileIO *, DriverLoad *);
/* Read one line from stdin into `buf` (cap >= 2). Strips the trailing
@@ -268,6 +268,6 @@ void driver_restore_sigint(void);
* `user` is ignored and may be NULL. Wired into `cfree run` so JITed code
* can call libc symbols (printf, malloc, ...) without an explicit linker
* step. */
-void *driver_dlsym_resolver(void *user, const char *name);
+void *driver_dlsym_resolver(void *user, CfreeSlice name);
#endif
diff --git a/driver/emu.c b/driver/emu.c
@@ -40,14 +40,16 @@ typedef struct EmuOptions {
} EmuOptions;
static void emu_usage(void) {
- driver_errf(EMU_TOOL, "%s",
- "usage: cfree emu [options] guest.elf [-- guest-arg...]\n"
- " cfree emu --help for full option reference");
+ driver_errf(EMU_TOOL, "%.*s",
+ CFREE_SLICE_ARG(CFREE_SLICE_LIT(
+ "usage: cfree emu [options] guest.elf [-- guest-arg...]\n"
+ " cfree emu --help for full option reference")));
}
void driver_help_emu(void) {
driver_printf(
- "%s",
+ "%.*s",
+ CFREE_SLICE_ARG(CFREE_SLICE_LIT(
"cfree emu — run a guest user-mode ELF on the host\n"
"\n"
"USAGE\n"
@@ -81,7 +83,7 @@ void driver_help_emu(void) {
"\n"
"EXIT CODES\n"
" Returns the guest's exit code on clean exit, or 1 on internal\n"
- " failure. 2 on bad command-line usage.\n");
+ " failure. 2 on bad command-line usage.\n")));
}
static int emu_alloc_arrays(EmuOptions* o, int argc) {
@@ -108,7 +110,8 @@ static int emu_record_arch(EmuOptions* o, const char* val) {
o->guest_arch_set = 1;
return 0;
}
- driver_errf(EMU_TOOL, "unsupported -arch value: %s", val);
+ driver_errf(EMU_TOOL, "unsupported -arch value: %.*s",
+ CFREE_SLICE_ARG(cfree_slice_cstr(val)));
return 1;
}
@@ -165,13 +168,15 @@ static int emu_parse(int argc, char** argv, EmuOptions* o) {
}
if (a[0] == '-' && a[1] != '\0') {
- driver_errf(EMU_TOOL, "unknown flag: %s", a);
+ driver_errf(EMU_TOOL, "unknown flag: %.*s",
+ CFREE_SLICE_ARG(cfree_slice_cstr(a)));
return 1;
}
if (o->elf_path) {
- driver_errf(EMU_TOOL, "multiple guest ELF inputs: %s, %s", o->elf_path,
- a);
+ driver_errf(EMU_TOOL, "multiple guest ELF inputs: %.*s, %.*s",
+ CFREE_SLICE_ARG(cfree_slice_cstr(o->elf_path)),
+ CFREE_SLICE_ARG(cfree_slice_cstr(a)));
return 1;
}
o->elf_path = a;
@@ -220,18 +225,19 @@ static const char* emu_arch_name(CfreeEmuArch a) {
/* Auto-detect the guest arch from the ELF magic when -arch was not set.
* Honors a user-supplied -arch verbatim (no cross-check against the ELF;
* mismatches surface as decode failures inside the emu). */
-static int emu_resolve_arch(EmuOptions* o, const CfreeBytes* elf) {
+static int emu_resolve_arch(EmuOptions* o, const CfreeSlice* elf) {
CfreeTarget detected;
if (o->guest_arch_set) return 0;
if (cfree_detect_target(elf->data, elf->len, &detected) != CFREE_OK) {
- driver_errf(EMU_TOOL, "could not detect target from %s; pass -arch",
- o->elf_path);
+ driver_errf(EMU_TOOL, "could not detect target from %.*s; pass -arch",
+ CFREE_SLICE_ARG(cfree_slice_cstr(o->elf_path)));
return 1;
}
if (emu_arch_from_kind(detected.arch, &o->guest_arch) != 0) {
driver_errf(EMU_TOOL,
- "unsupported guest arch in %s; v1 supports aarch64 and riscv64",
- o->elf_path);
+ "unsupported guest arch in %.*s; v1 supports aarch64 and "
+ "riscv64",
+ CFREE_SLICE_ARG(cfree_slice_cstr(o->elf_path)));
return 1;
}
o->guest_arch_set = 1;
@@ -258,7 +264,7 @@ int driver_emu(int argc, char** argv) {
CfreeContext ctx;
CfreeCompiler* compiler = NULL;
DriverLoad elf_lf = {0};
- CfreeBytes elf_in;
+ CfreeSlice elf_in;
CfreeEmuOptions opts;
const char** guest_argv;
int exit_code = 0;
@@ -314,8 +320,9 @@ int driver_emu(int argc, char** argv) {
opts.envp = 0;
if (cfree_emu_run(compiler, &opts, &exit_code) != CFREE_OK) {
- driver_errf(EMU_TOOL, "emulation of %s (%s) failed", eo.elf_path,
- emu_arch_name(eo.guest_arch));
+ driver_errf(EMU_TOOL, "emulation of %.*s (%.*s) failed",
+ CFREE_SLICE_ARG(cfree_slice_cstr(eo.elf_path)),
+ CFREE_SLICE_ARG(cfree_slice_cstr(emu_arch_name(eo.guest_arch))));
goto out;
}
diff --git a/driver/env.c b/driver/env.c
@@ -183,16 +183,18 @@ static void diag_stderr_emit(CfreeDiagSink *s, CfreeDiagKind k, CfreeSrcLoc loc,
const char *fmt, va_list ap) {
(void)s;
if (loc.file_id || loc.line) {
- const char *name =
+ CfreeSlice name =
cfree_compiler_file_name(g_diag_active_compiler, loc.file_id);
- if (name && *name) {
- fprintf(stderr, "%s:%u:%u: %s: ", name, loc.line, loc.col, diag_label(k));
+ if (name.len) {
+ fprintf(stderr, "%.*s:%u:%u: %.*s: ",
+ CFREE_SLICE_ARG(name), loc.line, loc.col,
+ CFREE_SLICE_ARG(cfree_slice_cstr(diag_label(k))));
} else {
- fprintf(stderr, "<file:%u>:%u:%u: %s: ", loc.file_id, loc.line, loc.col,
- diag_label(k));
+ fprintf(stderr, "<file:%u>:%u:%u: %.*s: ", loc.file_id, loc.line, loc.col,
+ CFREE_SLICE_ARG(cfree_slice_cstr(diag_label(k))));
}
} else {
- fprintf(stderr, "%s: ", diag_label(k));
+ fprintf(stderr, "%.*s: ", CFREE_SLICE_ARG(cfree_slice_cstr(diag_label(k))));
}
vfprintf(stderr, fmt, ap);
fputc('\n', stderr);
@@ -1354,25 +1356,44 @@ CfreeDbgHost driver_env_to_dbg_host(const DriverEnv *e) {
/* ---------------- host-shim helpers ---------------- */
-int driver_streq(const char *a, const char *b) { return strcmp(a, b) == 0; }
+/* The driver's only NUL-terminated-string handling: thin boundary shims that
+ * route every length scan through cfree_slice_cstr and otherwise use the
+ * length-based mem* primitives. No libc str* is used. */
+
+int driver_streq(const char *a, const char *b) {
+ return cfree_slice_eq(cfree_slice_cstr(a), cfree_slice_cstr(b));
+}
int driver_strneq(const char *a, const char *b, size_t n) {
- return strncmp(a, b, n) == 0;
+ size_t i;
+ for (i = 0; i < n; ++i) {
+ unsigned char ca = (unsigned char)a[i], cb = (unsigned char)b[i];
+ if (ca != cb) return 0;
+ if (ca == '\0') return 1;
+ }
+ return 1;
}
-size_t driver_strlen(const char *s) { return strlen(s); }
+size_t driver_strlen(const char *s) { return cfree_slice_cstr(s).len; }
-const char *driver_strchr(const char *s, int c) { return strchr(s, c); }
+const char *driver_strchr(const char *s, int c) {
+ /* search includes the terminator so driver_strchr(s, 0) works like strchr */
+ return (const char *)memchr(s, c, cfree_slice_cstr(s).len + 1u);
+}
const char *driver_basename(const char *path) {
- const char *slash = strrchr(path, '/');
- return slash ? slash + 1 : path;
+ size_t i = cfree_slice_cstr(path).len;
+ while (i > 0) {
+ if (path[i - 1] == '/') return path + i;
+ --i;
+ }
+ return path;
}
int driver_has_suffix(const char *s, const char *suffix) {
- size_t ls = strlen(s);
- size_t lf = strlen(suffix);
- return ls >= lf && strcmp(s + ls - lf, suffix) == 0;
+ size_t ls = cfree_slice_cstr(s).len;
+ size_t lf = cfree_slice_cstr(suffix).len;
+ return ls >= lf && memcmp(s + ls - lf, suffix, lf) == 0;
}
int driver_path_exists(const char *path) {
@@ -1413,7 +1434,7 @@ int driver_mkdir_p(DriverEnv *env, const char *path) {
if (!path || !path[0])
return 1;
- len = strlen(path);
+ len = cfree_slice_cstr(path).len;
buf = (char *)driver_alloc(env, len + 1);
if (!buf)
return 1;
@@ -1425,7 +1446,7 @@ int driver_mkdir_p(DriverEnv *env, const char *path) {
continue;
if (!at_end)
buf[i] = '\0';
- if (buf[0] != '\0' && strcmp(buf, ".") != 0) {
+ if (buf[0] != '\0' && !driver_streq(buf, ".")) {
if (mkdir(buf, 0755) != 0 && errno != EEXIST) {
driver_free(env, buf, len + 1);
return 1;
@@ -1477,7 +1498,7 @@ void driver_memcpy(void *dst, const void *src, size_t n) {
void driver_errf(const char *tool, const char *fmt, ...) {
va_list ap;
- fprintf(stderr, "%s: ", tool);
+ fprintf(stderr, "%.*s: ", CFREE_SLICE_ARG(cfree_slice_cstr(tool)));
va_start(ap, fmt);
vfprintf(stderr, fmt, ap);
va_end(ap);
@@ -1511,7 +1532,7 @@ uint64_t driver_now_ns(void) {
const char *driver_getenv(const char *name) { return getenv(name); }
int driver_load_bytes(const CfreeFileIO *io, const char *tool, const char *path,
- DriverLoad *out, CfreeBytes *in) {
+ DriverLoad *out, CfreeSlice *in) {
out->loaded = 0;
out->fd.data = NULL;
out->fd.size = 0;
@@ -1521,11 +1542,11 @@ int driver_load_bytes(const CfreeFileIO *io, const char *tool, const char *path,
return 1;
}
if (io->read_all(io->user, path, &out->fd) != CFREE_OK) {
- driver_errf(tool, "failed to read: %s", path);
+ driver_errf(tool, "failed to read: %.*s",
+ CFREE_SLICE_ARG(cfree_slice_cstr(path)));
return 1;
}
out->loaded = 1;
- in->name = path;
in->data = out->fd.data;
in->len = out->fd.size;
return 0;
@@ -1655,12 +1676,12 @@ int driver_edit_temp(DriverEnv *e, const char *suffix, const uint8_t *initial,
return 0;
*out_data = NULL;
*out_size = 0;
- suffix_len = suffix ? strlen(suffix) : 0u;
+ suffix_len = suffix ? cfree_slice_cstr(suffix).len : 0u;
tmpdir = getenv("TMPDIR");
if (!tmpdir || !*tmpdir)
tmpdir = "/tmp";
- tmpdir_len = strlen(tmpdir);
- base_len = strlen(base);
+ tmpdir_len = cfree_slice_cstr(tmpdir).len;
+ base_len = cfree_slice_cstr(base).len;
path_len = tmpdir_len + base_len + suffix_len;
path = e->heap->alloc(e->heap, path_len + 1u, 1);
if (!path)
@@ -1690,7 +1711,7 @@ int driver_edit_temp(DriverEnv *e, const char *suffix, const uint8_t *initial,
if (!editor || !*editor)
editor = "vi";
{
- size_t editor_len = strlen(editor);
+ size_t editor_len = cfree_slice_cstr(editor).len;
size_t quoted_len = 0;
char *quoted = driver_shell_quote_path(e, path, path_len, "ed_len);
char *cmd;
@@ -1746,10 +1767,13 @@ out:
return ok;
}
-void *driver_dlsym_resolver(void *user, const char *name) {
+void *driver_dlsym_resolver(void *user, CfreeSlice name_s) {
+ /* The linker hands us interned/pool slices that are NUL-terminated, so
+ * we can pass .s straight to dlsym (a host libc boundary). */
+ const char *name = name_s.s;
void *p;
(void)user;
- if (!name)
+ if (!name || name_s.len == 0)
return NULL;
/* On Mach-O hosts the linker hands us C names with a leading underscore
* (obj_format_c_mangle), but dlsym(RTLD_DEFAULT) expects the
diff --git a/driver/hosted.c b/driver/hosted.c
@@ -51,7 +51,8 @@ static int hosted_add_required(DriverHostedInput* items, uint32_t* n,
return 1;
}
if (!driver_path_exists(path)) {
- driver_errf(req->tool, "hosted profile missing required file: %s", path);
+ driver_errf(req->tool, "hosted profile missing required file: %.*s",
+ CFREE_SLICE_ARG(cfree_slice_cstr(path)));
driver_free(req->env, path, size);
return 1;
}
@@ -84,8 +85,8 @@ static int hosted_add_existing_include(DriverHostedPlan* plan, DriverEnv* env,
static int hosted_add_define(DriverHostedPlan* plan, const char* name,
const char* body) {
if (plan->ndefines >= DRIVER_HOSTED_MAX_DEFINES) return 1;
- plan->defines[plan->ndefines].name = name;
- plan->defines[plan->ndefines].body = body;
+ plan->defines[plan->ndefines].name = cfree_slice_cstr(name);
+ plan->defines[plan->ndefines].body = cfree_slice_cstr(body);
plan->ndefines++;
return 0;
}
@@ -188,8 +189,8 @@ static int hosted_resolve_darwin(const DriverHostedRequest* req,
}
}
if (!driver_path_exists(libsystem)) {
- driver_errf(req->tool, "hosted profile missing required file: %s",
- libsystem);
+ driver_errf(req->tool, "hosted profile missing required file: %.*s",
+ CFREE_SLICE_ARG(cfree_slice_cstr(libsystem)));
driver_free(req->env, libsystem, size);
return 1;
}
@@ -366,8 +367,8 @@ static int hosted_resolve_linux(const DriverHostedRequest* req,
if (!req->static_link && has_libc_so)
return hosted_resolve_linux_musl_dynamic(req, plan);
driver_errf(req->tool,
- "no supported Linux hosted libc found under sysroot: %s",
- req->sysroot);
+ "no supported Linux hosted libc found under sysroot: %.*s",
+ CFREE_SLICE_ARG(cfree_slice_cstr(req->sysroot)));
return 1;
}
diff --git a/driver/inputs.c b/driver/inputs.c
@@ -53,7 +53,7 @@ static int inputs_record_stdin(DriverInputs* in) {
return -1;
}
slot = &in->source_memory[in->nsource_memory++];
- slot->bytes.name = "<stdin>";
+ slot->name = CFREE_SLICE_LIT("<stdin>");
slot->bytes.data = in->stdin_buf;
slot->bytes.len = in->stdin_size;
slot->lang = CFREE_LANG_C;
@@ -85,7 +85,7 @@ uint32_t driver_inputs_count(const DriverInputs* in) {
const char* driver_inputs_first_name(const DriverInputs* in) {
if (in->nsources) return in->sources[0];
- if (in->nsource_memory) return in->source_memory[0].bytes.name;
+ if (in->nsource_memory) return in->source_memory[0].name.s;
if (in->nobject_files) return in->object_files[0];
if (in->narchives) return in->archives[0];
return NULL;
@@ -98,7 +98,7 @@ int driver_inputs_compile_and_jit(DriverInputs* in, CfreeCompiler* compiler,
const CfreeJitHost* host,
const CfreeCCompileOptions* copts,
const char* entry,
- void* (*extern_resolver)(void*, const char*),
+ void* (*extern_resolver)(void*, CfreeSlice),
void* extern_resolver_user,
CfreeJit** out_jit) {
DriverEnv* env = in->env;
@@ -108,8 +108,8 @@ int driver_inputs_compile_and_jit(DriverInputs* in, CfreeCompiler* compiler,
DriverLoad* src_lf = NULL;
DriverLoad* obj_lf = NULL;
DriverLoad* arch_lf = NULL;
- CfreeBytes* src_bytes = NULL; /* per-path source bytes for loads */
- CfreeBytes* obj_in = NULL;
+ CfreeSlice* src_bytes = NULL; /* per-path source bytes for loads */
+ CfreeSlice* obj_in = NULL;
CfreeLinkArchiveInput* arch_in = NULL;
CfreeObjBuilder** objs = NULL;
CfreeLinkSession* link = NULL;
@@ -154,7 +154,7 @@ int driver_inputs_compile_and_jit(DriverInputs* in, CfreeCompiler* compiler,
}
}
- /* Load source files into CfreeBytes and compile them into object builders. */
+ /* Load source files into CfreeSlice and compile them into object builders. */
cfree_frontend_metrics_scope_begin(compiler, "driver.load_sources");
for (i = 0; i < in->nsources; ++i) {
if (driver_load_bytes(io, tool, in->sources[i], &src_lf[i],
@@ -184,6 +184,7 @@ int driver_inputs_compile_and_jit(DriverInputs* in, CfreeCompiler* compiler,
sopts.compile.language_options = copts;
}
memset(&sin, 0, sizeof(sin));
+ sin.name = cfree_slice_cstr(in->sources[i]);
sin.bytes = src_bytes[i];
sin.lang = lang;
st = cfree_compile_session_new(compiler, &sopts, &session);
@@ -236,7 +237,7 @@ int driver_inputs_compile_and_jit(DriverInputs* in, CfreeCompiler* compiler,
CfreeStatus st;
memset(&lopts, 0, sizeof(lopts));
lopts.output_kind = CFREE_LINK_OUTPUT_JIT;
- lopts.entry = entry;
+ lopts.entry = cfree_slice_cstr(entry);
lopts.jit_host = host;
lopts.extern_resolver = extern_resolver;
lopts.extern_resolver_user = extern_resolver_user;
@@ -245,7 +246,8 @@ int driver_inputs_compile_and_jit(DriverInputs* in, CfreeCompiler* compiler,
for (i = 0; st == CFREE_OK && i < nsrc; ++i)
st = cfree_link_session_add_obj(link, objs[i]);
for (i = 0; st == CFREE_OK && i < in->nobject_files; ++i)
- st = cfree_link_session_add_obj_bytes(link, &obj_in[i]);
+ st = cfree_link_session_add_obj_bytes(
+ link, cfree_slice_cstr(in->object_files[i]), &obj_in[i]);
for (i = 0; st == CFREE_OK && i < in->narchives; ++i)
st = cfree_link_session_add_archive_bytes(link, &arch_in[i]);
cfree_frontend_metrics_scope_end(compiler, "driver.link_setup");
@@ -280,9 +282,9 @@ out:
* ---------------------------------------------------------------------- */
int driver_collect_obj_global_syms(DriverEnv* env, const CfreeContext* ctx,
- const char* tool, const CfreeBytes* member,
+ const char* tool, const CfreeSlice* member,
void** blob_out, size_t* blob_size_out,
- const char*** names_out,
+ const CfreeSlice** names_out,
uint32_t* count_out) {
CfreeObjFile* of = NULL;
CfreeObjSymIter* it = NULL;
@@ -291,7 +293,7 @@ int driver_collect_obj_global_syms(DriverEnv* env, const CfreeContext* ctx,
size_t name_bytes = 0;
size_t alloc_sz;
char* blob;
- const char** name_arr;
+ CfreeSlice* name_arr;
char* name_storage;
size_t cursor = 0;
@@ -300,7 +302,7 @@ int driver_collect_obj_global_syms(DriverEnv* env, const CfreeContext* ctx,
*names_out = NULL;
*count_out = 0;
- if (cfree_obj_open(ctx, member, &of) != CFREE_OK) {
+ if (cfree_obj_open(ctx, CFREE_SLICE_NULL, member, &of) != CFREE_OK) {
/* Not a recognized object — caller treats as "no symbols". */
return 0;
}
@@ -316,13 +318,9 @@ int driver_collect_obj_global_syms(DriverEnv* env, const CfreeContext* ctx,
if (r != CFREE_ITER_ITEM) break;
if (si.bind != CFREE_SB_GLOBAL) continue;
if (si.section == CFREE_SECTION_NONE) continue;
- if (!si.name || !si.name[0]) continue;
+ if (!si.name.len) continue;
count += 1;
- {
- const char* p = si.name;
- while (*p++) ++name_bytes;
- name_bytes += 1; /* NUL */
- }
+ name_bytes += si.name.len + 1; /* +NUL */
}
cfree_obj_symiter_free(it);
@@ -331,15 +329,15 @@ int driver_collect_obj_global_syms(DriverEnv* env, const CfreeContext* ctx,
return 0;
}
- alloc_sz = (size_t)count * sizeof(const char*) + name_bytes;
+ alloc_sz = (size_t)count * sizeof(CfreeSlice) + name_bytes;
blob = (char*)driver_alloc_zeroed(env, alloc_sz);
if (!blob) {
cfree_obj_free(of);
driver_errf(tool, "out of memory");
return 1;
}
- name_arr = (const char**)blob;
- name_storage = blob + (size_t)count * sizeof(const char*);
+ name_arr = (CfreeSlice*)blob;
+ name_storage = blob + (size_t)count * sizeof(CfreeSlice);
/* Pass B: copy names. */
if (cfree_obj_symiter_new(of, &it) != CFREE_OK) {
@@ -352,17 +350,18 @@ int driver_collect_obj_global_syms(DriverEnv* env, const CfreeContext* ctx,
uint32_t k = 0;
for (;;) {
CfreeIterResult r;
- const char* p;
char* dst;
+ size_t j;
if (k >= count) break;
r = cfree_obj_symiter_next(it, &si);
if (r != CFREE_ITER_ITEM) break;
if (si.bind != CFREE_SB_GLOBAL) continue;
if (si.section == CFREE_SECTION_NONE) continue;
- if (!si.name || !si.name[0]) continue;
+ if (!si.name.len) continue;
dst = name_storage + cursor;
- name_arr[k] = dst;
- for (p = si.name; *p; ++p) *dst++ = *p;
+ name_arr[k].s = dst;
+ name_arr[k].len = si.name.len;
+ for (j = 0; j < si.name.len; ++j) *dst++ = si.name.s[j];
*dst++ = '\0';
cursor = (size_t)(dst - name_storage);
k++;
diff --git a/driver/inputs.h b/driver/inputs.h
@@ -89,8 +89,7 @@ int driver_inputs_compile_and_jit(DriverInputs *, CfreeCompiler *,
const CfreeJitHost *,
const CfreeCCompileOptions *copts,
const char *entry,
- void *(*extern_resolver)(void *,
- const char *),
+ void *(*extern_resolver)(void *, CfreeSlice),
void *extern_resolver_user,
CfreeJit **out_jit);
@@ -104,8 +103,9 @@ int driver_inputs_compile_and_jit(DriverInputs *, CfreeCompiler *,
* of every SB_GLOBAL symbol with a defining section.
*
* driver_collect_obj_global_syms allocates a single heap block laid out
- * as [const char* names[count]][NUL-separated name bytes]. The caller
- * frees the block via driver_collect_obj_global_syms_free.
+ * as [CfreeSlice names[count]][NUL-separated name bytes]. The caller
+ * frees the block via driver_collect_obj_global_syms_free. Each name
+ * slice points into the name-byte region and is NUL-terminated there.
*
* Returns:
* 0 member parsed, output filled (count may be 0 if the object has
@@ -116,9 +116,9 @@ int driver_inputs_compile_and_jit(DriverInputs *, CfreeCompiler *,
*/
int driver_collect_obj_global_syms(DriverEnv *env, const CfreeContext *ctx,
const char *tool,
- const CfreeBytes *member, void **blob_out,
+ const CfreeSlice *member, void **blob_out,
size_t *blob_size_out,
- const char ***names_out,
+ const CfreeSlice **names_out,
uint32_t *count_out);
void driver_collect_obj_global_syms_free(DriverEnv *env, void *blob,
diff --git a/driver/ld.c b/driver/ld.c
@@ -46,7 +46,7 @@
/* Per-archive metadata mirroring the relevant subset of
* CfreeLinkArchiveInput plus driver-side ownership info. */
typedef struct LdArchive {
- const char* path; /* path used for both open and CfreeBytesInput.name */
+ const char* path; /* path used for both open and CfreeSliceInput.name */
int owned; /* 1 if `path` was alloc'd by lib_resolve */
size_t owned_size; /* allocation size (for driver_free) */
uint8_t whole_archive; /* nonzero == --whole-archive */
@@ -55,11 +55,11 @@ typedef struct LdArchive {
} LdArchive;
/* Per-DSO ownership info. The DSO bytes are loaded straight off disk
- * via env->file_io into the CfreeBytes passed to libcfree; only
+ * via env->file_io into the CfreeSlice passed to libcfree; only
* the path itself may need to be free'd if it came from -l<name>
* resolution. */
typedef struct LdDso {
- const char* path; /* path used for both open and CfreeBytesInput.name */
+ const char* path; /* path used for both open and CfreeSliceInput.name */
int owned; /* 1 if `path` was alloc'd by lib_resolve */
size_t owned_size; /* allocation size (for driver_free) */
} LdDso;
@@ -129,14 +129,16 @@ typedef struct LdOptions {
} LdOptions;
static void ld_usage(void) {
- driver_errf(LD_TOOL, "%s",
+ driver_errf(LD_TOOL, "%.*s",
+ CFREE_SLICE_ARG(CFREE_SLICE_LIT(
"usage: cfree ld -o out [options...] inputs.o|inputs.a...\n"
- " cfree ld --help for full option reference");
+ " cfree ld --help for full option reference")));
}
void driver_help_ld(void) {
driver_printf(
- "%s",
+ "%.*s",
+ CFREE_SLICE_ARG(CFREE_SLICE_LIT(
"cfree ld — link objects/archives into an executable or shared library\n"
"\n"
"USAGE\n"
@@ -210,7 +212,7 @@ void driver_help_ld(void) {
" -h, --help Show this help and exit\n"
"\n"
"EXIT CODES\n"
- " 0 success 1 link error 2 bad usage\n");
+ " 0 success 1 link error 2 bad usage\n")));
}
/* ---------- argv-sized scratch arrays ---------- */
@@ -356,7 +358,8 @@ static int ld_parse_build_id(LdOptions* o, const char* val) {
return 0;
}
- driver_errf(LD_TOOL, "--build-id: unknown value: %s", val);
+ driver_errf(LD_TOOL, "--build-id: unknown value: %.*s",
+ CFREE_SLICE_ARG(cfree_slice_cstr(val)));
return 1;
}
@@ -428,7 +431,8 @@ static int ld_parse_pe_subsystem(LdOptions* o, const char* val) {
o->pe_subsystem = CFREE_PE_SUBSYSTEM_WINDOWS_GUI;
return 0;
}
- driver_errf(LD_TOOL, "unsupported subsystem: %s", val);
+ driver_errf(LD_TOOL, "unsupported subsystem: %.*s",
+ CFREE_SLICE_ARG(cfree_slice_cstr(val)));
return 1;
}
@@ -479,7 +483,8 @@ static int ld_try_ms_flag(LdOptions* o, const char* a) {
if (driver_lib_resolve_for_os(o->env, val, mode, LIB_RESOLVE_OS_WINDOWS,
o->lib_dirs, o->nlib_dirs, &resolved,
&resolved_size, &kind) != 0) {
- driver_errf(LD_TOOL, "/DEFAULTLIB: cannot find %s", val);
+ driver_errf(LD_TOOL, "/DEFAULTLIB: cannot find %.*s",
+ CFREE_SLICE_ARG(cfree_slice_cstr(val)));
return -1;
}
if (kind == LIB_RESOLVE_KIND_SHARED || kind == LIB_RESOLVE_KIND_TBD) {
@@ -503,7 +508,8 @@ static int ld_try_ms_flag(LdOptions* o, const char* a) {
/* Any other `/key[:val]` shape under --ms-link-driver: warn + skip.
* We treat the entire arg as consumed so it doesn't fall through to
* the positional path and try to open a file. */
- driver_errf(LD_TOOL, "ignoring unsupported MS-style flag: %s", a);
+ driver_errf(LD_TOOL, "ignoring unsupported MS-style flag: %.*s",
+ CFREE_SLICE_ARG(cfree_slice_cstr(a)));
return 1;
}
@@ -667,7 +673,8 @@ static int ld_parse(int argc, char** argv, LdOptions* o) {
if (driver_lib_resolve_for_os(o->env, name, mode, resolve_os, o->lib_dirs,
o->nlib_dirs, &resolved, &resolved_size,
&kind) != 0) {
- driver_errf(LD_TOOL, "cannot find -l%s", name);
+ driver_errf(LD_TOOL, "cannot find -l%.*s",
+ CFREE_SLICE_ARG(cfree_slice_cstr(name)));
return 1;
}
if (kind == LIB_RESOLVE_KIND_SHARED || kind == LIB_RESOLVE_KIND_TBD) {
@@ -690,7 +697,8 @@ static int ld_parse(int argc, char** argv, LdOptions* o) {
if (driver_lib_resolve_for_os(o->env, val, mode, resolve_os, o->lib_dirs,
o->nlib_dirs, &resolved, &resolved_size,
&kind) != 0) {
- driver_errf(LD_TOOL, "cannot find -l%s", val);
+ driver_errf(LD_TOOL, "cannot find -l%.*s",
+ CFREE_SLICE_ARG(cfree_slice_cstr(val)));
return 1;
}
if (kind == LIB_RESOLVE_KIND_SHARED || kind == LIB_RESOLVE_KIND_TBD) {
@@ -717,7 +725,8 @@ static int ld_parse(int argc, char** argv, LdOptions* o) {
if (driver_lib_resolve_for_os(o->env, argv[i], mode, resolve_os,
o->lib_dirs, o->nlib_dirs, &resolved,
&resolved_size, &kind) != 0) {
- driver_errf(LD_TOOL, "cannot find -l%s", argv[i]);
+ driver_errf(LD_TOOL, "cannot find -l%.*s",
+ CFREE_SLICE_ARG(cfree_slice_cstr(argv[i])));
return 1;
}
if (kind == LIB_RESOLVE_KIND_SHARED || kind == LIB_RESOLVE_KIND_TBD) {
@@ -839,7 +848,8 @@ static int ld_parse(int argc, char** argv, LdOptions* o) {
o->allow_undefined = 0;
continue;
}
- driver_errf(LD_TOOL, "unsupported -z option: %s", argv[i]);
+ driver_errf(LD_TOOL, "unsupported -z option: %.*s",
+ CFREE_SLICE_ARG(cfree_slice_cstr(argv[i])));
return 1;
}
@@ -900,7 +910,8 @@ static int ld_parse(int argc, char** argv, LdOptions* o) {
}
if (a[0] == '-' && a[1] != '\0') {
- driver_errf(LD_TOOL, "unknown flag: %s", a);
+ driver_errf(LD_TOOL, "unknown flag: %.*s",
+ CFREE_SLICE_ARG(cfree_slice_cstr(a)));
return 1;
}
@@ -1031,9 +1042,9 @@ static int ld_run_link(LdOptions* o) {
LoadedFile* arch_lf = NULL;
LoadedFile* dso_lf = NULL;
LoadedFile script_lf = {0};
- CfreeBytes* obj_in = NULL;
+ CfreeSlice* obj_in = NULL;
CfreeLinkArchiveInput* arch_in = NULL;
- CfreeBytes* dso_in = NULL;
+ CfreeSlice* dso_in = NULL;
CfreeLinkScript* script = NULL;
CfreeLinkSession* link = NULL;
uint32_t i;
@@ -1074,10 +1085,10 @@ static int ld_run_link(LdOptions* o) {
for (i = 0; i < o->nobject_files; ++i) {
const char* path = o->object_files[i];
if (load_file(io, path, &obj_lf[i]) != 0) {
- driver_errf(LD_TOOL, "failed to read: %s", path);
+ driver_errf(LD_TOOL, "failed to read: %.*s",
+ CFREE_SLICE_ARG(cfree_slice_cstr(path)));
goto out;
}
- obj_in[i].name = path;
obj_in[i].data = obj_lf[i].data.data;
obj_in[i].len = obj_lf[i].data.size;
}
@@ -1085,10 +1096,11 @@ static int ld_run_link(LdOptions* o) {
for (i = 0; i < o->narchives; ++i) {
const LdArchive* a = &o->archives[i];
if (load_file(io, a->path, &arch_lf[i]) != 0) {
- driver_errf(LD_TOOL, "failed to read: %s", a->path);
+ driver_errf(LD_TOOL, "failed to read: %.*s",
+ CFREE_SLICE_ARG(cfree_slice_cstr(a->path)));
goto out;
}
- arch_in[i].bytes.name = a->path;
+ arch_in[i].name = cfree_slice_cstr(a->path);
arch_in[i].bytes.data = arch_lf[i].data.data;
arch_in[i].bytes.len = arch_lf[i].data.size;
arch_in[i].whole_archive = a->whole_archive;
@@ -1099,10 +1111,10 @@ static int ld_run_link(LdOptions* o) {
for (i = 0; i < o->ndsos; ++i) {
const LdDso* d = &o->dsos[i];
if (load_file(io, d->path, &dso_lf[i]) != 0) {
- driver_errf(LD_TOOL, "failed to read: %s", d->path);
+ driver_errf(LD_TOOL, "failed to read: %.*s",
+ CFREE_SLICE_ARG(cfree_slice_cstr(d->path)));
goto out;
}
- dso_in[i].name = d->path;
dso_in[i].data = dso_lf[i].data.data;
dso_in[i].len = dso_lf[i].data.size;
}
@@ -1112,7 +1124,8 @@ static int ld_run_link(LdOptions* o) {
* compiler is destroyed. */
if (o->script_path) {
if (load_file(io, o->script_path, &script_lf) != 0) {
- driver_errf(LD_TOOL, "failed to read: %s", o->script_path);
+ driver_errf(LD_TOOL, "failed to read: %.*s",
+ CFREE_SLICE_ARG(cfree_slice_cstr(o->script_path)));
goto out;
}
}
@@ -1135,15 +1148,17 @@ static int ld_run_link(LdOptions* o) {
}
if (script_lf.loaded) {
- if (cfree_link_script_parse(&ctx, (const char*)script_lf.data.data,
- script_lf.data.size, &script) != CFREE_OK) {
+ CfreeSlice script_text = {.s = (const char*)script_lf.data.data,
+ .len = script_lf.data.size};
+ if (cfree_link_script_parse(&ctx, script_text, &script) != CFREE_OK) {
/* The parser reports a diagnostic via env.diag. */
goto out;
}
}
if (io->open_writer(io->user, o->output_path, &writer) != CFREE_OK) {
- driver_errf(LD_TOOL, "failed to open output: %s", o->output_path);
+ driver_errf(LD_TOOL, "failed to open output: %.*s",
+ CFREE_SLICE_ARG(cfree_slice_cstr(o->output_path)));
goto out;
}
@@ -1157,11 +1172,23 @@ static int ld_run_link(LdOptions* o) {
{
CfreeLinkSessionOptions lopts;
CfreeStatus st;
+ CfreeSlice* rpath_slices = NULL;
+ /* Lift the argv-derived -rpath dirs into slices for the linker. */
+ if (o->nrpaths) {
+ rpath_slices =
+ driver_alloc_zeroed(o->env, o->nrpaths * sizeof(*rpath_slices));
+ if (!rpath_slices) {
+ driver_errf(LD_TOOL, "out of memory");
+ goto out;
+ }
+ for (i = 0; i < o->nrpaths; ++i)
+ rpath_slices[i] = cfree_slice_cstr(o->rpaths[i]);
+ }
memset(&lopts, 0, sizeof(lopts));
lopts.output_kind = o->relocatable ? CFREE_LINK_OUTPUT_RELOCATABLE
: o->shared ? CFREE_LINK_OUTPUT_SHARED
: CFREE_LINK_OUTPUT_EXE;
- lopts.entry = o->entry;
+ lopts.entry = cfree_slice_cstr(o->entry);
lopts.linker_script = script;
lopts.build_id_mode = o->build_id_mode;
lopts.build_id_bytes = o->build_id_bytes;
@@ -1169,8 +1196,8 @@ static int ld_run_link(LdOptions* o) {
lopts.gc_sections = o->gc_sections;
lopts.pie = o->pie;
lopts.pe_subsystem = o->pe_subsystem;
- lopts.interp_path = o->interp_path;
- lopts.soname = o->soname;
+ lopts.interp_path = cfree_slice_cstr(o->interp_path);
+ lopts.soname = cfree_slice_cstr(o->soname);
/* Per --enable-new-dtags / --disable-new-dtags: when new_dtags is
* set (the default), -rpath entries land in DT_RUNPATH; otherwise
* in DT_RPATH. -rpath-link is link-time-only and is forwarded as
@@ -1179,10 +1206,10 @@ static int ld_run_link(LdOptions* o) {
* write itself, so this matches GNU-ld behaviour where rpath-link
* does not appear in DT_*PATH). */
if (o->new_dtags) {
- lopts.runpaths = o->rpaths;
+ lopts.runpaths = rpath_slices;
lopts.nrunpaths = o->nrpaths;
} else {
- lopts.rpaths = o->rpaths;
+ lopts.rpaths = rpath_slices;
lopts.nrpaths = o->nrpaths;
}
/* By default shared output may resolve symbols against its loader at
@@ -1197,24 +1224,30 @@ static int ld_run_link(LdOptions* o) {
switch ((CfreeLinkInputOrderKind)ord->kind) {
case CFREE_LINK_INPUT_OBJ:
case CFREE_LINK_INPUT_OBJ_BYTES:
- st = cfree_link_session_add_obj_bytes(link, &obj_in[ord->index]);
+ st = cfree_link_session_add_obj_bytes(
+ link, cfree_slice_cstr(o->object_files[ord->index]),
+ &obj_in[ord->index]);
break;
case CFREE_LINK_INPUT_ARCHIVE:
st = cfree_link_session_add_archive_bytes(link,
&arch_in[ord->index]);
break;
case CFREE_LINK_INPUT_DSO:
- st = cfree_link_session_add_dso_bytes(link, &dso_in[ord->index]);
+ st = cfree_link_session_add_dso_bytes(
+ link, cfree_slice_cstr(o->dsos[ord->index].path),
+ &dso_in[ord->index]);
break;
}
}
} else {
for (i = 0; i < o->nobject_files && st == CFREE_OK; ++i)
- st = cfree_link_session_add_obj_bytes(link, &obj_in[i]);
+ st = cfree_link_session_add_obj_bytes(
+ link, cfree_slice_cstr(o->object_files[i]), &obj_in[i]);
for (i = 0; i < o->narchives && st == CFREE_OK; ++i)
st = cfree_link_session_add_archive_bytes(link, &arch_in[i]);
for (i = 0; i < o->ndsos && st == CFREE_OK; ++i)
- st = cfree_link_session_add_dso_bytes(link, &dso_in[i]);
+ st = cfree_link_session_add_dso_bytes(
+ link, cfree_slice_cstr(o->dsos[i].path), &dso_in[i]);
}
if (st == CFREE_OK) st = cfree_link_session_emit(link, writer);
rc = st == CFREE_OK ? 0 : 1;
@@ -1228,7 +1261,8 @@ out:
* the writer so the bits are stable on disk. */
if (rc == 0 && o->output_path && !o->relocatable) {
if (driver_mark_executable_output(o->output_path) != 0) {
- driver_errf(LD_TOOL, "failed to set executable mode: %s", o->output_path);
+ driver_errf(LD_TOOL, "failed to set executable mode: %.*s",
+ CFREE_SLICE_ARG(cfree_slice_cstr(o->output_path)));
rc = 1;
}
}
diff --git a/driver/main.c b/driver/main.c
@@ -115,7 +115,8 @@ int driver_argv_wants_help(int argc, char** argv, int accept_short_h) {
void driver_help_top(void) {
driver_printf(
- "%s",
+ "%.*s",
+ CFREE_SLICE_ARG(CFREE_SLICE_LIT(
"cfree — freestanding C compiler toolchain\n"
"\n"
"USAGE\n"
@@ -151,7 +152,7 @@ void driver_help_top(void) {
"EXIT CODES\n"
" 0 success\n"
" 1 tool-reported error (compile, link, I/O, ...)\n"
- " 2 bad command-line usage\n");
+ " 2 bad command-line usage\n")));
}
int driver_main(int argc, char** argv) {
@@ -184,7 +185,8 @@ int driver_main(int argc, char** argv) {
return 0;
}
if (print_tool_help(argv[2]) == 0) return 0;
- driver_errf("cfree", "no such tool: %s", argv[2]);
+ driver_errf("cfree", "no such tool: %.*s",
+ CFREE_SLICE_ARG(cfree_slice_cstr(argv[2])));
return 2;
}
@@ -196,7 +198,8 @@ int driver_main(int argc, char** argv) {
if (rc != -1) return rc;
}
- driver_errf("cfree", "no such tool: %s", argv[1]);
+ driver_errf("cfree", "no such tool: %.*s",
+ CFREE_SLICE_ARG(cfree_slice_cstr(argv[1])));
driver_help_top();
return 2;
}
diff --git a/driver/objcopy.c b/driver/objcopy.c
@@ -35,7 +35,8 @@
void driver_help_objcopy(void) {
driver_printf(
- "%s",
+ "%.*s",
+ CFREE_SLICE_ARG(CFREE_SLICE_LIT(
"cfree objcopy — copy and transform an object file\n"
"\n"
"USAGE\n"
@@ -63,7 +64,7 @@ void driver_help_objcopy(void) {
" names: elf*, mach-o / macho*, coff*, wasm*\n"
"\n"
"EXIT CODES\n"
- " 0 success 1 I/O or strip error 2 bad usage\n");
+ " 0 success 1 I/O or strip error 2 bad usage\n")));
}
typedef enum CopyOp {
@@ -117,11 +118,11 @@ typedef struct CopyOpts {
const char* output;
} CopyOpts;
-static int name_in_list(const char* name, const char* const* list, uint32_t n) {
+static int name_in_list(CfreeSlice name, const char* const* list, uint32_t n) {
uint32_t i;
- if (!name) return 0;
+ if (!name.len) return 0;
for (i = 0; i < n; ++i) {
- if (list[i] && strcmp(list[i], name) == 0) return 1;
+ if (list[i] && cfree_slice_eq_cstr(name, list[i])) return 1;
}
return 0;
}
@@ -168,12 +169,12 @@ static int push_pair(DriverEnv* env, NamePair** arr, uint32_t* n, uint32_t* cap,
static int take_value(int* i, int argc, char** argv, const char* flag,
const char** out) {
const char* a = argv[*i];
- size_t flen = strlen(flag);
- if (strncmp(a, flag, flen) == 0 && a[flen] == '=') {
+ size_t flen = cfree_slice_cstr(flag).len;
+ if (driver_strneq(a, flag, flen) && a[flen] == '=') {
*out = a + flen + 1;
return 1;
}
- if (strcmp(a, flag) == 0) {
+ if (driver_streq(a, flag)) {
if (*i + 1 >= argc) return -1;
*out = argv[++(*i)];
return 1;
@@ -184,7 +185,7 @@ static int take_value(int* i, int argc, char** argv, const char* flag,
/* Split "old=new" / "name=file" at the first '='. */
static int split_pair(DriverEnv* env, const char* spec, const char** out_left,
const char** out_right) {
- const char* eq = strchr(spec, '=');
+ const char* eq = driver_strchr(spec, '=');
size_t llen;
char* left;
if (!eq || eq == spec || !eq[1]) return -1;
@@ -200,19 +201,20 @@ static int split_pair(DriverEnv* env, const char* spec, const char** out_left,
static int parse_fmt_name(const char* name, CfreeObjFmt* out) {
if (!name) return -1;
- if (strncmp(name, "elf", 3) == 0) {
+ if (driver_strneq(name, "elf", sizeof("elf") - 1)) {
*out = CFREE_OBJ_ELF;
return 0;
}
- if (strncmp(name, "mach", 4) == 0) {
+ if (driver_strneq(name, "mach", sizeof("mach") - 1)) {
*out = CFREE_OBJ_MACHO;
return 0;
}
- if (strncmp(name, "coff", 4) == 0 || strncmp(name, "pe-", 3) == 0) {
+ if (driver_strneq(name, "coff", sizeof("coff") - 1) ||
+ driver_strneq(name, "pe-", sizeof("pe-") - 1)) {
*out = CFREE_OBJ_COFF;
return 0;
}
- if (strncmp(name, "wasm", 4) == 0) {
+ if (driver_strneq(name, "wasm", sizeof("wasm") - 1)) {
*out = CFREE_OBJ_WASM;
return 0;
}
@@ -222,7 +224,7 @@ static int parse_fmt_name(const char* name, CfreeObjFmt* out) {
/* Lookup a symbol by name; CFREE_OBJ_SYMBOL_NONE if not found. */
static CfreeObjSymbol find_sym_id(CfreeObjFile* of, const char* name) {
CfreeObjSymInfo si;
- if (cfree_obj_symbol_by_name(of, name, &si) != CFREE_OK) {
+ if (cfree_obj_symbol_by_name(of, cfree_slice_cstr(name), &si) != CFREE_OK) {
return CFREE_OBJ_SYMBOL_NONE;
}
return si.id;
@@ -231,7 +233,7 @@ static CfreeObjSymbol find_sym_id(CfreeObjFile* of, const char* name) {
/* Lookup a section by name; CFREE_SECTION_NONE if not found. */
static CfreeObjSection find_sec_id(CfreeObjFile* of, const char* name) {
CfreeObjSection s = CFREE_SECTION_NONE;
- if (cfree_obj_section_by_name(of, name, &s) != CFREE_OK) {
+ if (cfree_obj_section_by_name(of, cfree_slice_cstr(name), &s) != CFREE_OK) {
return CFREE_SECTION_NONE;
}
return s;
@@ -377,12 +379,14 @@ static int run_transforms(DriverEnv* env, const CfreeContext* ctx,
for (i = 0; i < opts->nrename_sec; ++i) {
CfreeObjSection sid = find_sec_id(of, opts->rename_sections[i].old_name);
if (sid == CFREE_SECTION_NONE) {
- driver_errf(OBJCOPY_TOOL, "rename-section: '%s' not found",
- opts->rename_sections[i].old_name);
+ driver_errf(OBJCOPY_TOOL, "rename-section: '%.*s' not found",
+ CFREE_SLICE_ARG(
+ cfree_slice_cstr(opts->rename_sections[i].old_name)));
return 1;
}
- CfreeSym ns = cfree_sym_intern(cfree_obj_builder_compiler(b),
- opts->rename_sections[i].new_name);
+ CfreeSym ns = cfree_sym_intern(
+ cfree_obj_builder_compiler(b),
+ cfree_slice_cstr(opts->rename_sections[i].new_name));
cfree_obj_builder_rename_section(b, sid, ns);
}
@@ -391,15 +395,17 @@ static int run_transforms(DriverEnv* env, const CfreeContext* ctx,
CfreeObjSection sid = find_sec_id(of, opts->update_sections[i].old_name);
CfreeFileData fd = {0};
if (sid == CFREE_SECTION_NONE) {
- driver_errf(OBJCOPY_TOOL, "update-section: '%s' not found",
- opts->update_sections[i].old_name);
+ driver_errf(OBJCOPY_TOOL, "update-section: '%.*s' not found",
+ CFREE_SLICE_ARG(
+ cfree_slice_cstr(opts->update_sections[i].old_name)));
return 1;
}
if (ctx->file_io->read_all(ctx->file_io->user,
opts->update_sections[i].new_name,
&fd) != CFREE_OK) {
- driver_errf(OBJCOPY_TOOL, "update-section: cannot read %s",
- opts->update_sections[i].new_name);
+ driver_errf(OBJCOPY_TOOL, "update-section: cannot read %.*s",
+ CFREE_SLICE_ARG(
+ cfree_slice_cstr(opts->update_sections[i].new_name)));
return 1;
}
cfree_obj_builder_section_replace_bytes(b, sid, fd.data, fd.size);
@@ -415,20 +421,23 @@ static int run_transforms(DriverEnv* env, const CfreeContext* ctx,
if (ctx->file_io->read_all(ctx->file_io->user,
opts->add_sections[i].new_name, &fd) !=
CFREE_OK) {
- driver_errf(OBJCOPY_TOOL, "add-section: cannot read %s",
- opts->add_sections[i].new_name);
+ driver_errf(OBJCOPY_TOOL, "add-section: cannot read %.*s",
+ CFREE_SLICE_ARG(
+ cfree_slice_cstr(opts->add_sections[i].new_name)));
return 1;
}
memset(&desc, 0, sizeof desc);
- desc.name = cfree_sym_intern(cfree_obj_builder_compiler(b),
- opts->add_sections[i].old_name);
+ desc.name = cfree_sym_intern(
+ cfree_obj_builder_compiler(b),
+ cfree_slice_cstr(opts->add_sections[i].old_name));
desc.kind = CFREE_SEC_OTHER;
desc.flags = 0;
desc.align = 1;
desc.entsize = 0;
if (cfree_obj_builder_section(b, &desc, &nsid) != CFREE_OK) {
- driver_errf(OBJCOPY_TOOL, "add-section: failed to create '%s'",
- opts->add_sections[i].old_name);
+ driver_errf(OBJCOPY_TOOL, "add-section: failed to create '%.*s'",
+ CFREE_SLICE_ARG(
+ cfree_slice_cstr(opts->add_sections[i].old_name)));
ctx->file_io->release(ctx->file_io->user, &fd);
return 1;
}
@@ -443,7 +452,7 @@ static int run_transforms(DriverEnv* env, const CfreeContext* ctx,
cfree_obj_builder_rename_symbol(
b, sid,
cfree_sym_intern(cfree_obj_builder_compiler(b),
- opts->redefine_syms[i].new_name));
+ cfree_slice_cstr(opts->redefine_syms[i].new_name)));
}
/* --globalize-symbol / --localize-symbol / --weaken-symbol */
@@ -467,21 +476,24 @@ static int run_transforms(DriverEnv* env, const CfreeContext* ctx,
}
static int copy_one_object(DriverEnv* env, const CfreeContext* ctx,
- const CfreeBytes* input, const CopyOpts* opts,
- const char* output_path) {
+ const char* input_name, const CfreeSlice* input,
+ const CopyOpts* opts, const char* output_path) {
CfreeObjFile* of = NULL;
CfreeObjBuilder* b;
CfreeWriter* w = NULL;
CfreeStatus st;
int rc = 1;
- if (cfree_obj_open(ctx, input, &of) != CFREE_OK) {
- driver_errf(OBJCOPY_TOOL, "%s: not a recognized object", input->name);
+ if (cfree_obj_open(ctx, cfree_slice_cstr(input_name), input, &of) !=
+ CFREE_OK) {
+ driver_errf(OBJCOPY_TOOL, "%.*s: not a recognized object",
+ CFREE_SLICE_ARG(cfree_slice_cstr(input_name)));
return 1;
}
b = cfree_obj_file_builder(of);
if (!b) {
- driver_errf(OBJCOPY_TOOL, "%s: no builder", input->name);
+ driver_errf(OBJCOPY_TOOL, "%.*s: no builder",
+ CFREE_SLICE_ARG(cfree_slice_cstr(input_name)));
cfree_obj_free(of);
return 1;
}
@@ -491,7 +503,8 @@ static int copy_one_object(DriverEnv* env, const CfreeContext* ctx,
}
if (ctx->file_io->open_writer(ctx->file_io->user, output_path, &w) !=
CFREE_OK) {
- driver_errf(OBJCOPY_TOOL, "cannot open %s", output_path);
+ driver_errf(OBJCOPY_TOOL, "cannot open %.*s",
+ CFREE_SLICE_ARG(cfree_slice_cstr(output_path)));
cfree_obj_free(of);
return 1;
}
@@ -517,7 +530,7 @@ int driver_objcopy(int argc, char** argv) {
CfreeContext ctx;
CopyOpts opts;
CfreeFileData in_fd = {0};
- CfreeBytes input;
+ CfreeSlice input;
int have_in = 0;
int rc = 1;
int i;
@@ -556,7 +569,8 @@ int driver_objcopy(int argc, char** argv) {
goto done;
}
if (parse_fmt_name(argv[++i], &opts.output_fmt) != 0) {
- driver_errf(OBJCOPY_TOOL, "unknown output format: %s", argv[i]);
+ driver_errf(OBJCOPY_TOOL, "unknown output format: %.*s",
+ CFREE_SLICE_ARG(cfree_slice_cstr(argv[i])));
rc = 2;
goto done;
}
@@ -584,8 +598,8 @@ int driver_objcopy(int argc, char** argv) {
if (matched) {
const char *left, *right;
if (split_pair(&env, val, &left, &right) != 0) {
- driver_errf(OBJCOPY_TOOL, "rename-section: expected OLD=NEW (got %s)",
- val);
+ driver_errf(OBJCOPY_TOOL, "rename-section: expected OLD=NEW (got %.*s)",
+ CFREE_SLICE_ARG(cfree_slice_cstr(val)));
rc = 2;
goto done;
}
@@ -599,8 +613,8 @@ int driver_objcopy(int argc, char** argv) {
if (matched) {
const char *left, *right;
if (split_pair(&env, val, &left, &right) != 0) {
- driver_errf(OBJCOPY_TOOL, "add-section: expected NAME=FILE (got %s)",
- val);
+ driver_errf(OBJCOPY_TOOL, "add-section: expected NAME=FILE (got %.*s)",
+ CFREE_SLICE_ARG(cfree_slice_cstr(val)));
rc = 2;
goto done;
}
@@ -614,8 +628,8 @@ int driver_objcopy(int argc, char** argv) {
if (matched) {
const char *left, *right;
if (split_pair(&env, val, &left, &right) != 0) {
- driver_errf(OBJCOPY_TOOL, "update-section: expected NAME=FILE (got %s)",
- val);
+ driver_errf(OBJCOPY_TOOL, "update-section: expected NAME=FILE (got %.*s)",
+ CFREE_SLICE_ARG(cfree_slice_cstr(val)));
rc = 2;
goto done;
}
@@ -629,8 +643,8 @@ int driver_objcopy(int argc, char** argv) {
if (matched) {
const char *left, *right;
if (split_pair(&env, val, &left, &right) != 0) {
- driver_errf(OBJCOPY_TOOL, "redefine-sym: expected OLD=NEW (got %s)",
- val);
+ driver_errf(OBJCOPY_TOOL, "redefine-sym: expected OLD=NEW (got %.*s)",
+ CFREE_SLICE_ARG(cfree_slice_cstr(val)));
rc = 2;
goto done;
}
@@ -662,7 +676,8 @@ int driver_objcopy(int argc, char** argv) {
continue;
}
if (a[0] == '-' && a[1] != '\0') {
- driver_errf(OBJCOPY_TOOL, "unknown option: %s", a);
+ driver_errf(OBJCOPY_TOOL, "unknown option: %.*s",
+ CFREE_SLICE_ARG(cfree_slice_cstr(a)));
rc = 2;
goto done;
}
@@ -671,7 +686,8 @@ int driver_objcopy(int argc, char** argv) {
} else if (!opts.output) {
opts.output = a;
} else {
- driver_errf(OBJCOPY_TOOL, "unexpected argument: %s", a);
+ driver_errf(OBJCOPY_TOOL, "unexpected argument: %.*s",
+ CFREE_SLICE_ARG(cfree_slice_cstr(a)));
rc = 2;
goto done;
}
@@ -686,15 +702,15 @@ int driver_objcopy(int argc, char** argv) {
if (ctx.file_io->read_all(ctx.file_io->user, opts.input, &in_fd) !=
CFREE_OK) {
- driver_errf(OBJCOPY_TOOL, "cannot read %s", opts.input);
+ driver_errf(OBJCOPY_TOOL, "cannot read %.*s",
+ CFREE_SLICE_ARG(cfree_slice_cstr(opts.input)));
goto done;
}
have_in = 1;
- input.name = opts.input;
input.data = in_fd.data;
input.len = in_fd.size;
- rc = copy_one_object(&env, &ctx, &input, &opts, out_path);
+ rc = copy_one_object(&env, &ctx, opts.input, &input, &opts, out_path);
done:
if (have_in) ctx.file_io->release(ctx.file_io->user, &in_fd);
@@ -729,7 +745,8 @@ done:
return rc;
missing_value:
- driver_errf(OBJCOPY_TOOL, "%s requires a value", argv[i]);
+ driver_errf(OBJCOPY_TOOL, "%.*s requires a value",
+ CFREE_SLICE_ARG(cfree_slice_cstr(argv[i])));
rc = 2;
goto done;
oom:
diff --git a/driver/objdump.c b/driver/objdump.c
@@ -30,15 +30,17 @@ typedef struct ObjdumpOpts {
} ObjdumpOpts;
static void objdump_usage(void) {
- driver_errf(OBJDUMP_TOOL, "%s",
+ driver_errf(OBJDUMP_TOOL, "%.*s",
+ CFREE_SLICE_ARG(CFREE_SLICE_LIT(
"usage: cfree objdump [-h] [-t] [-d] [-D] [-r] [-s] [-j NAME "
"...] input...\n"
- " cfree objdump --help for full option reference");
+ " cfree objdump --help for full option reference")));
}
void driver_help_objdump(void) {
driver_printf(
- "%s",
+ "%.*s",
+ CFREE_SLICE_ARG(CFREE_SLICE_LIT(
"cfree objdump — print info about object files and archives\n"
"\n"
"USAGE\n"
@@ -94,7 +96,7 @@ void driver_help_objdump(void) {
"\n"
"EXIT CODES\n"
" 0 success 1 parse / I/O error 2 bad "
- "usage\n");
+ "usage\n")));
}
/* ---- PE/COFF private-header walker (used by `-p`) ----
@@ -140,7 +142,7 @@ void driver_help_objdump(void) {
#define OBJDUMP_IMAGE_SCN_MEM_DISCARDABLE 0x02000000u
#define OBJDUMP_IMAGE_SCN_MEM_SHARED 0x10000000u
-static int j_match(const ObjdumpOpts* o, const char* name);
+static int j_match(const ObjdumpOpts* o, CfreeSlice name);
static uint16_t pe_rd_u16(const uint8_t* p) {
return (uint16_t)(p[0] | ((uint32_t)p[1] << 8));
@@ -302,7 +304,9 @@ static void pe_dump_imports(const uint8_t* buf, size_t buf_len, size_t sec_off,
dll[0] = '\0';
}
}
- driver_printf(" DLL Name: %s\n", dll[0] ? dll : "(unreadable)");
+ driver_printf(" DLL Name: %.*s\n",
+ CFREE_SLICE_ARG(cfree_slice_cstr(dll[0] ? dll
+ : "(unreadable)")));
driver_printf(" ILT RVA: 0x%x IAT RVA: 0x%x\n", ilt_rva, iat_rva);
/* Prefer walking the original first thunk (ILT) for names. Some
* mingw-emitted images zero the ILT and only ship the IAT; fall
@@ -330,7 +334,8 @@ static void pe_dump_imports(const uint8_t* buf, size_t buf_len, size_t sec_off,
sizeof name) != 0) {
continue;
}
- driver_printf(" Name: %s\n", name);
+ driver_printf(" Name: %.*s\n",
+ CFREE_SLICE_ARG(cfree_slice_cstr(name)));
}
}
}
@@ -410,17 +415,20 @@ static const char* pe_machine_name(uint16_t m) {
* Counterpart to dump_file_header for inputs that cfree_obj_open can't
* parse yet (PE executables / DLLs vs .obj). */
static void dump_pe_file_header(const char* label, const PeImage* pe) {
- driver_printf("%s:\tfile format pei-%s\n\n", label,
- pe_machine_name(pe->machine));
- driver_printf("architecture: %s, flags 0x%04x\n",
- pe_machine_name(pe->machine), (unsigned)pe->file_chars);
+ driver_printf("%.*s:\tfile format pei-%.*s\n\n",
+ CFREE_SLICE_ARG(cfree_slice_cstr(label)),
+ CFREE_SLICE_ARG(cfree_slice_cstr(pe_machine_name(pe->machine))));
+ driver_printf("architecture: %.*s, flags 0x%04x\n",
+ CFREE_SLICE_ARG(cfree_slice_cstr(pe_machine_name(pe->machine))),
+ (unsigned)pe->file_chars);
if (pe->opt_magic == PE_OPT_HDR64_MAGIC) {
driver_printf("start address 0x%016llx\n",
(unsigned long long)(pe->image_base + pe->entry_rva));
driver_printf(
- "image base: 0x%llx, entry rva: 0x%x, subsystem: %u (%s)\n\n",
+ "image base: 0x%llx, entry rva: 0x%x, subsystem: %u (%.*s)\n\n",
(unsigned long long)pe->image_base, pe->entry_rva,
- (unsigned)pe->subsystem, pe_subsystem_name(pe->subsystem));
+ (unsigned)pe->subsystem,
+ CFREE_SLICE_ARG(cfree_slice_cstr(pe_subsystem_name(pe->subsystem))));
} else {
driver_printf("PE32 (magic 0x%x) — only PE32+ inspection is implemented\n\n",
(unsigned)pe->opt_magic);
@@ -468,7 +476,8 @@ static void dump_pe_sections(const char* label, const PeImage* pe,
uint16_t i;
char flagbuf[160];
char name[9];
- driver_printf("%s:\tSections (PE image):\n", label);
+ driver_printf("%.*s:\tSections (PE image):\n",
+ CFREE_SLICE_ARG(cfree_slice_cstr(label)));
driver_printf("Idx Name VMA Size "
"FileOff Align Flags\n");
for (i = 0; i < pe->nsec; ++i) {
@@ -491,11 +500,12 @@ static void dump_pe_sections(const char* label, const PeImage* pe,
ch = pe_rd_u32(buf + sh + 36);
align_field = (ch >> 20) & 0xFu;
align_log2 = align_field ? (align_field - 1u) : 0u;
- if (!j_match(opts, name)) continue;
+ if (!j_match(opts, cfree_slice_cstr(name))) continue;
render_pe_sec_flags(ch, flagbuf, sizeof(flagbuf));
- driver_printf("%3u %-16s %016llx %08x %08x 2**%-2u %s\n", (unsigned)i,
+ driver_printf("%3u %-16s %016llx %08x %08x 2**%-2u %.*s\n", (unsigned)i,
name, (unsigned long long)(pe->image_base + va),
- vsize ? vsize : raw_size, raw_off, align_log2, flagbuf);
+ vsize ? vsize : raw_size, raw_off, align_log2,
+ CFREE_SLICE_ARG(cfree_slice_cstr(flagbuf)));
driver_printf(" Characteristics: 0x%08x\n",
ch);
}
@@ -514,21 +524,24 @@ static void dump_pe_private(const char* label, const uint8_t* buf,
uint32_t i;
if (!pe_parse_image(buf, buf_len, &pe) || !pe.valid) return;
if (pe.opt_magic != PE_OPT_HDR64_MAGIC) {
- driver_printf("%s:\tPE optional header magic 0x%x (PE32) — skipping\n",
- label, (unsigned)pe.opt_magic);
+ driver_printf("%.*s:\tPE optional header magic 0x%x (PE32) — skipping\n",
+ CFREE_SLICE_ARG(cfree_slice_cstr(label)),
+ (unsigned)pe.opt_magic);
return;
}
- driver_printf("\n%s:\tPE32+ private headers\n", label);
+ driver_printf("\n%.*s:\tPE32+ private headers\n",
+ CFREE_SLICE_ARG(cfree_slice_cstr(label)));
driver_printf(" Magic: 0x%x (PE32+)\n", pe.opt_magic);
- driver_printf(" Machine: 0x%04x (%s)\n", (unsigned)pe.machine,
- pe_machine_name(pe.machine));
+ driver_printf(" Machine: 0x%04x (%.*s)\n", (unsigned)pe.machine,
+ CFREE_SLICE_ARG(cfree_slice_cstr(pe_machine_name(pe.machine))));
driver_printf(" Characteristics: 0x%04x\n", (unsigned)pe.file_chars);
driver_printf(" ImageBase: 0x%llx\n",
(unsigned long long)pe.image_base);
driver_printf(" AddressOfEntryPoint: 0x%x\n", pe.entry_rva);
- driver_printf(" Subsystem: %u (%s)\n", (unsigned)pe.subsystem,
- pe_subsystem_name(pe.subsystem));
+ driver_printf(" Subsystem: %u (%.*s)\n", (unsigned)pe.subsystem,
+ CFREE_SLICE_ARG(
+ cfree_slice_cstr(pe_subsystem_name(pe.subsystem))));
driver_printf(" DllCharacteristics: 0x%04x\n", (unsigned)pe.dllchars);
driver_printf(" NumberOfSections: %u\n", (unsigned)pe.nsec);
@@ -626,11 +639,11 @@ static char sym_kind_char(CfreeSymKind k) {
return ' ';
}
-static int j_match(const ObjdumpOpts* o, const char* name) {
+static int j_match(const ObjdumpOpts* o, CfreeSlice name) {
int i;
if (o->nj == 0) return 1;
for (i = 0; i < o->nj; ++i) {
- if (driver_streq(o->j[i], name)) return 1;
+ if (cfree_slice_eq_cstr(name, o->j[i])) return 1;
}
return 0;
}
@@ -677,7 +690,8 @@ static void render_sec_flags(const CfreeObjSecInfo* sec, CfreeObjFmt fmt,
}
if (sec->entsize && n + 1 < cap) {
char tmp[32];
- int k = snprintf(tmp, sizeof tmp, "%sentsize=%u", n ? "," : "",
+ int k = snprintf(tmp, sizeof tmp, "%.*sentsize=%u",
+ CFREE_SLICE_ARG(cfree_slice_cstr(n ? "," : "")),
sec->entsize);
size_t j;
for (j = 0; k > 0 && j < (size_t)k && n + 1 < cap; ++j)
@@ -702,10 +716,10 @@ static void dump_sections(CfreeObjFile* f, const ObjdumpOpts* opts) {
cfree_obj_section_format_flags(f, i, &raw_type, NULL);
render_sec_flags(&sec, fmt, raw_type, flagbuf, sizeof(flagbuf));
driver_printf(
- "%3u %-20s %08llx 2**%-2u %s\n", i, sec.name[0] ? sec.name : "(anon)",
- (unsigned long long)sec.size,
+ "%3u %-20s %08llx 2**%-2u %.*s\n", i,
+ sec.name.len ? sec.name.s : "(anon)", (unsigned long long)sec.size,
sec.align ? (unsigned)__builtin_ctz(sec.align ? sec.align : 1) : 0,
- flagbuf);
+ CFREE_SLICE_ARG(cfree_slice_cstr(flagbuf)));
/* Show the raw IMAGE_SCN_* value on a continuation line for COFF
* inputs — useful when diagnosing why a section ended up with the
* tags it did. The hex is much shorter than printing every set bit
@@ -736,17 +750,19 @@ static void dump_groups(CfreeObjFile* f, const ObjdumpOpts* opts) {
driver_printf("COMDAT groups:\n");
printed_header = 1;
}
- driver_printf(" group %s (signature sym #%u, %u section%s)\n",
- g.name && g.name[0] ? g.name : "(anon)",
+ driver_printf(" group %.*s (signature sym #%u, %u section%.*s)\n",
+ CFREE_SLICE_ARG(g.name.len ? g.name
+ : CFREE_SLICE_LIT("(anon)")),
(unsigned)g.signature, (unsigned)g.nsections,
- g.nsections == 1 ? "" : "s");
+ CFREE_SLICE_ARG(cfree_slice_cstr(g.nsections == 1 ? "" : "s")));
for (k = 0; k < g.nsections; ++k) {
CfreeObjSection sid = g.sections[k];
CfreeObjSecInfo si;
if (sid == CFREE_SECTION_NONE) continue;
if (cfree_obj_section(f, sid, &si) != CFREE_OK) continue;
- driver_printf(" [%3u] %s\n", (unsigned)sid,
- si.name && si.name[0] ? si.name : "(anon)");
+ driver_printf(" [%3u] %.*s\n", (unsigned)sid,
+ CFREE_SLICE_ARG(si.name.len ? si.name
+ : CFREE_SLICE_LIT("(anon)")));
}
}
cfree_obj_groupiter_free(it);
@@ -761,20 +777,21 @@ static void dump_symbols(CfreeObjFile* f, const ObjdumpOpts* opts) {
if (cfree_obj_symiter_new(f, &it) != CFREE_OK) return;
for (;;) {
CfreeIterResult r = cfree_obj_symiter_next(it, &sym);
- const char* secname;
+ CfreeSlice secname;
if (r != CFREE_ITER_ITEM) break;
if (sym.section == CFREE_SECTION_NONE) {
- secname = "*UND*";
+ secname = CFREE_SLICE_LIT("*UND*");
} else {
CfreeObjSecInfo sec;
if (cfree_obj_section(f, sym.section, &sec) != CFREE_OK) continue;
- secname = sec.name[0] ? sec.name : "(none)";
+ secname = sec.name.len ? sec.name : CFREE_SLICE_LIT("(none)");
if (opts->nj && !j_match(opts, secname)) continue;
}
driver_printf(
- "%016llx %c %c %-18s %016llx %s\n", (unsigned long long)sym.value,
- sym_bind_char(sym.bind), sym_kind_char(sym.kind), secname,
- (unsigned long long)sym.size, sym.name[0] ? sym.name : "(none)");
+ "%016llx %c %c %-18s %016llx %.*s\n", (unsigned long long)sym.value,
+ sym_bind_char(sym.bind), sym_kind_char(sym.kind), secname.s,
+ (unsigned long long)sym.size,
+ CFREE_SLICE_ARG(sym.name.len ? sym.name : CFREE_SLICE_LIT("(none)")));
}
cfree_obj_symiter_free(it);
driver_printf("\n");
@@ -795,8 +812,9 @@ static void dump_hex(CfreeObjFile* f, const ObjdumpOpts* opts) {
if (cfree_obj_section_data(f, i, &data, &len) != CFREE_OK) continue;
if (!data || len == 0) continue;
- driver_printf("Contents of section %s:\n",
- sec.name[0] ? sec.name : "(anon)");
+ driver_printf("Contents of section %.*s:\n",
+ CFREE_SLICE_ARG(sec.name.len ? sec.name
+ : CFREE_SLICE_LIT("(anon)")));
for (ofs = 0; ofs < len; ofs += 16) {
size_t j;
char ascii[17];
@@ -814,7 +832,7 @@ static void dump_hex(CfreeObjFile* f, const ObjdumpOpts* opts) {
if ((j & 1) == 1) driver_printf(" ");
}
ascii[16] = '\0';
- driver_printf(" %s\n", ascii);
+ driver_printf(" %.*s\n", CFREE_SLICE_ARG(cfree_slice_cstr(ascii)));
}
}
driver_printf("\n");
@@ -837,23 +855,27 @@ static void dump_relocs(CfreeObjFile* f, const ObjdumpOpts* opts) {
if (r.section != cur_sec) {
if (printed_header) driver_printf("\n");
- driver_printf("RELOCATION RECORDS FOR [%s]:\n",
- sec.name[0] ? sec.name : "(anon)");
+ driver_printf("RELOCATION RECORDS FOR [%.*s]:\n",
+ CFREE_SLICE_ARG(sec.name.len ? sec.name
+ : CFREE_SLICE_LIT("(anon)")));
driver_printf("OFFSET TYPE VALUE\n");
cur_sec = r.section;
printed_header = 1;
}
if (r.addend) {
- driver_printf("%016llx %-17s %s%c0x%llx\n", (unsigned long long)r.offset,
- r.kind_name ? r.kind_name : "?",
- r.sym_name && r.sym_name[0] ? r.sym_name : "*ABS*",
+ driver_printf("%016llx %-17s %.*s%c0x%llx\n",
+ (unsigned long long)r.offset,
+ r.kind_name.len ? r.kind_name.s : "?",
+ CFREE_SLICE_ARG(r.sym_name.len ? r.sym_name
+ : CFREE_SLICE_LIT("*ABS*")),
r.addend < 0 ? '-' : '+',
(unsigned long long)(r.addend < 0 ? -r.addend : r.addend));
} else {
- driver_printf("%016llx %-17s %s\n", (unsigned long long)r.offset,
- r.kind_name ? r.kind_name : "?",
- r.sym_name && r.sym_name[0] ? r.sym_name : "*ABS*");
+ driver_printf("%016llx %-17s %.*s\n", (unsigned long long)r.offset,
+ r.kind_name.len ? r.kind_name.s : "?",
+ CFREE_SLICE_ARG(r.sym_name.len ? r.sym_name
+ : CFREE_SLICE_LIT("*ABS*")));
}
emitted_any = 1;
}
@@ -861,18 +883,18 @@ static void dump_relocs(CfreeObjFile* f, const ObjdumpOpts* opts) {
if (emitted_any) driver_printf("\n");
}
-static const char* objdump_sym_at(CfreeObjFile* f, uint32_t section_idx,
- uint64_t value) {
+static CfreeSlice objdump_sym_at(CfreeObjFile* f, uint32_t section_idx,
+ uint64_t value) {
CfreeObjSymIter* it = NULL;
CfreeObjSymInfo sym;
- const char* best = NULL;
+ CfreeSlice best = CFREE_SLICE_NULL;
- if (cfree_obj_symiter_new(f, &it) != CFREE_OK) return NULL;
+ if (cfree_obj_symiter_new(f, &it) != CFREE_OK) return CFREE_SLICE_NULL;
for (;;) {
CfreeIterResult r = cfree_obj_symiter_next(it, &sym);
if (r != CFREE_ITER_ITEM) break;
if (sym.section != section_idx || sym.value != value) continue;
- if (!sym.name || !sym.name[0]) continue;
+ if (!sym.name.len) continue;
if (sym.kind == CFREE_SK_SECTION) continue;
best = sym.name;
if (sym.kind == CFREE_SK_FUNC || sym.bind != CFREE_SB_LOCAL) break;
@@ -907,29 +929,30 @@ static void dump_disasm(const CfreeDisasmContext* dctx, CfreeObjFile* f,
if (cfree_obj_section_data(f, i, &data, &len) != CFREE_OK) continue;
if (!data || len == 0) continue;
- driver_printf("Disassembly of section %s:\n\n",
- sec.name[0] ? sec.name : "(anon)");
+ driver_printf("Disassembly of section %.*s:\n\n",
+ CFREE_SLICE_ARG(sec.name.len ? sec.name
+ : CFREE_SLICE_LIT("(anon)")));
if (cfree_disasm_iter_new(&file_dctx, data, len, 0, f, &dis) != CFREE_OK)
continue;
for (;;) {
CfreeIterResult r = cfree_disasm_iter_next(dis, &insn);
uint32_t b;
- const char* label;
+ CfreeSlice label;
if (r != CFREE_ITER_ITEM) break;
label = objdump_sym_at(f, i, insn.vaddr);
- if (label)
- driver_printf("%016llx <%s>:\n", (unsigned long long)insn.vaddr,
- label);
+ if (label.len)
+ driver_printf("%016llx <%.*s>:\n", (unsigned long long)insn.vaddr,
+ CFREE_SLICE_ARG(label));
driver_printf("%8llx:\t", (unsigned long long)insn.vaddr);
for (b = 0; b < insn.nbytes; ++b) driver_printf("%02x ", insn.bytes[b]);
for (b = insn.nbytes; b < 8; ++b) driver_printf(" ");
- driver_printf("\t%s", insn.mnemonic ? insn.mnemonic : "");
- if (insn.operands && insn.operands[0]) {
- driver_printf(" %s", insn.operands);
+ driver_printf("\t%.*s", CFREE_SLICE_ARG(insn.mnemonic));
+ if (insn.operands.len) {
+ driver_printf(" %.*s", CFREE_SLICE_ARG(insn.operands));
}
- if (insn.annotation && insn.annotation[0]) {
- driver_printf(" # %s", insn.annotation);
+ if (insn.annotation.len) {
+ driver_printf(" # %.*s", CFREE_SLICE_ARG(insn.annotation));
}
driver_printf("\n");
}
@@ -969,14 +992,15 @@ static void dump_file_header(CfreeObjFile* f, const char* label) {
if (has_relocs) flags |= 0x0001u;
if (nsym) flags |= 0x0010u;
- driver_printf("architecture: %s, flags 0x%08x:\n", arch_str(target.arch),
- flags);
+ driver_printf("architecture: %.*s, flags 0x%08x:\n",
+ CFREE_SLICE_ARG(cfree_slice_cstr(arch_str(target.arch))), flags);
if (has_relocs) driver_printf("HAS_RELOC, ");
if (nsym) driver_printf("HAS_SYMS");
if (has_relocs || nsym) driver_printf("\n");
driver_printf("start address 0x%016llx\n", 0ull);
- driver_printf("format: %s, sections: %u, symbols: %u\n\n",
- fmt_str(fmt, target.ptr_size), nsec, nsym);
+ driver_printf("format: %.*s, sections: %u, symbols: %u\n\n",
+ CFREE_SLICE_ARG(cfree_slice_cstr(fmt_str(fmt, target.ptr_size))),
+ nsec, nsym);
(void)label;
}
@@ -985,8 +1009,10 @@ static void dump_obj(const CfreeDisasmContext* dctx, const char* label,
CfreeTarget target = cfree_obj_target(f);
CfreeObjFmt fmt = cfree_obj_fmt(f);
- driver_printf("%s:\tfile format %s-%s\n\n", label,
- fmt_str(fmt, target.ptr_size), arch_str(target.arch));
+ driver_printf("%.*s:\tfile format %.*s-%.*s\n\n",
+ CFREE_SLICE_ARG(cfree_slice_cstr(label)),
+ CFREE_SLICE_ARG(cfree_slice_cstr(fmt_str(fmt, target.ptr_size))),
+ CFREE_SLICE_ARG(cfree_slice_cstr(arch_str(target.arch))));
if (opts->f) dump_file_header(f, label);
if (opts->h) dump_sections(f, opts);
@@ -997,7 +1023,7 @@ static void dump_obj(const CfreeDisasmContext* dctx, const char* label,
if (opts->r) dump_relocs(f, opts);
}
-static int dump_archive(const char* path, const CfreeBytes* input,
+static int dump_archive(const char* path, const CfreeSlice* input,
const CfreeContext* ctx,
const CfreeDisasmContext* dctx,
const ObjdumpOpts* opts) {
@@ -1006,12 +1032,13 @@ static int dump_archive(const char* path, const CfreeBytes* input,
char label[256];
int j;
- driver_printf("In archive %s:\n\n", path);
+ driver_printf("In archive %.*s:\n\n",
+ CFREE_SLICE_ARG(cfree_slice_cstr(path)));
if (cfree_ar_iter_new(ctx, input, &it) != CFREE_OK) return 1;
for (;;) {
CfreeIterResult r = cfree_ar_iter_next(it, &member);
- CfreeBytes min;
+ CfreeSlice min;
CfreeObjFile* f = NULL;
if (r != CFREE_ITER_ITEM) break;
@@ -1023,18 +1050,18 @@ static int dump_archive(const char* path, const CfreeBytes* input,
}
label[j++] = '(';
{
- const char* p = member.name;
- while (*p && j < 252) label[j++] = *p++;
+ size_t k = 0;
+ while (k < member.name.len && j < 252) label[j++] = member.name.s[k++];
}
label[j++] = ')';
label[j] = '\0';
- min.name = member.name;
min.data = member.data;
min.len = member.size;
- if (cfree_obj_open(ctx, &min, &f) != CFREE_OK) {
- driver_errf(OBJDUMP_TOOL, "failed to parse member: %s", label);
+ if (cfree_obj_open(ctx, member.name, &min, &f) != CFREE_OK) {
+ driver_errf(OBJDUMP_TOOL, "failed to parse member: %.*s",
+ CFREE_SLICE_ARG(cfree_slice_cstr(label)));
continue;
}
dump_obj(dctx, label, f, opts);
@@ -1153,12 +1180,14 @@ int driver_objdump(int argc, char** argv) {
if (a[0] != '-' || a[1] == '\0') continue;
if (driver_streq(a, "-j")) {
if (i + 1 >= argc) {
- driver_errf(OBJDUMP_TOOL, "%s", "-j requires a section name");
+ driver_errf(OBJDUMP_TOOL, "%.*s",
+ CFREE_SLICE_ARG(CFREE_SLICE_LIT("-j requires a section name")));
rc = 2;
goto done;
}
if (opts.nj >= MAX_J_FILTERS) {
- driver_errf(OBJDUMP_TOOL, "%s", "too many -j filters");
+ driver_errf(OBJDUMP_TOOL, "%.*s",
+ CFREE_SLICE_ARG(CFREE_SLICE_LIT("too many -j filters")));
rc = 2;
goto done;
}
@@ -1192,7 +1221,7 @@ int driver_objdump(int argc, char** argv) {
for (i = 1; i < argc && rc == 0; ++i) {
const char* a = argv[i];
CfreeFileData fd = {0};
- CfreeBytes input;
+ CfreeSlice input;
CfreeBinFmt bin;
if (a[0] == '-' && a[1] != '\0') {
@@ -1202,12 +1231,12 @@ int driver_objdump(int argc, char** argv) {
saw_input = 1;
if (ctx.file_io->read_all(ctx.file_io->user, a, &fd) != CFREE_OK) {
- driver_errf(OBJDUMP_TOOL, "failed to read: %s", a);
+ driver_errf(OBJDUMP_TOOL, "failed to read: %.*s",
+ CFREE_SLICE_ARG(cfree_slice_cstr(a)));
rc = 1;
break;
}
- input.name = a;
input.data = fd.data;
input.len = fd.size;
@@ -1227,7 +1256,7 @@ int driver_objdump(int argc, char** argv) {
* -h / -p by walking the raw image bytes; -t / -d / -r / -s
* still need an ObjFile and are skipped with a soft error so
* the other ops don't get swallowed. */
- if (cfree_obj_open(&ctx, &input, &f) != CFREE_OK) {
+ if (cfree_obj_open(&ctx, cfree_slice_cstr(a), &input, &f) != CFREE_OK) {
if (bin == CFREE_BIN_PE) {
PeImage pe;
int parsed = pe_parse_image(input.data, input.len, &pe) && pe.valid;
@@ -1246,13 +1275,14 @@ int driver_objdump(int argc, char** argv) {
}
if (!handled) {
driver_errf(OBJDUMP_TOOL,
- "%s: PE images support only -f / -h / -p; "
+ "%.*s: PE images support only -f / -h / -p; "
"use -p for image details",
- a);
+ CFREE_SLICE_ARG(cfree_slice_cstr(a)));
rc = 1;
}
} else {
- driver_errf(OBJDUMP_TOOL, "failed to parse: %s", a);
+ driver_errf(OBJDUMP_TOOL, "failed to parse: %.*s",
+ CFREE_SLICE_ARG(cfree_slice_cstr(a)));
rc = 1;
}
} else {
@@ -1266,7 +1296,8 @@ int driver_objdump(int argc, char** argv) {
}
case CFREE_BIN_UNKNOWN:
default:
- driver_errf(OBJDUMP_TOOL, "unsupported file format: %s", a);
+ driver_errf(OBJDUMP_TOOL, "unsupported file format: %.*s",
+ CFREE_SLICE_ARG(cfree_slice_cstr(a)));
rc = 1;
break;
}
diff --git a/driver/ranlib.c b/driver/ranlib.c
@@ -24,7 +24,8 @@
void driver_help_ranlib(void) {
driver_printf(
- "%s",
+ "%.*s",
+ CFREE_SLICE_ARG(CFREE_SLICE_LIT(
"cfree ranlib — refresh the symbol index of an `ar` archive\n"
"\n"
"USAGE\n"
@@ -45,7 +46,7 @@ void driver_help_ranlib(void) {
"\n"
"EXIT CODES\n"
" 0 success 1 archive I/O error 2 bad "
- "usage\n");
+ "usage\n")));
}
static uint64_t ranlib_epoch_from_env(void) {
@@ -63,10 +64,10 @@ int driver_ranlib(int argc, char** argv) {
DriverEnv env;
CfreeContext ctx;
CfreeFileData old_fd = {0};
- CfreeBytes input;
+ CfreeSlice input;
CfreeArIter* it = NULL;
CfreeArMember m;
- CfreeBytes* members = NULL;
+ CfreeArInput* members = NULL;
char* name_storage = NULL;
size_t name_bytes_total = 0;
uint32_t nmembers = 0;
@@ -95,11 +96,11 @@ int driver_ranlib(int argc, char** argv) {
if (ctx.file_io->read_all(ctx.file_io->user, archive_path, &old_fd) !=
CFREE_OK) {
- driver_errf(RANLIB_TOOL, "failed to read: %s", archive_path);
+ driver_errf(RANLIB_TOOL, "failed to read: %.*s",
+ CFREE_SLICE_ARG(cfree_slice_cstr(archive_path)));
goto out;
}
have_old = 1;
- input.name = archive_path;
input.data = old_fd.data;
input.len = old_fd.size;
@@ -107,14 +108,15 @@ int driver_ranlib(int argc, char** argv) {
* the iterator alias an internal buffer overwritten on each next(), so
* we stash a stable copy). */
if (cfree_ar_iter_new(&ctx, &input, &it) != CFREE_OK) {
- driver_errf(RANLIB_TOOL, "not an archive: %s", archive_path);
+ driver_errf(RANLIB_TOOL, "not an archive: %.*s",
+ CFREE_SLICE_ARG(cfree_slice_cstr(archive_path)));
goto out;
}
for (;;) {
CfreeIterResult r = cfree_ar_iter_next(it, &m);
if (r != CFREE_ITER_ITEM) break;
nmembers++;
- name_bytes_total += driver_strlen(m.name) + 1;
+ name_bytes_total += m.name.len + 1;
}
cfree_ar_iter_free(it);
it = NULL;
@@ -124,7 +126,8 @@ int driver_ranlib(int argc, char** argv) {
* GNU ranlib's behaviour). */
if (ctx.file_io->open_writer(ctx.file_io->user, archive_path, &out) !=
CFREE_OK) {
- driver_errf(RANLIB_TOOL, "failed to open: %s", archive_path);
+ driver_errf(RANLIB_TOOL, "failed to open: %.*s",
+ CFREE_SLICE_ARG(cfree_slice_cstr(archive_path)));
goto out;
}
opts.epoch = ranlib_epoch_from_env();
@@ -134,7 +137,7 @@ int driver_ranlib(int argc, char** argv) {
goto out;
}
- members = (CfreeBytes*)driver_alloc_zeroed(
+ members = (CfreeArInput*)driver_alloc_zeroed(
&env, (size_t)nmembers * sizeof(*members));
if (!members) {
driver_errf(RANLIB_TOOL, "out of memory");
@@ -159,14 +162,15 @@ int driver_ranlib(int argc, char** argv) {
while (k < nmembers) {
CfreeIterResult r = cfree_ar_iter_next(it, &m);
char* dst;
- const char* p;
+ size_t j;
if (r != CFREE_ITER_ITEM) break;
dst = name_storage + cursor;
- for (p = m.name; *p; ++p) *dst++ = *p;
+ for (j = 0; j < m.name.len; ++j) *dst++ = m.name.s[j];
*dst++ = '\0';
- members[k].name = name_storage + cursor;
- members[k].data = m.data;
- members[k].len = m.size;
+ members[k].name.s = name_storage + cursor;
+ members[k].name.len = m.name.len;
+ members[k].bytes.data = m.data;
+ members[k].bytes.len = m.size;
cursor = (size_t)(dst - name_storage);
k++;
}
@@ -188,9 +192,9 @@ int driver_ranlib(int argc, char** argv) {
for (i = 0; i < nmembers; ++i) {
void* blob = NULL;
size_t blob_size = 0;
- const char** names = NULL;
+ const CfreeSlice* names = NULL;
uint32_t count = 0;
- if (driver_collect_obj_global_syms(&env, &ctx, RANLIB_TOOL, &members[i],
+ if (driver_collect_obj_global_syms(&env, &ctx, RANLIB_TOOL, &members[i].bytes,
&blob, &blob_size, &names,
&count) != 0) {
goto out;
@@ -203,7 +207,8 @@ int driver_ranlib(int argc, char** argv) {
if (ctx.file_io->open_writer(ctx.file_io->user, archive_path, &out) !=
CFREE_OK) {
- driver_errf(RANLIB_TOOL, "failed to open: %s", archive_path);
+ driver_errf(RANLIB_TOOL, "failed to open: %.*s",
+ CFREE_SLICE_ARG(cfree_slice_cstr(archive_path)));
goto out;
}
opts.epoch = ranlib_epoch_from_env();
diff --git a/driver/run.c b/driver/run.c
@@ -191,14 +191,17 @@ static void run_metrics_finish(RunMetrics* m) {
const RunMetricEvent* e = &seg->events[i];
if (e->kind == RUN_METRIC_EVENT_SCOPE) {
if (m->bench_time) {
- driver_logf("cfree-run %s -- %.3f msec", e->name,
+ driver_logf("cfree-run %.*s -- %.3f msec",
+ CFREE_SLICE_ARG(cfree_slice_cstr(e->name)),
(double)e->value / 1000000.0);
} else {
- driver_logf("%*s%s %.3f ms", (int)((unsigned)e->depth * 2u), "",
- e->name, (double)e->value / 1000000.0);
+ driver_logf("%*s%.*s %.3f ms", (int)((unsigned)e->depth * 2u), "",
+ CFREE_SLICE_ARG(cfree_slice_cstr(e->name)),
+ (double)e->value / 1000000.0);
}
} else {
- driver_logf("%*s%s=%llu", (int)((unsigned)e->depth * 2u), "", e->name,
+ driver_logf("%*s%.*s=%llu", (int)((unsigned)e->depth * 2u), "",
+ CFREE_SLICE_ARG(cfree_slice_cstr(e->name)),
(unsigned long long)e->value);
}
}
@@ -217,18 +220,21 @@ static void run_metrics_finish(RunMetrics* m) {
}
static void run_bench_time(const char* name, uint64_t ns) {
- driver_logf("cfree-run %s -- %.3f msec", name, (double)ns / 1000000.0);
+ driver_logf("cfree-run %.*s -- %.3f msec",
+ CFREE_SLICE_ARG(cfree_slice_cstr(name)), (double)ns / 1000000.0);
}
static void run_usage(void) {
- driver_errf(RUN_TOOL, "%s",
- "usage: cfree run [options] inputs... [-- prog-arg...]\n"
- " cfree run --help for full option reference");
+ driver_errf(RUN_TOOL, "%.*s",
+ CFREE_SLICE_ARG(CFREE_SLICE_LIT(
+ "usage: cfree run [options] inputs... [-- prog-arg...]\n"
+ " cfree run --help for full option reference")));
}
void driver_help_run(void) {
driver_printf(
- "%s",
+ "%.*s",
+ CFREE_SLICE_ARG(CFREE_SLICE_LIT(
"cfree run — JIT-compile inputs and invoke the entry symbol in-process\n"
"\n"
"USAGE\n"
@@ -295,7 +301,7 @@ void driver_help_run(void) {
"\n"
"EXIT CODES\n"
" Returns the exit code of the JITed entry, or 1 on internal failure.\n"
- " 2 on bad command-line usage.\n");
+ " 2 on bad command-line usage.\n")));
}
static int run_alloc_arrays(RunOptions* o, int argc) {
@@ -348,7 +354,8 @@ static int run_record_mcmodel(RunOptions* o, const char* val) {
o->target.code_model = CFREE_CM_LARGE;
return 0;
}
- driver_errf(RUN_TOOL, "unknown -mcmodel value: %s", val);
+ driver_errf(RUN_TOOL, "unknown -mcmodel value: %.*s",
+ CFREE_SLICE_ARG(cfree_slice_cstr(val)));
return 1;
}
@@ -356,7 +363,8 @@ static int run_classify_positional(RunOptions* o, const char* a) {
int r = driver_inputs_classify(&o->inputs, a);
if (r < 0) return 1;
if (r == 0) {
- driver_errf(RUN_TOOL, "input does not have a recognized suffix: %s", a);
+ driver_errf(RUN_TOOL, "input does not have a recognized suffix: %.*s",
+ CFREE_SLICE_ARG(cfree_slice_cstr(a)));
return 1;
}
return 0;
@@ -483,14 +491,16 @@ static int run_parse(int argc, char** argv, RunOptions* o) {
return 1;
}
if (driver_target_from_triple(argv[i], &o->target) != 0) {
- driver_errf(RUN_TOOL, "unrecognized target triple: %s", argv[i]);
+ driver_errf(RUN_TOOL, "unrecognized target triple: %.*s",
+ CFREE_SLICE_ARG(cfree_slice_cstr(argv[i])));
return 1;
}
continue;
}
if (driver_streq(a, "--sysroot") || driver_streq(a, "-isysroot")) {
if (++i >= argc) {
- driver_errf(RUN_TOOL, "%s requires an argument", a);
+ driver_errf(RUN_TOOL, "%.*s requires an argument",
+ CFREE_SLICE_ARG(cfree_slice_cstr(a)));
return 1;
}
o->sysroot = argv[i];
@@ -510,8 +520,8 @@ static int run_parse(int argc, char** argv, RunOptions* o) {
return 1;
}
if (!driver_streq(argv[i], "c")) {
- driver_errf(RUN_TOOL, "unsupported hosted library for JIT: -l%s",
- argv[i]);
+ driver_errf(RUN_TOOL, "unsupported hosted library for JIT: -l%.*s",
+ CFREE_SLICE_ARG(cfree_slice_cstr(argv[i])));
return 1;
}
o->wants_hosted_libc = 1;
@@ -519,7 +529,8 @@ static int run_parse(int argc, char** argv, RunOptions* o) {
}
if (driver_strneq(a, "-l", 2)) {
if (!driver_streq(a + 2, "c")) {
- driver_errf(RUN_TOOL, "unsupported hosted library for JIT: %s", a);
+ driver_errf(RUN_TOOL, "unsupported hosted library for JIT: %.*s",
+ CFREE_SLICE_ARG(cfree_slice_cstr(a)));
return 1;
}
o->wants_hosted_libc = 1;
@@ -540,7 +551,8 @@ static int run_parse(int argc, char** argv, RunOptions* o) {
continue;
}
if (a[0] == '-' && a[1] != '\0') {
- driver_errf(RUN_TOOL, "unknown flag: %s", a);
+ driver_errf(RUN_TOOL, "unknown flag: %.*s",
+ CFREE_SLICE_ARG(cfree_slice_cstr(a)));
return 1;
}
@@ -607,7 +619,7 @@ typedef struct RunWasmMemoryPrefix {
static int run_call_wasm_entry(RunOptions* ro, CfreeJit* jit, void* entry,
int* rc_out) {
- void* init_sym = cfree_jit_lookup(jit, "__cfree_wasm_init");
+ void* init_sym = cfree_jit_lookup(jit, CFREE_SLICE_LIT("__cfree_wasm_init"));
uint8_t* instance;
uint8_t* memory;
union {
@@ -710,10 +722,11 @@ int driver_run(int argc, char** argv) {
}
run_metrics_begin(metrics, "run.jit_lookup");
- sym = cfree_jit_lookup(jit, ro.entry);
+ sym = cfree_jit_lookup(jit, cfree_slice_cstr(ro.entry));
run_metrics_end(metrics, "run.jit_lookup");
if (!sym) {
- driver_errf(RUN_TOOL, "entry symbol not found: %s", ro.entry);
+ driver_errf(RUN_TOOL, "entry symbol not found: %.*s",
+ CFREE_SLICE_ARG(cfree_slice_cstr(ro.entry)));
cfree_jit_free(jit);
driver_compiler_free(compiler);
run_metrics_finish(metrics);
diff --git a/driver/runtime.c b/driver/runtime.c
@@ -373,8 +373,8 @@ static int rt_prepare_pp(DriverEnv* env, const DriverRuntimeSupport* support,
const RuntimeVariant* variant, int assembler,
CfreePreprocessOptions* pp, char*** owned_dirs,
size_t** owned_sizes, uint32_t* owned_count) {
- static const char* const def_int128_1 = "1";
- static const char* const def_int128_0 = "0";
+ static const CfreeSlice def_int128_1 = CFREE_SLICE_LIT("1");
+ static const CfreeSlice def_int128_0 = CFREE_SLICE_LIT("0");
char** dirs = NULL;
size_t* sizes = NULL;
const char** include_dirs;
@@ -443,17 +443,17 @@ static int rt_prepare_pp(DriverEnv* env, const DriverRuntimeSupport* support,
}
}
- defs[0].name = "HAS_INT128";
+ defs[0].name = CFREE_SLICE_LIT("HAS_INT128");
defs[0].body = variant->has_int128 ? def_int128_1 : def_int128_0;
i = 1;
if (variant->ldbl128) {
- defs[i].name = "CFREERT_LDBL128";
- defs[i].body = "1";
+ defs[i].name = CFREE_SLICE_LIT("CFREERT_LDBL128");
+ defs[i].body = CFREE_SLICE_LIT("1");
++i;
}
if (assembler) {
- defs[i].name = "__ASSEMBLER__";
- defs[i].body = "1";
+ defs[i].name = CFREE_SLICE_LIT("__ASSEMBLER__");
+ defs[i].body = CFREE_SLICE_LIT("1");
}
pp->include_dirs = include_dirs;
@@ -494,14 +494,14 @@ static int rt_compile_source(DriverEnv* env,
const DriverRuntimeSupport* support,
const RuntimeVariant* variant,
CfreeCompiler* compiler, const char* rel,
- CfreeBytes* member, CfreeWriter** obj_writer) {
+ CfreeArInput* member, CfreeWriter** obj_writer) {
CfreeContext ctx = driver_env_to_context(env);
char* lib_path = NULL;
char* src_path = NULL;
size_t lib_path_size = 0;
size_t src_path_size = 0;
DriverLoad src_load = {0};
- CfreeBytes input = {0};
+ CfreeSlice input = {0};
CfreeWriter* writer = NULL;
CfreeWriter* pp_writer = NULL;
const uint8_t* obj_data;
@@ -524,7 +524,7 @@ static int rt_compile_source(DriverEnv* env,
preprocess_asm = driver_has_suffix(rel, ".S");
if (is_asm) {
CfreeAsmCompileOptions aopts = {0};
- CfreeBytes asm_input = input;
+ CfreeSlice asm_input = input;
if (preprocess_asm) {
CfreePreprocessOptions pp;
char** owned_dirs = NULL;
@@ -537,7 +537,8 @@ static int rt_compile_source(DriverEnv* env,
rt_free_pp(env, &pp, owned_dirs, owned_sizes, owned_count);
goto out;
}
- st = cfree_cpp_preprocess(compiler, &pp, &input, pp_writer);
+ st = cfree_cpp_preprocess(compiler, &pp, cfree_slice_cstr(src_path),
+ &input, pp_writer);
rt_free_pp(env, &pp, owned_dirs, owned_sizes, owned_count);
if (st != CFREE_OK || cfree_writer_status(pp_writer) != CFREE_OK)
goto out;
@@ -554,6 +555,7 @@ static int rt_compile_source(DriverEnv* env,
sopts.compile.diagnostics = aopts.diagnostics;
sopts.compile.language_options = &aopts;
memset(&sin, 0, sizeof(sin));
+ sin.name = cfree_slice_cstr(src_path);
sin.bytes = asm_input;
sin.lang = CFREE_LANG_ASM;
st = cfree_compile_session_new(compiler, &sopts, &session);
@@ -581,6 +583,7 @@ static int rt_compile_source(DriverEnv* env,
sopts.compile.diagnostics = copts.diagnostics;
sopts.compile.language_options = &copts;
memset(&sin, 0, sizeof(sin));
+ sin.name = cfree_slice_cstr(src_path);
sin.bytes = input;
sin.lang = CFREE_LANG_C;
st = cfree_compile_session_new(compiler, &sopts, &session);
@@ -591,14 +594,15 @@ static int rt_compile_source(DriverEnv* env,
rt_free_pp(env, &copts.preprocess, owned_dirs, owned_sizes, owned_count);
}
if (st != CFREE_OK || cfree_writer_status(writer) != CFREE_OK) {
- driver_errf(RT_TOOL, "failed to build runtime source: %s", src_path);
+ driver_errf(RT_TOOL, "failed to build runtime source: %.*s",
+ CFREE_SLICE_ARG(cfree_slice_cstr(src_path)));
goto out;
}
obj_data = cfree_writer_mem_bytes(writer, &obj_len);
- member->name = driver_basename(rel);
- member->data = obj_data;
- member->len = obj_len;
+ member->name = cfree_slice_cstr(driver_basename(rel));
+ member->bytes.data = obj_data;
+ member->bytes.len = obj_len;
*obj_writer = writer;
writer = NULL;
rc = 0;
@@ -618,14 +622,14 @@ static int rt_build_archive(DriverEnv* env, const DriverRuntimeSupport* support,
CfreeContext ctx = driver_env_to_context(env);
CfreeCompiler* compiler = NULL;
CfreeWriter* archive_writer = NULL;
- CfreeBytes* members = NULL;
+ CfreeArInput* members = NULL;
CfreeWriter** obj_writers = NULL;
CfreeArWriteOptions ar_opts = {0};
CfreeTarget target;
uint32_t i;
int rc = 1;
- members = (CfreeBytes*)driver_alloc_zeroed(
+ members = (CfreeArInput*)driver_alloc_zeroed(
env, (size_t)variant->nsources * sizeof(*members));
obj_writers = (CfreeWriter**)driver_alloc_zeroed(
env, (size_t)variant->nsources * sizeof(*obj_writers));
@@ -656,7 +660,8 @@ static int rt_build_archive(DriverEnv* env, const DriverRuntimeSupport* support,
if (ctx.file_io->open_writer(ctx.file_io->user, archive_path,
&archive_writer) != CFREE_OK) {
- driver_errf(RT_TOOL, "failed to open runtime archive: %s", archive_path);
+ driver_errf(RT_TOOL, "failed to open runtime archive: %.*s",
+ CFREE_SLICE_ARG(cfree_slice_cstr(archive_path)));
goto out;
}
@@ -664,7 +669,8 @@ static int rt_build_archive(DriverEnv* env, const DriverRuntimeSupport* support,
ar_opts.long_names = 1;
if (cfree_ar_write(archive_writer, members, variant->nsources, &ar_opts) !=
CFREE_OK) {
- driver_errf(RT_TOOL, "failed to write runtime archive: %s", archive_path);
+ driver_errf(RT_TOOL, "failed to write runtime archive: %.*s",
+ CFREE_SLICE_ARG(cfree_slice_cstr(archive_path)));
goto out;
}
rc = 0;
@@ -748,15 +754,17 @@ int driver_runtime_ensure_archive(DriverEnv* env,
if (!driver_path_exists(archive_path) ||
rt_is_archive_stale(env, support, variant, archive_path)) {
if (driver_mkdir_p(env, cache_dir) != 0) {
- driver_errf(RT_TOOL, "failed to create runtime cache: %s", cache_dir);
+ driver_errf(RT_TOOL, "failed to create runtime cache: %.*s",
+ CFREE_SLICE_ARG(cfree_slice_cstr(cache_dir)));
driver_free(env, archive_path, archive_path_size);
driver_free(env, cache_dir, cache_dir_size);
return 1;
}
if (rt_build_archive(env, support, variant, epoch, archive_path) != 0) {
- driver_errf(RT_TOOL, "compiler runtime for %s could not be built",
- variant->key);
- driver_errf(RT_TOOL, "support dir: %s", support->support_root);
+ driver_errf(RT_TOOL, "compiler runtime for %.*s could not be built",
+ CFREE_SLICE_ARG(cfree_slice_cstr(variant->key)));
+ driver_errf(RT_TOOL, "support dir: %.*s",
+ CFREE_SLICE_ARG(cfree_slice_cstr(support->support_root)));
driver_free(env, archive_path, archive_path_size);
driver_free(env, cache_dir, cache_dir_size);
return 1;
diff --git a/driver/strip.c b/driver/strip.c
@@ -31,7 +31,8 @@
void driver_help_strip(void) {
driver_printf(
- "%s",
+ "%.*s",
+ CFREE_SLICE_ARG(CFREE_SLICE_LIT(
"cfree strip — drop debug sections and/or symbols\n"
"\n"
"USAGE\n"
@@ -55,7 +56,7 @@ void driver_help_strip(void) {
" executables / shared libraries are not supported yet.\n"
"\n"
"EXIT CODES\n"
- " 0 success 1 I/O or strip error 2 bad usage\n");
+ " 0 success 1 I/O or strip error 2 bad usage\n")));
}
typedef enum StripOp {
@@ -76,11 +77,11 @@ typedef struct StripOpts {
const char* input;
} StripOpts;
-static int name_in_list(const char* name, const char* const* list, uint32_t n) {
+static int name_in_list(CfreeSlice name, const char* const* list, uint32_t n) {
uint32_t i;
- if (!name) return 0;
+ if (!name.len) return 0;
for (i = 0; i < n; ++i) {
- if (list[i] && strcmp(list[i], name) == 0) return 1;
+ if (list[i] && cfree_slice_eq_cstr(name, list[i])) return 1;
}
return 0;
}
@@ -109,21 +110,21 @@ static int push_name(DriverEnv* env, const char*** arr, uint32_t* n,
static int parse_name_arg(int* i, int argc, char** argv, const char* flag,
const char* short_flag, const char** out) {
const char* a = argv[*i];
- size_t flen = strlen(flag);
- /* --flag=NAME */
- if (strncmp(a, flag, flen) == 0 && a[flen] == '=') {
+ size_t flen = cfree_slice_cstr(flag).len;
+ /* --flag=NAME ; prefix match */
+ if (driver_strneq(a, flag, flen) && a[flen] == '=') {
*out = a + flen + 1;
return 1;
}
/* --flag NAME (no '='): treat as "next argv" form, used when --flag is
* passed without value. Not standard; skip. */
- if (strcmp(a, flag) == 0) {
+ if (driver_streq(a, flag)) {
if (*i + 1 >= argc) return -1;
*out = argv[++(*i)];
return 1;
}
/* -K NAME / -N NAME */
- if (short_flag && strcmp(a, short_flag) == 0) {
+ if (short_flag && driver_streq(a, short_flag)) {
if (*i + 1 >= argc) return -1;
*out = argv[++(*i)];
return 1;
@@ -278,7 +279,7 @@ done:
}
static int strip_object_bytes(DriverEnv* env, const CfreeContext* ctx,
- const CfreeBytes* input, const StripOpts* opts,
+ const CfreeSlice* input, const StripOpts* opts,
uint8_t** out_data, size_t* out_size) {
CfreeObjFile* of = NULL;
CfreeObjBuilder* b;
@@ -291,13 +292,13 @@ static int strip_object_bytes(DriverEnv* env, const CfreeContext* ctx,
*out_data = NULL;
*out_size = 0;
- if (cfree_obj_open(ctx, input, &of) != CFREE_OK) {
- driver_errf(STRIP_TOOL, "%s: not a recognized object", input->name);
+ if (cfree_obj_open(ctx, CFREE_SLICE_NULL, input, &of) != CFREE_OK) {
+ driver_errf(STRIP_TOOL, "not a recognized object");
return 1;
}
b = cfree_obj_file_builder(of);
if (!b) {
- driver_errf(STRIP_TOOL, "%s: no builder for object", input->name);
+ driver_errf(STRIP_TOOL, "no builder for object");
cfree_obj_free(of);
return 1;
}
@@ -313,7 +314,7 @@ static int strip_object_bytes(DriverEnv* env, const CfreeContext* ctx,
return 1;
}
if (cfree_obj_builder_emit(b, w) != CFREE_OK) {
- driver_errf(STRIP_TOOL, "%s: emit failed", input->name);
+ driver_errf(STRIP_TOOL, "emit failed");
cfree_writer_close(w);
cfree_obj_free(of);
return 1;
@@ -351,11 +352,11 @@ static uint64_t strip_epoch_from_env(void) {
* a refreshed System-V symbol index. Non-object members pass through
* unchanged. */
static int strip_archive(DriverEnv* env, const CfreeContext* ctx,
- const CfreeBytes* input, const StripOpts* opts,
+ const CfreeSlice* input, const StripOpts* opts,
const char* output_path) {
CfreeArIter* it = NULL;
CfreeArMember m;
- CfreeBytes* members = NULL;
+ CfreeArInput* members = NULL;
uint8_t** owned_data = NULL;
size_t* owned_size = NULL;
char* name_storage = NULL;
@@ -370,20 +371,20 @@ static int strip_archive(DriverEnv* env, const CfreeContext* ctx,
/* Pass 1: count members + total name bytes. */
if (cfree_ar_iter_new(ctx, input, &it) != CFREE_OK) {
- driver_errf(STRIP_TOOL, "%s: not an archive", input->name);
+ driver_errf(STRIP_TOOL, "not an archive");
return 1;
}
for (;;) {
CfreeIterResult r = cfree_ar_iter_next(it, &m);
if (r != CFREE_ITER_ITEM) break;
nmembers++;
- name_bytes_total += driver_strlen(m.name) + 1;
+ name_bytes_total += m.name.len + 1;
}
cfree_ar_iter_free(it);
it = NULL;
if (nmembers) {
- members = (CfreeBytes*)driver_alloc_zeroed(
+ members = (CfreeArInput*)driver_alloc_zeroed(
env, (size_t)nmembers * sizeof(*members));
owned_data = (uint8_t**)driver_alloc_zeroed(
env, (size_t)nmembers * sizeof(*owned_data));
@@ -412,18 +413,18 @@ static int strip_archive(DriverEnv* env, const CfreeContext* ctx,
k = 0;
while (k < nmembers) {
CfreeIterResult r = cfree_ar_iter_next(it, &m);
- const char* p;
+ size_t j;
char* dst;
CfreeBinFmt fmt;
- CfreeBytes mbytes;
+ CfreeSlice mbytes;
if (r != CFREE_ITER_ITEM) break;
dst = name_storage + cursor;
- for (p = m.name; *p; ++p) *dst++ = *p;
+ for (j = 0; j < m.name.len; ++j) *dst++ = m.name.s[j];
*dst++ = '\0';
- members[k].name = name_storage + cursor;
+ members[k].name.s = name_storage + cursor;
+ members[k].name.len = m.name.len;
cursor = (size_t)(dst - name_storage);
- mbytes.name = members[k].name;
mbytes.data = m.data;
mbytes.len = m.size;
fmt = cfree_detect_fmt(m.data, m.size);
@@ -438,11 +439,11 @@ static int strip_archive(DriverEnv* env, const CfreeContext* ctx,
}
owned_data[k] = sd;
owned_size[k] = ss;
- members[k].data = sd;
- members[k].len = ss;
+ members[k].bytes.data = sd;
+ members[k].bytes.len = ss;
} else {
- members[k].data = m.data;
- members[k].len = m.size;
+ members[k].bytes.data = m.data;
+ members[k].bytes.len = m.size;
}
k++;
}
@@ -465,9 +466,9 @@ static int strip_archive(DriverEnv* env, const CfreeContext* ctx,
for (k = 0; k < nmembers; ++k) {
void* blob = NULL;
size_t blob_size = 0;
- const char** names = NULL;
+ const CfreeSlice* names = NULL;
uint32_t count = 0;
- if (driver_collect_obj_global_syms(env, ctx, STRIP_TOOL, &members[k],
+ if (driver_collect_obj_global_syms(env, ctx, STRIP_TOOL, &members[k].bytes,
&blob, &blob_size, &names,
&count) != 0) {
goto done;
@@ -481,7 +482,8 @@ static int strip_archive(DriverEnv* env, const CfreeContext* ctx,
if (ctx->file_io->open_writer(ctx->file_io->user, output_path, &out) !=
CFREE_OK) {
- driver_errf(STRIP_TOOL, "failed to open: %s", output_path);
+ driver_errf(STRIP_TOOL, "failed to open: %.*s",
+ CFREE_SLICE_ARG(cfree_slice_cstr(output_path)));
goto done;
}
opts_ar.epoch = strip_epoch_from_env();
@@ -524,7 +526,7 @@ int driver_strip(int argc, char** argv) {
CfreeContext ctx;
StripOpts opts;
CfreeFileData input_fd = {0};
- CfreeBytes input;
+ CfreeSlice input;
CfreeWriter* w = NULL;
uint8_t* out_data = NULL;
size_t out_size = 0;
@@ -569,7 +571,8 @@ int driver_strip(int argc, char** argv) {
}
matched = parse_name_arg(&i, argc, argv, "--keep-symbol", "-K", &val);
if (matched < 0) {
- driver_errf(STRIP_TOOL, "%s requires a symbol name", a);
+ driver_errf(STRIP_TOOL, "%.*s requires a symbol name",
+ CFREE_SLICE_ARG(cfree_slice_cstr(a)));
rc = 2;
goto done;
}
@@ -582,7 +585,8 @@ int driver_strip(int argc, char** argv) {
}
matched = parse_name_arg(&i, argc, argv, "--strip-symbol", "-N", &val);
if (matched < 0) {
- driver_errf(STRIP_TOOL, "%s requires a symbol name", a);
+ driver_errf(STRIP_TOOL, "%.*s requires a symbol name",
+ CFREE_SLICE_ARG(cfree_slice_cstr(a)));
rc = 2;
goto done;
}
@@ -595,7 +599,8 @@ int driver_strip(int argc, char** argv) {
continue;
}
if (a[0] == '-' && a[1] != '\0') {
- driver_errf(STRIP_TOOL, "unknown option: %s", a);
+ driver_errf(STRIP_TOOL, "unknown option: %.*s",
+ CFREE_SLICE_ARG(cfree_slice_cstr(a)));
rc = 2;
goto done;
}
@@ -615,11 +620,11 @@ int driver_strip(int argc, char** argv) {
if (ctx.file_io->read_all(ctx.file_io->user, opts.input, &input_fd) !=
CFREE_OK) {
- driver_errf(STRIP_TOOL, "failed to read: %s", opts.input);
+ driver_errf(STRIP_TOOL, "failed to read: %.*s",
+ CFREE_SLICE_ARG(cfree_slice_cstr(opts.input)));
goto done;
}
have_input = 1;
- input.name = opts.input;
input.data = input_fd.data;
input.len = input_fd.size;
@@ -636,12 +641,14 @@ int driver_strip(int argc, char** argv) {
}
if (ctx.file_io->open_writer(ctx.file_io->user, out_path, &w) !=
CFREE_OK) {
- driver_errf(STRIP_TOOL, "failed to open: %s", out_path);
+ driver_errf(STRIP_TOOL, "failed to open: %.*s",
+ CFREE_SLICE_ARG(cfree_slice_cstr(out_path)));
goto done;
}
cfree_writer_write(w, out_data, out_size);
if (cfree_writer_status(w) != CFREE_OK) {
- driver_errf(STRIP_TOOL, "write failed: %s", out_path);
+ driver_errf(STRIP_TOOL, "write failed: %.*s",
+ CFREE_SLICE_ARG(cfree_slice_cstr(out_path)));
goto done;
}
rc = 0;
diff --git a/driver/target.c b/driver/target.c
@@ -10,7 +10,7 @@
* layer). */
static int triple_tok_eq(const char* s, size_t n, const char* lit) {
- size_t l = strlen(lit);
+ size_t l = cfree_slice_cstr(lit).len;
return n == l && memcmp(s, lit, n) == 0;
}
@@ -28,9 +28,9 @@ int driver_target_from_triple(const char* triple, CfreeTarget* out) {
p = triple;
while (np < 4) {
- const char* dash = strchr(p, '-');
+ const char* dash = driver_strchr(p, '-');
parts[np] = p;
- plen[np] = dash ? (size_t)(dash - p) : strlen(p);
+ plen[np] = dash ? (size_t)(dash - p) : cfree_slice_cstr(p).len;
if (plen[np] == 0) return 1;
np++;
if (!dash) break;
@@ -176,6 +176,7 @@ int driver_target_to_triple(CfreeTarget target, char* buf, size_t cap) {
break;
}
- n = snprintf(buf, cap, "%s-%s", arch, os);
+ n = snprintf(buf, cap, "%.*s-%.*s", CFREE_SLICE_ARG(cfree_slice_cstr(arch)),
+ CFREE_SLICE_ARG(cfree_slice_cstr(os)));
return n < 0 || (size_t)n >= cap;
}
diff --git a/include/cfree/arch.h b/include/cfree/arch.h
@@ -16,11 +16,11 @@ typedef struct CfreeUnwindFrame {
typedef struct CfreeArchReg {
uint32_t dwarf_idx;
- const char *name;
+ CfreeSlice name;
} CfreeArchReg;
-const char *cfree_arch_register_name(CfreeArchKind, uint32_t dwarf_idx);
-CfreeStatus cfree_arch_register_index(CfreeArchKind, const char *name,
+CfreeSlice cfree_arch_register_name(CfreeArchKind, uint32_t dwarf_idx);
+CfreeStatus cfree_arch_register_index(CfreeArchKind, CfreeSlice name,
uint32_t *idx_out);
uint32_t cfree_arch_register_count(CfreeArchKind);
CfreeStatus cfree_arch_register_at(CfreeArchKind, uint32_t idx,
diff --git a/include/cfree/archive.h b/include/cfree/archive.h
@@ -11,7 +11,7 @@
*/
typedef struct CfreeArMemberSymbols {
- const char *const *names;
+ const CfreeSlice *names;
uint32_t count;
} CfreeArMemberSymbols;
@@ -22,20 +22,27 @@ typedef struct CfreeArWriteOptions {
const CfreeArMemberSymbols *member_symbols;
} CfreeArWriteOptions;
-CfreeStatus cfree_ar_write(CfreeWriter *out, const CfreeBytes *members,
+/* One member to be written into an archive: its name (e.g. "foo.o") and its
+ * contents. Neither slice needs NUL termination. */
+typedef struct CfreeArInput {
+ CfreeSlice name;
+ CfreeSlice bytes;
+} CfreeArInput;
+
+CfreeStatus cfree_ar_write(CfreeWriter *out, const CfreeArInput *members,
uint32_t nmembers,
const CfreeArWriteOptions *opts);
-CfreeStatus cfree_ar_list(const CfreeBytes *archive, CfreeWriter *out);
+CfreeStatus cfree_ar_list(const CfreeSlice *archive, CfreeWriter *out);
typedef struct CfreeArIter CfreeArIter;
typedef struct CfreeArMember {
- const char *name;
+ CfreeSlice name;
const uint8_t *data;
size_t size;
} CfreeArMember;
-CfreeStatus cfree_ar_iter_new(const CfreeContext *, const CfreeBytes *archive,
+CfreeStatus cfree_ar_iter_new(const CfreeContext *, const CfreeSlice *archive,
CfreeArIter **out);
CfreeIterResult cfree_ar_iter_next(CfreeArIter *, CfreeArMember *out);
void cfree_ar_iter_free(CfreeArIter *);
diff --git a/include/cfree/cg.h b/include/cfree/cg.h
@@ -932,8 +932,7 @@ typedef struct CfreeCgInlineAsm {
* are pre-interned strings. clobber_abi_sets names target-defined ABI register
* sets such as all caller-saved registers. */
void cfree_cg_inline_asm(CfreeCg*, CfreeCgInlineAsm asm_block);
-void cfree_cg_file_scope_asm(CfreeCg*, const char* asm_source,
- size_t asm_source_len);
+void cfree_cg_file_scope_asm(CfreeCg*, CfreeSlice asm_source);
/* ============================================================
* Data Definitions
diff --git a/include/cfree/compile.h b/include/cfree/compile.h
@@ -46,10 +46,11 @@ typedef enum CfreeFrontendInputKind {
} CfreeFrontendInputKind;
typedef struct CfreeSourceInput {
- CfreeBytes bytes;
+ CfreeSlice name; /* diagnostic label / source path; may be empty */
+ CfreeSlice bytes;
CfreeLanguage lang;
CfreeFrontendInputKind input_kind;
- const char* repl_entry_name;
+ CfreeSlice repl_entry_name;
} CfreeSourceInput;
typedef struct CfreeFrontendCompileOptions {
@@ -57,7 +58,7 @@ typedef struct CfreeFrontendCompileOptions {
CfreeDiagnosticOptions diagnostics;
const void* language_options;
CfreeFrontendInputKind input_kind;
- const char* repl_entry_name;
+ CfreeSlice repl_entry_name;
} CfreeFrontendCompileOptions;
typedef struct CfreeFrontend CfreeFrontend;
@@ -74,13 +75,14 @@ typedef struct CfreeFrontendVTable {
CfreeFrontendCompileFn compile;
CfreeFrontendFreeFn free_frontend;
- /* NULL-terminated list of lowercase file extensions (no leading dot)
- * that this frontend claims. cfree_language_for_path walks every
- * registered frontend's list to map a path's extension back to a
- * CfreeLanguage. May be NULL for frontends with no canonical
- * extension. Matching is case-insensitive so `.S` and `.s` both map
- * to the asm frontend's `"s"` entry. */
- const char* const* extensions;
+ /* Counted list of lowercase file extensions (no leading dot) that this
+ * frontend claims. cfree_language_for_path walks every registered
+ * frontend's list to map a path's extension back to a CfreeLanguage.
+ * May be NULL/0 for frontends with no canonical extension. Matching is
+ * case-insensitive so `.S` and `.s` both map to the asm frontend's
+ * `"s"` entry. */
+ const CfreeSlice* extensions;
+ uint32_t nextensions;
} CfreeFrontendVTable;
CfreeLanguage cfree_language_for_path(CfreeCompiler*, const char* path);
@@ -106,8 +108,8 @@ void cfree_compile_session_free(CfreeCompileSession*);
typedef struct CfreeDepIter CfreeDepIter;
typedef struct CfreeDepEdge {
- const char* includer_name;
- const char* included_name;
+ CfreeSlice includer_name;
+ CfreeSlice included_name;
CfreeSrcLoc include_loc;
uint8_t from_system_path;
uint8_t bracketed;
diff --git a/include/cfree/core.h b/include/cfree/core.h
@@ -53,11 +53,63 @@ typedef struct CfreeSrcLoc {
uint32_t col;
} CfreeSrcLoc;
-typedef struct CfreeBytes {
- const char* name; /* diagnostic label; may be NULL */
- const uint8_t* data;
+/*
+ * Fat-pointer view over borrowed bytes/text. The pointer can be read as text
+ * (`s`) or raw bytes (`data`); both name the same address. `len` is the byte
+ * count and never counts a trailing NUL. cfree never relies on NUL
+ * termination internally; where a NUL is present it is a boundary convenience
+ * only. This is the one fat-pointer type used throughout the API.
+ */
+typedef struct CfreeSlice {
+ union {
+ const char* s;
+ const uint8_t* data;
+ };
size_t len;
-} CfreeBytes;
+} CfreeSlice;
+
+/* Build a slice from a string literal (length is compile-time, no strlen). */
+#define CFREE_SLICE_LIT(lit) \
+ ((CfreeSlice){ .s = (lit), .len = sizeof(lit) - 1 })
+/* The empty slice. */
+#define CFREE_SLICE_NULL ((CfreeSlice){ .s = NULL, .len = 0 })
+/* Spread a slice into printf "%.*s" arguments: printf("%.*s", CFREE_SLICE_ARG(x)). */
+#define CFREE_SLICE_ARG(x) (int)(x).len, (x).s
+
+/* Lift a NUL-terminated C string into a slice. The sanctioned boundary helper
+ * for strings arriving from the OS (argv, getenv) or other foreign APIs; the
+ * length scan happens here so callers need none elsewhere. NULL -> empty. */
+static inline CfreeSlice cfree_slice_cstr(const char* z) {
+ CfreeSlice out;
+ size_t n = 0;
+ if (!z) {
+ out.s = NULL;
+ out.len = 0;
+ return out;
+ }
+ while (z[n]) ++n;
+ out.s = z;
+ out.len = n;
+ return out;
+}
+
+/* Byte-exact slice equality. */
+static inline bool cfree_slice_eq(CfreeSlice a, CfreeSlice b) {
+ size_t i;
+ if (a.len != b.len) return false;
+ for (i = 0; i < a.len; ++i)
+ if (a.s[i] != b.s[i]) return false;
+ return true;
+}
+
+/* Equality against a NUL-terminated string (compares bytes, ignores z's NUL). */
+static inline bool cfree_slice_eq_cstr(CfreeSlice a, const char* z) {
+ size_t i;
+ if (!z) return a.len == 0;
+ for (i = 0; i < a.len; ++i)
+ if (z[i] == '\0' || z[i] != a.s[i]) return false;
+ return z[a.len] == '\0';
+}
typedef enum CfreeArchKind {
CFREE_ARCH_X86_32,
@@ -244,11 +296,13 @@ CfreeTarget cfree_compiler_target(CfreeCompiler*);
const CfreeContext* cfree_compiler_context(CfreeCompiler*);
-const char* cfree_compiler_file_name(CfreeCompiler*, uint32_t file_id);
+CfreeSlice cfree_compiler_file_name(CfreeCompiler*, uint32_t file_id);
-CfreeSym cfree_sym_intern(CfreeCompiler*, const char* str);
-CfreeSym cfree_sym_intern_len(CfreeCompiler*, const char* str, size_t len);
-const char* cfree_sym_str(CfreeCompiler*, CfreeSym, size_t* len_out);
+/* Intern a slice's bytes, returning its canonical symbol (0 for the empty
+ * slice). Retrieve the bytes with cfree_sym_str, which returns a slice whose
+ * pointer is NUL-terminated (the NUL is not counted in len). */
+CfreeSym cfree_sym_intern(CfreeCompiler*, CfreeSlice);
+CfreeSlice cfree_sym_str(CfreeCompiler*, CfreeSym);
CfreeStatus cfree_writer_mem(CfreeHeap*, CfreeWriter** out);
const uint8_t* cfree_writer_mem_bytes(CfreeWriter*, size_t* len_out);
diff --git a/include/cfree/disasm.h b/include/cfree/disasm.h
@@ -14,9 +14,9 @@ typedef struct CfreeInsn {
uint64_t vaddr;
const uint8_t *bytes;
uint32_t nbytes;
- const char *mnemonic;
- const char *operands;
- const char *annotation;
+ CfreeSlice mnemonic;
+ CfreeSlice operands;
+ CfreeSlice annotation;
} CfreeInsn;
typedef struct CfreeDisasmIter CfreeDisasmIter;
@@ -36,7 +36,7 @@ void cfree_disasm_iter_free(CfreeDisasmIter *);
CfreeStatus cfree_disasm_obj(const CfreeContext *, const CfreeObjFile *,
CfreeWriter *out);
-CfreeStatus cfree_disasm_obj_bytes(const CfreeContext *, const CfreeBytes *,
+CfreeStatus cfree_disasm_obj_bytes(const CfreeContext *, const CfreeSlice *,
CfreeWriter *out);
#endif
diff --git a/include/cfree/dwarf.h b/include/cfree/dwarf.h
@@ -19,29 +19,29 @@ CfreeStatus cfree_dwarf_open(const CfreeContext *, const CfreeObjFile *,
void cfree_dwarf_free(CfreeDebugInfo *);
CfreeStatus cfree_dwarf_addr_to_line(CfreeDebugInfo *, uint64_t pc,
- const char **file_out,
+ CfreeSlice *file_out,
uint32_t *line_out, uint32_t *col_out);
-CfreeStatus cfree_dwarf_line_to_addr(CfreeDebugInfo *, const char *file,
+CfreeStatus cfree_dwarf_line_to_addr(CfreeDebugInfo *, CfreeSlice file,
uint32_t line, uint64_t *pc_out);
typedef struct CfreeDwarfLineMatch {
uint64_t pc;
- const char *file;
+ CfreeSlice file;
} CfreeDwarfLineMatch;
-CfreeStatus cfree_dwarf_line_to_addr_all(CfreeDebugInfo *, const char *file,
+CfreeStatus cfree_dwarf_line_to_addr_all(CfreeDebugInfo *, CfreeSlice file,
uint32_t line,
CfreeDwarfLineMatch *out,
uint32_t cap, uint32_t *n_out);
CfreeStatus cfree_dwarf_func_at(CfreeDebugInfo *, uint64_t pc,
- const char **name_out, uint64_t *low_pc_out,
+ CfreeSlice *name_out, uint64_t *low_pc_out,
uint64_t *high_pc_out);
typedef struct CfreeDwarfSubprogram {
- const char *name;
+ CfreeSlice name;
uint64_t low_pc;
uint64_t high_pc;
- const char *decl_file;
+ CfreeSlice decl_file;
uint32_t decl_line;
const CfreeDwarfType *return_type;
bool inlined;
@@ -49,7 +49,7 @@ typedef struct CfreeDwarfSubprogram {
CfreeStatus cfree_dwarf_subprogram_at(CfreeDebugInfo *, uint64_t pc,
CfreeDwarfSubprogram *out);
-CfreeStatus cfree_dwarf_subprogram_named(CfreeDebugInfo *, const char *name,
+CfreeStatus cfree_dwarf_subprogram_named(CfreeDebugInfo *, CfreeSlice name,
CfreeDwarfSubprogram *out);
CfreeStatus cfree_dwarf_unwind_step(CfreeDebugInfo *, CfreeUnwindFrame *);
@@ -72,7 +72,7 @@ typedef enum CfreeDwarfTypeKind {
typedef struct CfreeDwarfTypeInfo {
CfreeDwarfTypeKind kind;
uint32_t byte_size;
- const char *name;
+ CfreeSlice name;
uint32_t element_count;
const CfreeDwarfType *inner;
} CfreeDwarfTypeInfo;
@@ -81,7 +81,7 @@ CfreeDwarfTypeInfo cfree_dwarf_type_info(const CfreeDwarfType *);
typedef struct CfreeDwarfFieldIter CfreeDwarfFieldIter;
typedef struct CfreeDwarfField {
- const char *name;
+ CfreeSlice name;
uint32_t byte_offset;
uint32_t bit_offset;
uint32_t bit_size;
@@ -97,7 +97,7 @@ void cfree_dwarf_field_iter_free(CfreeDwarfFieldIter *);
typedef struct CfreeDwarfEnumIter CfreeDwarfEnumIter;
typedef struct CfreeDwarfEnumVal {
- const char *name;
+ CfreeSlice name;
int64_t value;
} CfreeDwarfEnumVal;
@@ -134,7 +134,7 @@ typedef CfreeStatus (*CfreeDwarfReadMemFn)(void *user, uint64_t addr,
void *dst, size_t n);
CfreeStatus cfree_dwarf_var_at(CfreeDebugInfo *, uint64_t pc,
- const char *name, CfreeDwarfVarLoc *out);
+ CfreeSlice name, CfreeDwarfVarLoc *out);
CfreeStatus cfree_dwarf_loc_read(CfreeDebugInfo *, const CfreeDwarfVarLoc *,
const CfreeUnwindFrame *,
CfreeDwarfReadMemFn read_mem, void *read_user,
@@ -154,7 +154,7 @@ typedef enum CfreeDwarfVarRoleMask {
} CfreeDwarfVarRoleMask;
typedef struct CfreeDwarfVar {
- const char *name;
+ CfreeSlice name;
CfreeDwarfVarRole role;
CfreeDwarfVarLoc loc;
} CfreeDwarfVar;
@@ -173,7 +173,7 @@ typedef struct CfreeDwarfParamIter CfreeDwarfParamIter;
CfreeStatus cfree_dwarf_param_iter_new(CfreeDebugInfo *, uint64_t pc,
CfreeDwarfParamIter **out);
CfreeStatus cfree_dwarf_param_iter_new_named(CfreeDebugInfo *,
- const char *name,
+ CfreeSlice name,
CfreeDwarfParamIter **out);
CfreeIterResult cfree_dwarf_param_iter_next(CfreeDwarfParamIter *,
CfreeDwarfVar *out);
diff --git a/include/cfree/jit.h b/include/cfree/jit.h
@@ -48,7 +48,7 @@ typedef struct CfreeJitHost {
} CfreeJitHost;
void cfree_jit_free(CfreeJit*);
-void* cfree_jit_lookup(CfreeJit*, const char* name);
+void* cfree_jit_lookup(CfreeJit*, CfreeSlice name);
uint64_t cfree_jit_generation(CfreeJit*);
void cfree_jit_run_dtors(CfreeJit*);
@@ -71,14 +71,14 @@ CfreeStatus cfree_jit_publish(CfreeJit*, const CfreeJitPublishOptions*,
const CfreeObjFile* cfree_jit_view(CfreeJit*);
CfreeStatus cfree_jit_addr_to_sym(CfreeJit*, uint64_t addr,
- const char** name_out, uint64_t* off_out);
+ CfreeSlice* name_out, uint64_t* off_out);
uint64_t cfree_jit_runtime_to_image(CfreeJit*, uint64_t runtime_pc);
uint64_t cfree_jit_image_to_runtime(CfreeJit*, uint64_t image_vaddr);
typedef struct CfreeJitSymIter CfreeJitSymIter;
typedef struct CfreeJitSym {
- const char* name;
+ CfreeSlice name;
uint64_t addr;
uint64_t size;
CfreeSymKind kind;
diff --git a/include/cfree/link.h b/include/cfree/link.h
@@ -11,7 +11,7 @@
* response-file handling are driver responsibilities.
*/
-typedef void* (*CfreeExternResolver)(void* user, const char* name);
+typedef void* (*CfreeExternResolver)(void* user, CfreeSlice name);
typedef struct CfreeJitHost CfreeJitHost;
typedef enum CfreeBuildIdMode {
@@ -47,7 +47,7 @@ struct CfreeLinkExpr {
uint8_t kind; /* CfreeLinkExprKind */
union {
int64_t int_val;
- const char* name;
+ CfreeSlice name;
struct {
const CfreeLinkExpr* lhs;
const CfreeLinkExpr* rhs;
@@ -66,15 +66,15 @@ typedef enum CfreeLinkRegionFlag {
} CfreeLinkRegionFlag;
typedef struct CfreeLinkRegion {
- const char* name;
+ CfreeSlice name;
uint8_t flags; /* CfreeLinkRegionFlag */
uint64_t origin;
uint64_t length;
} CfreeLinkRegion;
typedef struct CfreeLinkInputMatch {
- const char* file_pattern; /* NULL means "*" */
- const char* section_pattern;
+ CfreeSlice file_pattern; /* empty means "*" */
+ CfreeSlice section_pattern;
int keep;
} CfreeLinkInputMatch;
@@ -86,24 +86,24 @@ typedef enum CfreeLinkAsnKind {
typedef struct CfreeLinkAssignment {
uint8_t kind; /* CfreeLinkAsnKind */
- const char* sym;
+ CfreeSlice sym;
const CfreeLinkExpr* expr;
} CfreeLinkAssignment;
typedef struct CfreeLinkOutputSection {
- const char* name;
+ CfreeSlice name;
const CfreeLinkExpr* vma;
const CfreeLinkExpr* lma;
const CfreeLinkInputMatch* inputs;
uint32_t ninputs;
- const char* region;
- const char* load_region;
+ CfreeSlice region;
+ CfreeSlice load_region;
const CfreeLinkAssignment* asns;
uint32_t nasns;
} CfreeLinkOutputSection;
typedef struct CfreeLinkScript {
- const char* entry;
+ CfreeSlice entry;
const CfreeLinkRegion* regions;
uint32_t nregions;
const CfreeLinkOutputSection* sections;
@@ -112,8 +112,8 @@ typedef struct CfreeLinkScript {
uint32_t ntop_asns;
} CfreeLinkScript;
-CfreeStatus cfree_link_script_parse(const CfreeContext*, const char* text,
- size_t len, CfreeLinkScript** out);
+CfreeStatus cfree_link_script_parse(const CfreeContext*, CfreeSlice text,
+ CfreeLinkScript** out);
void cfree_link_script_free(const CfreeContext*, CfreeLinkScript*);
typedef enum CfreeLinkMode {
@@ -124,7 +124,8 @@ typedef enum CfreeLinkMode {
} CfreeLinkMode;
typedef struct CfreeLinkArchiveInput {
- CfreeBytes bytes;
+ CfreeSlice name; /* diagnostic label / archive path; may be empty */
+ CfreeSlice bytes;
uint8_t link_mode; /* CfreeLinkMode */
bool whole_archive;
uint8_t group_id;
@@ -162,19 +163,19 @@ typedef struct CfreeLinkSessionOptions {
bool gc_sections;
bool pie;
uint16_t pe_subsystem; /* CfreePeSubsystem; 0 => target default */
- const char* interp_path;
- const char* entry;
+ CfreeSlice interp_path;
+ CfreeSlice entry;
const CfreeLinkScript* linker_script;
uint8_t build_id_mode; /* CfreeBuildIdMode */
const uint8_t* build_id_bytes;
uint32_t build_id_len;
- const char* soname;
- const char* const* rpaths;
+ CfreeSlice soname;
+ const CfreeSlice* rpaths;
uint32_t nrpaths;
- const char* const* runpaths;
+ const CfreeSlice* runpaths;
uint32_t nrunpaths;
- const char* const* exports;
+ const CfreeSlice* exports;
uint32_t nexports;
bool allow_undefined;
@@ -187,12 +188,12 @@ CfreeStatus cfree_link_session_new(CfreeCompiler*,
const CfreeLinkSessionOptions*,
CfreeLinkSession** out);
CfreeStatus cfree_link_session_add_obj(CfreeLinkSession*, CfreeObjBuilder*);
-CfreeStatus cfree_link_session_add_obj_bytes(CfreeLinkSession*,
- const CfreeBytes*);
+CfreeStatus cfree_link_session_add_obj_bytes(CfreeLinkSession*, CfreeSlice name,
+ const CfreeSlice*);
CfreeStatus cfree_link_session_add_archive_bytes(CfreeLinkSession*,
const CfreeLinkArchiveInput*);
-CfreeStatus cfree_link_session_add_dso_bytes(CfreeLinkSession*,
- const CfreeBytes*);
+CfreeStatus cfree_link_session_add_dso_bytes(CfreeLinkSession*, CfreeSlice name,
+ const CfreeSlice*);
CfreeStatus cfree_link_session_resolve(CfreeLinkSession*);
CfreeStatus cfree_link_session_emit(CfreeLinkSession*, CfreeWriter* out);
CfreeStatus cfree_link_session_jit(CfreeLinkSession*, CfreeJit** out_jit);
diff --git a/include/cfree/object.h b/include/cfree/object.h
@@ -60,7 +60,7 @@ typedef struct CfreeRelocKind {
} CfreeRelocKind;
typedef struct CfreeObjSecInfo {
- const char *name;
+ CfreeSlice name;
CfreeSecKind kind;
uint32_t flags; /* CfreeSecFlag */
uint64_t size; /* bytes; BSS uses virtual size */
@@ -69,7 +69,7 @@ typedef struct CfreeObjSecInfo {
} CfreeObjSecInfo;
typedef struct CfreeObjSymInfo {
- const char *name;
+ CfreeSlice name;
CfreeObjSymbol id; /* stable handle within this CfreeObjFile / builder;
usable as the target of cfree_obj_builder_remove_symbol,
rename_symbol, etc. */
@@ -84,10 +84,10 @@ typedef struct CfreeObjReloc {
CfreeObjSection section;
uint64_t offset;
CfreeObjSymbol sym;
- const char *sym_name;
+ CfreeSlice sym_name;
int64_t addend;
CfreeRelocKind kind;
- const char *kind_name; /* diagnostic spelling, when known */
+ CfreeSlice kind_name; /* diagnostic spelling, when known */
} CfreeObjReloc;
/* ============================================================
@@ -224,7 +224,7 @@ typedef struct CfreeObjRelocIter CfreeObjRelocIter;
typedef struct CfreeObjGroupIter CfreeObjGroupIter;
typedef struct CfreeObjGroupInfo {
- const char *name;
+ CfreeSlice name;
CfreeObjSymbol signature; /* COMDAT key, or CFREE_OBJ_SYMBOL_NONE */
uint32_t flags; /* CfreeObjGroupFlag */
uint32_t nsections;
@@ -237,8 +237,8 @@ CfreeBinFmt cfree_detect_fmt(const uint8_t *data, size_t len);
CfreeStatus cfree_detect_target(const uint8_t *data, size_t len,
CfreeTarget *out);
-CfreeStatus cfree_obj_open(const CfreeContext *, const CfreeBytes *,
- CfreeObjFile **out);
+CfreeStatus cfree_obj_open(const CfreeContext *, CfreeSlice name,
+ const CfreeSlice *, CfreeObjFile **out);
void cfree_obj_free(CfreeObjFile *);
CfreeObjFmt cfree_obj_fmt(const CfreeObjFile *);
@@ -249,7 +249,7 @@ CfreeStatus cfree_obj_section(const CfreeObjFile *, CfreeObjSection idx,
CfreeObjSecInfo *out);
CfreeStatus cfree_obj_section_data(const CfreeObjFile *, CfreeObjSection idx,
const uint8_t **data_out, size_t *len_out);
-CfreeStatus cfree_obj_section_by_name(const CfreeObjFile *, const char *name,
+CfreeStatus cfree_obj_section_by_name(const CfreeObjFile *, CfreeSlice name,
CfreeObjSection *out);
/* Format-specific raw section attributes preserved by the reader.
@@ -270,7 +270,7 @@ CfreeStatus cfree_obj_section_format_flags(const CfreeObjFile *,
uint32_t *raw_type_out,
uint32_t *raw_flags_out);
-CfreeStatus cfree_obj_symbol_by_name(const CfreeObjFile *, const char *name,
+CfreeStatus cfree_obj_symbol_by_name(const CfreeObjFile *, CfreeSlice name,
CfreeObjSymInfo *out);
CfreeStatus cfree_obj_symiter_new(CfreeObjFile *, CfreeObjSymIter **out);
diff --git a/include/cfree/preprocess.h b/include/cfree/preprocess.h
@@ -14,8 +14,8 @@
*/
typedef struct CfreeDefine {
- const char* name;
- const char* body; /* NULL means "1" */
+ CfreeSlice name;
+ CfreeSlice body; /* empty slice means "1" */
} CfreeDefine;
typedef CfreeDefine CfreePredefinedMacro;
@@ -27,11 +27,12 @@ typedef struct CfreePreprocessOptions {
uint32_t nsystem_include_dirs;
const CfreeDefine* defines;
uint32_t ndefines;
- const char* const* undefines;
+ const CfreeSlice* undefines;
uint32_t nundefines;
} CfreePreprocessOptions;
CfreeStatus cfree_cpp_preprocess(CfreeCompiler*, const CfreePreprocessOptions*,
- const CfreeBytes*, CfreeWriter*);
+ CfreeSlice name, const CfreeSlice*,
+ CfreeWriter*);
#endif
diff --git a/include/cfree/source.h b/include/cfree/source.h
@@ -13,9 +13,9 @@
CfreeStatus cfree_source_add_file(CfreeCompiler *, const char *path,
int system_header, uint32_t *file_id_out);
-CfreeStatus cfree_source_add_memory(CfreeCompiler *, const char *name,
+CfreeStatus cfree_source_add_memory(CfreeCompiler *, CfreeSlice name,
uint32_t *file_id_out);
-CfreeStatus cfree_source_add_builtin(CfreeCompiler *, const char *name,
+CfreeStatus cfree_source_add_builtin(CfreeCompiler *, CfreeSlice name,
uint32_t *file_id_out);
CfreeStatus cfree_source_add_include(CfreeCompiler *, uint32_t includer_file_id,
uint32_t included_file_id,
diff --git a/lang/c/abi/c_abi.c b/lang/c/abi/c_abi.c
@@ -138,19 +138,19 @@ const Type* c_abi_va_list_type(TargetABI* a, Pool* p) {
case CFREE_ARCH_X86_64: {
const Type* vp = type_ptr(p, type_void(p));
const Type* uit = type_prim(p, TY_UINT);
- Sym name = pool_intern_cstr(p, "__va_list_tag");
+ Sym name = cfree_sym_intern(p->c, CFREE_SLICE_LIT("__va_list_tag"));
SrcLoc nl = {0, 0, 0};
TagId tg = type_tag_new(p, TAG_STRUCT, name, nl);
TypeRecordBuilder* b = type_record_begin(p, TY_STRUCT, tg, name);
type_record_field(
- b, (Field){.name = pool_intern_cstr(p, "gp_offset"), .type = uit});
+ b, (Field){.name = cfree_sym_intern(p->c, CFREE_SLICE_LIT("gp_offset")), .type = uit});
type_record_field(
- b, (Field){.name = pool_intern_cstr(p, "fp_offset"), .type = uit});
+ b, (Field){.name = cfree_sym_intern(p->c, CFREE_SLICE_LIT("fp_offset")), .type = uit});
type_record_field(
- b, (Field){.name = pool_intern_cstr(p, "overflow_arg_area"),
+ b, (Field){.name = cfree_sym_intern(p->c, CFREE_SLICE_LIT("overflow_arg_area")),
.type = vp});
type_record_field(
- b, (Field){.name = pool_intern_cstr(p, "reg_save_area"), .type = vp});
+ b, (Field){.name = cfree_sym_intern(p->c, CFREE_SLICE_LIT("reg_save_area")), .type = vp});
return type_record_end(p, b);
}
case CFREE_ARCH_ARM_64:
@@ -159,20 +159,20 @@ const Type* c_abi_va_list_type(TargetABI* a, Pool* p) {
} else {
const Type* vp = type_ptr(p, type_void(p));
const Type* it = type_prim(p, TY_INT);
- Sym name = pool_intern_cstr(p, "__va_list");
+ Sym name = cfree_sym_intern(p->c, CFREE_SLICE_LIT("__va_list"));
SrcLoc nl = {0, 0, 0};
TagId tg = type_tag_new(p, TAG_STRUCT, name, nl);
TypeRecordBuilder* b = type_record_begin(p, TY_STRUCT, tg, name);
type_record_field(
- b, (Field){.name = pool_intern_cstr(p, "__stack"), .type = vp});
+ b, (Field){.name = cfree_sym_intern(p->c, CFREE_SLICE_LIT("__stack")), .type = vp});
type_record_field(
- b, (Field){.name = pool_intern_cstr(p, "__gr_top"), .type = vp});
+ b, (Field){.name = cfree_sym_intern(p->c, CFREE_SLICE_LIT("__gr_top")), .type = vp});
type_record_field(
- b, (Field){.name = pool_intern_cstr(p, "__vr_top"), .type = vp});
+ b, (Field){.name = cfree_sym_intern(p->c, CFREE_SLICE_LIT("__vr_top")), .type = vp});
type_record_field(
- b, (Field){.name = pool_intern_cstr(p, "__gr_offs"), .type = it});
+ b, (Field){.name = cfree_sym_intern(p->c, CFREE_SLICE_LIT("__gr_offs")), .type = it});
type_record_field(
- b, (Field){.name = pool_intern_cstr(p, "__vr_offs"), .type = it});
+ b, (Field){.name = cfree_sym_intern(p->c, CFREE_SLICE_LIT("__vr_offs")), .type = it});
return type_record_end(p, b);
}
case CFREE_ARCH_RV64:
diff --git a/lang/c/c.c b/lang/c/c.c
@@ -16,7 +16,8 @@ static SrcLoc c_no_loc(void) {
}
static _Noreturn void c_bad_options(Compiler* c, const char* msg) {
- compiler_panic(c, c_no_loc(), "bad C frontend options: %s", msg);
+ compiler_panic(c, c_no_loc(), "bad C frontend options: %.*s",
+ CFREE_SLICE_ARG(cfree_slice_cstr(msg)));
}
static void c_apply_pp_options(Pp* pp, const CfreePreprocessOptions* opts) {
@@ -29,11 +30,12 @@ static void c_apply_pp_options(Pp* pp, const CfreePreprocessOptions* opts) {
pp_add_include_dir(pp, opts->system_include_dirs[i], 1);
}
for (i = 0; i < opts->ndefines; ++i) {
- const char* body = opts->defines[i].body ? opts->defines[i].body : "1";
- pp_define(pp, opts->defines[i].name, body);
+ const char* body =
+ opts->defines[i].body.len ? opts->defines[i].body.s : "1";
+ pp_define(pp, opts->defines[i].name.s, body);
}
for (i = 0; i < opts->nundefines; ++i) {
- pp_undef(pp, opts->undefines[i]);
+ pp_undef(pp, opts->undefines[i].s);
}
}
@@ -60,7 +62,7 @@ static CfreeStatus c_frontend_compile(
/* The libcfree pipeline plants the original CfreeCCompileOptions* in
* language_options. Recover it for preprocessor configuration. */
const CfreeCCompileOptions* opts;
- const CfreeBytes* bytes;
+ const CfreeSlice* bytes;
Pool* pool;
Lexer* lex;
Pp* pp;
@@ -81,7 +83,7 @@ static CfreeStatus c_frontend_compile(
cfree_frontend_metrics_scope_end(c, "compile.c.pool_new");
if (!pool) compiler_panic(c, c_no_loc(), "C compiler out of memory");
cfree_frontend_metrics_scope_begin(c, "compile.c.lex_open");
- lex = lex_open_mem(c, bytes->name, (const char*)bytes->data, bytes->len);
+ lex = lex_open_mem(c, input->name.s, bytes->s, bytes->len);
cfree_frontend_metrics_scope_end(c, "compile.c.lex_open");
cfree_frontend_metrics_scope_begin(c, "compile.c.pp_new");
pp = pp_new(c);
@@ -142,4 +144,5 @@ const CfreeFrontendVTable cfree_c_frontend_vtable = {
c_frontend_compile,
c_frontend_free,
NULL,
+ 0,
};
diff --git a/lang/c/decl/decl_attrs.c b/lang/c/decl/decl_attrs.c
@@ -18,21 +18,21 @@ static void apply_visibility(Compiler* c, const Attr* a, Decl* out) {
if (a->v.sym == 0) {
compiler_panic(c, a->loc, "visibility attribute missing argument");
}
- size_t n = 0;
- const char* s = compiler_sym_str(c, a->v.sym, &n);
- if (s && strcmp(s, "default") == 0) {
+ CfreeSlice ss = cfree_sym_str(c, a->v.sym);
+ const char* s = ss.s;
+ if (s && cfree_slice_eq_cstr(ss, "default")) {
out->visibility = SV_DEFAULT;
- } else if (s && strcmp(s, "hidden") == 0) {
+ } else if (s && cfree_slice_eq_cstr(ss, "hidden")) {
out->visibility = SV_HIDDEN;
- } else if (s && strcmp(s, "protected") == 0) {
+ } else if (s && cfree_slice_eq_cstr(ss, "protected")) {
out->visibility = SV_PROTECTED;
- } else if (s && strcmp(s, "internal") == 0) {
+ } else if (s && cfree_slice_eq_cstr(ss, "internal")) {
out->visibility = SV_INTERNAL;
} else {
compiler_panic(c, a->loc,
- "unknown visibility '%s' (expected default|hidden|"
+ "unknown visibility '%.*s' (expected default|hidden|"
"protected|internal)",
- s ? s : "");
+ CFREE_SLICE_ARG(cfree_slice_cstr(s ? s : "")));
}
}
diff --git a/lang/c/parse/cg_adapter.c b/lang/c/parse/cg_adapter.c
@@ -1032,11 +1032,11 @@ void pcg_inline_asm(Parser* p, const char* tmpl, const AsmConstraint* outs,
CfreeCgAsmOperand* in = NULL;
CfreeSym* cl = NULL;
memset(&a, 0, sizeof a);
- a.tmpl = cfree_sym_intern(p->c, tmpl ? tmpl : "");
+ a.tmpl = cfree_sym_intern(p->c, cfree_slice_cstr(tmpl ? tmpl : ""));
if (nout) {
o = arena_zarray(p->pool->arena, CfreeCgAsmOperand, nout);
for (u32 i = 0; i < nout; ++i) {
- o[i].constraint = cfree_sym_intern(p->c, outs[i].str ? outs[i].str : "");
+ o[i].constraint = cfree_sym_intern(p->c, cfree_slice_cstr(outs[i].str ? outs[i].str : ""));
o[i].name = outs[i].name;
o[i].type = pcg_tid(p, outs[i].type);
o[i].dir = CFREE_CG_ASM_OUT;
@@ -1045,7 +1045,7 @@ void pcg_inline_asm(Parser* p, const char* tmpl, const AsmConstraint* outs,
if (nin) {
in = arena_zarray(p->pool->arena, CfreeCgAsmOperand, nin);
for (u32 i = 0; i < nin; ++i) {
- in[i].constraint = cfree_sym_intern(p->c, ins[i].str ? ins[i].str : "");
+ in[i].constraint = cfree_sym_intern(p->c, cfree_slice_cstr(ins[i].str ? ins[i].str : ""));
in[i].name = ins[i].name;
in[i].type = pcg_tid(p, ins[i].type);
in[i].dir =
diff --git a/lang/c/parse/parse.c b/lang/c/parse/parse.c
@@ -107,9 +107,11 @@ static Tok fuse_string_lits(Parser* p, Tok a, Tok b) {
u16 ae = (u16)(a.flags & STR_ENC_MASK);
u16 be = (u16)(b.flags & STR_ENC_MASK);
u16 fused_enc;
- size_t alen = 0, blen = 0;
- const char* as = pool_str(p->pool, a.spelling, &alen);
- const char* bs = pool_str(p->pool, b.spelling, &blen);
+ CfreeSlice a_sl = cfree_sym_str(p->pool->c, a.spelling);
+ CfreeSlice b_sl = cfree_sym_str(p->pool->c, b.spelling);
+ size_t alen = a_sl.len, blen = b_sl.len;
+ const char* as = a_sl.s;
+ const char* bs = b_sl.s;
size_t apfx, bpfx;
size_t a_content_len, b_content_len;
size_t out_pfx_len;
@@ -153,7 +155,7 @@ static Tok fuse_string_lits(Parser* p, Tok a, Tok b) {
}
buf[k++] = '"';
out = a;
- out.spelling = pool_intern(p->pool, buf, k);
+ out.spelling = cfree_sym_intern(p->pool->c, (CfreeSlice){ .s = buf, .len = k });
out.flags = (u16)((a.flags & ~STR_ENC_MASK) | fused_enc);
out.lit = LIT_NONE;
h->free(h, buf, 0);
@@ -210,7 +212,7 @@ Tok peek1(Parser* p) {
void expect_punct(Parser* p, u32 punct, const char* what) {
if (!accept_punct(p, punct)) {
- perr(p, "expected %s", what);
+ perr(p, "expected %.*s", CFREE_SLICE_ARG(cfree_slice_cstr(what)));
}
}
@@ -659,8 +661,9 @@ static VLABound* build_param_vla_bounds(Parser* p, const ParamInfo* info,
/* Mint a unique linker name for a static local: `<orig>.<counter>`. */
Sym mint_static_local_sym(Parser* p, Sym orig) {
- size_t olen = 0;
- const char* on = pool_str(p->pool, orig, &olen);
+ CfreeSlice orig_sl = cfree_sym_str(p->pool->c, orig);
+ size_t olen = orig_sl.len;
+ const char* on = orig_sl.s;
char buf[128];
u32 wlen = 0;
u32 id = ++p->static_local_counter;
@@ -679,7 +682,7 @@ Sym mint_static_local_sym(Parser* p, Sym orig) {
}
while (dn && wlen < sizeof buf - 1) buf[wlen++] = digits[--dn];
}
- return pool_intern(p->pool, buf, wlen);
+ return cfree_sym_intern(p->pool->c, (CfreeSlice){ .s = buf, .len = wlen });
}
/* ============================================================
@@ -800,7 +803,7 @@ static void parse_init_declarator(Parser* p, const DeclSpecs* specs) {
const Type* composite = NULL;
CSemCheck chk =
c_sem_check_redeclaration(p->pool, prior->type, var_ty, &composite);
- if (!chk.ok) perr(p, "%s", chk.message);
+ if (!chk.ok) perr(p, "%.*s", CFREE_SLICE_ARG(cfree_slice_cstr(chk.message)));
if (cur && cur->kind != SEK_GLOBAL) {
perr(p, "redefinition of identifier");
}
@@ -903,7 +906,7 @@ static void parse_init_declarator(Parser* p, const DeclSpecs* specs) {
const Type* rhs = cg_top_type(p->cg);
CSemCheck chk =
c_sem_check_assignment(p->pool, var_ty, rhs, C_SEM_ASSIGN_INIT);
- if (!chk.ok) perr(p, "%s", chk.message);
+ if (!chk.ok) perr(p, "%.*s", CFREE_SLICE_ARG(cfree_slice_cstr(chk.message)));
}
coerce_top_to_lvalue(p);
cg_store(p->cg);
@@ -1028,7 +1031,7 @@ static SymEntry* declare_function(Parser* p, Sym fname, const Type* fn_ty,
const Type* composite = NULL;
CSemCheck chk =
c_sem_check_redeclaration(p->pool, existing->type, fn_ty, &composite);
- if (!chk.ok) perr(p, "%s", chk.message);
+ if (!chk.ok) perr(p, "%.*s", CFREE_SLICE_ARG(cfree_slice_cstr(chk.message)));
if (specs->storage == DS_STATIC && existing->linkage == DL_EXTERNAL) {
perr(p, "static declaration follows non-static declaration");
}
@@ -1054,7 +1057,7 @@ static SymEntry* declare_function(Parser* p, Sym fname, const Type* fn_ty,
const Type* composite = NULL;
CSemCheck chk =
c_sem_check_redeclaration(p->pool, existing->type, fn_ty, &composite);
- if (!chk.ok) perr(p, "%s", chk.message);
+ if (!chk.ok) perr(p, "%.*s", CFREE_SLICE_ARG(cfree_slice_cstr(chk.message)));
if (specs->storage == DS_STATIC && existing->linkage == DL_EXTERNAL) {
perr(p, "static declaration follows non-static declaration");
}
@@ -1296,10 +1299,9 @@ static void parse_external_decl(Parser* p) {
if (fn_alias_target != 0) {
SymEntry* te = scope_lookup(p, fn_alias_target);
if (!te) {
- size_t nl = 0;
- const char* nm = pool_str(p->pool, fn_alias_target, &nl);
- compiler_panic(p->c, loc, "alias target '%s' is undefined",
- nm ? nm : "?");
+ const char* nm = cfree_sym_str(p->pool->c, fn_alias_target).s;
+ compiler_panic(p->c, loc, "alias target '%.*s' is undefined",
+ CFREE_SLICE_ARG(cfree_slice_cstr(nm ? nm : "?")));
}
CfreeCgAlias alias;
memset(&alias, 0, sizeof alias);
@@ -1310,10 +1312,9 @@ static void parse_external_decl(Parser* p) {
(fn_decl_flags & DF_WEAK) ? CFREE_SB_WEAK : CFREE_SB_GLOBAL;
alias.sym.visibility = CFREE_CG_VIS_DEFAULT;
if (cfree_cg_alias(p->cg, alias) == CFREE_CG_SYM_NONE) {
- size_t nl = 0;
- const char* nm = pool_str(p->pool, fn_alias_target, &nl);
- compiler_panic(p->c, loc, "alias target '%s' is undefined",
- nm ? nm : "?");
+ const char* nm = cfree_sym_str(p->pool->c, fn_alias_target).s;
+ compiler_panic(p->c, loc, "alias target '%.*s' is undefined",
+ CFREE_SLICE_ARG(cfree_slice_cstr(nm ? nm : "?")));
}
}
return;
@@ -1342,7 +1343,7 @@ static void parse_external_decl(Parser* p) {
const Type* composite = NULL;
CSemCheck chk = c_sem_check_redeclaration(p->pool, existing->type,
base_ty, &composite);
- if (!chk.ok) perr(p, "%s", chk.message);
+ if (!chk.ok) perr(p, "%.*s", CFREE_SLICE_ARG(cfree_slice_cstr(chk.message)));
if (specs.storage == DS_STATIC && existing->linkage == DL_EXTERNAL) {
perr(p, "static declaration follows non-static declaration");
}
@@ -1445,7 +1446,8 @@ static void parse_file_scope_asm(Parser* p) {
expect_punct(p, ';', "';' after file-scope asm");
if (nbytes > 0) --nbytes; /* drop decode_string_literal's trailing NUL */
if (pcg_emit_enabled(p)) {
- cfree_cg_file_scope_asm(p->cg, (const char*)bytes, nbytes);
+ CfreeSlice asm_src = {{(const char*)bytes}, nbytes};
+ cfree_cg_file_scope_asm(p->cg, asm_src);
}
}
@@ -1487,68 +1489,68 @@ void parse_c(Compiler* c, Pool* pool, Pp* pp, DeclTable* decls, CG* cg) {
p.pool = pool;
for (i = (CKw)1; i < KW_COUNT; ++i) {
- p.kw_sym[i] = pool_intern_cstr(p.pool, kw_names[i]);
- }
-
- p.sym_b_alloca = pool_intern_cstr(p.pool, "__builtin_alloca");
- p.sym_b_ctz = pool_intern_cstr(p.pool, "__builtin_ctz");
- p.sym_b_ctzl = pool_intern_cstr(p.pool, "__builtin_ctzl");
- p.sym_b_ctzll = pool_intern_cstr(p.pool, "__builtin_ctzll");
- p.sym_b_clz = pool_intern_cstr(p.pool, "__builtin_clz");
- p.sym_b_clzl = pool_intern_cstr(p.pool, "__builtin_clzl");
- p.sym_b_clzll = pool_intern_cstr(p.pool, "__builtin_clzll");
- p.sym_b_trap = pool_intern_cstr(p.pool, "__builtin_trap");
- p.sym_b_unreachable = pool_intern_cstr(p.pool, "__builtin_unreachable");
- p.sym_b_memcpy = pool_intern_cstr(p.pool, "__builtin_memcpy");
- p.sym_b_memmove = pool_intern_cstr(p.pool, "__builtin_memmove");
- p.sym_b_memcmp = pool_intern_cstr(p.pool, "__builtin_memcmp");
- p.sym_b_memset = pool_intern_cstr(p.pool, "__builtin_memset");
- p.sym_b_clear_cache = pool_intern_cstr(p.pool, "__builtin___clear_cache");
- p.sym_b_isnan = pool_intern_cstr(p.pool, "__builtin_isnan");
- p.sym_b_fabs = pool_intern_cstr(p.pool, "__builtin_fabs");
- p.sym_b_fabsf = pool_intern_cstr(p.pool, "__builtin_fabsf");
- p.sym_b_fabsl = pool_intern_cstr(p.pool, "__builtin_fabsl");
- p.sym_b_inf = pool_intern_cstr(p.pool, "__builtin_inf");
- p.sym_b_inff = pool_intern_cstr(p.pool, "__builtin_inff");
- p.sym_b_infl = pool_intern_cstr(p.pool, "__builtin_infl");
- p.sym_b_huge_val = pool_intern_cstr(p.pool, "__builtin_huge_val");
- p.sym_b_huge_valf = pool_intern_cstr(p.pool, "__builtin_huge_valf");
- p.sym_b_huge_vall = pool_intern_cstr(p.pool, "__builtin_huge_vall");
- p.sym_func = pool_intern_cstr(p.pool, "__func__");
- p.sym_func_gcc = pool_intern_cstr(p.pool, "__FUNCTION__");
- p.sym_pretty_func_gcc = pool_intern_cstr(p.pool, "__PRETTY_FUNCTION__");
- p.sym_b_expect = pool_intern_cstr(p.pool, "__builtin_expect");
- p.sym_b_offsetof = pool_intern_cstr(p.pool, "__builtin_offsetof");
- p.sym_b_va_list = pool_intern_cstr(p.pool, "__builtin_va_list");
- p.sym_b_va_start = pool_intern_cstr(p.pool, "__builtin_va_start");
- p.sym_b_va_arg = pool_intern_cstr(p.pool, "__builtin_va_arg");
- p.sym_b_va_end = pool_intern_cstr(p.pool, "__builtin_va_end");
- p.sym_b_va_copy = pool_intern_cstr(p.pool, "__builtin_va_copy");
- p.sym_attribute = pool_intern_cstr(p.pool, "__attribute__");
- p.sym_volatile_alias = pool_intern_cstr(p.pool, "__volatile__");
- p.sym_alignof_alias = pool_intern_cstr(p.pool, "__alignof__");
- p.sym_asm_alias = pool_intern_cstr(p.pool, "__asm");
- p.sym_inline_alias = pool_intern_cstr(p.pool, "__inline");
- p.sym_inline_alias2 = pool_intern_cstr(p.pool, "__inline__");
- p.sym_thread_alias = pool_intern_cstr(p.pool, "__thread");
- p.sym_int128 = pool_intern_cstr(p.pool, "__int128");
- p.sym_int128_t = pool_intern_cstr(p.pool, "__int128_t");
- p.sym_uint128_t = pool_intern_cstr(p.pool, "__uint128_t");
- p.sym_a_load_n = pool_intern_cstr(p.pool, "__atomic_load_n");
- p.sym_a_store_n = pool_intern_cstr(p.pool, "__atomic_store_n");
- p.sym_a_exchange_n = pool_intern_cstr(p.pool, "__atomic_exchange_n");
- p.sym_a_fetch_add = pool_intern_cstr(p.pool, "__atomic_fetch_add");
- p.sym_a_fetch_sub = pool_intern_cstr(p.pool, "__atomic_fetch_sub");
- p.sym_a_fetch_and = pool_intern_cstr(p.pool, "__atomic_fetch_and");
- p.sym_a_fetch_or = pool_intern_cstr(p.pool, "__atomic_fetch_or");
- p.sym_a_fetch_xor = pool_intern_cstr(p.pool, "__atomic_fetch_xor");
- p.sym_a_fetch_nand = pool_intern_cstr(p.pool, "__atomic_fetch_nand");
- p.sym_a_cas_n = pool_intern_cstr(p.pool, "__atomic_compare_exchange_n");
+ p.kw_sym[i] = cfree_sym_intern(p.pool->c, cfree_slice_cstr(kw_names[i]));
+ }
+
+ p.sym_b_alloca = cfree_sym_intern(p.pool->c, CFREE_SLICE_LIT("__builtin_alloca"));
+ p.sym_b_ctz = cfree_sym_intern(p.pool->c, CFREE_SLICE_LIT("__builtin_ctz"));
+ p.sym_b_ctzl = cfree_sym_intern(p.pool->c, CFREE_SLICE_LIT("__builtin_ctzl"));
+ p.sym_b_ctzll = cfree_sym_intern(p.pool->c, CFREE_SLICE_LIT("__builtin_ctzll"));
+ p.sym_b_clz = cfree_sym_intern(p.pool->c, CFREE_SLICE_LIT("__builtin_clz"));
+ p.sym_b_clzl = cfree_sym_intern(p.pool->c, CFREE_SLICE_LIT("__builtin_clzl"));
+ p.sym_b_clzll = cfree_sym_intern(p.pool->c, CFREE_SLICE_LIT("__builtin_clzll"));
+ p.sym_b_trap = cfree_sym_intern(p.pool->c, CFREE_SLICE_LIT("__builtin_trap"));
+ p.sym_b_unreachable = cfree_sym_intern(p.pool->c, CFREE_SLICE_LIT("__builtin_unreachable"));
+ p.sym_b_memcpy = cfree_sym_intern(p.pool->c, CFREE_SLICE_LIT("__builtin_memcpy"));
+ p.sym_b_memmove = cfree_sym_intern(p.pool->c, CFREE_SLICE_LIT("__builtin_memmove"));
+ p.sym_b_memcmp = cfree_sym_intern(p.pool->c, CFREE_SLICE_LIT("__builtin_memcmp"));
+ p.sym_b_memset = cfree_sym_intern(p.pool->c, CFREE_SLICE_LIT("__builtin_memset"));
+ p.sym_b_clear_cache = cfree_sym_intern(p.pool->c, CFREE_SLICE_LIT("__builtin___clear_cache"));
+ p.sym_b_isnan = cfree_sym_intern(p.pool->c, CFREE_SLICE_LIT("__builtin_isnan"));
+ p.sym_b_fabs = cfree_sym_intern(p.pool->c, CFREE_SLICE_LIT("__builtin_fabs"));
+ p.sym_b_fabsf = cfree_sym_intern(p.pool->c, CFREE_SLICE_LIT("__builtin_fabsf"));
+ p.sym_b_fabsl = cfree_sym_intern(p.pool->c, CFREE_SLICE_LIT("__builtin_fabsl"));
+ p.sym_b_inf = cfree_sym_intern(p.pool->c, CFREE_SLICE_LIT("__builtin_inf"));
+ p.sym_b_inff = cfree_sym_intern(p.pool->c, CFREE_SLICE_LIT("__builtin_inff"));
+ p.sym_b_infl = cfree_sym_intern(p.pool->c, CFREE_SLICE_LIT("__builtin_infl"));
+ p.sym_b_huge_val = cfree_sym_intern(p.pool->c, CFREE_SLICE_LIT("__builtin_huge_val"));
+ p.sym_b_huge_valf = cfree_sym_intern(p.pool->c, CFREE_SLICE_LIT("__builtin_huge_valf"));
+ p.sym_b_huge_vall = cfree_sym_intern(p.pool->c, CFREE_SLICE_LIT("__builtin_huge_vall"));
+ p.sym_func = cfree_sym_intern(p.pool->c, CFREE_SLICE_LIT("__func__"));
+ p.sym_func_gcc = cfree_sym_intern(p.pool->c, CFREE_SLICE_LIT("__FUNCTION__"));
+ p.sym_pretty_func_gcc = cfree_sym_intern(p.pool->c, CFREE_SLICE_LIT("__PRETTY_FUNCTION__"));
+ p.sym_b_expect = cfree_sym_intern(p.pool->c, CFREE_SLICE_LIT("__builtin_expect"));
+ p.sym_b_offsetof = cfree_sym_intern(p.pool->c, CFREE_SLICE_LIT("__builtin_offsetof"));
+ p.sym_b_va_list = cfree_sym_intern(p.pool->c, CFREE_SLICE_LIT("__builtin_va_list"));
+ p.sym_b_va_start = cfree_sym_intern(p.pool->c, CFREE_SLICE_LIT("__builtin_va_start"));
+ p.sym_b_va_arg = cfree_sym_intern(p.pool->c, CFREE_SLICE_LIT("__builtin_va_arg"));
+ p.sym_b_va_end = cfree_sym_intern(p.pool->c, CFREE_SLICE_LIT("__builtin_va_end"));
+ p.sym_b_va_copy = cfree_sym_intern(p.pool->c, CFREE_SLICE_LIT("__builtin_va_copy"));
+ p.sym_attribute = cfree_sym_intern(p.pool->c, CFREE_SLICE_LIT("__attribute__"));
+ p.sym_volatile_alias = cfree_sym_intern(p.pool->c, CFREE_SLICE_LIT("__volatile__"));
+ p.sym_alignof_alias = cfree_sym_intern(p.pool->c, CFREE_SLICE_LIT("__alignof__"));
+ p.sym_asm_alias = cfree_sym_intern(p.pool->c, CFREE_SLICE_LIT("__asm"));
+ p.sym_inline_alias = cfree_sym_intern(p.pool->c, CFREE_SLICE_LIT("__inline"));
+ p.sym_inline_alias2 = cfree_sym_intern(p.pool->c, CFREE_SLICE_LIT("__inline__"));
+ p.sym_thread_alias = cfree_sym_intern(p.pool->c, CFREE_SLICE_LIT("__thread"));
+ p.sym_int128 = cfree_sym_intern(p.pool->c, CFREE_SLICE_LIT("__int128"));
+ p.sym_int128_t = cfree_sym_intern(p.pool->c, CFREE_SLICE_LIT("__int128_t"));
+ p.sym_uint128_t = cfree_sym_intern(p.pool->c, CFREE_SLICE_LIT("__uint128_t"));
+ p.sym_a_load_n = cfree_sym_intern(p.pool->c, CFREE_SLICE_LIT("__atomic_load_n"));
+ p.sym_a_store_n = cfree_sym_intern(p.pool->c, CFREE_SLICE_LIT("__atomic_store_n"));
+ p.sym_a_exchange_n = cfree_sym_intern(p.pool->c, CFREE_SLICE_LIT("__atomic_exchange_n"));
+ p.sym_a_fetch_add = cfree_sym_intern(p.pool->c, CFREE_SLICE_LIT("__atomic_fetch_add"));
+ p.sym_a_fetch_sub = cfree_sym_intern(p.pool->c, CFREE_SLICE_LIT("__atomic_fetch_sub"));
+ p.sym_a_fetch_and = cfree_sym_intern(p.pool->c, CFREE_SLICE_LIT("__atomic_fetch_and"));
+ p.sym_a_fetch_or = cfree_sym_intern(p.pool->c, CFREE_SLICE_LIT("__atomic_fetch_or"));
+ p.sym_a_fetch_xor = cfree_sym_intern(p.pool->c, CFREE_SLICE_LIT("__atomic_fetch_xor"));
+ p.sym_a_fetch_nand = cfree_sym_intern(p.pool->c, CFREE_SLICE_LIT("__atomic_fetch_nand"));
+ p.sym_a_cas_n = cfree_sym_intern(p.pool->c, CFREE_SLICE_LIT("__atomic_compare_exchange_n"));
p.sym_a_always_lock_free =
- pool_intern_cstr(p.pool, "__atomic_always_lock_free");
- p.sym_a_is_lock_free = pool_intern_cstr(p.pool, "__atomic_is_lock_free");
- p.sym_a_thread_fence = pool_intern_cstr(p.pool, "__atomic_thread_fence");
- p.sym_a_signal_fence = pool_intern_cstr(p.pool, "__atomic_signal_fence");
+ cfree_sym_intern(p.pool->c, CFREE_SLICE_LIT("__atomic_always_lock_free"));
+ p.sym_a_is_lock_free = cfree_sym_intern(p.pool->c, CFREE_SLICE_LIT("__atomic_is_lock_free"));
+ p.sym_a_thread_fence = cfree_sym_intern(p.pool->c, CFREE_SLICE_LIT("__atomic_thread_fence"));
+ p.sym_a_signal_fence = cfree_sym_intern(p.pool->c, CFREE_SLICE_LIT("__atomic_signal_fence"));
p.scope = scope_new(&p, NULL);
diff --git a/lang/c/parse/parse_expr.c b/lang/c/parse/parse_expr.c
@@ -71,11 +71,15 @@ static int null_pointer_constant(Parser* p, const Type* ty) {
}
static void require_scalar(Parser* p, const Type* ty, const char* what) {
- if (!c_type_is_scalar(ty)) perr(p, "%s requires scalar operand", what);
+ if (!c_type_is_scalar(ty))
+ perr(p, "%.*s requires scalar operand",
+ CFREE_SLICE_ARG(cfree_slice_cstr(what)));
}
static void require_arith(Parser* p, const Type* ty, const char* what) {
- if (!type_is_arith(ty)) perr(p, "%s requires arithmetic operand", what);
+ if (!type_is_arith(ty))
+ perr(p, "%.*s requires arithmetic operand",
+ CFREE_SLICE_ARG(cfree_slice_cstr(what)));
}
static const Type* conditional_pointer_type(Parser* p, const Type* then_ty,
@@ -100,8 +104,9 @@ static u32 cint_bits(Parser* p, const Type* ty);
static int cint_signed(Parser* p, const Type* ty);
static u64 parse_int_literal_u64(Parser* p, const Tok* t, int* decimal_out) {
- size_t len = 0;
- const char* s = pool_str(p->pool, t->spelling, &len);
+ CfreeSlice spell_sl = cfree_sym_str(p->pool->c, t->spelling);
+ size_t len = spell_sl.len;
+ const char* s = spell_sl.s;
size_t i = 0;
u64 base = 10;
u64 acc = 0;
@@ -219,8 +224,9 @@ static const Type* int_literal_type(Parser* p, const Tok* t) {
}
double parse_float_literal(Parser* p, const Tok* t) {
- size_t len = 0;
- const char* s = pool_str(p->pool, t->spelling, &len);
+ CfreeSlice spell_sl = cfree_sym_str(p->pool->c, t->spelling);
+ size_t len = spell_sl.len;
+ const char* s = spell_sl.s;
size_t i = 0;
int is_hex = 0;
double v = 0.0;
@@ -361,8 +367,9 @@ int string_literal_initializes_array(Parser* p, const Type* elem,
}
i64 decode_char_literal(Parser* p, const Tok* t) {
- size_t len = 0;
- const char* s = pool_str(p->pool, t->spelling, &len);
+ CfreeSlice spell_sl = cfree_sym_str(p->pool->c, t->spelling);
+ size_t len = spell_sl.len;
+ const char* s = spell_sl.s;
size_t i = 0;
CLitUnit unit;
const char* err = NULL;
@@ -382,10 +389,12 @@ i64 decode_char_literal(Parser* p, const Tok* t) {
i++;
if (i >= len || s[i] == '\'') perr(p, "empty character literal");
if (!c_lit_decode_unit(s, len, &i, &unit, &err)) {
- compiler_panic(p->c, t->loc, "%s", err ? err : "bad character literal");
+ compiler_panic(p->c, t->loc, "%.*s",
+ CFREE_SLICE_ARG(cfree_slice_cstr(err ? err : "bad character literal")));
}
if (!c_lit_encode_char_unit(enc, bits, unit, &v, &err)) {
- compiler_panic(p->c, t->loc, "%s", err ? err : "bad character literal");
+ compiler_panic(p->c, t->loc, "%.*s",
+ CFREE_SLICE_ARG(cfree_slice_cstr(err ? err : "bad character literal")));
}
if (i >= len || s[i] != '\'') {
perr(p, "multi-character constants are not supported");
@@ -394,8 +403,9 @@ i64 decode_char_literal(Parser* p, const Tok* t) {
}
u8* decode_string_literal(Parser* p, const Tok* t, size_t* nlen_out) {
- size_t len = 0;
- const char* s = pool_str(p->pool, t->spelling, &len);
+ CfreeSlice spell_sl = cfree_sym_str(p->pool->c, t->spelling);
+ size_t len = spell_sl.len;
+ const char* s = spell_sl.s;
size_t i = 0;
Heap* h = cfree_compiler_context(p->c)->heap;
u8* buf;
@@ -418,10 +428,12 @@ u8* decode_string_literal(Parser* p, const Tok* t, size_t* nlen_out) {
while (i < len && s[i] != '"') {
CLitUnit unit;
if (!c_lit_decode_unit(s, len, &i, &unit, &err)) {
- compiler_panic(p->c, t->loc, "%s", err ? err : "bad string literal");
+ compiler_panic(p->c, t->loc, "%.*s",
+ CFREE_SLICE_ARG(cfree_slice_cstr(err ? err : "bad string literal")));
}
if (!c_lit_append_string_unit(buf, &k, enc, elem_size, unit, &err)) {
- compiler_panic(p->c, t->loc, "%s", err ? err : "bad string literal");
+ compiler_panic(p->c, t->loc, "%.*s",
+ CFREE_SLICE_ARG(cfree_slice_cstr(err ? err : "bad string literal")));
}
}
c_lit_encode_uint_le(buf + k, elem_size, 0);
@@ -1104,7 +1116,8 @@ static void coerce_top_to_type(Parser* p, const Type* dst) {
static const Type* atomic_pointee_type(Parser* p, const Type* ptr_ty,
const char* who) {
if (!ptr_ty || ptr_ty->kind != TY_PTR) {
- perr(p, "%s: pointer argument must have pointer type", who);
+ perr(p, "%.*s: pointer argument must have pointer type",
+ CFREE_SLICE_ARG(cfree_slice_cstr(who)));
}
return ptr_ty->ptr.pointee;
}
@@ -1142,7 +1155,7 @@ static int atomic_lock_free_for_const_size(Parser* p, i64 size) {
static CfreeCgSym builtin_libcall_sym(Parser* p, const char* name,
const Type* fn_ty) {
CfreeCgDecl decl;
- Sym source_name = pool_intern_cstr(p->pool, name);
+ Sym source_name = cfree_sym_intern(p->pool->c, cfree_slice_cstr(name));
memset(&decl, 0, sizeof decl);
decl.kind = CFREE_CG_DECL_FUNC;
decl.display_name = source_name;
@@ -1360,10 +1373,8 @@ typedef struct BuiltinOverflowInfo {
} BuiltinOverflowInfo;
static int sym_eq_cstr(Parser* p, Sym sym, const char* want) {
- size_t got_len = 0;
- size_t want_len = strlen(want);
- const char* got = pool_str(p->pool, sym, &got_len);
- return got && got_len == want_len && memcmp(got, want, want_len) == 0;
+ CfreeSlice got = cfree_sym_str(p->pool->c, sym);
+ return got.s && cfree_slice_eq_cstr(got, want);
}
static int builtin_overflow_info(Parser* p, Sym name,
@@ -1583,8 +1594,9 @@ static int parse_builtin_fabs_call(Parser* p, Sym name, SrcLoc loc) {
}
static int parse_builtin_abs_call(Parser* p, Sym name, SrcLoc loc) {
- size_t nlen = 0;
- const char* nm = pool_str(p->pool, name, &nlen);
+ CfreeSlice name_sl = cfree_sym_str(p->pool->c, name);
+ size_t nlen = name_sl.len;
+ const char* nm = name_sl.s;
const char* libname = NULL;
const Type* int_ty = NULL;
const Type* params[1];
@@ -1991,13 +2003,15 @@ static void parse_primary(Parser* p) {
if (t.v.ident == p->sym_func || t.v.ident == p->sym_func_gcc ||
t.v.ident == p->sym_pretty_func_gcc) {
if (p->cur_func_name == 0) {
- compiler_panic(p->c, t.loc, "'%s' used outside a function",
- t.v.ident == p->sym_func ? "__func__"
- : t.v.ident == p->sym_func_gcc ? "__FUNCTION__"
- : "__PRETTY_FUNCTION__");
+ compiler_panic(p->c, t.loc, "'%.*s' used outside a function",
+ CFREE_SLICE_ARG(cfree_slice_cstr(
+ t.v.ident == p->sym_func ? "__func__"
+ : t.v.ident == p->sym_func_gcc ? "__FUNCTION__"
+ : "__PRETTY_FUNCTION__")));
}
- size_t nlen = 0;
- const char* fn_name = pool_str(p->pool, p->cur_func_name, &nlen);
+ CfreeSlice fn_name_sl = cfree_sym_str(p->pool->c, p->cur_func_name);
+ size_t nlen = fn_name_sl.len;
+ const char* fn_name = fn_name_sl.s;
Heap* h = cfree_compiler_context(p->c)->heap;
u8* bytes = (u8*)h->alloc(h, nlen + 1u, 1u);
for (size_t i = 0; i < nlen; ++i) bytes[i] = (u8)fn_name[i];
@@ -2012,8 +2026,9 @@ static void parse_primary(Parser* p) {
}
e = scope_lookup(p, t.v.ident);
if (!e) {
- size_t nlen = 0;
- const char* nm = pool_str(p->pool, t.v.ident, &nlen);
+ CfreeSlice ident_sl = cfree_sym_str(p->pool->c, t.v.ident);
+ size_t nlen = ident_sl.len;
+ const char* nm = ident_sl.s;
compiler_panic(p->c, t.loc, "undeclared identifier '%.*s'", (int)nlen,
nm ? nm : "?");
}
@@ -2194,7 +2209,7 @@ static void parse_postfix(Parser* p) {
if (param_ty) {
CSemCheck chk = c_sem_check_assignment(
p->pool, param_ty, cg_top_type(p->cg), C_SEM_ASSIGN_EXPR);
- if (!chk.ok) perr(p, "%s", chk.message);
+ if (!chk.ok) perr(p, "%.*s", CFREE_SLICE_ARG(cfree_slice_cstr(chk.message)));
coerce_top_to_type(p, param_ty);
}
++nargs;
@@ -3347,7 +3362,7 @@ void parse_assign_expr(Parser* p) {
const Type* rhs = cg_top_type(p->cg);
CSemCheck chk =
c_sem_check_assignment(p->pool, lhs, rhs, C_SEM_ASSIGN_EXPR);
- if (!chk.ok) perr(p, "%s", chk.message);
+ if (!chk.ok) perr(p, "%.*s", CFREE_SLICE_ARG(cfree_slice_cstr(chk.message)));
}
coerce_top_to_lvalue(p);
cg_store(p->cg);
@@ -3408,7 +3423,7 @@ void parse_assign_expr(Parser* p) {
break;
}
CSemCheck chk = c_sem_check_compound_assignment(p->pool, lhs, rhs, op);
- if (!chk.ok) perr(p, "%s", chk.message);
+ if (!chk.ok) perr(p, "%.*s", CFREE_SLICE_ARG(cfree_slice_cstr(chk.message)));
}
if (compound == BO_IADD || compound == BO_ISUB) {
emit_add_or_sub(p, compound);
diff --git a/lang/c/parse/parse_init.c b/lang/c/parse/parse_init.c
@@ -329,7 +329,7 @@ static void init_field_at(Parser* p, FrameSlot slot, const Type* arr_ty,
const Type* rhs = cg_top_type(p->cg);
CSemCheck chk =
c_sem_check_assignment(p->pool, f->type, rhs, C_SEM_ASSIGN_INIT);
- if (!chk.ok) perr(p, "%s", chk.message);
+ if (!chk.ok) perr(p, "%.*s", CFREE_SLICE_ARG(cfree_slice_cstr(chk.message)));
}
coerce_top_to_lvalue(p);
cg_store(p->cg);
@@ -750,7 +750,7 @@ void init_at(Parser* p, FrameSlot slot, const Type* arr_ty, u32 offset,
{
const Type* rhs = cg_top_type(p->cg);
CSemCheck chk = c_sem_check_assignment(p->pool, ty, rhs, C_SEM_ASSIGN_INIT);
- if (!chk.ok) perr(p, "%s", chk.message);
+ if (!chk.ok) perr(p, "%.*s", CFREE_SLICE_ARG(cfree_slice_cstr(chk.message)));
}
coerce_top_to_lvalue(p);
cg_store(p->cg);
@@ -1001,7 +1001,7 @@ static Sym mint_compound_literal_sym(Parser* p) {
}
while (dn) buf[wlen++] = digits[--dn];
}
- return pool_intern(p->pool, buf, wlen);
+ return cfree_sym_intern(p->pool->c, (CfreeSlice){ .s = buf, .len = wlen });
}
static void static_relocs_swap_empty(Parser* p, StaticRelocSave* save) {
diff --git a/lang/c/parse/parse_stmt.c b/lang/c/parse/parse_stmt.c
@@ -172,7 +172,7 @@ static void parse_return_stmt(Parser* p) {
const Type* rhs = cg_top_type(p->cg);
CSemCheck chk = c_sem_check_assignment(p->pool, p->cur_func_ret, rhs,
C_SEM_ASSIGN_RETURN);
- if (!chk.ok) perr(p, "%s", chk.message);
+ if (!chk.ok) perr(p, "%.*s", CFREE_SLICE_ARG(cfree_slice_cstr(chk.message)));
}
expect_punct(p, ';', "';' after return value");
cg_ret(p->cg, 1);
@@ -443,8 +443,9 @@ void parse_static_assert(Parser* p) {
expect_punct(p, ')', "')' after _Static_assert");
expect_punct(p, ';', "';' after _Static_assert");
if (!v) {
- size_t mlen = 0;
- const char* mstr = pool_str(p->pool, msg.spelling, &mlen);
+ CfreeSlice msg_sl = cfree_sym_str(p->pool->c, msg.spelling);
+ size_t mlen = msg_sl.len;
+ const char* mstr = msg_sl.s;
compiler_panic(p->c, loc, "static assertion failed: %.*s", (int)mlen,
mstr ? mstr : "");
}
@@ -478,15 +479,16 @@ static const char* parse_asm_str(Parser* p, const char* what) {
Sym s;
Tok t;
if (p->cur.kind != TOK_STR) {
- perr(p, "expected string literal in %s", what);
+ perr(p, "expected string literal in %.*s",
+ CFREE_SLICE_ARG(cfree_slice_cstr(what)));
}
t = p->cur;
advance(p);
bytes = decode_string_literal(p, &t, &nlen);
if (nlen > 0) nlen -= 1;
- s = pool_intern(p->pool, (const char*)bytes, nlen);
+ s = cfree_sym_intern(p->pool->c, (CfreeSlice){ .s = (const char*)bytes, .len = nlen });
cfree_compiler_context(p->c)->heap->free(cfree_compiler_context(p->c)->heap, bytes, 0);
- return pool_str(p->pool, s, NULL);
+ return cfree_sym_str(p->pool->c, s).s;
}
static void parse_asm_stmt(Parser* p) {
@@ -613,7 +615,7 @@ static void parse_asm_stmt(Parser* p) {
const char* cstr;
Sym cs;
cstr = parse_asm_str(p, "asm clobber");
- cs = pool_intern_cstr(p->pool, cstr);
+ cs = cfree_sym_intern(p->pool->c, cfree_slice_cstr(cstr));
if (nclob == cap_clob) {
u32 nc = cap_clob * 2;
Sym* nb = (Sym*)arena_array(p->pool->arena, Sym, nc);
diff --git a/lang/c/parse/parse_type.c b/lang/c/parse/parse_type.c
@@ -71,14 +71,14 @@ static int accept_kw(Parser* p, CKw k) {
}
static int attr_sym_canon_eq(Parser* p, Sym sym, const char* want) {
- size_t len = 0;
- const char* s = pool_str(p->pool, sym, &len);
+ CfreeSlice sym_sl = cfree_sym_str(p->pool->c, sym);
+ size_t len = sym_sl.len;
+ const char* s = sym_sl.s;
const char* cs;
size_t clen;
- size_t wlen = strlen(want);
if (!s) return 0;
attr_canon_range(s, len, &cs, &clen);
- return clen == wlen && memcmp(cs, want, wlen) == 0;
+ return cfree_slice_eq_cstr((CfreeSlice){ .s = cs, .len = clen }, want);
}
static const Type* attrs_apply_type_mode(Parser* p, const Type* base,
@@ -163,8 +163,9 @@ static void attr_canon_range(const char* s, size_t len, const char** out_p,
}
static AttrKind classify_attr(Parser* p, Sym name, AttrArgShape* shape_out) {
- size_t len = 0;
- const char* s = pool_str(p->pool, name, &len);
+ CfreeSlice name_sl = cfree_sym_str(p->pool->c, name);
+ size_t len = name_sl.len;
+ const char* s = name_sl.s;
const char* cs;
size_t clen;
size_t i;
@@ -175,8 +176,7 @@ static AttrKind classify_attr(Parser* p, Sym name, AttrArgShape* shape_out) {
attr_canon_range(s, len, &cs, &clen);
for (i = 0; i < sizeof(kAttrTable) / sizeof(kAttrTable[0]); ++i) {
const char* tn = kAttrTable[i].name;
- size_t tlen = strlen(tn);
- if (tlen == clen && memcmp(tn, cs, clen) == 0) {
+ if (cfree_slice_eq_cstr((CfreeSlice){ .s = cs, .len = clen }, tn)) {
*shape_out = kAttrTable[i].shape;
return kAttrTable[i].kind;
}
@@ -214,13 +214,15 @@ static void parse_attr_args(Parser* p, Attr* a, AttrArgShape shape,
shape == AS_OPAQUE) {
return;
}
- perr(p, "attribute '%s' expects '(' arguments", attr_diag_name);
+ perr(p, "attribute '%.*s' expects '(' arguments",
+ CFREE_SLICE_ARG(cfree_slice_cstr(attr_diag_name)));
}
switch (shape) {
case AS_NONE: {
advance(p); /* '(' */
if (!accept_punct(p, ')')) {
- perr(p, "attribute '%s' takes no arguments", attr_diag_name);
+ perr(p, "attribute '%.*s' takes no arguments",
+ CFREE_SLICE_ARG(cfree_slice_cstr(attr_diag_name)));
}
return;
}
@@ -234,7 +236,8 @@ static void parse_attr_args(Parser* p, Attr* a, AttrArgShape shape,
advance(p); /* '(' */
if (is_punct(&p->cur, ')')) {
if (shape == AS_INT) {
- perr(p, "attribute '%s' expects an integer argument", attr_diag_name);
+ perr(p, "attribute '%.*s' expects an integer argument",
+ CFREE_SLICE_ARG(cfree_slice_cstr(attr_diag_name)));
}
advance(p);
return;
@@ -252,14 +255,15 @@ static void parse_attr_args(Parser* p, Attr* a, AttrArgShape shape,
case AS_STRING: {
advance(p); /* '(' */
if (p->cur.kind != TOK_STR) {
- perr(p, "attribute '%s' expects a string literal", attr_diag_name);
+ perr(p, "attribute '%.*s' expects a string literal",
+ CFREE_SLICE_ARG(cfree_slice_cstr(attr_diag_name)));
}
{
Tok t = p->cur;
size_t nlen = 0;
u8* bytes = decode_string_literal(p, &t, &nlen);
u32 ilen = (nlen > 0) ? (u32)(nlen - 1) : 0;
- a->v.sym = pool_intern(p->pool, (const char*)bytes, ilen);
+ a->v.sym = cfree_sym_intern(p->pool->c, (CfreeSlice){ .s = (const char*)bytes, .len = ilen });
cfree_compiler_context(p->c)->heap->free(cfree_compiler_context(p->c)->heap, bytes, 0);
}
a->nargs = 1;
@@ -270,7 +274,8 @@ static void parse_attr_args(Parser* p, Attr* a, AttrArgShape shape,
case AS_IDENT: {
advance(p); /* '(' */
if (p->cur.kind != TOK_IDENT) {
- perr(p, "attribute '%s' expects an identifier", attr_diag_name);
+ perr(p, "attribute '%.*s' expects an identifier",
+ CFREE_SLICE_ARG(cfree_slice_cstr(attr_diag_name)));
}
a->v.sym = p->cur.v.ident;
a->nargs = 1;
@@ -339,7 +344,11 @@ Attr* parse_attribute_spec_list(Parser* p) {
a->name = aname;
a->kind = (u16)classify_attr(p, aname, &shape);
advance(p);
- diag_name = pool_str(p->pool, aname, &diag_len);
+ {
+ CfreeSlice aname_sl = cfree_sym_str(p->pool->c, aname);
+ diag_name = aname_sl.s;
+ diag_len = aname_sl.len;
+ }
attr_canon_range(diag_name, diag_len, &canon, &canon_len);
(void)canon;
(void)canon_len;
diff --git a/lang/c/sem/sem.c b/lang/c/sem/sem.c
@@ -1,5 +1,3 @@
-#include <string.h>
-
#include "sem/sem.h"
static int is_void_pointer(const Type* t) {
@@ -8,13 +6,12 @@ static int is_void_pointer(const Type* t) {
}
static int is_builtin_va_list_record(Pool* p, const Type* t) {
- size_t n = 0;
- const char* s;
+ CfreeSlice s;
if (!t || t->kind != TY_STRUCT || !t->rec.tag) return 0;
- s = pool_str(p, t->rec.tag, &n);
- if (!s) return 0;
- return (n == 9 && memcmp(s, "__va_list", 9) == 0) ||
- (n == 13 && memcmp(s, "__va_list_tag", 13) == 0);
+ s = cfree_sym_str(p->c, t->rec.tag);
+ if (!s.s) return 0;
+ return cfree_slice_eq_cstr(s, "__va_list") ||
+ cfree_slice_eq_cstr(s, "__va_list_tag");
}
static int pointer_pointees_assignable(Pool* p, const Type* lhs,
diff --git a/lang/cpp/cpp.c b/lang/cpp/cpp.c
@@ -20,7 +20,8 @@ static SrcLoc cpp_no_loc(void) {
}
static _Noreturn void cpp_bad_options(Compiler* c, const char* msg) {
- compiler_panic(c, cpp_no_loc(), "bad preprocess options: %s", msg);
+ compiler_panic(c, cpp_no_loc(), "bad preprocess options: %.*s",
+ CFREE_SLICE_ARG(cfree_slice_cstr(msg)));
}
static void cpp_apply_options(Pp* pp, const CfreePreprocessOptions* opts) {
@@ -33,17 +34,19 @@ static void cpp_apply_options(Pp* pp, const CfreePreprocessOptions* opts) {
pp_add_include_dir(pp, opts->system_include_dirs[i], 1);
}
for (i = 0; i < opts->ndefines; ++i) {
- const char* body = opts->defines[i].body ? opts->defines[i].body : "1";
- pp_define(pp, opts->defines[i].name, body);
+ const char* body =
+ opts->defines[i].body.len ? opts->defines[i].body.s : "1";
+ pp_define(pp, opts->defines[i].name.s, body);
}
for (i = 0; i < opts->nundefines; ++i) {
- pp_undef(pp, opts->undefines[i]);
+ pp_undef(pp, opts->undefines[i].s);
}
}
typedef struct CppRun {
const CfreePreprocessOptions* opts;
- const CfreeBytes* input;
+ CfreeSlice name;
+ const CfreeSlice* input;
CfreeWriter* out;
} CppRun;
@@ -53,18 +56,18 @@ static CfreeStatus cpp_preprocess_body(CfreeCompiler* c, void* user) {
Pp* pp;
const CfreePreprocessOptions* opts = r->opts;
- const CfreeBytes* input = r->input;
+ const CfreeSlice* input = r->input;
CfreeWriter* out = r->out;
if (!opts || !input || !out) {
cpp_bad_options(c, "preprocess args missing");
}
- if (!input->name) cpp_bad_options(c, "input name is NULL");
+ if (!r->name.s) cpp_bad_options(c, "input name is NULL");
if (!input->data && input->len != 0) {
cpp_bad_options(c, "input data is NULL but len > 0");
}
- lex = lex_open_mem(c, input->name, (const char*)input->data, input->len);
+ lex = lex_open_mem(c, r->name.s, input->s, input->len);
pp = pp_new(c);
if (!lex || !pp)
compiler_panic(c, cpp_no_loc(), "C preprocessor out of memory");
@@ -77,9 +80,11 @@ static CfreeStatus cpp_preprocess_body(CfreeCompiler* c, void* user) {
CfreeStatus cfree_cpp_preprocess(CfreeCompiler* c,
const CfreePreprocessOptions* opts,
- const CfreeBytes* input, CfreeWriter* out) {
+ CfreeSlice name, const CfreeSlice* input,
+ CfreeWriter* out) {
CppRun r;
r.opts = opts;
+ r.name = name;
r.input = input;
r.out = out;
return cfree_frontend_run(c, cpp_preprocess_body, &r);
diff --git a/lang/cpp/cpp_support.h b/lang/cpp/cpp_support.h
@@ -57,23 +57,6 @@ static inline void c_pool_free(Pool* p) {
if (h) h->free(h, p, sizeof(*p));
}
-static inline Sym pool_intern(Pool* p, const char* s, size_t len) {
- return cfree_sym_intern_len(p->c, s, len);
-}
-
-static inline Sym pool_intern_cstr(Pool* p, const char* s) {
- return cfree_sym_intern(p->c, s);
-}
-
-static inline const char* pool_str(Pool* p, Sym sym, size_t* len_out) {
- return cfree_sym_str(p->c, sym, len_out);
-}
-
-static inline const char* compiler_sym_str(Compiler* c, Sym sym,
- size_t* len_out) {
- return cfree_sym_str(c, sym, len_out);
-}
-
#define arena_alloc(a, size, align) cfree_arena_alloc((a), (size), (align))
#define arena_zalloc(a, size, align) cfree_arena_zalloc((a), (size), (align))
#define arena_strdup(a, s, len) cfree_arena_strdup((a), (s), (len))
diff --git a/lang/cpp/lex/lex.c b/lang/cpp/lex/lex.c
@@ -138,7 +138,7 @@ Lexer* lex_open_mem(Compiler* c, const char* name, const char* src,
l->len = src ? len : 0;
l->pos = 0;
l->file_id = 0;
- (void)cfree_source_add_memory(c, name, &l->file_id);
+ (void)cfree_source_add_memory(c, cfree_slice_cstr(name), &l->file_id);
l->line = 1;
l->col = 1;
l->at_bol = 1;
@@ -175,7 +175,9 @@ static Sym intern_spliced(Lexer* l, size_t start, size_t end) {
break;
}
}
- if (!has_splice) return pool_intern(l->pool, l->src + start, end - start);
+ if (!has_splice)
+ return cfree_sym_intern(
+ l->pool->c, (CfreeSlice){ .s = l->src + start, .len = end - start });
buf = (char*)l->heap->alloc(l->heap, end - start, 1);
k = 0;
@@ -186,7 +188,7 @@ static Sym intern_spliced(Lexer* l, size_t start, size_t end) {
}
buf[k++] = l->src[i++];
}
- sym = pool_intern(l->pool, buf, k);
+ sym = cfree_sym_intern(l->pool->c, (CfreeSlice){ .s = buf, .len = k });
l->heap->free(l->heap, buf, end - start);
return sym;
}
@@ -455,9 +457,8 @@ Tok lex_next(Lexer* l) {
t.spelling = intern_spliced(l, start, l->pos);
t.v.ident = t.spelling;
if (l->dstate == 1) {
- size_t slen = 0;
- const char* sstr = pool_str(l->pool, t.spelling, &slen);
- l->dstate = (sstr && matches_include_kw(sstr, slen)) ? 2 : 0;
+ CfreeSlice s = cfree_sym_str(l->pool->c, t.spelling);
+ l->dstate = (s.s && matches_include_kw(s.s, s.len)) ? 2 : 0;
} else {
l->dstate = 0;
}
@@ -525,7 +526,7 @@ Tok lex_next(Lexer* l) {
break;
}
}
- t.spelling = pool_intern(l->pool, pbuf, k);
+ t.spelling = cfree_sym_intern(l->pool->c, (CfreeSlice){ .s = pbuf, .len = k });
l->heap->free(l->heap, pbuf, plen ? plen : 1);
l->dstate = 0;
return t;
diff --git a/lang/cpp/pp/pp.c b/lang/cpp/pp/pp.c
@@ -181,9 +181,8 @@ void pp_emit_text(Pp* pp, Writer* out) {
w_str(out, " ", 1);
}
if (t.spelling) {
- size_t slen = 0;
- const char* s = pool_str(pp->pool, t.spelling, &slen);
- w_str(out, s, slen);
+ CfreeSlice s = cfree_sym_str(pp->pool->c, t.spelling);
+ w_str(out, s.s, s.len);
}
at_bol = 0;
}
@@ -195,31 +194,31 @@ void pp_emit_text(Pp* pp, Writer* out) {
static void pp_intern_keywords(Pp* pp) {
Pool* p = pp->pool;
- pp->sym_define = pool_intern_cstr(p, "define");
- pp->sym_undef = pool_intern_cstr(p, "undef");
- pp->sym_include = pool_intern_cstr(p, "include");
- pp->sym_if = pool_intern_cstr(p, "if");
- pp->sym_ifdef = pool_intern_cstr(p, "ifdef");
- pp->sym_ifndef = pool_intern_cstr(p, "ifndef");
- pp->sym_elif = pool_intern_cstr(p, "elif");
- pp->sym_else = pool_intern_cstr(p, "else");
- pp->sym_endif = pool_intern_cstr(p, "endif");
- pp->sym_line = pool_intern_cstr(p, "line");
- pp->sym_pragma = pool_intern_cstr(p, "pragma");
+ pp->sym_define = cfree_sym_intern(p->c, CFREE_SLICE_LIT("define"));
+ pp->sym_undef = cfree_sym_intern(p->c, CFREE_SLICE_LIT("undef"));
+ pp->sym_include = cfree_sym_intern(p->c, CFREE_SLICE_LIT("include"));
+ pp->sym_if = cfree_sym_intern(p->c, CFREE_SLICE_LIT("if"));
+ pp->sym_ifdef = cfree_sym_intern(p->c, CFREE_SLICE_LIT("ifdef"));
+ pp->sym_ifndef = cfree_sym_intern(p->c, CFREE_SLICE_LIT("ifndef"));
+ pp->sym_elif = cfree_sym_intern(p->c, CFREE_SLICE_LIT("elif"));
+ pp->sym_else = cfree_sym_intern(p->c, CFREE_SLICE_LIT("else"));
+ pp->sym_endif = cfree_sym_intern(p->c, CFREE_SLICE_LIT("endif"));
+ pp->sym_line = cfree_sym_intern(p->c, CFREE_SLICE_LIT("line"));
+ pp->sym_pragma = cfree_sym_intern(p->c, CFREE_SLICE_LIT("pragma"));
pp->sym_pragma_kw = pp->sym_pragma;
- pp->sym_error = pool_intern_cstr(p, "error");
- pp->sym_warning = pool_intern_cstr(p, "warning");
- pp->sym_embed = pool_intern_cstr(p, "embed");
- pp->sym_defined = pool_intern_cstr(p, "defined");
- pp->sym_va_args = pool_intern_cstr(p, "__VA_ARGS__");
- pp->sym_line__ = pool_intern_cstr(p, "__LINE__");
- pp->sym_file__ = pool_intern_cstr(p, "__FILE__");
- pp->sym_date__ = pool_intern_cstr(p, "__DATE__");
- pp->sym_time__ = pool_intern_cstr(p, "__TIME__");
- pp->sym_stdc__ = pool_intern_cstr(p, "__STDC__");
- pp->sym_stdc_hosted__ = pool_intern_cstr(p, "__STDC_HOSTED__");
- pp->sym_stdc_version__ = pool_intern_cstr(p, "__STDC_VERSION__");
- pp->sym__pragma = pool_intern_cstr(p, "_Pragma");
+ pp->sym_error = cfree_sym_intern(p->c, CFREE_SLICE_LIT("error"));
+ pp->sym_warning = cfree_sym_intern(p->c, CFREE_SLICE_LIT("warning"));
+ pp->sym_embed = cfree_sym_intern(p->c, CFREE_SLICE_LIT("embed"));
+ pp->sym_defined = cfree_sym_intern(p->c, CFREE_SLICE_LIT("defined"));
+ pp->sym_va_args = cfree_sym_intern(p->c, CFREE_SLICE_LIT("__VA_ARGS__"));
+ pp->sym_line__ = cfree_sym_intern(p->c, CFREE_SLICE_LIT("__LINE__"));
+ pp->sym_file__ = cfree_sym_intern(p->c, CFREE_SLICE_LIT("__FILE__"));
+ pp->sym_date__ = cfree_sym_intern(p->c, CFREE_SLICE_LIT("__DATE__"));
+ pp->sym_time__ = cfree_sym_intern(p->c, CFREE_SLICE_LIT("__TIME__"));
+ pp->sym_stdc__ = cfree_sym_intern(p->c, CFREE_SLICE_LIT("__STDC__"));
+ pp->sym_stdc_hosted__ = cfree_sym_intern(p->c, CFREE_SLICE_LIT("__STDC_HOSTED__"));
+ pp->sym_stdc_version__ = cfree_sym_intern(p->c, CFREE_SLICE_LIT("__STDC_VERSION__"));
+ pp->sym__pragma = cfree_sym_intern(p->c, CFREE_SLICE_LIT("_Pragma"));
}
/* Decompose unix seconds into UTC y/M/d/h/m/s. Algorithm: Howard Hinnant,
@@ -275,8 +274,10 @@ static void compute_date_time(Pp* pp) {
int64_t t = cfree_compiler_context(pp->c)->now;
PpYMD ymd;
if (t < 0) {
- pp->val_date_str = pool_intern_cstr(pp->pool, "\"??? ?? ????\"");
- pp->val_time_str = pool_intern_cstr(pp->pool, "\"??:??:??\"");
+ pp->val_date_str =
+ cfree_sym_intern(pp->pool->c, CFREE_SLICE_LIT("\"??? ?? ????\""));
+ pp->val_time_str =
+ cfree_sym_intern(pp->pool->c, CFREE_SLICE_LIT("\"??:??:??\""));
return;
}
pp_break_time(t, &ymd);
@@ -295,7 +296,8 @@ static void compute_date_time(Pp* pp) {
date[p++] = (char)('0' + (yyyy / 10) % 10);
date[p++] = (char)('0' + (yyyy) % 10);
date[p++] = '"';
- pp->val_date_str = pool_intern(pp->pool, date, (size_t)p);
+ pp->val_date_str =
+ cfree_sym_intern(pp->pool->c, (CfreeSlice){ .s = date, .len = (size_t)p });
}
{
int hh = ymd.h, mm = ymd.m, ss = ymd.s;
@@ -310,7 +312,8 @@ static void compute_date_time(Pp* pp) {
tm[p++] = (char)('0' + (ss / 10) % 10);
tm[p++] = (char)('0' + ss % 10);
tm[p++] = '"';
- pp->val_time_str = pool_intern(pp->pool, tm, (size_t)p);
+ pp->val_time_str =
+ cfree_sym_intern(pp->pool->c, (CfreeSlice){ .s = tm, .len = (size_t)p });
}
}
@@ -349,7 +352,7 @@ static void pp_register_target_predefined(Pp* pp) {
int wchar16 = win;
for (i = 0; i < narch_defs; ++i) {
- pp_define(pp, arch_defs[i].name, arch_defs[i].body);
+ pp_define(pp, arch_defs[i].name.s, arch_defs[i].body.s);
}
pp_define(pp, "__USER_LABEL_PREFIX__",
@@ -770,8 +773,8 @@ void pp_define(Pp* pp, const char* name, const char* body) {
/* Stage 1+2: build a synthetic source line "name body\n" and run it
* through the lexer + define machinery so command-line -D matches the
* normal #define path. */
- size_t nlen = name ? strlen(name) : 0;
- size_t blen = body ? strlen(body) : 0;
+ size_t nlen = name ? cfree_slice_cstr(name).len : 0;
+ size_t blen = body ? cfree_slice_cstr(body).len : 0;
Heap* h = pp_heap(pp);
char* buf;
size_t pos = 0;
@@ -810,7 +813,7 @@ void pp_define(Pp* pp, const char* name, const char* body) {
void pp_undef(Pp* pp, const char* name) {
Sym s;
if (!name || !*name) return;
- s = pool_intern_cstr(pp->pool, name);
+ s = cfree_sym_intern(pp->pool->c, cfree_slice_cstr(name));
mt_del(pp, s);
}
diff --git a/lang/cpp/pp/pp_directive.c b/lang/cpp/pp/pp_directive.c
@@ -120,7 +120,9 @@ static void prepass_defined(Pp* pp, const Tok* in, u32 nin, TokVec* out) {
t.kind = TOK_NUM;
t.flags = in[i].flags & (TF_AT_BOL | TF_HAS_SPACE);
t.loc = in[i].loc;
- t.spelling = pool_intern_cstr(pp->pool, mt_get(pp, ident) ? "1" : "0");
+ t.spelling = cfree_sym_intern(
+ pp->pool->c, mt_get(pp, ident) ? CFREE_SLICE_LIT("1")
+ : CFREE_SLICE_LIT("0"));
tv_push(pp, out, t);
}
i = j - 1;
@@ -157,7 +159,7 @@ static void expand_for_if(Pp* pp, const Tok* in, u32 nin, TokVec* out) {
* has been handled. */
static void replace_remaining_if_identifiers(Pp* pp, TokVec* toks) {
u32 i;
- Sym zero = pool_intern_cstr(pp->pool, "0");
+ Sym zero = cfree_sym_intern(pp->pool->c, CFREE_SLICE_LIT("0"));
for (i = 0; i < toks->n; ++i) {
if (toks->data[i].kind == TOK_IDENT) {
toks->data[i].kind = TOK_NUM;
@@ -194,19 +196,17 @@ static i64 ee_primary(EE* e) {
const Tok* t = ee_peek(e);
if (!t) compiler_panic(e->pp->c, e->loc, "#if: missing operand");
if (t->kind == TOK_NUM) {
- size_t slen;
- const char* s = pool_str(e->pp->pool, t->spelling, &slen);
+ CfreeSlice s = cfree_sym_str(e->pp->pool->c, t->spelling);
++e->pos;
- return parse_pp_int(s, slen);
+ return parse_pp_int(s.s, s.len);
}
if (t->kind == TOK_CHR) {
/* Treat as the codepoint of the first character (post-decoding
* not implemented; cover the common case of a single ASCII
* char). */
- size_t slen;
- const char* s = pool_str(e->pp->pool, t->spelling, &slen);
+ CfreeSlice s = cfree_sym_str(e->pp->pool->c, t->spelling);
++e->pos;
- if (slen >= 3 && s[0] == '\'') return (unsigned char)s[1];
+ if (s.len >= 3 && s.s[0] == '\'') return (unsigned char)s.s[1];
return 0;
}
if (t->kind == TOK_PUNCT && t->v.punct == '(') {
@@ -629,7 +629,9 @@ static int includer_dir(Pp* pp, SrcLoc loc, char* dir_out, size_t cap) {
size_t dlen;
memset(&sf, 0, sizeof(sf));
if (cfree_source_file(pp->c, loc.file_id, &sf) == 0 && sf.name) {
- p = pool_str(pp->pool, sf.name, &plen);
+ CfreeSlice s = cfree_sym_str(pp->pool->c, sf.name);
+ p = s.s;
+ plen = s.len;
}
if (!p || plen == 0 || p[0] == '<') {
if (cap < 2) return 0;
@@ -670,7 +672,7 @@ static int find_and_open_include(Pp* pp, const char* path, int system,
char* resolved, size_t resolved_cap) {
char buf[4096];
u32 i;
- size_t plen = strlen(path);
+ size_t plen = cfree_slice_cstr(path).len;
if (plen > 0 && path[0] == '/') {
if (try_open_include(pp, path, data, size)) {
@@ -684,7 +686,7 @@ static int find_and_open_include(Pp* pp, const char* path, int system,
if (!system) {
char dir[4096];
if (includer_dir(pp, loc, dir, sizeof(dir))) {
- size_t dlen = strlen(dir);
+ size_t dlen = cfree_slice_cstr(dir).len;
if (dlen + 1 + plen + 1 <= sizeof(buf)) {
memcpy(buf, dir, dlen);
buf[dlen] = '/';
@@ -700,7 +702,7 @@ static int find_and_open_include(Pp* pp, const char* path, int system,
}
for (i = 0; i < pp->ninc_dirs; ++i) {
const char* d = pp->inc_dirs[i].path;
- size_t dlen = strlen(d);
+ size_t dlen = cfree_slice_cstr(d).len;
if (dlen + 1 + plen + 1 > sizeof(buf)) continue;
memcpy(buf, d, dlen);
buf[dlen] = '/';
@@ -724,8 +726,9 @@ static void parse_include_path(Pp* pp, const Tok* line, u32 n, SrcLoc loc,
if (n == 0) compiler_panic(pp->c, loc, "#include: missing path");
if (line[0].kind == TOK_HEADER) {
- size_t slen = 0;
- const char* s = pool_str(pp->pool, line[0].spelling, &slen);
+ CfreeSlice sl = cfree_sym_str(pp->pool->c, line[0].spelling);
+ const char* s = sl.s;
+ size_t slen = sl.len;
if (slen < 2) compiler_panic(pp->c, loc, "#include: malformed header name");
if (s[0] == '<' && s[slen - 1] == '>')
*system_out = 1;
@@ -751,8 +754,9 @@ static void parse_include_path(Pp* pp, const Tok* line, u32 n, SrcLoc loc,
compiler_panic(pp->c, loc, "#include: empty after macro replacement");
}
if (exp.data[0].kind == TOK_STR) {
- size_t slen = 0;
- const char* s = pool_str(pp->pool, exp.data[0].spelling, &slen);
+ CfreeSlice sl = cfree_sym_str(pp->pool->c, exp.data[0].spelling);
+ const char* s = sl.s;
+ size_t slen = sl.len;
if (slen < 2 || s[0] != '"' || s[slen - 1] != '"') {
compiler_panic(pp->c, loc, "#include: malformed string");
}
@@ -774,7 +778,9 @@ static void parse_include_path(Pp* pp, const Tok* line, u32 n, SrcLoc loc,
break;
}
if (exp.data[i].spelling) {
- s = pool_str(pp->pool, exp.data[i].spelling, &slen);
+ CfreeSlice sl = cfree_sym_str(pp->pool->c, exp.data[i].spelling);
+ s = sl.s;
+ slen = sl.len;
}
if (s && pos + slen + 1 <= cap) {
memcpy(path_out + pos, s, slen);
@@ -806,7 +812,8 @@ static void do_include(Pp* pp, const Tok* line, u32 n, SrcLoc loc) {
if (!find_and_open_include(pp, path, system_form, loc, &data, &size, resolved,
sizeof(resolved))) {
- compiler_panic(pp->c, loc, "#include: file not found: %s", path);
+ compiler_panic(pp->c, loc, "#include: file not found: %.*s",
+ CFREE_SLICE_ARG(cfree_slice_cstr(path)));
}
/* Walk the source stack to find the current includer's file_id. */
@@ -861,19 +868,18 @@ static void do_line(Pp* pp, const Tok* line, u32 n, SrcLoc loc) {
compiler_panic(pp->c, loc, "#line: expected line number");
}
{
- size_t sl = 0;
- const char* s = pool_str(pp->pool, exp.data[0].spelling, &sl);
- target_line = parse_pp_int(s, sl);
+ CfreeSlice s = cfree_sym_str(pp->pool->c, exp.data[0].spelling);
+ target_line = parse_pp_int(s.s, s.len);
}
if (exp.n >= 2) {
if (exp.data[1].kind != TOK_STR) {
compiler_panic(pp->c, loc, "#line: file argument must be a string");
}
{
- size_t sl = 0;
- const char* s = pool_str(pp->pool, exp.data[1].spelling, &sl);
- if (sl >= 2 && s[0] == '"' && s[sl - 1] == '"') {
- target_file = pool_intern(pp->pool, s + 1, sl - 2);
+ CfreeSlice s = cfree_sym_str(pp->pool->c, exp.data[1].spelling);
+ if (s.len >= 2 && s.s[0] == '"' && s.s[s.len - 1] == '"') {
+ target_file = cfree_sym_intern(
+ pp->pool->c, (CfreeSlice){ .s = s.s + 1, .len = s.len - 2 });
}
}
}
@@ -907,7 +913,7 @@ void emit_pragma_line(Pp* pp, const Tok* line, u32 n, SrcLoc loc) {
hash.kind = TOK_PP_HASH;
hash.flags = TF_AT_BOL;
hash.loc = loc;
- hash.spelling = pool_intern_cstr(pp->pool, "#");
+ hash.spelling = cfree_sym_intern(pp->pool->c, CFREE_SLICE_LIT("#"));
tv_push(pp, &out, hash);
memset(&ident, 0, sizeof(ident));
@@ -939,11 +945,14 @@ void emit_pragma_line(Pp* pp, const Tok* line, u32 n, SrcLoc loc) {
}
static int pragma_num_u32(Pp* pp, const Tok* t, u32* out) {
- size_t len = 0;
const char* s;
+ size_t len;
u32 v = 0;
+ CfreeSlice sl;
if (!t || t->kind != TOK_NUM || !out) return 0;
- s = pool_str(pp->pool, t->spelling, &len);
+ sl = cfree_sym_str(pp->pool->c, t->spelling);
+ s = sl.s;
+ len = sl.len;
if (!s || len == 0) return 0;
for (size_t i = 0; i < len; ++i) {
if (s[i] < '0' || s[i] > '9') break;
@@ -957,8 +966,9 @@ static void handle_pragma_pack(Pp* pp, const Tok* line, u32 n) {
u32 i = 0;
if (n < 3 || line[0].kind != TOK_IDENT) return;
{
- size_t len = 0;
- const char* s = pool_str(pp->pool, line[0].v.ident, &len);
+ CfreeSlice sl = cfree_sym_str(pp->pool->c, line[0].v.ident);
+ const char* s = sl.s;
+ size_t len = sl.len;
if (!s || len != 4 || memcmp(s, "pack", 4) != 0) return;
}
if (line[1].kind != TOK_PUNCT || line[1].v.punct != '(') return;
@@ -968,8 +978,9 @@ static void handle_pragma_pack(Pp* pp, const Tok* line, u32 n) {
return;
}
if (i < n && line[i].kind == TOK_IDENT) {
- size_t len = 0;
- const char* s = pool_str(pp->pool, line[i].v.ident, &len);
+ CfreeSlice sl = cfree_sym_str(pp->pool->c, line[i].v.ident);
+ const char* s = sl.s;
+ size_t len = sl.len;
if (s && len == 4 && memcmp(s, "push", 4) == 0) {
if (pp->pack_stack_n <
(u32)(sizeof pp->pack_stack / sizeof pp->pack_stack[0])) {
@@ -1007,8 +1018,9 @@ static void do_pragma(Pp* pp, const Tok* line, u32 n, SrcLoc loc) {
* does its own escape handling for any string literals nested inside. */
static void destringize(Pp* pp, const Tok* str_tok, char* out, size_t cap,
size_t* out_len) {
- size_t slen = 0;
- const char* s = pool_str(pp->pool, str_tok->spelling, &slen);
+ CfreeSlice sl = cfree_sym_str(pp->pool->c, str_tok->spelling);
+ const char* s = sl.s;
+ size_t slen = sl.len;
size_t i, w = 0;
if (slen < 2 || s[0] != '"' || s[slen - 1] != '"') {
compiler_panic(pp->c, str_tok->loc,
@@ -1094,9 +1106,11 @@ int try_expand_pragma_op(Pp* pp, const Tok* invoke) {
static void directive_message(Pp* pp, const Tok* line, u32 n, CharBuf* cb) {
u32 i;
for (i = 0; i < n; ++i) {
- size_t sl = 0;
- const char* s =
- line[i].spelling ? pool_str(pp->pool, line[i].spelling, &sl) : NULL;
+ CfreeSlice slc = line[i].spelling
+ ? cfree_sym_str(pp->pool->c, line[i].spelling)
+ : CFREE_SLICE_NULL;
+ const char* s = slc.s;
+ size_t sl = slc.len;
if (i > 0) cb_putc(pp, cb, ' ');
if (s && sl) cb_append(pp, cb, s, (u32)sl);
}
@@ -1117,13 +1131,15 @@ static void pp_warn(Pp* pp, SrcLoc loc, const char* fmt, ...) {
static void do_error(Pp* pp, const Tok* line, u32 n, SrcLoc loc) {
CharBuf cb = {0};
directive_message(pp, line, n, &cb);
- compiler_panic(pp->c, loc, "#error: %s", cb.data ? cb.data : "");
+ compiler_panic(pp->c, loc, "#error: %.*s",
+ CFREE_SLICE_ARG(cfree_slice_cstr(cb.data ? cb.data : "")));
}
static void do_warning(Pp* pp, const Tok* line, u32 n, SrcLoc loc) {
CharBuf cb = {0};
directive_message(pp, line, n, &cb);
- pp_warn(pp, loc, "#warning: %s", cb.data ? cb.data : "");
+ pp_warn(pp, loc, "#warning: %.*s",
+ CFREE_SLICE_ARG(cfree_slice_cstr(cb.data ? cb.data : "")));
}
/* ============================================================
@@ -1147,8 +1163,9 @@ static void do_embed(Pp* pp, const Tok* line, u32 n, SrcLoc loc) {
if (n == 0) compiler_panic(pp->c, loc, "#embed: missing path");
if (line[0].kind == TOK_HEADER) {
- size_t sl = 0;
- const char* s = pool_str(pp->pool, line[0].spelling, &sl);
+ CfreeSlice slc = cfree_sym_str(pp->pool->c, line[0].spelling);
+ const char* s = slc.s;
+ size_t sl = slc.len;
if (sl < 2) compiler_panic(pp->c, loc, "#embed: malformed header name");
if (s[0] == '<' && s[sl - 1] == '>')
system_form = 1;
@@ -1167,8 +1184,9 @@ static void do_embed(Pp* pp, const Tok* line, u32 n, SrcLoc loc) {
j = arg_start;
while (j < n) {
if (line[j].kind == TOK_IDENT) {
- size_t sl = 0;
- const char* s = pool_str(pp->pool, line[j].v.ident, &sl);
+ CfreeSlice slc = cfree_sym_str(pp->pool->c, line[j].v.ident);
+ const char* s = slc.s;
+ size_t sl = slc.len;
if (sl == 5 && memcmp(s, "limit", 5) == 0) {
if (j + 1 >= n || line[j + 1].kind != TOK_PUNCT ||
line[j + 1].v.punct != '(') {
@@ -1179,9 +1197,8 @@ static void do_embed(Pp* pp, const Tok* line, u32 n, SrcLoc loc) {
compiler_panic(pp->c, loc, "#embed: limit() expects an integer");
}
{
- size_t sl2 = 0;
- const char* s2 = pool_str(pp->pool, line[j].spelling, &sl2);
- limit_n = parse_pp_int(s2, sl2);
+ CfreeSlice s2 = cfree_sym_str(pp->pool->c, line[j].spelling);
+ limit_n = parse_pp_int(s2.s, s2.len);
}
++j;
if (j >= n || line[j].kind != TOK_PUNCT || line[j].v.punct != ')') {
@@ -1225,7 +1242,8 @@ static void do_embed(Pp* pp, const Tok* line, u32 n, SrcLoc loc) {
if (!find_and_open_include(pp, path, system_form, loc, &data, &size, resolved,
sizeof(resolved))) {
- compiler_panic(pp->c, loc, "#embed: file not found: %s", path);
+ compiler_panic(pp->c, loc, "#embed: file not found: %.*s",
+ CFREE_SLICE_ARG(cfree_slice_cstr(path)));
}
/* Apply limit(). */
@@ -1268,7 +1286,8 @@ static void do_embed(Pp* pp, const Tok* line, u32 n, SrcLoc loc) {
memset(&t, 0, sizeof(t));
t.kind = TOK_NUM;
t.loc = loc;
- t.spelling = pool_intern(pp->pool, numbuf, (size_t)nl);
+ t.spelling = cfree_sym_intern(
+ pp->pool->c, (CfreeSlice){ .s = numbuf, .len = (size_t)nl });
if (i == 0) t.flags = TF_AT_BOL;
/* Bytes after a comma get a leading space to match
* clang's `, ` separator format. */
@@ -1282,7 +1301,7 @@ static void do_embed(Pp* pp, const Tok* line, u32 n, SrcLoc loc) {
comma.kind = TOK_PUNCT;
comma.v.punct = ',';
comma.loc = loc;
- comma.spelling = pool_intern_cstr(pp->pool, ",");
+ comma.spelling = cfree_sym_intern(pp->pool->c, CFREE_SLICE_LIT(","));
tv_push(pp, &out, comma);
}
}
diff --git a/lang/cpp/pp/pp_expand.c b/lang/cpp/pp/pp_expand.c
@@ -662,9 +662,10 @@ static Tok make_stringize(Pp* pp, const Tok* arg, u32 lo, u32 hi, SrcLoc loc) {
cb_putc(pp, &b, '"');
for (i = lo; i < hi; ++i) {
const Tok* at = &arg[i];
- size_t slen = 0;
- const char* s =
- at->spelling ? pool_str(pp->pool, at->spelling, &slen) : NULL;
+ CfreeSlice sl =
+ at->spelling ? cfree_sym_str(pp->pool->c, at->spelling) : CFREE_SLICE_NULL;
+ const char* s = sl.s;
+ size_t slen = sl.len;
if (i > lo && (at->flags & TF_HAS_SPACE)) cb_putc(pp, &b, ' ');
if (s && slen) {
int esc = (at->kind == TOK_STR || at->kind == TOK_CHR);
@@ -678,7 +679,7 @@ static Tok make_stringize(Pp* pp, const Tok* arg, u32 lo, u32 hi, SrcLoc loc) {
}
cb_putc(pp, &b, '"');
- sp = pool_intern(pp->pool, b.data, b.len);
+ sp = cfree_sym_intern(pp->pool->c, (CfreeSlice){ .s = b.data, .len = b.len });
memset(&t, 0, sizeof(t));
t.kind = TOK_STR;
t.loc = loc;
@@ -700,8 +701,20 @@ static Tok paste_tokens(Pp* pp, Tok lhs, Tok rhs, SrcLoc loc) {
if (lhs.kind == TOK_PP_PLACEMARKER) return rhs;
if (rhs.kind == TOK_PP_PLACEMARKER) return lhs;
- a = lhs.spelling ? pool_str(pp->pool, lhs.spelling, &alen) : "";
- b = rhs.spelling ? pool_str(pp->pool, rhs.spelling, &blen) : "";
+ if (lhs.spelling) {
+ CfreeSlice s = cfree_sym_str(pp->pool->c, lhs.spelling);
+ a = s.s;
+ alen = s.len;
+ } else {
+ a = "";
+ }
+ if (rhs.spelling) {
+ CfreeSlice s = cfree_sym_str(pp->pool->c, rhs.spelling);
+ b = s.s;
+ blen = s.len;
+ } else {
+ b = "";
+ }
if (alen + blen + 2 > sizeof(buf)) {
compiler_panic(pp->c, loc, "token paste: spelling too long");
}
@@ -987,7 +1000,8 @@ Tok pp_next_raw(Pp* pp) {
while (j > 0) buf[k++] = tmp[--j];
}
t.kind = TOK_NUM;
- t.spelling = pool_intern(pp->pool, buf, (size_t)k);
+ t.spelling =
+ cfree_sym_intern(pp->pool->c, (CfreeSlice){ .s = buf, .len = (size_t)k });
return t;
}
if (id == pp->sym_file__) {
@@ -1005,13 +1019,18 @@ Tok pp_next_raw(Pp* pp) {
name = sf.name;
}
}
- if (name) nstr = pool_str(pp->pool, name, &nlen);
+ if (name) {
+ CfreeSlice s = cfree_sym_str(pp->pool->c, name);
+ nstr = s.s;
+ nlen = s.len;
+ }
buf = (char*)arena_alloc(pp->arena, nlen + 2, 1);
buf[0] = '"';
if (nlen) memcpy(buf + 1, nstr, nlen);
buf[nlen + 1] = '"';
t.kind = TOK_STR;
- t.spelling = pool_intern(pp->pool, buf, nlen + 2);
+ t.spelling =
+ cfree_sym_intern(pp->pool->c, (CfreeSlice){ .s = buf, .len = nlen + 2 });
t.v.str = t.spelling;
return t;
}
diff --git a/lang/toy/asm.c b/lang/toy/asm.c
@@ -61,7 +61,7 @@ static int toy_asm_is_decimal_constraint(const char* s) {
static int toy_validate_asm_output_constraint(ToyParser* p,
const CfreeCgAsmOperand* op) {
- const char* s = cfree_sym_str(p->c, op->constraint, NULL);
+ const char* s = cfree_sym_str(p->c, op->constraint).s;
const char* body = toy_asm_constraint_body(s);
if (op->dir == CFREE_CG_ASM_OUT) {
if (!s || s[0] != '=' || body[0] != 'r' || body[1] != '\0') {
@@ -79,7 +79,7 @@ static int toy_validate_asm_output_constraint(ToyParser* p,
static int toy_validate_asm_input_constraint(ToyParser* p,
const CfreeCgAsmOperand* op) {
- const char* s = cfree_sym_str(p->c, op->constraint, NULL);
+ const char* s = cfree_sym_str(p->c, op->constraint).s;
if ((s && s[0] && !s[1] &&
(s[0] == 'r' || s[0] == 'i' || s[0] == 'm')) ||
toy_asm_is_decimal_constraint(s)) {
@@ -179,7 +179,7 @@ static int toy_parse_asm_input_operand(ToyParser* p,
toy_error(p, p->cur.loc, "expected asm input operand");
return 0;
}
- mem_constraint = cfree_sym_intern(p->c, "m");
+ mem_constraint = cfree_sym_intern(p->c, CFREE_SLICE_LIT("m"));
if (operand->constraint == mem_constraint && p->cur.kind == TOK_IDENT) {
CfreeSym name = toy_tok_sym(p, p->cur);
toy_parser_advance(p);
diff --git a/lang/toy/builtins.c b/lang/toy/builtins.c
@@ -112,7 +112,7 @@ static int toy_parse_memory_align_operand(ToyParser* p, int64_t* align,
}
static int toy_parse_access_group(ToyParser* p, CfreeCgMemAccess* access) {
- CfreeSym access_name = cfree_sym_intern(p->c, "access");
+ CfreeSym access_name = cfree_sym_intern(p->c, CFREE_SLICE_LIT("access"));
if (p->cur.kind != TOK_IDENT || toy_tok_sym(p, p->cur) != access_name)
return 0;
toy_parser_advance(p);
@@ -495,12 +495,13 @@ CfreeCgTypeId toy_parse_builtin_call(ToyParser* p, CfreeSym name,
if (toy_sym_is(p, name, "compile_error")) {
CfreeSym msg;
size_t msg_len;
- const char* text;
+ CfreeSlice text;
if (!toy_parser_expect(p, TOK_LPAREN) ||
!toy_parse_string_sym(p, &msg, &msg_len) ||
!toy_parser_expect(p, TOK_RPAREN)) return CFREE_CG_TYPE_NONE;
- text = cfree_sym_str(p->c, msg, NULL);
- toy_error(p, p->cur.loc, "compile_error: %s", text ? text : "");
+ text = cfree_sym_str(p->c, msg);
+ toy_error(p, p->cur.loc, "compile_error: %.*s",
+ CFREE_SLICE_ARG(text));
cfree_cg_push_int(p->cg, 0, p->int_type);
return p->int_type;
}
@@ -959,9 +960,9 @@ CfreeCgTypeId toy_parse_generic_builtin(ToyParser* p, CfreeSym name,
}
cfree_cg_intrinsic(p->cg, intrin, 2, ty);
memset(fields, 0, sizeof fields);
- fields[0].name = cfree_sym_intern(p->c, "value");
+ fields[0].name = cfree_sym_intern(p->c, CFREE_SLICE_LIT("value"));
fields[0].type = ty;
- fields[1].name = cfree_sym_intern(p->c, "overflow");
+ fields[1].name = cfree_sym_intern(p->c, CFREE_SLICE_LIT("overflow"));
fields[1].type = toy_builtin_type(p, CFREE_CG_BUILTIN_BOOL);
rec_ty = cfree_cg_type_record(p->c, 0, fields, 2);
rec_slot = cfree_cg_local(p->cg, rec_ty, toy_slot_attrs(0));
@@ -1279,9 +1280,9 @@ CfreeCgTypeId toy_parse_atomic_generic_builtin(ToyParser* p, CfreeSym name,
}
cfree_cg_atomic_cmpxchg(p->cg, access, success_order, failure_order, weak);
memset(fields, 0, sizeof fields);
- fields[0].name = cfree_sym_intern(p->c, "prior");
+ fields[0].name = cfree_sym_intern(p->c, CFREE_SLICE_LIT("prior"));
fields[0].type = ty;
- fields[1].name = cfree_sym_intern(p->c, "ok");
+ fields[1].name = cfree_sym_intern(p->c, CFREE_SLICE_LIT("ok"));
fields[1].type = toy_builtin_type(p, CFREE_CG_BUILTIN_BOOL);
rec_ty = cfree_cg_type_record(p->c, 0, fields, 2);
rec_slot = cfree_cg_local(p->cg, rec_ty, toy_slot_attrs(0));
diff --git a/lang/toy/compile.c b/lang/toy/compile.c
@@ -34,7 +34,7 @@ static int toy_build_repl_source(ToyFrontend* fe,
const uint8_t** source_out,
size_t* source_len_out, char** owned_out,
size_t* owned_cap_out) {
- const char* name = opts->repl_entry_name;
+ CfreeSlice name = opts->repl_entry_name;
const char* body = input->bytes.data ? (const char*)input->bytes.data : "";
size_t body_len = input->bytes.data ? input->bytes.len : 0u;
char* src = NULL;
@@ -49,9 +49,9 @@ static int toy_build_repl_source(ToyFrontend* fe,
*source_len_out = body_len;
return 1;
}
- if (!name || !*name) return 0;
+ if (!name.s || !name.len) return 0;
if (!toy_buf_append(fe, &src, &len, &cap, "fn ", 3) ||
- !toy_buf_append(fe, &src, &len, &cap, name, strlen(name)) ||
+ !toy_buf_append(fe, &src, &len, &cap, name.s, name.len) ||
!toy_buf_append(fe, &src, &len, &cap, "(): i64 {\n", 10)) {
goto oom;
}
@@ -163,11 +163,11 @@ static CfreeStatus toy_frontend_compile(CfreeFrontendState* frontend,
if (st != CFREE_OK) goto done_status;
if (!fe->parser_live) {
- toy_parser_init(&fe->parser, c, cg, source, source_len, input->bytes.name);
+ toy_parser_init(&fe->parser, c, cg, source, source_len, input->name.s);
fe->parser.input_kind = opts->input_kind;
fe->parser_live = 1;
} else {
- toy_parser_reinit(&fe->parser, c, cg, source, source_len, input->bytes.name,
+ toy_parser_reinit(&fe->parser, c, cg, source, source_len, input->name.s,
opts->input_kind);
}
p = fe->parser;
@@ -215,11 +215,12 @@ static void toy_frontend_free(CfreeFrontendState* frontend) {
h->free(h, fe, sizeof(*fe));
}
-static const char* const toy_extensions[] = {"toy", NULL};
+static const CfreeSlice toy_extensions[] = {CFREE_SLICE_LIT("toy")};
const CfreeFrontendVTable cfree_toy_frontend_vtable = {
toy_frontend_new,
toy_frontend_compile,
toy_frontend_free,
toy_extensions,
+ (uint32_t)(sizeof toy_extensions / sizeof toy_extensions[0]),
};
diff --git a/lang/toy/decls.c b/lang/toy/decls.c
@@ -157,7 +157,7 @@ int toy_parse_tuple_decl(ToyParser* p) {
goto done;
}
snprintf(field_name_buf, sizeof field_name_buf, "%u", (uint32_t)nfields);
- fields[nfields].name = cfree_sym_intern(p->c, field_name_buf);
+ fields[nfields].name = cfree_sym_intern(p->c, cfree_slice_cstr(field_name_buf));
fields[nfields].type = toy_parse_type(p);
if (fields[nfields].type == CFREE_CG_TYPE_NONE) goto done;
field_infos[nfields].name = fields[nfields].name;
diff --git a/lang/toy/literals.c b/lang/toy/literals.c
@@ -32,7 +32,7 @@ int toy_parse_string_sym(ToyParser* p, CfreeSym* out, size_t* len_out) {
}
memcpy(buf, p->cur.text + 1, len);
buf[len] = '\0';
- *out = cfree_sym_intern(p->c, buf);
+ *out = cfree_sym_intern(p->c, (CfreeSlice){ .s = buf, .len = len });
if (len_out) *len_out = len;
toy_parser_advance(p);
return 1;
diff --git a/lang/toy/parser.c b/lang/toy/parser.c
@@ -735,7 +735,7 @@ static int toy_parse_let_stmt(ToyParser* p) {
}
}
snprintf(sym_name, sizeof sym_name, ".Ltoy_static_%u", p->static_counter++);
- linkage_name = cfree_sym_intern(p->c, sym_name);
+ linkage_name = cfree_sym_intern(p->c, cfree_slice_cstr(sym_name));
memset(&decl, 0, sizeof decl);
decl.kind = CFREE_CG_DECL_OBJECT;
decl.linkage_name = linkage_name;
diff --git a/lang/toy/parser_core.c b/lang/toy/parser_core.c
@@ -15,12 +15,14 @@ void* toy_parser_zalloc(ToyParser* p, size_t count, size_t elem_size,
size_t size = count * elem_size;
void* items;
if (count != 0 && size / count != elem_size) {
- toy_error(p, p->cur.loc, "out of memory growing %s", what);
+ toy_error(p, p->cur.loc, "out of memory growing %.*s",
+ CFREE_SLICE_ARG(cfree_slice_cstr(what)));
return NULL;
}
items = h->alloc(h, size ? size : 1u, 1);
if (!items) {
- toy_error(p, p->cur.loc, "out of memory growing %s", what);
+ toy_error(p, p->cur.loc, "out of memory growing %.*s",
+ CFREE_SLICE_ARG(cfree_slice_cstr(what)));
return NULL;
}
memset(items, 0, size ? size : 1u);
@@ -37,7 +39,7 @@ void toy_parser_free_mem(ToyParser* p, void* items, size_t size) {
static uint32_t toy_source_file_id(CfreeCompiler* c, const char* name) {
uint32_t file_id = 0;
if (name && *name)
- (void)cfree_source_add_memory(c, name, &file_id);
+ (void)cfree_source_add_memory(c, cfree_slice_cstr(name), &file_id);
return file_id;
}
@@ -189,14 +191,16 @@ int toy_parser_reserve(ToyParser* p, void** items, size_t* cap, size_t want,
old_size = *cap * elem_size;
new_size = new_cap * elem_size;
if (new_cap != 0 && new_size / new_cap != elem_size) {
- toy_error(p, p->cur.loc, "out of memory growing %s", what);
+ toy_error(p, p->cur.loc, "out of memory growing %.*s",
+ CFREE_SLICE_ARG(cfree_slice_cstr(what)));
return 0;
}
h = cfree_compiler_context(p->c)->heap;
new_items = h->realloc(h, *items, old_size ? old_size : 1u,
new_size ? new_size : 1u, 1);
if (!new_items) {
- toy_error(p, p->cur.loc, "out of memory growing %s", what);
+ toy_error(p, p->cur.loc, "out of memory growing %.*s",
+ CFREE_SLICE_ARG(cfree_slice_cstr(what)));
return 0;
}
memset((uint8_t*)new_items + (*cap * elem_size), 0,
@@ -245,11 +249,11 @@ CfreeSym toy_tok_sym(ToyParser* p, ToyToken tok) {
}
memcpy(buf, tok.text, tok.text_len);
buf[tok.text_len] = '\0';
- return cfree_sym_intern(p->c, buf);
+ return cfree_sym_intern(p->c, (CfreeSlice){ .s = buf, .len = tok.text_len });
}
int toy_sym_is(ToyParser* p, CfreeSym sym, const char* name) {
- return sym == cfree_sym_intern(p->c, name);
+ return sym == cfree_sym_intern(p->c, cfree_slice_cstr(name));
}
int toy_skip_attr_list_ex(ToyParser* p, int* has_static) {
diff --git a/lang/toy/types.c b/lang/toy/types.c
@@ -584,9 +584,9 @@ ToyTypeId toy_type_register_slice(ToyParser* p, CfreeCgTypeId elem_cg,
}
ptr_ty = cfree_cg_type_ptr(p->c, elem_cg, 0);
memset(fields, 0, sizeof fields);
- fields[0].name = cfree_sym_intern(p->c, "ptr");
+ fields[0].name = cfree_sym_intern(p->c, CFREE_SLICE_LIT("ptr"));
fields[0].type = ptr_ty;
- fields[1].name = cfree_sym_intern(p->c, "len");
+ fields[1].name = cfree_sym_intern(p->c, CFREE_SLICE_LIT("len"));
fields[1].type = p->int_type;
memset(&type, 0, sizeof type);
type.kind = TOY_TYPE_SLICE;
diff --git a/lang/wasm/cg.c b/lang/wasm/cg.c
@@ -233,53 +233,53 @@ static void wasm_cg_build_runtime(CfreeCompiler* c, CfreeCgBuiltinTypes b,
rt->i8_ptr_ty = cfree_cg_type_ptr(c, b.id[CFREE_CG_BUILTIN_I8], 0);
rt->void_ptr_ty = rt->i8_ptr_ty;
memset(memory_fields, 0, sizeof memory_fields);
- memory_fields[0].name = cfree_sym_intern(c, "data");
+ memory_fields[0].name = cfree_sym_intern(c, CFREE_SLICE_LIT("data"));
memory_fields[0].type = rt->i8_ptr_ty;
- memory_fields[1].name = cfree_sym_intern(c, "pages");
+ memory_fields[1].name = cfree_sym_intern(c, CFREE_SLICE_LIT("pages"));
memory_fields[1].type = b.id[CFREE_CG_BUILTIN_I64];
- memory_fields[2].name = cfree_sym_intern(c, "max_pages");
+ memory_fields[2].name = cfree_sym_intern(c, CFREE_SLICE_LIT("max_pages"));
memory_fields[2].type = b.id[CFREE_CG_BUILTIN_I64];
- memory_fields[3].name = cfree_sym_intern(c, "flags");
+ memory_fields[3].name = cfree_sym_intern(c, CFREE_SLICE_LIT("flags"));
memory_fields[3].type = b.id[CFREE_CG_BUILTIN_I32];
rt->memory_ty = cfree_cg_type_record(
- c, cfree_sym_intern(c, "CfreeWasmMemory"), memory_fields, 4);
+ c, cfree_sym_intern(c, CFREE_SLICE_LIT("CfreeWasmMemory")), memory_fields, 4);
rt->memory_data_offset = wasm_cg_field_offset(c, rt->memory_ty, 0);
rt->memory_pages_offset = wasm_cg_field_offset(c, rt->memory_ty, 1);
rt->memory_max_pages_offset = wasm_cg_field_offset(c, rt->memory_ty, 2);
rt->memory_flags_offset = wasm_cg_field_offset(c, rt->memory_ty, 3);
memset(func_import_fields, 0, sizeof func_import_fields);
- func_import_fields[0].name = cfree_sym_intern(c, "fn");
+ func_import_fields[0].name = cfree_sym_intern(c, CFREE_SLICE_LIT("fn"));
func_import_fields[0].type = rt->void_ptr_ty;
rt->func_import_ty = cfree_cg_type_record(
- c, cfree_sym_intern(c, "CfreeWasmFuncImport"), func_import_fields, 1);
+ c, cfree_sym_intern(c, CFREE_SLICE_LIT("CfreeWasmFuncImport")), func_import_fields, 1);
rt->func_import_fn_offset = wasm_cg_field_offset(c, rt->func_import_ty, 0);
memset(global_import_fields, 0, sizeof global_import_fields);
- global_import_fields[0].name = cfree_sym_intern(c, "addr");
+ global_import_fields[0].name = cfree_sym_intern(c, CFREE_SLICE_LIT("addr"));
global_import_fields[0].type = rt->void_ptr_ty;
rt->global_import_ty = cfree_cg_type_record(
- c, cfree_sym_intern(c, "CfreeWasmGlobalImport"), global_import_fields, 1);
+ c, cfree_sym_intern(c, CFREE_SLICE_LIT("CfreeWasmGlobalImport")), global_import_fields, 1);
rt->global_import_addr_offset =
wasm_cg_field_offset(c, rt->global_import_ty, 0);
memset(table_entry_fields, 0, sizeof table_entry_fields);
- table_entry_fields[0].name = cfree_sym_intern(c, "fn");
+ table_entry_fields[0].name = cfree_sym_intern(c, CFREE_SLICE_LIT("fn"));
table_entry_fields[0].type = rt->void_ptr_ty;
- table_entry_fields[1].name = cfree_sym_intern(c, "typeidx");
+ table_entry_fields[1].name = cfree_sym_intern(c, CFREE_SLICE_LIT("typeidx"));
table_entry_fields[1].type = b.id[CFREE_CG_BUILTIN_I32];
rt->table_entry_ty = cfree_cg_type_record(
- c, cfree_sym_intern(c, "CfreeWasmTableEntry"), table_entry_fields, 2);
+ c, cfree_sym_intern(c, CFREE_SLICE_LIT("CfreeWasmTableEntry")), table_entry_fields, 2);
rt->table_entry_ptr_ty = cfree_cg_type_ptr(c, rt->table_entry_ty, 0);
rt->table_entry_fn_offset = wasm_cg_field_offset(c, rt->table_entry_ty, 0);
rt->table_entry_typeidx_offset =
wasm_cg_field_offset(c, rt->table_entry_ty, 1);
rt->table_entry_size = cfree_cg_type_size(c, rt->table_entry_ty);
memset(table_fields, 0, sizeof table_fields);
- table_fields[0].name = cfree_sym_intern(c, "entries");
+ table_fields[0].name = cfree_sym_intern(c, CFREE_SLICE_LIT("entries"));
table_fields[0].type = rt->table_entry_ptr_ty;
- table_fields[1].name = cfree_sym_intern(c, "len");
+ table_fields[1].name = cfree_sym_intern(c, CFREE_SLICE_LIT("len"));
table_fields[1].type = b.id[CFREE_CG_BUILTIN_I32];
- table_fields[2].name = cfree_sym_intern(c, "max");
+ table_fields[2].name = cfree_sym_intern(c, CFREE_SLICE_LIT("max"));
table_fields[2].type = b.id[CFREE_CG_BUILTIN_I32];
- rt->table_ty = cfree_cg_type_record(c, cfree_sym_intern(c, "CfreeWasmTable"),
+ rt->table_ty = cfree_cg_type_record(c, cfree_sym_intern(c, CFREE_SLICE_LIT("CfreeWasmTable")),
table_fields, 3);
rt->table_entries_ptr_offset = wasm_cg_field_offset(c, rt->table_ty, 0);
rt->table_len_offset = wasm_cg_field_offset(c, rt->table_ty, 1);
@@ -294,7 +294,7 @@ static void wasm_cg_build_runtime(CfreeCompiler* c, CfreeCgBuiltinTypes b,
else
wasm_indexed_name(name, sizeof name, "memory_", i);
memory_field_idx[i] = nfields;
- instance_fields[nfields].name = cfree_sym_intern(c, name);
+ instance_fields[nfields].name = cfree_sym_intern(c, cfree_slice_cstr(name));
instance_fields[nfields].type = rt->memory_ty;
nfields++;
}
@@ -305,7 +305,7 @@ static void wasm_cg_build_runtime(CfreeCompiler* c, CfreeCgBuiltinTypes b,
wasm_error(c, wasm_loc(0, 0), "wasm: instance layout too large");
wasm_indexed_name(name, sizeof name, "import_func_", i);
func_import_field_idx[i] = nfields;
- instance_fields[nfields].name = cfree_sym_intern(c, name);
+ instance_fields[nfields].name = cfree_sym_intern(c, cfree_slice_cstr(name));
instance_fields[nfields].type = rt->func_import_ty;
nfields++;
}
@@ -315,7 +315,7 @@ static void wasm_cg_build_runtime(CfreeCompiler* c, CfreeCgBuiltinTypes b,
wasm_error(c, wasm_loc(0, 0), "wasm: instance layout too large");
wasm_indexed_name(name, sizeof name, "func_ref_", i);
func_ref_entry_field_idx[i] = nfields;
- instance_fields[nfields].name = cfree_sym_intern(c, name);
+ instance_fields[nfields].name = cfree_sym_intern(c, cfree_slice_cstr(name));
instance_fields[nfields].type = rt->table_entry_ty;
nfields++;
}
@@ -327,7 +327,7 @@ static void wasm_cg_build_runtime(CfreeCompiler* c, CfreeCgBuiltinTypes b,
m->globals[i].is_import ? "import_global_" : "global_",
i);
global_field_idx[i] = nfields;
- instance_fields[nfields].name = cfree_sym_intern(c, name);
+ instance_fields[nfields].name = cfree_sym_intern(c, cfree_slice_cstr(name));
instance_fields[nfields].type =
m->globals[i].is_import ? rt->global_import_ty
: wasm_cg_type(c, b, m->globals[i].type);
@@ -340,18 +340,18 @@ static void wasm_cg_build_runtime(CfreeCompiler* c, CfreeCgBuiltinTypes b,
wasm_error(c, wasm_loc(0, 0), "wasm: instance layout too large");
wasm_indexed_name(name, sizeof name, "table_", i);
table_field_idx[i] = nfields;
- instance_fields[nfields].name = cfree_sym_intern(c, name);
+ instance_fields[nfields].name = cfree_sym_intern(c, cfree_slice_cstr(name));
instance_fields[nfields].type = rt->table_ty;
nfields++;
wasm_indexed_name(name, sizeof name, "table_entries_", i);
table_entries_field_idx[i] = nfields;
- instance_fields[nfields].name = cfree_sym_intern(c, name);
+ instance_fields[nfields].name = cfree_sym_intern(c, cfree_slice_cstr(name));
instance_fields[nfields].type =
cfree_cg_type_array(c, rt->table_entry_ty, max ? max : 1u);
nfields++;
}
rt->instance_ty = cfree_cg_type_record(
- c, cfree_sym_intern(c, "CfreeWasmInstance"), instance_fields, nfields);
+ c, cfree_sym_intern(c, CFREE_SLICE_LIT("CfreeWasmInstance")), instance_fields, nfields);
rt->instance_ptr_ty = cfree_cg_type_ptr(c, rt->instance_ty, 0);
for (uint32_t i = 0; i < m->nmemories; ++i)
rt->memory_offset[i] =
@@ -902,7 +902,7 @@ void wasm_emit_cg(CfreeCompiler* c, const CfreeCodeOptions* code_opts,
if (!rt.trap_func_ty)
wasm_error(c, wasm_loc(0, 0), "wasm: failed to create trap type");
for (uint32_t k = 0; k < WASM_TRAP_COUNT; ++k) {
- CfreeSym source_name = cfree_sym_intern(c, wasm_trap_name(k));
+ CfreeSym source_name = cfree_sym_intern(c, cfree_slice_cstr(wasm_trap_name(k)));
memset(&decl, 0, sizeof decl);
decl.kind = CFREE_CG_DECL_FUNC;
decl.linkage_name = cfree_cg_c_linkage_name(c, source_name);
@@ -929,7 +929,7 @@ void wasm_emit_cg(CfreeCompiler* c, const CfreeCodeOptions* code_opts,
memset(&decl, 0, sizeof decl);
decl.kind = CFREE_CG_DECL_FUNC;
decl.linkage_name =
- cfree_cg_c_linkage_name(c, cfree_sym_intern(c, "__cfree_wasm_init"));
+ cfree_cg_c_linkage_name(c, cfree_sym_intern(c, CFREE_SLICE_LIT("__cfree_wasm_init")));
decl.display_name = decl.linkage_name;
decl.type = cfree_cg_type_func(c, sig);
decl.sym.bind = CFREE_SB_GLOBAL;
@@ -962,7 +962,7 @@ void wasm_emit_cg(CfreeCompiler* c, const CfreeCodeOptions* code_opts,
continue;
}
if (f->export_name) {
- source_name = cfree_sym_intern(c, f->export_name);
+ source_name = f->export_name;
} else {
size_t pos = 0;
const char prefix[] = "__cfree_wasm_func_";
@@ -975,7 +975,7 @@ void wasm_emit_cg(CfreeCompiler* c, const CfreeCodeOptions* code_opts,
div /= 10u;
}
local_name[pos] = '\0';
- source_name = cfree_sym_intern(c, local_name);
+ source_name = cfree_sym_intern(c, cfree_slice_cstr(local_name));
}
memset(&decl, 0, sizeof decl);
decl.kind = CFREE_CG_DECL_FUNC;
diff --git a/lang/wasm/decode.c b/lang/wasm/decode.c
@@ -94,15 +94,15 @@ static void bin_need(BinReader* r, size_t n) {
wasm_error(r->c, wasm_loc(0, 0), "wasm: section length out of bounds");
}
-static char* bin_name(BinReader* r, CfreeHeap* h, uint32_t* len_out) {
+static CfreeSym bin_name(BinReader* r, uint32_t* len_out) {
uint32_t n = bin_uleb(r);
- char* s;
+ CfreeSym sym;
bin_need(r, n);
- s = wasm_strdup(h, (const char*)(r->data + r->pos), n);
- if (!s) wasm_error(r->c, wasm_loc(0, 0), "wasm: out of memory");
+ sym = cfree_sym_intern(
+ r->c, (CfreeSlice){.s = (const char*)(r->data + r->pos), .len = n});
r->pos += n;
if (len_out) *len_out = n;
- return s;
+ return sym;
}
static WasmValType bin_val_type(BinReader* r, int refs_ok) {
@@ -124,7 +124,7 @@ static WasmValType bin_val_type(BinReader* r, int refs_ok) {
return WASM_VAL_I32;
}
-void wasm_decode_binary(CfreeCompiler* c, const CfreeBytes* input,
+void wasm_decode_binary(CfreeCompiler* c, const CfreeSlice* input,
WasmModule* out) {
BinReader r;
uint32_t nfunc_types = 0;
@@ -154,12 +154,12 @@ void wasm_decode_binary(CfreeCompiler* c, const CfreeBytes* input,
"wasm: relocatable object metadata is not frontend input");
{
WasmCustom* cs = wasm_add_custom(c, out);
- cs->name =
- wasm_strdup(out->heap, (const char*)(r.data + r.pos), name_len);
- if (!cs->name) wasm_error(c, wasm_loc(0, 0), "wasm: out of memory");
+ cs->name = cfree_sym_intern(
+ c,
+ (CfreeSlice){.s = (const char*)(r.data + r.pos), .len = name_len});
r.pos += name_len;
- if (strcmp(cs->name, "target_features") == 0 ||
- strcmp(cs->name, "target-feature") == 0)
+ if (cs->name == cfree_sym_intern(c, CFREE_SLICE_LIT("target_features")) ||
+ cs->name == cfree_sym_intern(c, CFREE_SLICE_LIT("target-feature")))
out->has_target_features = 1;
cs->len = (uint32_t)(end - r.pos);
if (cs->len) {
@@ -193,8 +193,8 @@ void wasm_decode_binary(CfreeCompiler* c, const CfreeBytes* input,
} else if (id == 2) {
uint32_t i, count = bin_uleb(&r);
for (i = 0; i < count; ++i) {
- char* mod = bin_name(&r, out->heap, NULL);
- char* name = bin_name(&r, out->heap, NULL);
+ CfreeSym mod = bin_name(&r, NULL);
+ CfreeSym name = bin_name(&r, NULL);
uint8_t kind = bin_u8(&r);
if (kind == 0) {
uint32_t typeidx = bin_uleb(&r);
@@ -341,11 +341,11 @@ void wasm_decode_binary(CfreeCompiler* c, const CfreeBytes* input,
} else if (id == 7) {
uint32_t i, count = bin_uleb(&r);
for (i = 0; i < count; ++i) {
- char* name;
+ CfreeSym name;
uint8_t kind;
uint32_t idx;
WasmExport* ex;
- name = bin_name(&r, out->heap, NULL);
+ name = bin_name(&r, NULL);
kind = bin_u8(&r);
idx = bin_uleb(&r);
if (kind > 3u) wasm_error(c, wasm_loc(0, 0), "wasm: bad export kind");
@@ -354,23 +354,13 @@ void wasm_decode_binary(CfreeCompiler* c, const CfreeBytes* input,
ex->kind = kind;
ex->index = idx;
if (kind == 0 && idx < out->nfuncs) {
- WasmFunc* f = &out->funcs[idx];
- wasm_free_str(out->heap, &f->export_name);
- f->export_name = wasm_strdup(out->heap, name, strlen(name));
- if (!f->export_name)
- wasm_error(c, wasm_loc(0, 0), "wasm: out of memory");
+ out->funcs[idx].export_name = name;
} else if (kind == 1 && idx < out->ntables) {
- wasm_free_str(out->heap, &out->tables[idx].export_name);
- out->tables[idx].export_name =
- wasm_strdup(out->heap, name, strlen(name));
+ out->tables[idx].export_name = name;
} else if (kind == 2 && idx < out->nmemories) {
- wasm_free_str(out->heap, &out->memories[idx].export_name);
- out->memories[idx].export_name =
- wasm_strdup(out->heap, name, strlen(name));
+ out->memories[idx].export_name = name;
} else if (kind == 3 && idx < out->nglobals) {
- wasm_free_str(out->heap, &out->globals[idx].export_name);
- out->globals[idx].export_name =
- wasm_strdup(out->heap, name, strlen(name));
+ out->globals[idx].export_name = name;
}
}
} else if (id == 8) {
@@ -1189,7 +1179,7 @@ void wasm_decode_binary(CfreeCompiler* c, const CfreeBytes* input,
}
}
-int wasm_is_binary(const CfreeBytes* input) {
+int wasm_is_binary(const CfreeSlice* input) {
return input->len >= 4u && input->data[0] == 0x00 && input->data[1] == 0x61 &&
input->data[2] == 0x73 && input->data[3] == 0x6d;
}
diff --git a/lang/wasm/encode.c b/lang/wasm/encode.c
@@ -38,10 +38,10 @@ static void write_f64(CfreeWriter* w, double value) {
for (uint32_t i = 0; i < 8u; ++i) write_byte(w, (uint8_t)(bits >> (i * 8u)));
}
-static void write_name(CfreeWriter* w, const char* s) {
- size_t n = strlen(s);
- write_uleb(w, n);
- w->write(w, s, n);
+static void write_name(CfreeWriter* w, const WasmModule* m, CfreeSym sym) {
+ CfreeSlice s = cfree_sym_str(m->c, sym);
+ write_uleb(w, s.len);
+ if (s.len) w->write(w, s.s, s.len);
}
static void encode_section(CfreeHeap* h, CfreeWriter* out, uint8_t id,
@@ -101,16 +101,16 @@ static void enc_import(CfreeWriter* w, const WasmModule* m) {
for (i = 0; i < m->nfuncs; ++i) {
const WasmFunc* f = &m->funcs[i];
if (!f->is_import) continue;
- write_name(w, f->import_module ? f->import_module : "");
- write_name(w, f->import_name ? f->import_name : "");
+ write_name(w, m, f->import_module);
+ write_name(w, m, f->import_name);
write_byte(w, 0);
write_uleb(w, f->typeidx);
}
for (i = 0; i < m->ntables; ++i) {
const WasmTable* t = &m->tables[i];
if (!t->is_import) continue;
- write_name(w, t->import_module ? t->import_module : "");
- write_name(w, t->import_name ? t->import_name : "");
+ write_name(w, m, t->import_module);
+ write_name(w, m, t->import_name);
write_byte(w, 1);
write_byte(w, (uint8_t)t->elem_type);
write_limits(w, t->min, t->max, t->has_max);
@@ -118,16 +118,16 @@ static void enc_import(CfreeWriter* w, const WasmModule* m) {
for (i = 0; i < m->nmemories; ++i) {
const WasmMemory* mem = &m->memories[i];
if (!mem->is_import) continue;
- write_name(w, mem->import_module ? mem->import_module : "");
- write_name(w, mem->import_name ? mem->import_name : "");
+ write_name(w, m, mem->import_module);
+ write_name(w, m, mem->import_name);
write_byte(w, 2);
write_memory_limits(w, mem);
}
for (i = 0; i < m->nglobals; ++i) {
const WasmGlobal* g = &m->globals[i];
if (!g->is_import) continue;
- write_name(w, g->import_module ? g->import_module : "");
- write_name(w, g->import_name ? g->import_name : "");
+ write_name(w, m, g->import_module);
+ write_name(w, m, g->import_name);
write_byte(w, 3);
write_byte(w, (uint8_t)g->type);
write_byte(w, g->mutable_);
@@ -161,7 +161,7 @@ static void enc_export(CfreeWriter* w, const WasmModule* m) {
uint32_t i;
write_uleb(w, m->nexports);
for (i = 0; i < m->nexports; ++i) {
- write_name(w, m->exports[i].name ? m->exports[i].name : "");
+ write_name(w, m, m->exports[i].name);
write_byte(w, m->exports[i].kind);
write_uleb(w, m->exports[i].index);
}
@@ -731,13 +731,13 @@ static void enc_start(CfreeWriter* w, const WasmModule* m) {
write_uleb(w, m->start_func);
}
-static void encode_custom(CfreeHeap* h, CfreeWriter* out,
+static void encode_custom(CfreeHeap* h, CfreeWriter* out, const WasmModule* m,
const WasmCustom* cs) {
CfreeWriter* tmp = NULL;
size_t len;
const uint8_t* bytes;
if (cfree_writer_mem(h, &tmp) != CFREE_OK) return;
- write_name(tmp, cs->name ? cs->name : "");
+ write_name(tmp, m, cs->name);
if (cs->len) tmp->write(tmp, cs->data, cs->len);
bytes = cfree_writer_mem_bytes(tmp, &len);
write_byte(out, 0);
@@ -753,7 +753,7 @@ void wasm_encode(CfreeCompiler* c, const WasmModule* m,
CfreeHeap* h = cfree_compiler_context(c)->heap;
out->write(out, magic, sizeof magic);
for (uint32_t i = 0; i < m->ncustoms; ++i)
- encode_custom(h, out, &m->customs[i]);
+ encode_custom(h, out, m, &m->customs[i]);
encode_section(h, out, 1, enc_type, m);
if (wasm_module_has_imports(m)) encode_section(h, out, 2, enc_import, m);
encode_section(h, out, 3, enc_func, m);
diff --git a/lang/wasm/insn.c b/lang/wasm/insn.c
@@ -22,8 +22,9 @@ void wasm_require_feature(CfreeCompiler* c, const WasmModule* m,
const char* feature_name,
const char* what) {
if (!wasm_feature_enabled(m, feature))
- wasm_error(c, wasm_loc(0, 0), "wasm: %s requires %s", what,
- feature_name);
+ wasm_error(c, wasm_loc(0, 0), "wasm: %.*s requires %.*s",
+ CFREE_SLICE_ARG(cfree_slice_cstr(what)),
+ CFREE_SLICE_ARG(cfree_slice_cstr(feature_name)));
}
diff --git a/lang/wasm/module.c b/lang/wasm/module.c
@@ -20,23 +20,9 @@ void* wasm_realloc(CfreeHeap* h, void* p, size_t old_n, size_t new_n) {
_Alignof(max_align_t));
}
-char* wasm_strdup(CfreeHeap* h, const char* s, size_t len) {
- char* out = (char*)h->alloc(h, len + 1u, 1);
- if (!out) return NULL;
- if (len) memcpy(out, s, len);
- out[len] = '\0';
- return out;
-}
-
-void wasm_free_str(CfreeHeap* h, char** s) {
- if (*s) {
- h->free(h, *s, strlen(*s) + 1u);
- *s = NULL;
- }
-}
-
-void wasm_module_init(WasmModule* m, CfreeHeap* heap) {
+void wasm_module_init(WasmModule* m, CfreeCompiler* c, CfreeHeap* heap) {
memset(m, 0, sizeof *m);
+ m->c = c;
m->heap = heap;
m->features = WASM_FEATURE_THREADS | WASM_FEATURE_TYPED_FUNC_REFS |
WASM_FEATURE_TAIL_CALLS | WASM_FEATURE_MULTI_MEMORY |
@@ -46,56 +32,33 @@ void wasm_module_init(WasmModule* m, CfreeHeap* heap) {
void wasm_module_free(WasmModule* m) {
uint32_t i;
if (!m || !m->heap) return;
- for (i = 0; i < m->ntypes; ++i) wasm_free_str(m->heap, &m->types[i].name);
+ /* Name fields are interned CfreeSyms owned by the compiler pool, not the
+ * module, so there is nothing to free for them here. */
if (m->types)
m->heap->free(m->heap, m->types, sizeof(*m->types) * m->cap_types);
for (i = 0; i < m->nfuncs; ++i) {
WasmFunc* f = &m->funcs[i];
- wasm_free_str(m->heap, &f->name);
- wasm_free_str(m->heap, &f->import_module);
- wasm_free_str(m->heap, &f->import_name);
- wasm_free_str(m->heap, &f->export_name);
- for (uint32_t j = 0; j < f->nparams + f->nlocals; ++j)
- wasm_free_str(m->heap, &f->local_names[j]);
if (f->insns)
m->heap->free(m->heap, f->insns, sizeof(*f->insns) * f->cap_insns);
}
if (m->funcs)
m->heap->free(m->heap, m->funcs, sizeof(*m->funcs) * m->cap_funcs);
for (i = 0; i < m->nmemories; ++i) {
- wasm_free_str(m->heap, &m->memories[i].name);
- wasm_free_str(m->heap, &m->memories[i].import_module);
- wasm_free_str(m->heap, &m->memories[i].import_name);
- wasm_free_str(m->heap, &m->memories[i].export_name);
if (m->memories[i].data)
m->heap->free(m->heap, m->memories[i].data,
(size_t)m->memories[i].data_len);
}
if (m->memories)
m->heap->free(m->heap, m->memories, sizeof(*m->memories) * m->cap_memories);
- for (i = 0; i < m->ntables; ++i) {
- wasm_free_str(m->heap, &m->tables[i].name);
- wasm_free_str(m->heap, &m->tables[i].import_module);
- wasm_free_str(m->heap, &m->tables[i].import_name);
- wasm_free_str(m->heap, &m->tables[i].export_name);
- }
if (m->tables)
m->heap->free(m->heap, m->tables, sizeof(*m->tables) * m->cap_tables);
- for (i = 0; i < m->nglobals; ++i) {
- wasm_free_str(m->heap, &m->globals[i].name);
- wasm_free_str(m->heap, &m->globals[i].import_module);
- wasm_free_str(m->heap, &m->globals[i].import_name);
- wasm_free_str(m->heap, &m->globals[i].export_name);
- }
if (m->globals)
m->heap->free(m->heap, m->globals, sizeof(*m->globals) * m->cap_globals);
if (m->elems)
m->heap->free(m->heap, m->elems, sizeof(*m->elems) * m->cap_elems);
- for (i = 0; i < m->nexports; ++i) wasm_free_str(m->heap, &m->exports[i].name);
if (m->exports)
m->heap->free(m->heap, m->exports, sizeof(*m->exports) * m->cap_exports);
for (i = 0; i < m->ncustoms; ++i) {
- wasm_free_str(m->heap, &m->customs[i].name);
if (m->customs[i].data)
m->heap->free(m->heap, m->customs[i].data, m->customs[i].len);
}
diff --git a/lang/wasm/validate.c b/lang/wasm/validate.c
@@ -42,7 +42,8 @@ static int wasm_stack_pop(CfreeCompiler* c, WasmValStack* s,
wasm_error(c, wasm_loc(0, 0), "wasm: operand stack underflow");
}
if (expected && s->vals[s->depth - 1u] != expected)
- wasm_error(c, wasm_loc(0, 0), "wasm: %s type mismatch", what);
+ wasm_error(c, wasm_loc(0, 0), "wasm: %.*s type mismatch",
+ CFREE_SLICE_ARG(cfree_slice_cstr(what)));
s->depth--;
return 1;
}
@@ -57,7 +58,9 @@ static WasmValType wasm_stack_pop_any(CfreeCompiler* c, WasmValStack* s,
wasm_error(c, wasm_loc(0, 0), "wasm: operand stack underflow");
}
vt = s->vals[s->depth - 1u];
- if (!vt) wasm_error(c, wasm_loc(0, 0), "wasm: %s type mismatch", what);
+ if (!vt)
+ wasm_error(c, wasm_loc(0, 0), "wasm: %.*s type mismatch",
+ CFREE_SLICE_ARG(cfree_slice_cstr(what)));
s->depth--;
return vt;
}
@@ -67,7 +70,8 @@ static void wasm_stack_pop_ref(CfreeCompiler* c, WasmValStack* s,
const char* what) {
WasmValType vt = wasm_stack_pop_any(c, s, frames, nframes, what);
if (!wasm_is_ref_type(vt))
- wasm_error(c, wasm_loc(0, 0), "wasm: %s type mismatch", what);
+ wasm_error(c, wasm_loc(0, 0), "wasm: %.*s type mismatch",
+ CFREE_SLICE_ARG(cfree_slice_cstr(what)));
}
static void wasm_mark_unreachable(WasmValStack* s, WasmControlFrame* frames,
diff --git a/lang/wasm/wasm.c b/lang/wasm/wasm.c
@@ -1,11 +1,11 @@
#include "wasm_internal.h"
-static void wasm_parse_any(CfreeCompiler* c, const CfreeBytes* input,
- WasmModule* m) {
+static void wasm_parse_any(CfreeCompiler* c, CfreeSlice name,
+ const CfreeSlice* input, WasmModule* m) {
if (wasm_is_binary(input))
wasm_decode_binary(c, input, m);
else
- wasm_parse_wat(c, input, m);
+ wasm_parse_wat(c, name, input, m);
wasm_validate(m, c);
}
@@ -33,8 +33,8 @@ static CfreeStatus wasm_frontend_compile(
if (!fe || !fe->c || !opts || !input || !out) return CFREE_INVALID;
c = fe->c;
(void)opts->language_options; /* wasm frontend has no per-language options */
- wasm_module_init(&m, cfree_compiler_context(c)->heap);
- wasm_parse_any(c, &input->bytes, &m);
+ wasm_module_init(&m, c, cfree_compiler_context(c)->heap);
+ wasm_parse_any(c, input->name, &input->bytes, &m);
wasm_emit_cg(c, &opts->code, out, &m);
wasm_module_free(&m);
return CFREE_OK;
@@ -48,20 +48,22 @@ static void wasm_frontend_free(CfreeFrontendState* frontend) {
h->free(h, fe, sizeof(*fe));
}
-static const char* const wasm_extensions[] = {"wat", "wasm", NULL};
+static const CfreeSlice wasm_extensions[] = {CFREE_SLICE_LIT("wat"),
+ CFREE_SLICE_LIT("wasm")};
const CfreeFrontendVTable cfree_wasm_frontend_vtable = {
wasm_frontend_new,
wasm_frontend_compile,
wasm_frontend_free,
wasm_extensions,
+ (uint32_t)(sizeof wasm_extensions / sizeof wasm_extensions[0]),
};
-int cfree_wasm_wat_to_wasm(CfreeCompiler* c, const CfreeBytes* input,
+int cfree_wasm_wat_to_wasm(CfreeCompiler* c, const CfreeSlice* input,
CfreeWriter* out) {
WasmModule m;
- wasm_module_init(&m, cfree_compiler_context(c)->heap);
- wasm_parse_wat(c, input, &m);
+ wasm_module_init(&m, c, cfree_compiler_context(c)->heap);
+ wasm_parse_wat(c, CFREE_SLICE_NULL, input, &m);
wasm_validate(&m, c);
wasm_encode(c, &m, out);
wasm_module_free(&m);
diff --git a/lang/wasm/wasm.h b/lang/wasm/wasm.h
@@ -11,7 +11,7 @@ extern const CfreeFrontendVTable cfree_wasm_frontend_vtable;
/* Internal test/developer helper: parse accepted WAT and write equivalent
* binary Wasm. This is intentionally not part of the installed public API. */
-int cfree_wasm_wat_to_wasm(CfreeCompiler*, const CfreeBytes* input,
+int cfree_wasm_wat_to_wasm(CfreeCompiler*, const CfreeSlice* input,
CfreeWriter* out);
#endif
diff --git a/lang/wasm/wasm_internal.h b/lang/wasm/wasm_internal.h
@@ -231,27 +231,27 @@ typedef struct WasmInsn {
} WasmInsn;
typedef struct WasmFunc {
- char* name;
+ CfreeSym name;
uint32_t typeidx;
int has_typeidx;
int is_import;
- char* import_module;
- char* import_name;
+ CfreeSym import_module;
+ CfreeSym import_name;
WasmValType params[16];
uint32_t nparams;
WasmValType locals[32];
uint32_t nlocals;
- char* local_names[48];
+ CfreeSym local_names[48];
WasmValType results[1];
uint32_t nresults;
- char* export_name;
+ CfreeSym export_name;
WasmInsn* insns;
uint32_t ninsns;
uint32_t cap_insns;
} WasmFunc;
typedef struct WasmFuncType {
- char* name;
+ CfreeSym name;
WasmValType params[16];
uint32_t nparams;
WasmValType results[1];
@@ -259,42 +259,42 @@ typedef struct WasmFuncType {
} WasmFuncType;
typedef struct WasmMemory {
- char* name;
+ CfreeSym name;
uint64_t min_pages;
uint64_t max_pages;
int has_max;
int is64;
int shared;
int is_import;
- char* import_module;
- char* import_name;
- char* export_name;
+ CfreeSym import_module;
+ CfreeSym import_name;
+ CfreeSym export_name;
uint8_t* data;
uint64_t data_len;
uint64_t data_init_len;
} WasmMemory;
typedef struct WasmTable {
- char* name;
+ CfreeSym name;
WasmValType elem_type;
uint32_t min;
uint32_t max;
int has_max;
int is_import;
- char* import_module;
- char* import_name;
- char* export_name;
+ CfreeSym import_module;
+ CfreeSym import_name;
+ CfreeSym export_name;
} WasmTable;
typedef struct WasmGlobal {
- char* name;
+ CfreeSym name;
WasmValType type;
uint8_t mutable_;
WasmInsn init;
int is_import;
- char* import_module;
- char* import_name;
- char* export_name;
+ CfreeSym import_module;
+ CfreeSym import_name;
+ CfreeSym export_name;
} WasmGlobal;
typedef struct WasmElemSegment {
@@ -305,18 +305,19 @@ typedef struct WasmElemSegment {
} WasmElemSegment;
typedef struct WasmExport {
- char* name;
+ CfreeSym name;
uint8_t kind;
uint32_t index;
} WasmExport;
typedef struct WasmCustom {
- char* name;
+ CfreeSym name;
uint8_t* data;
uint32_t len;
} WasmCustom;
typedef struct WasmModule {
+ CfreeCompiler* c;
CfreeHeap* heap;
WasmFuncType* types;
uint32_t ntypes;
@@ -351,10 +352,8 @@ typedef struct WasmModule {
CfreeSrcLoc wasm_loc(uint32_t line, uint32_t col);
void wasm_error(CfreeCompiler* c, CfreeSrcLoc loc, const char* fmt, ...);
void* wasm_realloc(CfreeHeap* h, void* p, size_t old_n, size_t new_n);
-char* wasm_strdup(CfreeHeap* h, const char* s, size_t len);
-void wasm_free_str(CfreeHeap* h, char** s);
-void wasm_module_init(WasmModule* m, CfreeHeap* heap);
+void wasm_module_init(WasmModule* m, CfreeCompiler* c, CfreeHeap* heap);
void wasm_module_free(WasmModule* m);
void wasm_memory_ensure(CfreeCompiler* c, WasmModule* m, uint32_t memidx,
uint64_t needed);
@@ -404,10 +403,11 @@ int wasm_fp_binop_kind(uint8_t kind, WasmValType* vt);
int wasm_fp_cmp_kind(uint8_t kind, WasmValType* vt);
int wasm_conversion_kind(uint8_t kind, WasmValType* src, WasmValType* dst);
-void wasm_parse_wat(CfreeCompiler* c, const CfreeBytes* input, WasmModule* out);
-void wasm_decode_binary(CfreeCompiler* c, const CfreeBytes* input,
+void wasm_parse_wat(CfreeCompiler* c, CfreeSlice name, const CfreeSlice* input,
+ WasmModule* out);
+void wasm_decode_binary(CfreeCompiler* c, const CfreeSlice* input,
WasmModule* out);
-int wasm_is_binary(const CfreeBytes* input);
+int wasm_is_binary(const CfreeSlice* input);
void wasm_validate(WasmModule* m, CfreeCompiler* c);
void wasm_emit_cg(CfreeCompiler* c, const CfreeCodeOptions* code_opts,
CfreeObjBuilder* out, const WasmModule* m);
diff --git a/lang/wasm/wat.c b/lang/wasm/wat.c
@@ -29,15 +29,13 @@ typedef struct WatParser {
} WatParser;
static int tok_is(WasmTok t, const char* s) {
- size_t n = strlen(s);
+ size_t n = cfree_slice_cstr(s).len;
return t.kind == WT_ATOM && t.len == n && memcmp(t.p, s, n) == 0;
}
-static int wasm_name_eq(const char* name, WasmTok t) {
- size_t n;
+static int wasm_name_eq(WatParser* p, CfreeSym name, WasmTok t) {
if (!name || t.kind != WT_ATOM) return 0;
- n = strlen(name);
- return t.len == n && memcmp(name, t.p, n) == 0;
+ return name == cfree_sym_intern(p->c, (CfreeSlice){.s = t.p, .len = t.len});
}
static int wat_hex(char ch) {
@@ -96,6 +94,22 @@ static char* wat_dup_string(WatParser* p, WasmTok t, size_t* len_out) {
return out;
}
+/* Decode a WAT string token's escapes and intern the bytes as a CfreeSym. The
+ * temporary decode buffer is freed; the interned bytes live in the compiler
+ * pool. */
+static CfreeSym wat_intern_string(WatParser* p, WasmTok t) {
+ size_t n = 0;
+ char* decoded = wat_dup_string(p, t, &n);
+ CfreeSym sym = cfree_sym_intern(p->c, (CfreeSlice){.s = decoded, .len = n});
+ p->module->heap->free(p->module->heap, decoded, t.len + 1u);
+ return sym;
+}
+
+/* Intern a raw token's bytes (e.g. a `$name` identifier) as a CfreeSym. */
+static CfreeSym wat_intern_tok(WatParser* p, WasmTok t) {
+ return cfree_sym_intern(p->c, (CfreeSlice){.s = t.p, .len = t.len});
+}
+
static void wat_next(WatParser* p) {
const char* s = p->src;
while (p->pos < p->len) {
@@ -208,8 +222,9 @@ static void wat_next(WatParser* p) {
static void wat_expect(WatParser* p, uint8_t kind, const char* what) {
if (p->tok.kind != kind)
- wasm_error(p->c, wasm_loc(p->tok.line, p->tok.col), "wasm wat: expected %s",
- what);
+ wasm_error(p->c, wasm_loc(p->tok.line, p->tok.col),
+ "wasm wat: expected %.*s",
+ CFREE_SLICE_ARG(cfree_slice_cstr(what)));
wat_next(p);
}
@@ -286,7 +301,9 @@ static void wat_require_feature(WatParser* p, WasmFeatureSet feature,
const char* feature_name, const char* what) {
if (!wasm_feature_enabled(p->module, feature))
wasm_error(p->c, wasm_loc(p->tok.line, p->tok.col),
- "wasm wat: %s requires %s", what, feature_name);
+ "wasm wat: %.*s requires %.*s",
+ CFREE_SLICE_ARG(cfree_slice_cstr(what)),
+ CFREE_SLICE_ARG(cfree_slice_cstr(feature_name)));
}
static uint8_t wasm_export_kind_from_tok(WasmTok t) {
@@ -1080,7 +1097,7 @@ static void wat_parse_func_index(WatParser* p, int64_t* out) {
uint32_t i;
if (p->tok.kind == WT_ATOM && p->tok.len && p->tok.p[0] == '$') {
for (i = 0; i < p->module->nfuncs; ++i) {
- if (wasm_name_eq(p->module->funcs[i].name, p->tok)) {
+ if (wasm_name_eq(p, p->module->funcs[i].name, p->tok)) {
*out = i;
return;
}
@@ -1097,7 +1114,7 @@ static void wat_parse_type_index(WatParser* p, int64_t* out) {
uint32_t i;
if (p->tok.kind == WT_ATOM && p->tok.len && p->tok.p[0] == '$') {
for (i = 0; i < p->module->ntypes; ++i) {
- if (wasm_name_eq(p->module->types[i].name, p->tok)) {
+ if (wasm_name_eq(p, p->module->types[i].name, p->tok)) {
*out = i;
return;
}
@@ -1114,7 +1131,7 @@ static void wat_parse_local_index(WatParser* p, WasmFunc* f, int64_t* out) {
uint32_t i, nlocals = f->nparams + f->nlocals;
if (p->tok.kind == WT_ATOM && p->tok.len && p->tok.p[0] == '$') {
for (i = 0; i < nlocals; ++i) {
- if (wasm_name_eq(f->local_names[i], p->tok)) {
+ if (wasm_name_eq(p, f->local_names[i], p->tok)) {
*out = i;
return;
}
@@ -1131,7 +1148,7 @@ static void wat_parse_global_index(WatParser* p, int64_t* out) {
uint32_t i;
if (p->tok.kind == WT_ATOM && p->tok.len && p->tok.p[0] == '$') {
for (i = 0; i < p->module->nglobals; ++i) {
- if (wasm_name_eq(p->module->globals[i].name, p->tok)) {
+ if (wasm_name_eq(p, p->module->globals[i].name, p->tok)) {
*out = i;
return;
}
@@ -1170,7 +1187,7 @@ static void wat_parse_instr_imm(WatParser* p, WasmFunc* f, WasmInsnKind kind,
static int wat_atom_prefix(WasmTok t, const char* prefix) {
- size_t n = strlen(prefix);
+ size_t n = cfree_slice_cstr(prefix).len;
return t.kind == WT_ATOM && t.len >= n && memcmp(t.p, prefix, n) == 0;
}
@@ -1225,7 +1242,7 @@ static void wat_parse_memory_index(WatParser* p, uint32_t* out) {
int64_t idx;
if (p->tok.kind == WT_ATOM && p->tok.len && p->tok.p[0] == '$') {
for (i = 0; i < p->module->nmemories; ++i) {
- if (wasm_name_eq(p->module->memories[i].name, p->tok)) {
+ if (wasm_name_eq(p, p->module->memories[i].name, p->tok)) {
*out = i;
return;
}
@@ -1296,7 +1313,8 @@ static void wat_reject_inline_result(WatParser* p, const char* what) {
return;
}
wasm_error(p->c, wasm_loc(p->tok.line, p->tok.col),
- "wasm wat: %s results are unsupported", what);
+ "wasm wat: %.*s results are unsupported",
+ CFREE_SLICE_ARG(cfree_slice_cstr(what)));
}
static void wat_parse_instr(WatParser* p, WasmFunc* f);
@@ -1687,10 +1705,7 @@ static void wat_parse_func(WatParser* p) {
"wasm wat: expected func");
wat_next(p);
if (p->tok.kind == WT_ATOM && p->tok.len > 0 && p->tok.p[0] == '$') {
- f->name = wasm_strdup(p->module->heap, p->tok.p, p->tok.len);
- if (!f->name)
- wasm_error(p->c, wasm_loc(p->tok.line, p->tok.col),
- "wasm: out of memory");
+ f->name = wat_intern_tok(p, p->tok);
wat_next(p);
}
while (p->tok.kind != WT_RPAREN && p->tok.kind != WT_EOF) {
@@ -1701,14 +1716,10 @@ static void wat_parse_func(WatParser* p) {
if (p->tok.kind != WT_STRING)
wasm_error(p->c, wasm_loc(p->tok.line, p->tok.col),
"wasm wat: expected export string");
- f->export_name = wat_dup_string(p, p->tok, NULL);
+ f->export_name = wat_intern_string(p, p->tok);
{
WasmExport* ex = wasm_add_export(p->c, p->module);
- ex->name = wasm_strdup(p->module->heap, f->export_name,
- strlen(f->export_name));
- if (!ex->name)
- wasm_error(p->c, wasm_loc(p->tok.line, p->tok.col),
- "wasm: out of memory");
+ ex->name = f->export_name;
ex->kind = 0;
ex->index = p->module->nfuncs - 1u;
}
@@ -1755,11 +1766,7 @@ static void wat_parse_func(WatParser* p) {
wasm_error(p->c, wasm_loc(p->tok.line, p->tok.col),
"wasm wat: parameter does not match type");
if (have_name) {
- f->local_names[checked_params] = wasm_strdup(
- p->module->heap, pending_name.p, pending_name.len);
- if (!f->local_names[checked_params])
- wasm_error(p->c, wasm_loc(p->tok.line, p->tok.col),
- "wasm: out of memory");
+ f->local_names[checked_params] = wat_intern_tok(p, pending_name);
have_name = 0;
}
checked_params++;
@@ -1770,11 +1777,7 @@ static void wat_parse_func(WatParser* p) {
wasm_error(p->c, wasm_loc(p->tok.line, p->tok.col),
"wasm wat: too many parameters");
if (have_name) {
- f->local_names[f->nparams] =
- wasm_strdup(p->module->heap, pending_name.p, pending_name.len);
- if (!f->local_names[f->nparams])
- wasm_error(p->c, wasm_loc(p->tok.line, p->tok.col),
- "wasm: out of memory");
+ f->local_names[f->nparams] = wat_intern_tok(p, pending_name);
have_name = 0;
}
f->params[f->nparams++] = vt;
@@ -1823,11 +1826,7 @@ static void wat_parse_func(WatParser* p) {
"wasm wat: too many locals");
if (have_name) {
uint32_t index = f->nparams + f->nlocals;
- f->local_names[index] =
- wasm_strdup(p->module->heap, pending_name.p, pending_name.len);
- if (!f->local_names[index])
- wasm_error(p->c, wasm_loc(p->tok.line, p->tok.col),
- "wasm: out of memory");
+ f->local_names[index] = wat_intern_tok(p, pending_name);
have_name = 0;
}
f->locals[f->nlocals++] = vt;
@@ -1860,10 +1859,7 @@ static void wat_parse_func(WatParser* p) {
static void wat_parse_type_field(WatParser* p) {
WasmFuncType* t = wasm_add_type(p->c, p->module);
if (p->tok.kind == WT_ATOM && p->tok.len && p->tok.p[0] == '$') {
- t->name = wasm_strdup(p->module->heap, p->tok.p, p->tok.len);
- if (!t->name)
- wasm_error(p->c, wasm_loc(p->tok.line, p->tok.col),
- "wasm: out of memory");
+ t->name = wat_intern_tok(p, p->tok);
wat_next(p);
}
wat_expect(p, WT_LPAREN, "'('");
@@ -1914,13 +1910,13 @@ static void wat_parse_type_field(WatParser* p) {
}
static void wat_parse_export_field(WatParser* p) {
- char* name;
+ CfreeSym name;
int64_t idx = 0;
uint8_t kind;
if (p->tok.kind != WT_STRING)
wasm_error(p->c, wasm_loc(p->tok.line, p->tok.col),
"wasm wat: expected export string");
- name = wat_dup_string(p, p->tok, NULL);
+ name = wat_intern_string(p, p->tok);
wat_next(p);
wat_expect(p, WT_LPAREN, "'('");
kind = wasm_export_kind_from_tok(p->tok);
@@ -1943,34 +1939,13 @@ static void wat_parse_export_field(WatParser* p) {
ex->index = (uint32_t)idx;
}
if (kind == 0 && (uint64_t)idx < p->module->nfuncs) {
- wasm_free_str(p->module->heap, &p->module->funcs[idx].export_name);
- p->module->funcs[idx].export_name =
- wasm_strdup(p->module->heap, name, strlen(name));
- if (!p->module->funcs[idx].export_name)
- wasm_error(p->c, wasm_loc(p->tok.line, p->tok.col),
- "wasm: out of memory");
+ p->module->funcs[idx].export_name = name;
} else if (kind == 2 && (uint64_t)idx < p->module->nmemories) {
- wasm_free_str(p->module->heap,
- &p->module->memories[(uint32_t)idx].export_name);
- p->module->memories[(uint32_t)idx].export_name =
- wasm_strdup(p->module->heap, name, strlen(name));
- if (!p->module->memories[(uint32_t)idx].export_name)
- wasm_error(p->c, wasm_loc(p->tok.line, p->tok.col),
- "wasm: out of memory");
+ p->module->memories[(uint32_t)idx].export_name = name;
} else if (kind == 1 && (uint64_t)idx < p->module->ntables) {
- wasm_free_str(p->module->heap, &p->module->tables[idx].export_name);
- p->module->tables[idx].export_name =
- wasm_strdup(p->module->heap, name, strlen(name));
- if (!p->module->tables[idx].export_name)
- wasm_error(p->c, wasm_loc(p->tok.line, p->tok.col),
- "wasm: out of memory");
+ p->module->tables[idx].export_name = name;
} else if (kind == 3 && (uint64_t)idx < p->module->nglobals) {
- wasm_free_str(p->module->heap, &p->module->globals[idx].export_name);
- p->module->globals[idx].export_name =
- wasm_strdup(p->module->heap, name, strlen(name));
- if (!p->module->globals[idx].export_name)
- wasm_error(p->c, wasm_loc(p->tok.line, p->tok.col),
- "wasm: out of memory");
+ p->module->globals[idx].export_name = name;
}
wat_next(p);
wat_expect(p, WT_RPAREN, "')'");
@@ -1981,10 +1956,7 @@ static void wat_parse_memory_field(WatParser* p) {
int64_t min_pages, max_pages;
WasmMemory* mem = wasm_add_memory(p->c, p->module);
if (p->tok.kind == WT_ATOM && p->tok.len && p->tok.p[0] == '$') {
- mem->name = wasm_strdup(p->module->heap, p->tok.p, p->tok.len);
- if (!mem->name)
- wasm_error(p->c, wasm_loc(p->tok.line, p->tok.col),
- "wasm: out of memory");
+ mem->name = wat_intern_tok(p, p->tok);
wat_next(p);
}
while (p->tok.kind == WT_ATOM && (tok_is(p->tok, "i64") ||
@@ -2095,16 +2067,16 @@ static void wat_parse_table_limits_and_type(WatParser* p, WasmTable* t) {
}
static void wat_parse_import_field(WatParser* p) {
- char *mod, *name;
+ CfreeSym mod, name;
if (p->tok.kind != WT_STRING)
wasm_error(p->c, wasm_loc(p->tok.line, p->tok.col),
"wasm wat: expected import module string");
- mod = wat_dup_string(p, p->tok, NULL);
+ mod = wat_intern_string(p, p->tok);
wat_next(p);
if (p->tok.kind != WT_STRING)
wasm_error(p->c, wasm_loc(p->tok.line, p->tok.col),
"wasm wat: expected import name string");
- name = wat_dup_string(p, p->tok, NULL);
+ name = wat_intern_string(p, p->tok);
wat_next(p);
wat_expect(p, WT_LPAREN, "'('");
if (tok_is(p->tok, "func")) {
@@ -2114,10 +2086,7 @@ static void wat_parse_import_field(WatParser* p) {
f->import_name = name;
wat_next(p);
if (p->tok.kind == WT_ATOM && p->tok.len && p->tok.p[0] == '$') {
- f->name = wasm_strdup(p->module->heap, p->tok.p, p->tok.len);
- if (!f->name)
- wasm_error(p->c, wasm_loc(p->tok.line, p->tok.col),
- "wasm: out of memory");
+ f->name = wat_intern_tok(p, p->tok);
wat_next(p);
}
while (p->tok.kind != WT_RPAREN && p->tok.kind != WT_EOF) {
@@ -2182,10 +2151,7 @@ static void wat_parse_import_field(WatParser* p) {
mem->import_name = name;
wat_next(p);
if (p->tok.kind == WT_ATOM && p->tok.len && p->tok.p[0] == '$') {
- mem->name = wasm_strdup(p->module->heap, p->tok.p, p->tok.len);
- if (!mem->name)
- wasm_error(p->c, wasm_loc(p->tok.line, p->tok.col),
- "wasm: out of memory");
+ mem->name = wat_intern_tok(p, p->tok);
wat_next(p);
}
wat_parse_memory_limits(p, mem);
@@ -2196,10 +2162,7 @@ static void wat_parse_import_field(WatParser* p) {
t->import_name = name;
wat_next(p);
if (p->tok.kind == WT_ATOM && p->tok.len && p->tok.p[0] == '$') {
- t->name = wasm_strdup(p->module->heap, p->tok.p, p->tok.len);
- if (!t->name)
- wasm_error(p->c, wasm_loc(p->tok.line, p->tok.col),
- "wasm: out of memory");
+ t->name = wat_intern_tok(p, p->tok);
wat_next(p);
}
wat_parse_table_limits_and_type(p, t);
@@ -2210,10 +2173,7 @@ static void wat_parse_import_field(WatParser* p) {
g->import_name = name;
wat_next(p);
if (p->tok.kind == WT_ATOM && p->tok.len && p->tok.p[0] == '$') {
- g->name = wasm_strdup(p->module->heap, p->tok.p, p->tok.len);
- if (!g->name)
- wasm_error(p->c, wasm_loc(p->tok.line, p->tok.col),
- "wasm: out of memory");
+ g->name = wat_intern_tok(p, p->tok);
wat_next(p);
}
if (p->tok.kind == WT_LPAREN) {
@@ -2245,10 +2205,7 @@ static void wat_parse_import_field(WatParser* p) {
static void wat_parse_table_field(WatParser* p) {
WasmTable* t = wasm_add_table(p->c, p->module);
if (p->tok.kind == WT_ATOM && p->tok.len && p->tok.p[0] == '$') {
- t->name = wasm_strdup(p->module->heap, p->tok.p, p->tok.len);
- if (!t->name)
- wasm_error(p->c, wasm_loc(p->tok.line, p->tok.col),
- "wasm: out of memory");
+ t->name = wat_intern_tok(p, p->tok);
wat_next(p);
}
wat_parse_table_limits_and_type(p, t);
@@ -2282,10 +2239,7 @@ static void wat_parse_const_expr(WatParser* p, WasmInsn* out) {
static void wat_parse_global_field(WatParser* p) {
WasmGlobal* g = wasm_add_global(p->c, p->module);
if (p->tok.kind == WT_ATOM && p->tok.len && p->tok.p[0] == '$') {
- g->name = wasm_strdup(p->module->heap, p->tok.p, p->tok.len);
- if (!g->name)
- wasm_error(p->c, wasm_loc(p->tok.line, p->tok.col),
- "wasm: out of memory");
+ g->name = wat_intern_tok(p, p->tok);
wat_next(p);
}
if (p->tok.kind == WT_LPAREN) {
@@ -2295,14 +2249,10 @@ static void wat_parse_global_field(WatParser* p) {
if (p->tok.kind != WT_STRING)
wasm_error(p->c, wasm_loc(p->tok.line, p->tok.col),
"wasm wat: expected export string");
- g->export_name = wat_dup_string(p, p->tok, NULL);
+ g->export_name = wat_intern_string(p, p->tok);
{
WasmExport* ex = wasm_add_export(p->c, p->module);
- ex->name = wasm_strdup(p->module->heap, g->export_name,
- strlen(g->export_name));
- if (!ex->name)
- wasm_error(p->c, wasm_loc(p->tok.line, p->tok.col),
- "wasm: out of memory");
+ ex->name = g->export_name;
ex->kind = 3;
ex->index = p->module->nglobals - 1u;
}
@@ -2390,9 +2340,9 @@ static void wat_parse_custom_field(WatParser* p) {
wasm_error(p->c, wasm_loc(p->tok.line, p->tok.col),
"wasm wat: expected custom section name");
cs = wasm_add_custom(p->c, p->module);
- cs->name = wat_dup_string(p, p->tok, NULL);
- if (strcmp(cs->name, "target_features") == 0 ||
- strcmp(cs->name, "target-feature") == 0)
+ cs->name = wat_intern_string(p, p->tok);
+ if (cs->name == cfree_sym_intern(p->c, CFREE_SLICE_LIT("target_features")) ||
+ cs->name == cfree_sym_intern(p->c, CFREE_SLICE_LIT("target-feature")))
p->module->has_target_features = 1;
wat_next(p);
if (p->tok.kind == WT_STRING) {
@@ -2476,13 +2426,13 @@ static void wat_parse_data_field(WatParser* p) {
wat_expect(p, WT_RPAREN, "')'");
}
-void wasm_parse_wat(CfreeCompiler* c, const CfreeBytes* input,
+void wasm_parse_wat(CfreeCompiler* c, CfreeSlice name, const CfreeSlice* input,
WasmModule* out) {
WatParser p;
memset(&p, 0, sizeof p);
p.c = c;
- p.name = input->name;
- p.src = (const char*)input->data;
+ p.name = name.s;
+ p.src = input->s;
p.len = input->len;
p.line = 1;
p.col = 1;
diff --git a/scripts/check_no_cstr.sh b/scripts/check_no_cstr.sh
@@ -0,0 +1,37 @@
+#!/usr/bin/env bash
+# Phase 6 gate: assert the NUL-terminated-string functions and printf %s have
+# been eliminated from the first-party tree (src/, lang/, driver/). rt/ is the
+# freestanding runtime/libc and is intentionally exempt. Test code is exempt.
+#
+# Allowed exceptions:
+# - slice_from_cstr / cfree_slice_cstr : the sanctioned boundary scan helpers
+# - driver_strlen / driver_streq / driver_strneq : driver host-shim wrappers
+# - reloc_kind_name / *_name returning canonical literals (not string ops)
+# - ordering compares left intentionally (marked with a nearby comment)
+#
+# Usage: scripts/check_no_cstr.sh (exit 1 on any disallowed hit)
+set -u
+cd "$(dirname "$0")/.."
+
+dirs="src lang driver"
+# Forbidden: bare libc string functions. We match the call form `name(`.
+banned='\b(strlen|strcmp|strncmp|strcpy|strncpy|strcat|strncat|strstr|strchr|strrchr|strdup)\s*\('
+# printf-family bare %s (not %.*s, not %%s, not width-padded %-Ns / %*s).
+pct_s='%[^%."*0-9-]*s|"[^"]*%s'
+
+fail=0
+
+echo "== banned string functions =="
+# src/core/slice.c is the one sanctioned home of a NUL scan (slice_from_cstr).
+hits=$(rg -n --pcre2 "$banned" $dirs -g '!*/tests/*' -g '!src/core/slice.c' 2>/dev/null \
+ | rg -v 'slice_from_cstr|cfree_slice_cstr|driver_strlen|driver_streq|driver_strneq|driver_strchr|driver_strdup' \
+ | rg -v 'ordering|sort|/\* *TODO slice' )
+if [ -n "$hits" ]; then echo "$hits"; fail=1; else echo " clean"; fi
+
+echo "== bare printf %s =="
+# Heuristic: lines containing "%s" inside a string literal, excluding the
+# allowed width/precision/.* forms. Manual review still recommended.
+shits=$(rg -n '"[^"]*%s' $dirs 2>/dev/null | rg -v '%\.\*s|%-[0-9]+s|%\*s|%%s')
+if [ -n "$shits" ]; then echo "$shits"; fail=1; else echo " clean"; fi
+
+exit $fail
diff --git a/src/api/arch.c b/src/api/arch.c
@@ -5,19 +5,24 @@
#include <cfree/arch.h>
#include <stddef.h>
-const char* cfree_arch_register_name(CfreeArchKind arch, uint32_t dwarf_idx) {
+CfreeSlice cfree_arch_register_name(CfreeArchKind arch, uint32_t dwarf_idx) {
const ArchImpl* impl = arch_lookup(arch);
- if (!impl || !impl->register_name) return NULL;
- return impl->register_name(dwarf_idx);
+ const char* nm;
+ if (!impl || !impl->register_name) return CFREE_SLICE_NULL;
+ nm = impl->register_name(dwarf_idx);
+ return cfree_slice_cstr(nm);
}
-CfreeStatus cfree_arch_register_index(CfreeArchKind arch, const char* name,
+CfreeStatus cfree_arch_register_index(CfreeArchKind arch, CfreeSlice name,
uint32_t* idx_out) {
const ArchImpl* impl;
- if (!name || !idx_out) return CFREE_INVALID;
+ /* Internal register tables compare NUL-terminated names; name.s comes from
+ * argv/interned/arena slices that carry a NUL at name.len. */
+ if (!name.s || !idx_out) return CFREE_INVALID;
impl = arch_lookup(arch);
if (!impl || !impl->register_index) return CFREE_UNSUPPORTED;
- return impl->register_index(name, idx_out) == 0 ? CFREE_OK : CFREE_NOT_FOUND;
+ return impl->register_index(name.s, idx_out) == 0 ? CFREE_OK
+ : CFREE_NOT_FOUND;
}
uint32_t cfree_arch_register_count(CfreeArchKind arch) {
diff --git a/src/api/archive.c b/src/api/archive.c
@@ -6,6 +6,7 @@
#include "core/bytes.h"
#include "core/core.h"
#include "core/heap.h"
+#include "core/slice.h"
/* ============================================================
* Write helpers
@@ -46,17 +47,12 @@ static CfreeStatus wh_be32(Writer* w, u32 v) {
return wh_bytes(w, b, 4);
}
-static void ar_name_basename(const char* in, const char** name_out,
- size_t* len_out) {
- const char* name = in;
- const char* p;
- size_t namelen = 0;
- for (p = in; *p; ++p) {
- if (*p == '/') name = p + 1;
+static Slice ar_name_basename(Slice in) {
+ size_t start = 0, i;
+ for (i = 0; i < in.len; ++i) {
+ if (in.s[i] == '/') start = i + 1;
}
- for (p = name; *p; ++p) ++namelen;
- *name_out = name;
- *len_out = namelen;
+ return (Slice){ .s = in.s + start, .len = in.len - start };
}
static int ar_name_needs_longtable(const char* name, size_t len) {
@@ -67,12 +63,6 @@ static int ar_name_needs_longtable(const char* name, size_t len) {
return 0;
}
-static size_t ar_strlen(const char* s) {
- size_t n = 0;
- while (s[n]) ++n;
- return n;
-}
-
static size_t ar_member_padded_size(size_t len) { return 60 + len + (len & 1); }
static void ar_fill_header(char hdr[60], const char name_field[16],
@@ -97,7 +87,7 @@ static void ar_fill_header(char hdr[60], const char name_field[16],
hdr[59] = '\n';
}
-CfreeStatus cfree_ar_write(CfreeWriter* out, const CfreeBytes* members,
+CfreeStatus cfree_ar_write(CfreeWriter* out, const CfreeArInput* members,
uint32_t nmembers, const CfreeArWriteOptions* opts) {
static const char magic[] = "!<arch>\n";
static const CfreeArWriteOptions default_opts = {0, 0, 0, NULL};
@@ -125,17 +115,16 @@ CfreeStatus cfree_ar_write(CfreeWriter* out, const CfreeBytes* members,
if (long_names) {
for (i = 0; i < nmembers; ++i) {
- const char* name;
- size_t namelen;
- if (!members[i].name) return CFREE_INVALID;
- ar_name_basename(members[i].name, &name, &namelen);
- if (ar_name_needs_longtable(name, namelen)) {
- longtab_size += (uint64_t)namelen + 2;
+ Slice base;
+ if (!members[i].name.s) return CFREE_INVALID;
+ base = ar_name_basename(members[i].name);
+ if (ar_name_needs_longtable(base.s, base.len)) {
+ longtab_size += (uint64_t)base.len + 2;
}
}
} else {
for (i = 0; i < nmembers; ++i) {
- if (!members[i].name) return CFREE_INVALID;
+ if (!members[i].name.s) return CFREE_INVALID;
}
}
@@ -145,10 +134,10 @@ CfreeStatus cfree_ar_write(CfreeWriter* out, const CfreeBytes* members,
u32 k;
if (msyms[i].count && !msyms[i].names) return CFREE_INVALID;
for (k = 0; k < msyms[i].count; ++k) {
- const char* nm = msyms[i].names[k];
- if (!nm) return CFREE_INVALID;
+ Slice nm = msyms[i].names[k];
+ if (!nm.s) return CFREE_INVALID;
nsyms += 1;
- names_size += (uint64_t)ar_strlen(nm) + 1;
+ names_size += (uint64_t)nm.len + 1;
}
}
}
@@ -181,7 +170,7 @@ CfreeStatus cfree_ar_write(CfreeWriter* out, const CfreeBytes* members,
for (k = 0; k < msyms[i].count; ++k) {
wh_be32(out, (u32)cur_offset);
}
- cur_offset += ar_member_padded_size(members[i].len);
+ cur_offset += ar_member_padded_size(members[i].bytes.len);
}
}
@@ -189,9 +178,10 @@ CfreeStatus cfree_ar_write(CfreeWriter* out, const CfreeBytes* members,
for (i = 0; i < nmembers; ++i) {
u32 k;
for (k = 0; k < msyms[i].count; ++k) {
- const char* nm = msyms[i].names[k];
- size_t nmlen = ar_strlen(nm);
- wh_bytes(out, nm, nmlen + 1);
+ Slice nm = msyms[i].names[k];
+ static const char nul = '\0';
+ wh_bytes(out, nm.s, nm.len);
+ wh_bytes(out, &nul, 1);
}
}
}
@@ -209,11 +199,9 @@ CfreeStatus cfree_ar_write(CfreeWriter* out, const CfreeBytes* members,
ar_fill_header(hdr, name_field, 0, longtab_size);
wh_bytes(out, hdr, 60);
for (i = 0; i < nmembers; ++i) {
- const char* name;
- size_t namelen;
- ar_name_basename(members[i].name, &name, &namelen);
- if (ar_name_needs_longtable(name, namelen)) {
- wh_bytes(out, name, namelen);
+ Slice base = ar_name_basename(members[i].name);
+ if (ar_name_needs_longtable(base.s, base.len)) {
+ wh_bytes(out, base.s, base.len);
wh_bytes(out, "/\n", 2);
}
}
@@ -223,30 +211,28 @@ CfreeStatus cfree_ar_write(CfreeWriter* out, const CfreeBytes* members,
{
uint64_t longtab_off = 0;
for (i = 0; i < nmembers; ++i) {
- const CfreeBytes* m = &members[i];
- const char* name;
- size_t namelen;
+ const CfreeArInput* m = &members[i];
+ Slice base = ar_name_basename(m->name);
char hdr[60];
char name_field[16];
size_t j;
- ar_name_basename(m->name, &name, &namelen);
-
for (j = 0; j < 16; ++j) name_field[j] = ' ';
- if (long_names && ar_name_needs_longtable(name, namelen)) {
+ if (long_names && ar_name_needs_longtable(base.s, base.len)) {
name_field[0] = '/';
wh_ar_num(name_field + 1, 15, longtab_off);
- longtab_off += (uint64_t)namelen + 2;
+ longtab_off += (uint64_t)base.len + 2;
} else {
- size_t emit = namelen > 15 ? 15 : namelen;
- for (j = 0; j < emit; ++j) name_field[j] = name[j];
+ size_t emit = base.len > 15 ? 15 : base.len;
+ for (j = 0; j < emit; ++j) name_field[j] = base.s[j];
name_field[emit] = '/';
}
- ar_fill_header(hdr, name_field, epoch, (uint64_t)m->len);
+ ar_fill_header(hdr, name_field, epoch, (uint64_t)m->bytes.len);
wh_bytes(out, hdr, 60);
- if (m->data && m->len) wh_bytes(out, m->data, m->len);
- if (m->len & 1) wh_bytes(out, &pad, 1);
+ if (m->bytes.data && m->bytes.len)
+ wh_bytes(out, m->bytes.data, m->bytes.len);
+ if (m->bytes.len & 1) wh_bytes(out, &pad, 1);
}
}
@@ -285,7 +271,7 @@ static size_t ar_resolve_longname(CfreeArIter* it, uint64_t off) {
}
CfreeStatus cfree_ar_iter_new(const CfreeContext* ctx,
- const CfreeBytes* archive, CfreeArIter** out) {
+ const CfreeSlice* archive, CfreeArIter** out) {
Heap* h;
CfreeArIter* it;
if (!out) return CFREE_INVALID;
@@ -377,7 +363,8 @@ CfreeIterResult cfree_ar_iter_next(CfreeArIter* it, CfreeArMember* out) {
it->namebuf[namelen] = '\0';
}
- out->name = it->namebuf;
+ out->name.s = it->namebuf;
+ out->name.len = namelen;
out->data = it->p;
out->size = (size_t)size;
@@ -404,12 +391,10 @@ void cfree_ar_iter_free(CfreeArIter* it) {
h->free(h, it, sizeof(*it));
}
-CfreeStatus cfree_ar_list(const CfreeBytes* archive, CfreeWriter* out) {
+CfreeStatus cfree_ar_list(const CfreeSlice* archive, CfreeWriter* out) {
/* Iter API requires a context; emulate locally without heap allocation. */
struct CfreeArIter local;
CfreeArMember m;
- size_t namelen;
- const char* p;
if (!out) return CFREE_INVALID;
if (!archive) return CFREE_INVALID;
@@ -425,9 +410,7 @@ CfreeStatus cfree_ar_list(const CfreeBytes* archive, CfreeWriter* out) {
for (;;) {
CfreeIterResult r = cfree_ar_iter_next(&local, &m);
if (r != CFREE_ITER_ITEM) break;
- namelen = 0;
- for (p = m.name; *p; ++p) ++namelen;
- wh_bytes(out, m.name, namelen);
+ wh_bytes(out, m.name.s, m.name.len);
wh_nl(out);
}
diff --git a/src/api/compile.c b/src/api/compile.c
@@ -11,6 +11,7 @@
#include "core/heap.h"
#include "core/metrics.h"
#include "core/pool.h"
+#include "core/slice.h"
#include "obj/obj.h"
typedef struct AsmFrontend {
@@ -38,13 +39,14 @@ static CfreeStatus asm_frontend_compile(CfreeFrontendState* fe,
CfreeObjBuilder* out);
static void asm_frontend_free(CfreeFrontendState* fe);
-static const char* const asm_extensions[] = {"s", NULL};
+static const CfreeSlice asm_extensions[] = {CFREE_SLICE_LIT("s")};
const CfreeFrontendVTable cfree_asm_frontend_vtable = {
asm_frontend_new,
asm_frontend_compile,
asm_frontend_free,
asm_extensions,
+ (uint32_t)(sizeof asm_extensions / sizeof asm_extensions[0]),
};
static SrcLoc no_loc(void) {
@@ -56,26 +58,31 @@ static SrcLoc no_loc(void) {
}
static _Noreturn void panic_bad_options(Compiler* c, const char* msg) {
- compiler_panic(c, no_loc(), "bad cfree options: %s", msg);
+ compiler_panic(c, no_loc(), "bad cfree options: %.*s",
+ SLICE_ARG(slice_from_cstr(msg)));
}
/* Compare `ext` to `pat` letter-for-letter, lowercasing ASCII A-Z in
- * the path side so `.S` matches asm's `"s"` entry. Both inputs are
- * NUL-terminated; returns nonzero on full match. */
-static int ext_eq_ci(const char* ext, const char* pat) {
- while (*ext && *pat) {
- char a = *ext++;
- char b = *pat++;
+ * the path side so `.S` matches asm's `"s"` entry. `ext` is a borrowed
+ * slice over the path tail; `pat` is the frontend's extension slice.
+ * Returns nonzero on full match. */
+static int ext_eq_ci(CfreeSlice ext, CfreeSlice pat) {
+ size_t i;
+ if (ext.len != pat.len) return 0;
+ for (i = 0; i < ext.len; ++i) {
+ char a = ext.s[i];
+ char b = pat.s[i];
if (a >= 'A' && a <= 'Z') a = (char)(a - 'A' + 'a');
if (a != b) return 0;
}
- return *ext == 0 && *pat == 0;
+ return 1;
}
CfreeLanguage cfree_language_for_path(CfreeCompiler* c, const char* path) {
size_t len;
size_t i;
- const char* ext;
+ CfreeSlice ext = SLICE_NULL;
+ int have_ext = 0;
unsigned lang;
if (!c || !path) return CFREE_LANG_C;
@@ -83,24 +90,25 @@ CfreeLanguage cfree_language_for_path(CfreeCompiler* c, const char* path) {
}
/* Strip back to the last `.` after the final `/`. No dot → no
* extension → fall through to the C default. */
- ext = NULL;
i = len;
while (i > 0) {
--i;
if (path[i] == '/') break;
if (path[i] == '.') {
- ext = path + i + 1;
+ ext.s = path + i + 1;
+ ext.len = len - (i + 1);
+ have_ext = 1;
break;
}
}
- if (!ext) return CFREE_LANG_C;
+ if (!have_ext) return CFREE_LANG_C;
for (lang = 0; lang < CFREE_LANG_COUNT; ++lang) {
const CfreeFrontendVTable* v = c->frontends[lang];
- const char* const* exts;
+ uint32_t e;
if (!v || !v->extensions) continue;
- for (exts = v->extensions; *exts; ++exts) {
- if (ext_eq_ci(ext, *exts)) return (CfreeLanguage)lang;
+ for (e = 0; e < v->nextensions; ++e) {
+ if (ext_eq_ci(ext, v->extensions[e])) return (CfreeLanguage)lang;
}
}
return CFREE_LANG_C;
@@ -130,9 +138,9 @@ uint32_t cfree_compiler_arch_predefines(CfreeCompiler* c,
return arch->npredefined_macros;
}
-static void validate_bytes(Compiler* c, const CfreeBytes* in) {
- if (!in->name) panic_bad_options(c, "input name is NULL");
- if (!in->data && in->len != 0) {
+static void validate_bytes(Compiler* c, const CfreeSourceInput* in) {
+ if (!in->name.s) panic_bad_options(c, "input name is NULL");
+ if (!in->bytes.data && in->bytes.len != 0) {
panic_bad_options(c, "input data is NULL but len > 0");
}
}
@@ -143,7 +151,7 @@ static const CfreeFrontendVTable* frontend_for_language(Compiler* c,
return c->frontends[lang];
}
-static void validate_bytes(Compiler* c, const CfreeBytes* in);
+static void validate_bytes(Compiler* c, const CfreeSourceInput* in);
static void compile_frontend_state_into(Compiler* c,
const CfreeFrontendVTable* vtable,
CfreeFrontendState* frontend,
@@ -198,7 +206,7 @@ static CfreeStatus cfree_frontend_compile(
compiler_panic_restore(c, &saved);
return CFREE_ERR;
}
- validate_bytes(c, &input->bytes);
+ validate_bytes(c, input);
metrics_scope_begin(c, "compile.tu");
metrics_count(c, "compile.input_bytes", (u64)input->bytes.len);
compile_frontend_state_into(c, frontend->vtable, frontend->state, opts, input,
@@ -293,8 +301,8 @@ static void compile_frontend_state_into(Compiler* c,
st = vtable->compile(frontend, opts, input, ob);
metrics_scope_end(c, "compile.frontend");
if (st != CFREE_OK) {
- compiler_panic(c, no_loc(), "frontend failed for input: %s",
- input->bytes.name);
+ compiler_panic(c, no_loc(), "frontend failed for input: %.*s",
+ SLICE_ARG(input->name));
}
metrics_scope_begin(c, "compile.obj_finalize");
@@ -331,8 +339,7 @@ static CfreeStatus asm_frontend_compile(CfreeFrontendState* frontend,
if (!fe || !fe->c || !input || !out) return CFREE_INVALID;
c = fe->c;
metrics_scope_begin(c, "compile.asm.lex_open");
- lex = asm_lex_open_mem(c, input->bytes.name, (const char*)input->bytes.data,
- input->bytes.len);
+ lex = asm_lex_open_mem(c, input->name.s, input->bytes.s, input->bytes.len);
metrics_scope_end(c, "compile.asm.lex_open");
metrics_scope_begin(c, "compile.asm.mc_new");
mc = mc_new(c, (ObjBuilder*)out);
@@ -387,9 +394,9 @@ CfreeIterResult cfree_dep_iter_next(CfreeDepIter* it, CfreeDepEdge* out) {
includer = source_file(it->c->sources, edge->includer_file_id);
included = source_file(it->c->sources, edge->included_file_id);
out->includer_name =
- includer ? pool_str(it->c->global, includer->name, NULL) : NULL;
+ includer ? pool_slice(it->c->global, includer->name) : CFREE_SLICE_NULL;
out->included_name =
- included ? pool_str(it->c->global, included->name, NULL) : NULL;
+ included ? pool_slice(it->c->global, included->name) : CFREE_SLICE_NULL;
out->include_loc = edge->include_loc;
out->from_system_path = (uint8_t)(edge->system ? 1 : 0);
out->bracketed = (uint8_t)(edge->system ? 1 : 0);
diff --git a/src/api/core.c b/src/api/core.c
@@ -7,6 +7,7 @@
#include "core/heap.h"
#include "core/pool.h"
+#include "core/slice.h"
CfreeStatus cfree_compiler_new(CfreeTarget target, const CfreeContext* ctx,
CfreeCompiler** out) {
@@ -42,30 +43,22 @@ const CfreeContext* cfree_compiler_context(CfreeCompiler* c) {
return (c && c->ctx) ? c->ctx : NULL;
}
-const char* cfree_compiler_file_name(CfreeCompiler* c, uint32_t file_id) {
+CfreeSlice cfree_compiler_file_name(CfreeCompiler* c, uint32_t file_id) {
const SourceFile* f;
- if (!c) return NULL;
+ if (!c) return SLICE_NULL;
f = source_file(c->sources, file_id);
- if (!f) return NULL;
- return pool_str(c->global, f->name, NULL);
+ if (!f) return SLICE_NULL;
+ return pool_slice(c->global, f->name);
}
-CfreeSym cfree_sym_intern(CfreeCompiler* c, const char* str) {
- if (!c || !str) return 0;
- return pool_intern_cstr(c->global, str);
+CfreeSym cfree_sym_intern(CfreeCompiler* c, CfreeSlice s) {
+ if (!c) return 0;
+ return pool_intern_slice(c->global, s);
}
-CfreeSym cfree_sym_intern_len(CfreeCompiler* c, const char* str, size_t len) {
- if (!c || !str || len == 0) return 0;
- return pool_intern(c->global, str, (u32)len);
-}
-
-const char* cfree_sym_str(CfreeCompiler* c, CfreeSym sym, size_t* len_out) {
- if (!c) {
- if (len_out) *len_out = 0;
- return NULL;
- }
- return pool_str(c->global, (Sym)sym, len_out);
+CfreeSlice cfree_sym_str(CfreeCompiler* c, CfreeSym sym) {
+ if (!c) return SLICE_NULL;
+ return pool_slice(c->global, (Sym)sym);
}
CfreeSym cfree_cg_c_linkage_name(CfreeCompiler* c, CfreeSym source_name) {
@@ -74,9 +67,12 @@ CfreeSym cfree_cg_c_linkage_name(CfreeCompiler* c, CfreeSym source_name) {
char* buf;
CfreeSym out;
Heap* h;
+ Slice nslice;
if (!c || !source_name) return 0;
- name = pool_str(c->global, (Sym)source_name, &len);
+ nslice = pool_slice(c->global, (Sym)source_name);
+ name = nslice.s;
+ len = nslice.len;
if (!name) return 0;
if (c->target.obj != CFREE_OBJ_MACHO) return source_name;
@@ -86,7 +82,7 @@ CfreeSym cfree_cg_c_linkage_name(CfreeCompiler* c, CfreeSym source_name) {
buf[0] = '_';
if (len) memcpy(buf + 1, name, len);
buf[len + 1u] = '\0';
- out = pool_intern(c->global, buf, (u32)(len + 1u));
+ out = pool_intern_slice(c->global, (Slice){ .s = buf, .len = (u32)(len + 1u) });
h->free(h, buf, len + 2u);
return out;
}
diff --git a/src/api/disasm.c b/src/api/disasm.c
@@ -9,6 +9,7 @@
#include "core/core.h"
#include "core/heap.h"
#include "core/pool.h"
+#include "core/slice.h"
#include "core/strbuf.h"
#include "obj/obj.h"
@@ -34,10 +35,10 @@ struct CfreeDisasmIter {
StrBuf ann;
};
-static const char* dasm_overlay(CfreeDisasmIter* it, uint64_t vaddr,
- uint32_t nbytes) {
+static Slice dasm_overlay(CfreeDisasmIter* it, uint64_t vaddr,
+ uint32_t nbytes) {
ObjBuilder* obj = it->annot_ob;
- if (!obj) return "";
+ if (!obj) return SLICE_LIT("");
strbuf_reset(&it->ann);
u64 want = vaddr - it->vaddr0;
@@ -55,10 +56,9 @@ static const char* dasm_overlay(CfreeDisasmIter* it, uint64_t vaddr,
: NULL;
if (sym && sym->name) {
Compiler* oc = obj_compiler(obj);
- size_t nlen = 0;
- const char* nm = oc ? pool_str(oc->global, sym->name, &nlen) : NULL;
- if (nm)
- strbuf_putn(&it->ann, nm, nlen);
+ Slice nm = oc ? pool_slice(oc->global, sym->name) : SLICE_NULL;
+ if (nm.s)
+ strbuf_putn(&it->ann, nm.s, nm.len);
else
strbuf_puts(&it->ann, "<anon>");
} else {
@@ -81,7 +81,7 @@ static const char* dasm_overlay(CfreeDisasmIter* it, uint64_t vaddr,
}
break;
}
- return strbuf_cstr(&it->ann);
+ return strbuf_slice(&it->ann);
}
static uint32_t dasm_find_section(const CfreeObjFile* f, const uint8_t* bytes,
@@ -146,9 +146,9 @@ CfreeIterResult cfree_disasm_iter_next(CfreeDisasmIter* it, CfreeInsn* out) {
out->vaddr = vaddr;
out->bytes = it->bytes + it->off;
out->nbytes = n;
- out->mnemonic = "(truncated)";
- out->operands = "";
- out->annotation = "";
+ out->mnemonic = SLICE_LIT("(truncated)");
+ out->operands = SLICE_LIT("");
+ out->annotation = SLICE_LIT("");
it->off += n;
return CFREE_ITER_ITEM;
}
@@ -167,7 +167,11 @@ void cfree_disasm_iter_free(CfreeDisasmIter* it) {
}
static CfreeStatus w_str(CfreeWriter* w, const char* s) {
- return cfree_writer_write(w, s, strlen(s));
+ return cfree_writer_write(w, s, slice_from_cstr(s).len);
+}
+
+static CfreeStatus w_slice(CfreeWriter* w, Slice s) {
+ return cfree_writer_write(w, s.s, s.len);
}
static CfreeStatus w_hex(CfreeWriter* w, u64 v, u32 width) {
@@ -205,19 +209,19 @@ static CfreeStatus w_hex_padded(CfreeWriter* w, u64 v, u32 minwidth) {
return cfree_writer_write(w, buf + i, sizeof(buf) - i);
}
-static const char* dasm_sym_at(const CfreeObjFile* f, uint32_t section_idx,
- uint64_t offset) {
+static Slice dasm_sym_at(const CfreeObjFile* f, uint32_t section_idx,
+ uint64_t offset) {
CfreeObjSymIter* si = NULL;
- const char* found = NULL;
+ Slice found = SLICE_NULL;
CfreeObjSymInfo s;
- if (cfree_obj_symiter_new((CfreeObjFile*)f, &si) != CFREE_OK) return NULL;
+ if (cfree_obj_symiter_new((CfreeObjFile*)f, &si) != CFREE_OK) return SLICE_NULL;
for (;;) {
CfreeIterResult r = cfree_obj_symiter_next(si, &s);
if (r != CFREE_ITER_ITEM) break;
if (s.section != section_idx) continue;
if (s.value != offset) continue;
- if (!s.name || !s.name[0]) continue;
- if (s.name[0] == '$') continue;
+ if (!s.name.len) continue;
+ if (s.name.s[0] == '$') continue;
found = s.name;
if (s.kind == CFREE_SK_FUNC) break;
}
@@ -239,7 +243,7 @@ CfreeStatus cfree_disasm_obj(const CfreeContext* ctx, const CfreeObjFile* f,
size_t n = 0;
CfreeDisasmIter* it = NULL;
CfreeStatus st;
- const char* head;
+ Slice head;
if (cfree_obj_section(f, i, &s) != CFREE_OK) continue;
if (s.kind != CFREE_SEC_TEXT) continue;
@@ -247,7 +251,7 @@ CfreeStatus cfree_disasm_obj(const CfreeContext* ctx, const CfreeObjFile* f,
if (!data || !n) continue;
w_str(out, "Disassembly of section ");
- w_str(out, s.name ? s.name : ".text");
+ w_slice(out, s.name.len ? s.name : SLICE_LIT(".text"));
w_str(out, ":\n\n");
st = cfree_disasm_iter_new(&dctx, data, n, 0, f, &it);
@@ -257,10 +261,10 @@ CfreeStatus cfree_disasm_obj(const CfreeContext* ctx, const CfreeObjFile* f,
CfreeIterResult r = cfree_disasm_iter_next(it, &ins);
if (r != CFREE_ITER_ITEM) break;
head = dasm_sym_at(f, i, ins.vaddr);
- if (head) {
+ if (head.len) {
w_hex(out, ins.vaddr, 16);
w_str(out, " <");
- w_str(out, head);
+ w_slice(out, head);
w_str(out, ">:\n");
}
w_hex_padded(out, ins.vaddr, 8);
@@ -278,14 +282,14 @@ CfreeStatus cfree_disasm_obj(const CfreeContext* ctx, const CfreeObjFile* f,
}
w_str(out, " \t");
}
- w_str(out, ins.mnemonic ? ins.mnemonic : "");
- if (ins.operands && ins.operands[0]) {
+ w_slice(out, ins.mnemonic);
+ if (ins.operands.len) {
w_str(out, "\t");
- w_str(out, ins.operands);
+ w_slice(out, ins.operands);
}
- if (ins.annotation && ins.annotation[0]) {
+ if (ins.annotation.len) {
w_str(out, " ; ");
- w_str(out, ins.annotation);
+ w_slice(out, ins.annotation);
}
w_str(out, "\n");
}
@@ -295,11 +299,11 @@ CfreeStatus cfree_disasm_obj(const CfreeContext* ctx, const CfreeObjFile* f,
}
CfreeStatus cfree_disasm_obj_bytes(const CfreeContext* ctx,
- const CfreeBytes* bytes, CfreeWriter* out) {
+ const CfreeSlice* bytes, CfreeWriter* out) {
CfreeObjFile* f = NULL;
CfreeStatus st;
if (!ctx || !bytes || !out) return CFREE_INVALID;
- st = cfree_obj_open(ctx, bytes, &f);
+ st = cfree_obj_open(ctx, SLICE_NULL, bytes, &f);
if (st != CFREE_OK) return st;
st = cfree_disasm_obj(ctx, f, out);
cfree_obj_free(f);
diff --git a/src/api/link.c b/src/api/link.c
@@ -129,7 +129,7 @@ CfreeStatus cfree_link_session_new(CfreeCompiler* c,
link_set_jit_host(l, opts->jit_host);
link_set_jit_mode(l, 1);
link_set_gc_sections(l, opts->gc_sections);
- if (!opts->entry) link_clear_entry(l);
+ if (!opts->entry.s || opts->entry.len == 0) link_clear_entry(l);
if (opts->extern_resolver) {
link_set_extern_resolver(l, opts->extern_resolver,
opts->extern_resolver_user);
@@ -137,11 +137,12 @@ CfreeStatus cfree_link_session_new(CfreeCompiler* c,
break;
}
if (opts->linker_script) link_set_script(l, opts->linker_script);
- if (opts->entry) {
+ if (opts->entry.s && opts->entry.len) {
link_set_entry(l, opts->entry);
} else if (opts->pe_subsystem == CFREE_PE_SUBSYSTEM_WINDOWS_GUI &&
- !(opts->linker_script && opts->linker_script->entry)) {
- link_set_entry(l, "WinMainCRTStartup");
+ !(opts->linker_script && opts->linker_script->entry.s &&
+ opts->linker_script->entry.len)) {
+ link_set_entry(l, CFREE_SLICE_LIT("WinMainCRTStartup"));
}
(void)opts->build_id_mode;
(void)opts->build_id_bytes;
@@ -171,19 +172,22 @@ CfreeStatus cfree_link_session_add_obj(CfreeLinkSession* s,
}
typedef struct LinkAddBytesArg {
- const CfreeBytes* bytes;
+ CfreeSlice name;
+ const CfreeSlice* bytes;
const CfreeLinkArchiveInput* archive;
} LinkAddBytesArg;
static void link_session_add_obj_bytes_inner(CfreeLinkSession* s, void* arg) {
- const CfreeBytes* b = ((LinkAddBytesArg*)arg)->bytes;
- link_add_obj_bytes(s->linker, b->name, b->data, b->len);
+ LinkAddBytesArg* a = (LinkAddBytesArg*)arg;
+ link_add_obj_bytes(s->linker, a->name.s, a->bytes->data, a->bytes->len);
}
CfreeStatus cfree_link_session_add_obj_bytes(CfreeLinkSession* s,
- const CfreeBytes* bytes) {
+ CfreeSlice name,
+ const CfreeSlice* bytes) {
LinkAddBytesArg arg;
if (!s || !bytes || s->resolved) return CFREE_INVALID;
+ arg.name = name;
arg.bytes = bytes;
arg.archive = NULL;
s->non_obj_inputs++;
@@ -193,7 +197,7 @@ CfreeStatus cfree_link_session_add_obj_bytes(CfreeLinkSession* s,
static void link_session_add_archive_bytes_inner(CfreeLinkSession* s,
void* arg) {
const CfreeLinkArchiveInput* a = ((LinkAddBytesArg*)arg)->archive;
- link_add_archive_bytes(s->linker, a->bytes.name, a->bytes.data, a->bytes.len,
+ link_add_archive_bytes(s->linker, a->name.s, a->bytes.data, a->bytes.len,
a->whole_archive, a->link_mode, a->group_id);
}
@@ -208,14 +212,16 @@ CfreeStatus cfree_link_session_add_archive_bytes(
}
static void link_session_add_dso_bytes_inner(CfreeLinkSession* s, void* arg) {
- const CfreeBytes* b = ((LinkAddBytesArg*)arg)->bytes;
- link_add_dso_bytes(s->linker, b->name, b->data, b->len);
+ LinkAddBytesArg* a = (LinkAddBytesArg*)arg;
+ link_add_dso_bytes(s->linker, a->name.s, a->bytes->data, a->bytes->len);
}
CfreeStatus cfree_link_session_add_dso_bytes(CfreeLinkSession* s,
- const CfreeBytes* bytes) {
+ CfreeSlice name,
+ const CfreeSlice* bytes) {
LinkAddBytesArg arg;
if (!s || !bytes || s->resolved) return CFREE_INVALID;
+ arg.name = name;
arg.bytes = bytes;
arg.archive = NULL;
s->non_obj_inputs++;
diff --git a/src/api/object_file.c b/src/api/object_file.c
@@ -9,6 +9,7 @@
#include "core/core.h"
#include "core/heap.h"
#include "core/pool.h"
+#include "core/slice.h"
#include "obj/obj.h"
struct CfreeObjFile {
@@ -37,8 +38,8 @@ static ObjBuilder* obj_read_bytes(Compiler* c, const char* name, const u8* data,
return NULL;
}
-CfreeStatus cfree_obj_open(const CfreeContext* ctx, const CfreeBytes* input,
- CfreeObjFile** out) {
+CfreeStatus cfree_obj_open(const CfreeContext* ctx, CfreeSlice name,
+ const CfreeSlice* input, CfreeObjFile** out) {
Heap* h;
CfreeObjFile* f;
CfreeTarget target;
@@ -67,7 +68,7 @@ CfreeStatus cfree_obj_open(const CfreeContext* ctx, const CfreeBytes* input,
h->free(h, f, sizeof(*f));
return CFREE_MALFORMED;
}
- f->ob = obj_read_bytes(&f->compiler, input->name, input->data, input->len,
+ f->ob = obj_read_bytes(&f->compiler, name.s, input->data, input->len,
target.obj);
if (!f->ob) {
compiler_fini(&f->compiler);
@@ -112,7 +113,8 @@ CfreeStatus cfree_obj_section(const CfreeObjFile* f, CfreeObjSection idx,
if (idx >= obj_section_count(f->ob)) return CFREE_NOT_FOUND;
sec = obj_section_get(f->ob, (ObjSecId)(idx + 1));
if (!sec) return CFREE_NOT_FOUND;
- out->name = sec->name ? pool_str(f->compiler.global, sec->name, NULL) : "";
+ out->name = sec->name ? pool_slice(f->compiler.global, sec->name)
+ : SLICE_LIT("");
out->kind = (CfreeSecKind)sec->kind;
out->flags = (uint32_t)sec->flags;
out->size = sec->bss_size ? sec->bss_size : sec->bytes.total;
@@ -193,17 +195,15 @@ CfreeStatus cfree_obj_section_format_flags(const CfreeObjFile* f,
return CFREE_OK;
}
-CfreeStatus cfree_obj_section_by_name(const CfreeObjFile* f, const char* name,
+CfreeStatus cfree_obj_section_by_name(const CfreeObjFile* f, CfreeSlice name,
CfreeObjSection* out) {
u32 n, i;
- if (!f || !name || !out) return CFREE_INVALID;
+ if (!f || !out) return CFREE_INVALID;
n = obj_section_count(f->ob);
for (i = 0; i < n; ++i) {
const Section* sec = obj_section_get(f->ob, (ObjSecId)(i + 1));
- const char* sn;
if (!sec || !sec->name) continue;
- sn = pool_str(f->compiler.global, sec->name, NULL);
- if (sn && strcmp(sn, name) == 0) {
+ if (slice_eq(pool_slice(f->compiler.global, sec->name), name)) {
*out = i;
return CFREE_OK;
}
@@ -213,7 +213,8 @@ CfreeStatus cfree_obj_section_by_name(const CfreeObjFile* f, const char* name,
static void fill_syminfo(const CfreeObjFile* f, ObjSymId id, const ObjSym* sym,
CfreeObjSymInfo* out) {
- out->name = sym->name ? pool_str(f->compiler.global, sym->name, NULL) : "";
+ out->name = sym->name ? pool_slice(f->compiler.global, sym->name)
+ : SLICE_LIT("");
out->id = (id != OBJ_SYM_NONE) ? (CfreeObjSymbol)id : CFREE_OBJ_SYMBOL_NONE;
out->bind = (CfreeSymBind)sym->bind;
out->kind = (CfreeSymKind)sym->kind;
@@ -224,18 +225,16 @@ static void fill_syminfo(const CfreeObjFile* f, ObjSymId id, const ObjSym* sym,
out->size = sym->size;
}
-CfreeStatus cfree_obj_symbol_by_name(const CfreeObjFile* f, const char* name,
+CfreeStatus cfree_obj_symbol_by_name(const CfreeObjFile* f, CfreeSlice name,
CfreeObjSymInfo* out) {
ObjSymIter* it;
ObjSymEntry e;
- if (!f || !name || !out) return CFREE_INVALID;
+ if (!f || !out) return CFREE_INVALID;
it = obj_symiter_new(f->ob);
if (!it) return CFREE_NOMEM;
while (obj_symiter_next(it, &e)) {
- const char* nm;
if (!e.sym || !e.sym->name) continue;
- nm = pool_str(f->compiler.global, e.sym->name, NULL);
- if (nm && strcmp(nm, name) == 0) {
+ if (slice_eq(pool_slice(f->compiler.global, e.sym->name), name)) {
fill_syminfo(f, e.id, e.sym, out);
obj_symiter_free(it);
return CFREE_OK;
@@ -384,18 +383,24 @@ CfreeIterResult cfree_obj_reliter_next(CfreeObjRelocIter* it,
out->kind.arch = it->file->target.arch;
out->kind.obj_fmt = it->file->fmt;
out->kind.code = (uint32_t)r->kind;
- out->kind_name = cfree_obj_reloc_kind_name(it->file->target.arch,
- it->file->fmt, r->kind);
+ {
+ /* Prefer the format-specific canonical spelling (e.g. "R_X86_64_PLT32");
+ * fall back to the arch-neutral diagnostic spelling ("RV_CALL"). */
+ const char* kn = cfree_obj_reloc_kind_name(it->file->target.arch,
+ it->file->fmt, r->kind);
+ if (!kn) kn = reloc_kind_name(r->kind);
+ out->kind_name = kn ? slice_from_cstr(kn) : SLICE_NULL;
+ }
if (r->sym == OBJ_SYM_NONE) {
out->sym = CFREE_OBJ_SYMBOL_NONE;
- out->sym_name = "";
+ out->sym_name = SLICE_LIT("");
} else {
out->sym = (CfreeObjSymbol)r->sym;
sym = obj_symbol_get(it->file->ob, r->sym);
out->sym_name = (sym && sym->name)
- ? pool_str(it->file->compiler.global, sym->name, NULL)
- : "";
+ ? pool_slice(it->file->compiler.global, sym->name)
+ : SLICE_LIT("");
}
return CFREE_ITER_ITEM;
}
@@ -458,8 +463,8 @@ CfreeIterResult cfree_obj_groupiter_next(CfreeObjGroupIter* it,
: CFREE_SECTION_NONE;
}
out->name = entry.group->name
- ? pool_str(it->file->compiler.global, entry.group->name, NULL)
- : "";
+ ? pool_slice(it->file->compiler.global, entry.group->name)
+ : CFREE_SLICE_NULL;
out->signature = (entry.group->signature != OBJ_SYM_NONE)
? (CfreeObjSymbol)entry.group->signature
: CFREE_OBJ_SYMBOL_NONE;
diff --git a/src/api/source.c b/src/api/source.c
@@ -17,7 +17,7 @@ CfreeStatus cfree_source_add_file(CfreeCompiler* c, const char* path,
return CFREE_OK;
}
-CfreeStatus cfree_source_add_memory(CfreeCompiler* c, const char* name,
+CfreeStatus cfree_source_add_memory(CfreeCompiler* c, CfreeSlice name,
uint32_t* file_id_out) {
uint32_t tmp;
CfreeStatus st;
@@ -28,7 +28,7 @@ CfreeStatus cfree_source_add_memory(CfreeCompiler* c, const char* name,
return CFREE_OK;
}
-CfreeStatus cfree_source_add_builtin(CfreeCompiler* c, const char* name,
+CfreeStatus cfree_source_add_builtin(CfreeCompiler* c, CfreeSlice name,
uint32_t* file_id_out) {
uint32_t tmp;
CfreeStatus st;
diff --git a/src/api/stubs.c b/src/api/stubs.c
@@ -1,11 +1,13 @@
/* Stub implementations for libcfree subsystems not yet implemented. */
#include "core/core.h"
+#include "core/slice.h"
#include "obj/obj.h"
static _Noreturn void unimplemented(Compiler* c, const char* what) {
SrcLoc loc = {0, 0, 0};
- compiler_panic(c, loc, "subsystem not implemented: %s", what);
+ compiler_panic(c, loc, "subsystem not implemented: %.*s",
+ SLICE_ARG(slice_from_cstr(what)));
}
/* WASM emit/read remain stubs until those writers/readers land.
diff --git a/src/arch/aa64/alloc.c b/src/arch/aa64/alloc.c
@@ -20,13 +20,12 @@ AASlot* aa64_slot_get(AAImpl* a, FrameSlot fs) {
static int aa_resolve_reg_name(CGTarget* t, Sym name, Reg* out,
RegClass* cls_out) {
(void)t;
- size_t len = 0;
- const char* s = pool_str(t->c->global, name, &len);
- if (!s || !len) return 1;
+ Slice ns = pool_slice(t->c->global, name);
+ if (!ns.s || !ns.len) return 1;
char buf[8];
- if (len >= sizeof buf) return 1;
- memcpy(buf, s, len);
- buf[len] = '\0';
+ if (ns.len >= sizeof buf) return 1;
+ memcpy(buf, ns.s, ns.len);
+ buf[ns.len] = '\0';
u32 dwarf;
if (aa64_register_index(buf, &dwarf) != 0) return 1;
if (dwarf <= 30u) {
diff --git a/src/arch/aa64/arch.c b/src/arch/aa64/arch.c
@@ -29,8 +29,12 @@ static const ABIVtable* aa64_abi_vtable(Compiler* c, CfreeOSKind os) {
}
static int aa64_register_at_public(uint32_t idx, CfreeArchReg* out) {
+ const char* nm = NULL;
+ int rc;
if (!out) return 1;
- return aa64_register_iter_get(idx, &out->dwarf_idx, &out->name);
+ rc = aa64_register_iter_get(idx, &out->dwarf_idx, &nm);
+ if (rc == 0) out->name = cfree_slice_cstr(nm);
+ return rc;
}
static void aa64_wr_u64_target(Compiler* c, u8* p, u64 v) {
@@ -158,15 +162,15 @@ static CGTarget* aa64_backend_make(Compiler* c, ObjBuilder* o,
}
static const CfreePredefinedMacro aa64_predefined_macros[] = {
- {"__aarch64__", "1"},
- {"__AARCH64EL__", "1"},
- {"__arm64", "1"},
- {"__arm64__", "1"},
- {"__LP64__", "1"},
- {"__ORDER_LITTLE_ENDIAN__", "1234"},
- {"__ORDER_BIG_ENDIAN__", "4321"},
- {"__BYTE_ORDER__", "__ORDER_LITTLE_ENDIAN__"},
- {"__LITTLE_ENDIAN__", "1"},
+ {CFREE_SLICE_LIT("__aarch64__"), CFREE_SLICE_LIT("1")},
+ {CFREE_SLICE_LIT("__AARCH64EL__"), CFREE_SLICE_LIT("1")},
+ {CFREE_SLICE_LIT("__arm64"), CFREE_SLICE_LIT("1")},
+ {CFREE_SLICE_LIT("__arm64__"), CFREE_SLICE_LIT("1")},
+ {CFREE_SLICE_LIT("__LP64__"), CFREE_SLICE_LIT("1")},
+ {CFREE_SLICE_LIT("__ORDER_LITTLE_ENDIAN__"), CFREE_SLICE_LIT("1234")},
+ {CFREE_SLICE_LIT("__ORDER_BIG_ENDIAN__"), CFREE_SLICE_LIT("4321")},
+ {CFREE_SLICE_LIT("__BYTE_ORDER__"), CFREE_SLICE_LIT("__ORDER_LITTLE_ENDIAN__")},
+ {CFREE_SLICE_LIT("__LITTLE_ENDIAN__"), CFREE_SLICE_LIT("1")},
};
const ArchImpl arch_impl_aa64 = {
diff --git a/src/arch/aa64/asm.c b/src/arch/aa64/asm.c
@@ -22,6 +22,7 @@
#include "arch/arch.h"
#include "core/arena.h"
#include "core/pool.h"
+#include "core/slice.h"
#include "core/strbuf.h"
#include "asm/asm_lex.h"
#include "obj/obj.h"
@@ -123,8 +124,9 @@ typedef struct AA64Reg {
} AA64Reg;
static int parse_reg_from_ident(AsmDriver* d, Sym ident, AA64Reg* out) {
- size_t n = 0;
- const char* p = pool_str(asm_driver_pool(d), ident, &n);
+ Slice sl = pool_slice(asm_driver_pool(d), ident);
+ const char* p = sl.s;
+ size_t n = sl.len;
if (!p || !n) return 0;
/* "sp" */
if (icase_eq(p, n, "sp")) {
@@ -204,8 +206,9 @@ static int parse_reg_from_ident(AsmDriver* d, Sym ident, AA64Reg* out) {
static int parse_fp_pair_reg_from_ident(AsmDriver* d, Sym ident,
AA64Reg* out) {
- size_t n = 0;
- const char* p = pool_str(asm_driver_pool(d), ident, &n);
+ Slice sl = pool_slice(asm_driver_pool(d), ident);
+ const char* p = sl.s;
+ size_t n = sl.len;
if (!p || n < 2 ||
(p[0] != 'd' && p[0] != 'D' && p[0] != 'q' && p[0] != 'Q'))
return 0;
@@ -246,13 +249,15 @@ static AA64Reg parse_ldstp_reg(AsmDriver* d) {
}
static void reject_sp_reg(AsmDriver* d, AA64Reg r, const char* what) {
- if (r.is_sp) asm_driver_panic(d, "asm: %s: SP register not allowed", what);
+ if (r.is_sp)
+ asm_driver_panic(d, "asm: %.*s: SP register not allowed",
+ SLICE_ARG(slice_from_cstr(what)));
}
static void require_sp_spelling(AsmDriver* d, AA64Reg r, const char* what) {
if (r.num == 31u && !r.is_sp)
- asm_driver_panic(d, "asm: %s: zero register not allowed in SP operand",
- what);
+ asm_driver_panic(d, "asm: %.*s: zero register not allowed in SP operand",
+ SLICE_ARG(slice_from_cstr(what)));
}
/* Parse "#imm" (with optional + / -) or a bare expression — GNU as is
@@ -280,8 +285,9 @@ static void emit32(AsmDriver* d, u32 word) {
}
static int parse_cond_from_ident(AsmDriver* d, Sym ident, u32* out) {
- size_t n = 0;
- const char* s = pool_str(asm_driver_pool(d), ident, &n);
+ Slice sl = pool_slice(asm_driver_pool(d), ident);
+ const char* s = sl.s;
+ size_t n = sl.len;
if (!s) return 0;
if (icase_eq(s, n, "eq")) *out = 0;
else if (icase_eq(s, n, "ne")) *out = 1;
@@ -306,13 +312,15 @@ static u32 parse_cond(AsmDriver* d, const char* what) {
AsmTok t = asm_driver_next(d);
u32 cond = 0;
if (t.kind != ASM_TOK_IDENT || !parse_cond_from_ident(d, t.v.ident, &cond))
- asm_driver_panic(d, "asm: %s: expected condition code", what);
+ asm_driver_panic(d, "asm: %.*s: expected condition code",
+ SLICE_ARG(slice_from_cstr(what)));
return cond;
}
static void expect_comma(AsmDriver* d, const char* what) {
if (!asm_driver_eat_comma(d))
- asm_driver_panic(d, "asm: expected ',' (%s)", what);
+ asm_driver_panic(d, "asm: expected ',' (%.*s)",
+ SLICE_ARG(slice_from_cstr(what)));
}
/* ---- per-mnemonic parsers ---- */
@@ -358,8 +366,9 @@ static u32 parse_barrier_option(AsmDriver* d, int allow_dmb_ld_st) {
AsmTok t = asm_driver_peek(d);
if (t.kind == ASM_TOK_IDENT) {
(void)asm_driver_next(d);
- size_t n = 0;
- const char* s = pool_str(asm_driver_pool(d), t.v.ident, &n);
+ Slice sl = pool_slice(asm_driver_pool(d), t.v.ident);
+ const char* s = sl.s;
+ size_t n = sl.len;
if (icase_eq(s, n, "sy")) return AA64_BARRIER_OPT_SY;
if (icase_eq(s, n, "ish")) return AA64_BARRIER_OPT_ISH;
if (icase_eq(s, n, "ishld")) return AA64_BARRIER_OPT_ISHLD;
@@ -480,8 +489,9 @@ static void p_movwide(AsmDriver* d, u32 opc) {
AsmTok lid = asm_driver_next(d);
if (lid.kind != ASM_TOK_IDENT)
asm_driver_panic(d, "asm: expected 'lsl'");
- size_t ln = 0;
- const char* lp = pool_str(asm_driver_pool(d), lid.v.ident, &ln);
+ Slice lsl = pool_slice(asm_driver_pool(d), lid.v.ident);
+ const char* lp = lsl.s;
+ size_t ln = lsl.len;
if (!lp || !icase_eq(lp, ln, "lsl"))
asm_driver_panic(d, "asm: expected 'lsl'");
i64 sh = parse_imm_const(d);
@@ -517,8 +527,9 @@ static void p_except(AsmDriver* d, u32 form) {
static int parse_shift_mod(AsmDriver* d, u32* shift_out, u32* imm6_out) {
AsmTok t = asm_driver_peek(d);
if (t.kind != ASM_TOK_IDENT) return 0;
- size_t n = 0;
- const char* p = pool_str(asm_driver_pool(d), t.v.ident, &n);
+ Slice sl = pool_slice(asm_driver_pool(d), t.v.ident);
+ const char* p = sl.s;
+ size_t n = sl.len;
u32 sh;
if (icase_eq(p, n, "lsl")) sh = 0;
else if (icase_eq(p, n, "lsr")) sh = 1;
@@ -563,8 +574,9 @@ static void p_addsub(AsmDriver* d, int is_sub, int set_flags) {
AsmTok lid = asm_driver_next(d);
if (lid.kind != ASM_TOK_IDENT)
asm_driver_panic(d, "asm: expected 'lsl #12'");
- size_t ln = 0;
- const char* lp = pool_str(asm_driver_pool(d), lid.v.ident, &ln);
+ Slice lsl = pool_slice(asm_driver_pool(d), lid.v.ident);
+ const char* lp = lsl.s;
+ size_t ln = lsl.len;
if (!lp || !icase_eq(lp, ln, "lsl"))
asm_driver_panic(d, "asm: expected 'lsl'");
i64 s = parse_imm_const(d);
@@ -611,11 +623,11 @@ static void p_cmp(AsmDriver* d, int is_neg /* cmn flips op */) {
u32 sh = 0;
if (asm_driver_eat_comma(d)) {
AsmTok lid = asm_driver_next(d);
- size_t ln = 0;
- const char* lp =
- (lid.kind == ASM_TOK_IDENT)
- ? pool_str(asm_driver_pool(d), lid.v.ident, &ln)
- : NULL;
+ Slice lsl = (lid.kind == ASM_TOK_IDENT)
+ ? pool_slice(asm_driver_pool(d), lid.v.ident)
+ : SLICE_NULL;
+ const char* lp = lsl.s;
+ size_t ln = lsl.len;
if (!lp || !icase_eq(lp, ln, "lsl"))
asm_driver_panic(d, "asm: cmp imm: expected 'lsl'");
i64 s = parse_imm_const(d);
@@ -653,9 +665,11 @@ static void p_condsel(AsmDriver* d, u32 op, u32 op2, const char* what) {
expect_comma(d, what);
u32 cond = parse_cond(d, what);
if (rd.is_sp || rn.is_sp || rm.is_sp)
- asm_driver_panic(d, "asm: %s: SP register not allowed", what);
+ asm_driver_panic(d, "asm: %.*s: SP register not allowed",
+ SLICE_ARG(slice_from_cstr(what)));
if (rd.is64 != rn.is64 || rd.is64 != rm.is64)
- asm_driver_panic(d, "asm: %s: width mismatch", what);
+ asm_driver_panic(d, "asm: %.*s: width mismatch",
+ SLICE_ARG(slice_from_cstr(what)));
u32 word = aa64_condsel_pack((AA64CondSel){.sf = (u32)rd.is64,
.op = op,
.S = 0,
@@ -671,7 +685,9 @@ static void p_cset_like(AsmDriver* d, u32 op, u32 op2, const char* what) {
AA64Reg rd = parse_reg(d);
expect_comma(d, what);
u32 cond = parse_cond(d, what);
- if (rd.is_sp) asm_driver_panic(d, "asm: %s: SP register not allowed", what);
+ if (rd.is_sp)
+ asm_driver_panic(d, "asm: %.*s: SP register not allowed",
+ SLICE_ARG(slice_from_cstr(what)));
u32 word = aa64_condsel_pack((AA64CondSel){.sf = (u32)rd.is64,
.op = op,
.S = 0,
@@ -1119,8 +1135,9 @@ static const AA64Mn kTable[] = {
void aa64_asm_insn(AA64Asm* a, AsmDriver* d, Sym mnemonic) {
(void)a;
- size_t mn = 0;
- const char* mp = pool_str(asm_driver_pool(d), mnemonic, &mn);
+ Slice msl = pool_slice(asm_driver_pool(d), mnemonic);
+ const char* mp = msl.s;
+ size_t mn = msl.len;
for (const AA64Mn* row = kTable; row->name; ++row) {
if (icase_eq(mp, mn, row->name)) {
row->fn(d);
@@ -1173,7 +1190,7 @@ static void render_indirect(StrBuf* sb, Reg base, i32 ofs) {
_Noreturn static void inline_panic(AA64Asm* a, const char* msg) {
SrcLoc loc = {0, 0, 0};
- compiler_panic(a->c, loc, "inline asm: %s", msg);
+ compiler_panic(a->c, loc, "inline asm: %.*s", SLICE_ARG(slice_from_cstr(msg)));
}
/* Resolve operand index N → (kind=0 forced default, 1=force-w, 2=force-x,
@@ -1265,16 +1282,19 @@ static void run_one_line(AA64Asm* a, MCEmitter* mc, const char* text,
AsmTok rest = asm_driver_next(d);
if (rest.kind != ASM_TOK_IDENT)
inline_panic(a, "composite mnemonic: expected ident after '.'");
- size_t hn = 0, rn = 0;
- const char* hp = pool_str(asm_driver_pool(d), mn, &hn);
- const char* rp = pool_str(asm_driver_pool(d), rest.v.ident, &rn);
+ Slice hsl = pool_slice(asm_driver_pool(d), mn);
+ Slice rsl = pool_slice(asm_driver_pool(d), rest.v.ident);
+ size_t hn = hsl.len, rn = rsl.len;
+ const char* hp = hsl.s;
+ const char* rp = rsl.s;
char buf[64];
if (hn + 1 + rn >= sizeof buf)
inline_panic(a, "composite mnemonic too long");
for (size_t k = 0; k < hn; ++k) buf[k] = hp[k];
buf[hn] = '.';
for (size_t k = 0; k < rn; ++k) buf[hn + 1 + k] = rp[k];
- mn = pool_intern(asm_driver_pool(d), buf, hn + 1 + rn);
+ mn = pool_intern_slice(asm_driver_pool(d),
+ (Slice){.s = buf, .len = hn + 1 + rn});
}
aa64_asm_insn(a, d, mn);
asm_driver_close_inline(d);
@@ -1312,7 +1332,8 @@ static void render_and_run_line(AA64Asm* a, MCEmitter* mc, StrBuf* sb,
while (nend < end && *nend != ']') ++nend;
if (nend == end) inline_panic(a, "unterminated %[name]");
size_t nlen = (size_t)(nend - nbeg);
- Sym needle = pool_intern(a->c->global, nbeg, nlen);
+ Sym needle = pool_intern_slice(a->c->global,
+ (Slice){.s = nbeg, .len = nlen});
u32 idx = (u32)-1;
for (u32 k = 0; k < a->nout; ++k) {
if (a->outs[k].name == needle) { idx = k; break; }
@@ -1344,7 +1365,8 @@ static void render_and_run_line(AA64Asm* a, MCEmitter* mc, StrBuf* sb,
while (nend < end && *nend != ']') ++nend;
if (nend == end) inline_panic(a, "unterminated %[name]");
size_t nlen = (size_t)(nend - nbeg);
- Sym needle = pool_intern(a->c->global, nbeg, nlen);
+ Sym needle = pool_intern_slice(a->c->global,
+ (Slice){.s = nbeg, .len = nlen});
u32 idx = (u32)-1;
for (u32 k = 0; k < a->nout; ++k) {
if (a->outs[k].name == needle) { idx = k; break; }
diff --git a/src/arch/aa64/disasm.c b/src/arch/aa64/disasm.c
@@ -51,7 +51,7 @@ static void aa64_write_mnemonic(AA64Disasm* d, const AA64InsnDesc* desc,
strbuf_puts(&d->mnem, aa64_cond_names[cond]);
return;
}
- strbuf_puts(&d->mnem, desc->mnemonic);
+ strbuf_put_slice(&d->mnem, desc->mnemonic);
}
static void aa64_write_operands(AA64Disasm* d, const AA64InsnDesc* desc,
@@ -106,9 +106,9 @@ static u32 aa64_decode(ArchDisasm* base, const u8* bytes, size_t len, u64 vaddr,
out->vaddr = vaddr;
out->bytes = bytes;
out->nbytes = 4;
- out->mnemonic = strbuf_cstr(&d->mnem);
- out->operands = strbuf_cstr(&d->ops);
- out->annotation = strbuf_cstr(&d->ann);
+ out->mnemonic = strbuf_slice(&d->mnem);
+ out->operands = strbuf_slice(&d->ops);
+ out->annotation = strbuf_slice(&d->ann);
return 4;
}
diff --git a/src/arch/aa64/isa.c b/src/arch/aa64/isa.c
@@ -22,203 +22,208 @@
#include <stddef.h>
+/* Mnemonic Slice literal for a static table row (compile-time length). */
+#define MN(s) {{(s)}, sizeof(s) - 1}
+
const AA64InsnDesc aa64_insn_table[] = {
/* ----- Move-wide immediate (MOVN / MOVZ / MOVK) ----- */
- {"movn", 0x12800000u, 0x7F800000u, AA64_FMT_MOVEWIDE, 0, {0, 0}},
- {"movz", 0x52800000u, 0x7F800000u, AA64_FMT_MOVEWIDE, 0, {0, 0}},
- {"movk", 0x72800000u, 0x7F800000u, AA64_FMT_MOVEWIDE, 0, {0, 0}},
+ {MN("movn"), 0x12800000u, 0x7F800000u, AA64_FMT_MOVEWIDE, 0, {0, 0}},
+ {MN("movz"), 0x52800000u, 0x7F800000u, AA64_FMT_MOVEWIDE, 0, {0, 0}},
+ {MN("movk"), 0x72800000u, 0x7F800000u, AA64_FMT_MOVEWIDE, 0, {0, 0}},
/* ----- Logical, shifted register -----
* Alias MOV Rd, Rm is ORR Rd, ZR, Rm with shift=0, imm6=0. The mask
* pins Rn (bits 9:5) to 11111 (ZR) and shift/imm6 to 0 so only the
* MOV spelling matches; broader ORR rows below catch the rest. */
- {"mov", 0x2A0003E0u, 0x7FE0FFE0u, AA64_FMT_LOG_SR, AA64_ASMFL_ALIAS,
+ {MN("mov"), 0x2A0003E0u, 0x7FE0FFE0u, AA64_FMT_LOG_SR, AA64_ASMFL_ALIAS,
{0, 0}},
/* MVN Rd, Rm ≡ ORN Rd, ZR, Rm (logical N=1, Rn=ZR, no shift) */
- {"mvn", 0x2A2003E0u, 0x7FE0FFE0u, AA64_FMT_LOG_SR, AA64_ASMFL_ALIAS,
+ {MN("mvn"), 0x2A2003E0u, 0x7FE0FFE0u, AA64_FMT_LOG_SR, AA64_ASMFL_ALIAS,
{0, 0}},
- {"and", 0x0A000000u, 0x7F200000u, AA64_FMT_LOG_SR, 0, {0, 0}},
- {"bic", 0x0A200000u, 0x7F200000u, AA64_FMT_LOG_SR, 0, {0, 0}},
- {"orr", 0x2A000000u, 0x7F200000u, AA64_FMT_LOG_SR, 0, {0, 0}},
- {"orn", 0x2A200000u, 0x7F200000u, AA64_FMT_LOG_SR, 0, {0, 0}},
- {"eor", 0x4A000000u, 0x7F200000u, AA64_FMT_LOG_SR, 0, {0, 0}},
- {"eon", 0x4A200000u, 0x7F200000u, AA64_FMT_LOG_SR, 0, {0, 0}},
- {"ands", 0x6A000000u, 0x7F200000u, AA64_FMT_LOG_SR, 0, {0, 0}},
- {"bics", 0x6A200000u, 0x7F200000u, AA64_FMT_LOG_SR, 0, {0, 0}},
+ {MN("and"), 0x0A000000u, 0x7F200000u, AA64_FMT_LOG_SR, 0, {0, 0}},
+ {MN("bic"), 0x0A200000u, 0x7F200000u, AA64_FMT_LOG_SR, 0, {0, 0}},
+ {MN("orr"), 0x2A000000u, 0x7F200000u, AA64_FMT_LOG_SR, 0, {0, 0}},
+ {MN("orn"), 0x2A200000u, 0x7F200000u, AA64_FMT_LOG_SR, 0, {0, 0}},
+ {MN("eor"), 0x4A000000u, 0x7F200000u, AA64_FMT_LOG_SR, 0, {0, 0}},
+ {MN("eon"), 0x4A200000u, 0x7F200000u, AA64_FMT_LOG_SR, 0, {0, 0}},
+ {MN("ands"), 0x6A000000u, 0x7F200000u, AA64_FMT_LOG_SR, 0, {0, 0}},
+ {MN("bics"), 0x6A200000u, 0x7F200000u, AA64_FMT_LOG_SR, 0, {0, 0}},
/* ----- Add/Sub, shifted register -----
* NEG Rd, Rm ≡ SUB Rd, ZR, Rm (Rn=ZR, shift=0, imm6=0). */
- {"neg", 0x4B0003E0u, 0x7FE0FFE0u, AA64_FMT_ADDSUB_SR, AA64_ASMFL_ALIAS,
+ {MN("neg"), 0x4B0003E0u, 0x7FE0FFE0u, AA64_FMT_ADDSUB_SR, AA64_ASMFL_ALIAS,
{0, 0}},
- {"negs", 0x6B0003E0u, 0x7FE0FFE0u, AA64_FMT_ADDSUB_SR, AA64_ASMFL_ALIAS,
+ {MN("negs"), 0x6B0003E0u, 0x7FE0FFE0u, AA64_FMT_ADDSUB_SR, AA64_ASMFL_ALIAS,
{0, 0}},
/* CMP Rn, Rm ≡ SUBS ZR, Rn, Rm. */
- {"cmp", 0x6B00001Fu, 0x7F20001Fu, AA64_FMT_ADDSUB_SR, AA64_ASMFL_ALIAS,
+ {MN("cmp"), 0x6B00001Fu, 0x7F20001Fu, AA64_FMT_ADDSUB_SR, AA64_ASMFL_ALIAS,
{0, 0}},
/* CMN Rn, Rm ≡ ADDS ZR, Rn, Rm. */
- {"cmn", 0x2B00001Fu, 0x7F20001Fu, AA64_FMT_ADDSUB_SR, AA64_ASMFL_ALIAS,
+ {MN("cmn"), 0x2B00001Fu, 0x7F20001Fu, AA64_FMT_ADDSUB_SR, AA64_ASMFL_ALIAS,
{0, 0}},
- {"add", 0x0B000000u, 0x7F200000u, AA64_FMT_ADDSUB_SR, 0, {0, 0}},
- {"adds", 0x2B000000u, 0x7F200000u, AA64_FMT_ADDSUB_SR, 0, {0, 0}},
- {"sub", 0x4B000000u, 0x7F200000u, AA64_FMT_ADDSUB_SR, 0, {0, 0}},
- {"subs", 0x6B000000u, 0x7F200000u, AA64_FMT_ADDSUB_SR, 0, {0, 0}},
+ {MN("add"), 0x0B000000u, 0x7F200000u, AA64_FMT_ADDSUB_SR, 0, {0, 0}},
+ {MN("adds"), 0x2B000000u, 0x7F200000u, AA64_FMT_ADDSUB_SR, 0, {0, 0}},
+ {MN("sub"), 0x4B000000u, 0x7F200000u, AA64_FMT_ADDSUB_SR, 0, {0, 0}},
+ {MN("subs"), 0x6B000000u, 0x7F200000u, AA64_FMT_ADDSUB_SR, 0, {0, 0}},
/* ----- Data-processing 3-source -----
* MUL Rd, Rn, Rm ≡ MADD Rd, Rn, Rm, ZR (Ra=ZR, op31=0, o0=0). */
- {"mul", 0x1B007C00u, 0x7FE0FC00u, AA64_FMT_DP3, AA64_ASMFL_ALIAS, {0, 0}},
+ {MN("mul"), 0x1B007C00u, 0x7FE0FC00u, AA64_FMT_DP3, AA64_ASMFL_ALIAS, {0, 0}},
/* MNEG Rd, Rn, Rm ≡ MSUB Rd, Rn, Rm, ZR. */
- {"mneg", 0x1B00FC00u, 0x7FE0FC00u, AA64_FMT_DP3, AA64_ASMFL_ALIAS, {0, 0}},
- {"madd", 0x1B000000u, 0x7FE08000u, AA64_FMT_DP3, 0, {0, 0}},
- {"msub", 0x1B008000u, 0x7FE08000u, AA64_FMT_DP3, 0, {0, 0}},
+ {MN("mneg"), 0x1B00FC00u, 0x7FE0FC00u, AA64_FMT_DP3, AA64_ASMFL_ALIAS, {0, 0}},
+ {MN("madd"), 0x1B000000u, 0x7FE08000u, AA64_FMT_DP3, 0, {0, 0}},
+ {MN("msub"), 0x1B008000u, 0x7FE08000u, AA64_FMT_DP3, 0, {0, 0}},
/* ----- Data-processing 2-source ----- */
- {"udiv", 0x1AC00800u, 0x5FE0FC00u, AA64_FMT_DP2, 0, {0, 0}},
- {"sdiv", 0x1AC00C00u, 0x5FE0FC00u, AA64_FMT_DP2, 0, {0, 0}},
- {"lslv", 0x1AC02000u, 0x5FE0FC00u, AA64_FMT_DP2, 0, {0, 0}},
- {"lsrv", 0x1AC02400u, 0x5FE0FC00u, AA64_FMT_DP2, 0, {0, 0}},
- {"asrv", 0x1AC02800u, 0x5FE0FC00u, AA64_FMT_DP2, 0, {0, 0}},
- {"rorv", 0x1AC02C00u, 0x5FE0FC00u, AA64_FMT_DP2, 0, {0, 0}},
+ {MN("udiv"), 0x1AC00800u, 0x5FE0FC00u, AA64_FMT_DP2, 0, {0, 0}},
+ {MN("sdiv"), 0x1AC00C00u, 0x5FE0FC00u, AA64_FMT_DP2, 0, {0, 0}},
+ {MN("lslv"), 0x1AC02000u, 0x5FE0FC00u, AA64_FMT_DP2, 0, {0, 0}},
+ {MN("lsrv"), 0x1AC02400u, 0x5FE0FC00u, AA64_FMT_DP2, 0, {0, 0}},
+ {MN("asrv"), 0x1AC02800u, 0x5FE0FC00u, AA64_FMT_DP2, 0, {0, 0}},
+ {MN("rorv"), 0x1AC02C00u, 0x5FE0FC00u, AA64_FMT_DP2, 0, {0, 0}},
/* ----- Conditional select -----
* CSET Rd, cond ≡ CSINC Rd, ZR, ZR, invert(cond).
* CSETM Rd, cond ≡ CSINV Rd, ZR, ZR, invert(cond).
* These aliases are expressible as fixed Rn/Rm=ZR masks, so put them
* before the canonical conditional-select rows. */
- {"cset", 0x1A9F07E0u, 0x7FE00C00u | (0x1Fu << 16) | (0x1Fu << 5),
+ {MN("cset"), 0x1A9F07E0u, 0x7FE00C00u | (0x1Fu << 16) | (0x1Fu << 5),
AA64_FMT_CONDSEL, AA64_ASMFL_ALIAS, {0, 0}},
- {"csetm", 0x5A9F03E0u, 0x7FE00C00u | (0x1Fu << 16) | (0x1Fu << 5),
+ {MN("csetm"), 0x5A9F03E0u, 0x7FE00C00u | (0x1Fu << 16) | (0x1Fu << 5),
AA64_FMT_CONDSEL, AA64_ASMFL_ALIAS, {0, 0}},
- {"csel", 0x1A800000u, 0x7FE00C00u, AA64_FMT_CONDSEL, 0, {0, 0}},
- {"csinc", 0x1A800400u, 0x7FE00C00u, AA64_FMT_CONDSEL, 0, {0, 0}},
- {"csinv", 0x5A800000u, 0x7FE00C00u, AA64_FMT_CONDSEL, 0, {0, 0}},
- {"csneg", 0x5A800400u, 0x7FE00C00u, AA64_FMT_CONDSEL, 0, {0, 0}},
+ {MN("csel"), 0x1A800000u, 0x7FE00C00u, AA64_FMT_CONDSEL, 0, {0, 0}},
+ {MN("csinc"), 0x1A800400u, 0x7FE00C00u, AA64_FMT_CONDSEL, 0, {0, 0}},
+ {MN("csinv"), 0x5A800000u, 0x7FE00C00u, AA64_FMT_CONDSEL, 0, {0, 0}},
+ {MN("csneg"), 0x5A800400u, 0x7FE00C00u, AA64_FMT_CONDSEL, 0, {0, 0}},
/* ----- Unconditional branch (register) -----
* RET aliases its no-operand spelling to RET X30 (Rn=11110). The
* tighter row matches when Rn=30 and prints "ret" without operands;
* the looser row below catches RET Xn for other Rn. */
- {"ret", 0xD65F03C0u, 0xFFFFFFFFu, AA64_FMT_BR_REG,
+ {MN("ret"), 0xD65F03C0u, 0xFFFFFFFFu, AA64_FMT_BR_REG,
AA64_ASMFL_ALIAS | AA64_ASMFL_NORN, {0, 0}},
- {"br", 0xD61F0000u, 0xFFFFFC1Fu, AA64_FMT_BR_REG, 0, {0, 0}},
- {"blr", 0xD63F0000u, 0xFFFFFC1Fu, AA64_FMT_BR_REG, 0, {0, 0}},
- {"ret", 0xD65F0000u, 0xFFFFFC1Fu, AA64_FMT_BR_REG, 0, {0, 0}},
+ {MN("br"), 0xD61F0000u, 0xFFFFFC1Fu, AA64_FMT_BR_REG, 0, {0, 0}},
+ {MN("blr"), 0xD63F0000u, 0xFFFFFC1Fu, AA64_FMT_BR_REG, 0, {0, 0}},
+ {MN("ret"), 0xD65F0000u, 0xFFFFFC1Fu, AA64_FMT_BR_REG, 0, {0, 0}},
/* ----- PC-relative addressing ----- */
- {"adr", 0x10000000u, 0x9F000000u, AA64_FMT_PCREL_ADR, 0, {0, 0}},
- {"adrp", 0x90000000u, 0x9F000000u, AA64_FMT_PCREL_ADR, 0, {0, 0}},
+ {MN("adr"), 0x10000000u, 0x9F000000u, AA64_FMT_PCREL_ADR, 0, {0, 0}},
+ {MN("adrp"), 0x90000000u, 0x9F000000u, AA64_FMT_PCREL_ADR, 0, {0, 0}},
/* ----- Add/Sub immediate -----
* CMP/CMN immediate are the Rd=ZR aliases of SUBS/ADDS immediate. */
- {"cmn", 0x3100001Fu, 0x7F00001Fu, AA64_FMT_ADDSUB_IMM, AA64_ASMFL_ALIAS,
+ {MN("cmn"), 0x3100001Fu, 0x7F00001Fu, AA64_FMT_ADDSUB_IMM, AA64_ASMFL_ALIAS,
{0, 0}},
- {"cmp", 0x7100001Fu, 0x7F00001Fu, AA64_FMT_ADDSUB_IMM, AA64_ASMFL_ALIAS,
+ {MN("cmp"), 0x7100001Fu, 0x7F00001Fu, AA64_FMT_ADDSUB_IMM, AA64_ASMFL_ALIAS,
{0, 0}},
- {"add", 0x11000000u, 0x7F000000u, AA64_FMT_ADDSUB_IMM, 0, {0, 0}},
- {"adds", 0x31000000u, 0x7F000000u, AA64_FMT_ADDSUB_IMM, 0, {0, 0}},
- {"sub", 0x51000000u, 0x7F000000u, AA64_FMT_ADDSUB_IMM, 0, {0, 0}},
- {"subs", 0x71000000u, 0x7F000000u, AA64_FMT_ADDSUB_IMM, 0, {0, 0}},
+ {MN("add"), 0x11000000u, 0x7F000000u, AA64_FMT_ADDSUB_IMM, 0, {0, 0}},
+ {MN("adds"), 0x31000000u, 0x7F000000u, AA64_FMT_ADDSUB_IMM, 0, {0, 0}},
+ {MN("sub"), 0x51000000u, 0x7F000000u, AA64_FMT_ADDSUB_IMM, 0, {0, 0}},
+ {MN("subs"), 0x71000000u, 0x7F000000u, AA64_FMT_ADDSUB_IMM, 0, {0, 0}},
/* ----- Load/store, unsigned 12-bit immediate (scaled) -----
* Mask: family bits 29:27 + 25:24 + size(31:30) + V(26) + opc(23:22). */
- {"strb", 0x39000000u, 0xFFC00000u, AA64_FMT_LDST_UIMM, 0, {0, 0}},
- {"ldrb", 0x39400000u, 0xFFC00000u, AA64_FMT_LDST_UIMM, 0, {0, 0}},
- {"strh", 0x79000000u, 0xFFC00000u, AA64_FMT_LDST_UIMM, 0, {0, 0}},
- {"ldrh", 0x79400000u, 0xFFC00000u, AA64_FMT_LDST_UIMM, 0, {0, 0}},
- {"str", 0xB9000000u, 0xFFC00000u, AA64_FMT_LDST_UIMM, 0, {0, 0}}, /* 32 */
- {"ldr", 0xB9400000u, 0xFFC00000u, AA64_FMT_LDST_UIMM, 0, {0, 0}},
- {"str", 0xF9000000u, 0xFFC00000u, AA64_FMT_LDST_UIMM, AA64_ASMFL_SF1,
+ {MN("strb"), 0x39000000u, 0xFFC00000u, AA64_FMT_LDST_UIMM, 0, {0, 0}},
+ {MN("ldrb"), 0x39400000u, 0xFFC00000u, AA64_FMT_LDST_UIMM, 0, {0, 0}},
+ {MN("strh"), 0x79000000u, 0xFFC00000u, AA64_FMT_LDST_UIMM, 0, {0, 0}},
+ {MN("ldrh"), 0x79400000u, 0xFFC00000u, AA64_FMT_LDST_UIMM, 0, {0, 0}},
+ {MN("str"), 0xB9000000u, 0xFFC00000u, AA64_FMT_LDST_UIMM, 0, {0, 0}}, /* 32 */
+ {MN("ldr"), 0xB9400000u, 0xFFC00000u, AA64_FMT_LDST_UIMM, 0, {0, 0}},
+ {MN("str"), 0xF9000000u, 0xFFC00000u, AA64_FMT_LDST_UIMM, AA64_ASMFL_SF1,
{0, 0}}, /* 64 */
- {"ldr", 0xF9400000u, 0xFFC00000u, AA64_FMT_LDST_UIMM, AA64_ASMFL_SF1,
+ {MN("ldr"), 0xF9400000u, 0xFFC00000u, AA64_FMT_LDST_UIMM, AA64_ASMFL_SF1,
{0, 0}},
/* SIMD/FP scaled loads/stores (V=1). size 0..2 select B/H/S; size=3
* selects D; the 128-bit Q form uses size=00 with opc bit 1 set and
* is not yet emitted by codegen. */
- {"str", 0x3D000000u, 0xFFC00000u, AA64_FMT_LDST_UIMM, 0, {0, 0}}, /* B */
- {"ldr", 0x3D400000u, 0xFFC00000u, AA64_FMT_LDST_UIMM, 0, {0, 0}},
- {"str", 0x7D000000u, 0xFFC00000u, AA64_FMT_LDST_UIMM, 0, {0, 0}}, /* H */
- {"ldr", 0x7D400000u, 0xFFC00000u, AA64_FMT_LDST_UIMM, 0, {0, 0}},
- {"str", 0xBD000000u, 0xFFC00000u, AA64_FMT_LDST_UIMM, 0, {0, 0}}, /* S */
- {"ldr", 0xBD400000u, 0xFFC00000u, AA64_FMT_LDST_UIMM, 0, {0, 0}},
- {"str", 0xFD000000u, 0xFFC00000u, AA64_FMT_LDST_UIMM, AA64_ASMFL_SF1,
+ {MN("str"), 0x3D000000u, 0xFFC00000u, AA64_FMT_LDST_UIMM, 0, {0, 0}}, /* B */
+ {MN("ldr"), 0x3D400000u, 0xFFC00000u, AA64_FMT_LDST_UIMM, 0, {0, 0}},
+ {MN("str"), 0x7D000000u, 0xFFC00000u, AA64_FMT_LDST_UIMM, 0, {0, 0}}, /* H */
+ {MN("ldr"), 0x7D400000u, 0xFFC00000u, AA64_FMT_LDST_UIMM, 0, {0, 0}},
+ {MN("str"), 0xBD000000u, 0xFFC00000u, AA64_FMT_LDST_UIMM, 0, {0, 0}}, /* S */
+ {MN("ldr"), 0xBD400000u, 0xFFC00000u, AA64_FMT_LDST_UIMM, 0, {0, 0}},
+ {MN("str"), 0xFD000000u, 0xFFC00000u, AA64_FMT_LDST_UIMM, AA64_ASMFL_SF1,
{0, 0}}, /* D */
- {"ldr", 0xFD400000u, 0xFFC00000u, AA64_FMT_LDST_UIMM, AA64_ASMFL_SF1,
+ {MN("ldr"), 0xFD400000u, 0xFFC00000u, AA64_FMT_LDST_UIMM, AA64_ASMFL_SF1,
{0, 0}},
/* ----- Load/store, unscaled signed 9-bit immediate (LDUR/STUR) -----
* V=0 first, V=1 next. Per-row mask narrows size+V+opc; family mask
* pins the high family bits + the SIMM9-vs-other-variant selector. */
- {"sturb", 0x38000000u, 0xFFE00C00u, AA64_FMT_LDST_SIMM9, 0, {0, 0}},
- {"ldurb", 0x38400000u, 0xFFE00C00u, AA64_FMT_LDST_SIMM9, 0, {0, 0}},
- {"sturh", 0x78000000u, 0xFFE00C00u, AA64_FMT_LDST_SIMM9, 0, {0, 0}},
- {"ldurh", 0x78400000u, 0xFFE00C00u, AA64_FMT_LDST_SIMM9, 0, {0, 0}},
- {"stur", 0xB8000000u, 0xFFE00C00u, AA64_FMT_LDST_SIMM9, 0, {0, 0}}, /* 32 */
- {"ldur", 0xB8400000u, 0xFFE00C00u, AA64_FMT_LDST_SIMM9, 0, {0, 0}},
- {"stur", 0xF8000000u, 0xFFE00C00u, AA64_FMT_LDST_SIMM9, AA64_ASMFL_SF1,
+ {MN("sturb"), 0x38000000u, 0xFFE00C00u, AA64_FMT_LDST_SIMM9, 0, {0, 0}},
+ {MN("ldurb"), 0x38400000u, 0xFFE00C00u, AA64_FMT_LDST_SIMM9, 0, {0, 0}},
+ {MN("sturh"), 0x78000000u, 0xFFE00C00u, AA64_FMT_LDST_SIMM9, 0, {0, 0}},
+ {MN("ldurh"), 0x78400000u, 0xFFE00C00u, AA64_FMT_LDST_SIMM9, 0, {0, 0}},
+ {MN("stur"), 0xB8000000u, 0xFFE00C00u, AA64_FMT_LDST_SIMM9, 0, {0, 0}}, /* 32 */
+ {MN("ldur"), 0xB8400000u, 0xFFE00C00u, AA64_FMT_LDST_SIMM9, 0, {0, 0}},
+ {MN("stur"), 0xF8000000u, 0xFFE00C00u, AA64_FMT_LDST_SIMM9, AA64_ASMFL_SF1,
{0, 0}},
- {"ldur", 0xF8400000u, 0xFFE00C00u, AA64_FMT_LDST_SIMM9, AA64_ASMFL_SF1,
+ {MN("ldur"), 0xF8400000u, 0xFFE00C00u, AA64_FMT_LDST_SIMM9, AA64_ASMFL_SF1,
{0, 0}},
- {"stur", 0x3C000000u, 0xFFE00C00u, AA64_FMT_LDST_SIMM9, 0, {0, 0}}, /* B */
- {"ldur", 0x3C400000u, 0xFFE00C00u, AA64_FMT_LDST_SIMM9, 0, {0, 0}},
- {"stur", 0x7C000000u, 0xFFE00C00u, AA64_FMT_LDST_SIMM9, 0, {0, 0}}, /* H */
- {"ldur", 0x7C400000u, 0xFFE00C00u, AA64_FMT_LDST_SIMM9, 0, {0, 0}},
- {"stur", 0xBC000000u, 0xFFE00C00u, AA64_FMT_LDST_SIMM9, 0, {0, 0}}, /* S */
- {"ldur", 0xBC400000u, 0xFFE00C00u, AA64_FMT_LDST_SIMM9, 0, {0, 0}},
- {"stur", 0xFC000000u, 0xFFE00C00u, AA64_FMT_LDST_SIMM9, AA64_ASMFL_SF1,
+ {MN("stur"), 0x3C000000u, 0xFFE00C00u, AA64_FMT_LDST_SIMM9, 0, {0, 0}}, /* B */
+ {MN("ldur"), 0x3C400000u, 0xFFE00C00u, AA64_FMT_LDST_SIMM9, 0, {0, 0}},
+ {MN("stur"), 0x7C000000u, 0xFFE00C00u, AA64_FMT_LDST_SIMM9, 0, {0, 0}}, /* H */
+ {MN("ldur"), 0x7C400000u, 0xFFE00C00u, AA64_FMT_LDST_SIMM9, 0, {0, 0}},
+ {MN("stur"), 0xBC000000u, 0xFFE00C00u, AA64_FMT_LDST_SIMM9, 0, {0, 0}}, /* S */
+ {MN("ldur"), 0xBC400000u, 0xFFE00C00u, AA64_FMT_LDST_SIMM9, 0, {0, 0}},
+ {MN("stur"), 0xFC000000u, 0xFFE00C00u, AA64_FMT_LDST_SIMM9, AA64_ASMFL_SF1,
{0, 0}}, /* D */
- {"ldur", 0xFC400000u, 0xFFE00C00u, AA64_FMT_LDST_SIMM9, AA64_ASMFL_SF1,
+ {MN("ldur"), 0xFC400000u, 0xFFE00C00u, AA64_FMT_LDST_SIMM9, AA64_ASMFL_SF1,
{0, 0}},
/* ----- Load/store pair, pre-indexed (opc=10 X / opc=01 D) ----- */
- {"stp", 0xA9800000u, 0xFFC00000u, AA64_FMT_LDSTP_PRE, AA64_ASMFL_SF1,
+ {MN("stp"), 0xA9800000u, 0xFFC00000u, AA64_FMT_LDSTP_PRE, AA64_ASMFL_SF1,
{0, 0}},
- {"ldp", 0xA9C00000u, 0xFFC00000u, AA64_FMT_LDSTP_PRE, AA64_ASMFL_SF1,
+ {MN("ldp"), 0xA9C00000u, 0xFFC00000u, AA64_FMT_LDSTP_PRE, AA64_ASMFL_SF1,
{0, 0}},
- {"stp", 0x6D800000u, 0xFFC00000u, AA64_FMT_LDSTP_PRE, 0, {0, 0}}, /* D */
- {"ldp", 0x6DC00000u, 0xFFC00000u, AA64_FMT_LDSTP_PRE, 0, {0, 0}},
- {"stp", 0xAD800000u, 0xFFC00000u, AA64_FMT_LDSTP_PRE, AA64_ASMFL_SF1,
+ {MN("stp"), 0x6D800000u, 0xFFC00000u, AA64_FMT_LDSTP_PRE, 0, {0, 0}}, /* D */
+ {MN("ldp"), 0x6DC00000u, 0xFFC00000u, AA64_FMT_LDSTP_PRE, 0, {0, 0}},
+ {MN("stp"), 0xAD800000u, 0xFFC00000u, AA64_FMT_LDSTP_PRE, AA64_ASMFL_SF1,
{0, 0}}, /* Q */
- {"ldp", 0xADC00000u, 0xFFC00000u, AA64_FMT_LDSTP_PRE, AA64_ASMFL_SF1,
+ {MN("ldp"), 0xADC00000u, 0xFFC00000u, AA64_FMT_LDSTP_PRE, AA64_ASMFL_SF1,
{0, 0}},
/* ----- Load/store pair, signed-offset ----- */
- {"stp", 0xA9000000u, 0xFFC00000u, AA64_FMT_LDSTP_SOFF, AA64_ASMFL_SF1,
+ {MN("stp"), 0xA9000000u, 0xFFC00000u, AA64_FMT_LDSTP_SOFF, AA64_ASMFL_SF1,
{0, 0}},
- {"ldp", 0xA9400000u, 0xFFC00000u, AA64_FMT_LDSTP_SOFF, AA64_ASMFL_SF1,
+ {MN("ldp"), 0xA9400000u, 0xFFC00000u, AA64_FMT_LDSTP_SOFF, AA64_ASMFL_SF1,
{0, 0}},
- {"stp", 0x6D000000u, 0xFFC00000u, AA64_FMT_LDSTP_SOFF, 0, {0, 0}}, /* D */
- {"ldp", 0x6D400000u, 0xFFC00000u, AA64_FMT_LDSTP_SOFF, 0, {0, 0}},
- {"stp", 0xAD000000u, 0xFFC00000u, AA64_FMT_LDSTP_SOFF, AA64_ASMFL_SF1,
+ {MN("stp"), 0x6D000000u, 0xFFC00000u, AA64_FMT_LDSTP_SOFF, 0, {0, 0}}, /* D */
+ {MN("ldp"), 0x6D400000u, 0xFFC00000u, AA64_FMT_LDSTP_SOFF, 0, {0, 0}},
+ {MN("stp"), 0xAD000000u, 0xFFC00000u, AA64_FMT_LDSTP_SOFF, AA64_ASMFL_SF1,
{0, 0}}, /* Q */
- {"ldp", 0xAD400000u, 0xFFC00000u, AA64_FMT_LDSTP_SOFF, AA64_ASMFL_SF1,
+ {MN("ldp"), 0xAD400000u, 0xFFC00000u, AA64_FMT_LDSTP_SOFF, AA64_ASMFL_SF1,
{0, 0}},
/* ----- Unconditional branch (immediate) ----- */
- {"b", 0x14000000u, 0xFC000000u, AA64_FMT_BR_IMM, 0, {0, 0}},
- {"bl", 0x94000000u, 0xFC000000u, AA64_FMT_BR_IMM, 0, {0, 0}},
+ {MN("b"), 0x14000000u, 0xFC000000u, AA64_FMT_BR_IMM, 0, {0, 0}},
+ {MN("bl"), 0x94000000u, 0xFC000000u, AA64_FMT_BR_IMM, 0, {0, 0}},
/* ----- Conditional branch (immediate) ----- */
- {"b.cond", 0x54000000u, 0xFF000010u, AA64_FMT_BR_COND, 0, {0, 0}},
+ {MN("b.cond"), 0x54000000u, 0xFF000010u, AA64_FMT_BR_COND, 0, {0, 0}},
/* ----- Compare-and-branch ----- */
- {"cbz", 0x34000000u, 0x7F000000u, AA64_FMT_CB, 0, {0, 0}},
- {"cbnz", 0x35000000u, 0x7F000000u, AA64_FMT_CB, 0, {0, 0}},
+ {MN("cbz"), 0x34000000u, 0x7F000000u, AA64_FMT_CB, 0, {0, 0}},
+ {MN("cbnz"), 0x35000000u, 0x7F000000u, AA64_FMT_CB, 0, {0, 0}},
/* ----- Exception generation ----- */
- {"svc", 0xD4000001u, 0xFFE0001Fu, AA64_FMT_EXCEPT, 0, {0, 0}},
- {"brk", 0xD4200000u, 0xFFE0001Fu, AA64_FMT_EXCEPT, 0, {0, 0}},
- {"hlt", 0xD4400000u, 0xFFE0001Fu, AA64_FMT_EXCEPT, 0, {0, 0}},
+ {MN("svc"), 0xD4000001u, 0xFFE0001Fu, AA64_FMT_EXCEPT, 0, {0, 0}},
+ {MN("brk"), 0xD4200000u, 0xFFE0001Fu, AA64_FMT_EXCEPT, 0, {0, 0}},
+ {MN("hlt"), 0xD4400000u, 0xFFE0001Fu, AA64_FMT_EXCEPT, 0, {0, 0}},
/* ----- Hint ----- */
- {"nop", 0xD503201Fu, 0xFFFFFFFFu, AA64_FMT_HINT, 0, {0, 0}},
+ {MN("nop"), 0xD503201Fu, 0xFFFFFFFFu, AA64_FMT_HINT, 0, {0, 0}},
/* ----- Memory barriers (DMB / DSB / ISB / CLREX) -----
* Mask covers everything but CRm at bits[11:8]. */
- {"dmb", 0xD50330BFu, 0xFFFFF0FFu, AA64_FMT_BARRIER, 0, {0, 0}},
- {"dsb", 0xD503309Fu, 0xFFFFF0FFu, AA64_FMT_BARRIER, 0, {0, 0}},
- {"isb", 0xD50330DFu, 0xFFFFF0FFu, AA64_FMT_BARRIER, 0, {0, 0}},
- {"clrex", 0xD503305Fu, 0xFFFFF0FFu, AA64_FMT_BARRIER, 0, {0, 0}},
+ {MN("dmb"), 0xD50330BFu, 0xFFFFF0FFu, AA64_FMT_BARRIER, 0, {0, 0}},
+ {MN("dsb"), 0xD503309Fu, 0xFFFFF0FFu, AA64_FMT_BARRIER, 0, {0, 0}},
+ {MN("isb"), 0xD50330DFu, 0xFFFFF0FFu, AA64_FMT_BARRIER, 0, {0, 0}},
+ {MN("clrex"), 0xD503305Fu, 0xFFFFF0FFu, AA64_FMT_BARRIER, 0, {0, 0}},
};
+#undef MN
+
const u32 aa64_insn_table_n =
(u32)(sizeof aa64_insn_table / sizeof aa64_insn_table[0]);
@@ -315,7 +320,7 @@ static void print_addsubsr(StrBuf* sb, u32 w, const AA64InsnDesc* d) {
AA64AddSubSR f = aa64_addsubsr_unpack(w);
if (d->flags & AA64_ASMFL_ALIAS) {
/* NEG / NEGS / CMP / CMN. */
- if (d->mnemonic[0] == 'c') {
+ if (d->mnemonic.s[0] == 'c') {
/* CMP / CMN — print Rn, Rm */
emit_reg(sb, f.Rn, (int)f.sf, 0);
strbuf_puts(sb, ", ");
@@ -590,14 +595,14 @@ static void print_barrier(StrBuf* sb, u32 w, const AA64InsnDesc* desc) {
case AA64_BARRIER_OPT_ISHLD: opt = "ishld"; break;
case AA64_BARRIER_OPT_ISHST: opt = "ishst"; break;
case AA64_BARRIER_OPT_ISH: opt = "ish"; break;
- case AA64_BARRIER_OPT_LD: opt = (desc && desc->mnemonic &&
- desc->mnemonic[0] == 'd' &&
- desc->mnemonic[1] == 'm')
+ case AA64_BARRIER_OPT_LD: opt = (desc && desc->mnemonic.len >= 2 &&
+ desc->mnemonic.s[0] == 'd' &&
+ desc->mnemonic.s[1] == 'm')
? "ld"
: NULL; break;
- case AA64_BARRIER_OPT_ST: opt = (desc && desc->mnemonic &&
- desc->mnemonic[0] == 'd' &&
- desc->mnemonic[1] == 'm')
+ case AA64_BARRIER_OPT_ST: opt = (desc && desc->mnemonic.len >= 2 &&
+ desc->mnemonic.s[0] == 'd' &&
+ desc->mnemonic.s[1] == 'm')
? "st"
: NULL; break;
case AA64_BARRIER_OPT_SY: opt = "sy"; break;
diff --git a/src/arch/aa64/isa.h b/src/arch/aa64/isa.h
@@ -26,6 +26,7 @@
* inline wrapper in the relevant format section. */
#include "core/core.h"
+#include "core/slice.h"
#include "core/strbuf.h"
/* ---- common register names ---- */
@@ -1131,7 +1132,7 @@ static inline u32 aa64_svc(u32 imm16) {
* ==================================================================== */
typedef struct AA64InsnDesc {
- const char* mnemonic;
+ Slice mnemonic;
u32 match;
u32 mask;
u8 fmt; /* AA64Format */
diff --git a/src/arch/aa64/ops.c b/src/arch/aa64/ops.c
@@ -2,6 +2,7 @@
* intrinsics, asm_block, set_loc, finalize/destroy, vtable constructor. */
#include "arch/aa64/internal.h"
+#include "core/slice.h"
/* ============================================================
* Data movement
@@ -20,7 +21,7 @@ static void aa_load_const(CGTarget* t, Operand dst, ConstBytes cb) {
compiler_panic(t->c, a->loc, "aarch64 load_const: only FP supported in v1");
}
- Sym ro_name = pool_intern_cstr(t->c->global, ".rodata");
+ Sym ro_name = pool_intern_slice(t->c->global, SLICE_LIT(".rodata"));
ObjSecId ro = obj_section(t->obj, ro_name, SEC_RODATA, SF_ALLOC, 1u);
u32 cur_section = t->mc->section_id;
@@ -48,7 +49,7 @@ static void aa_load_const(CGTarget* t, Operand dst, ConstBytes cb) {
for (int i = tn - 1; i >= 0; --i) namebuf[len++] = tmp[i];
namebuf[len] = 0;
}
- Sym sname = pool_intern_cstr(t->c->global, namebuf);
+ Sym sname = pool_intern_slice(t->c->global, slice_from_cstr(namebuf));
ObjSymId sym = obj_symbol(t->obj, sname, SB_LOCAL, SK_OBJ, ro, (u64)ro_off,
(u64)cb.size);
@@ -246,7 +247,8 @@ static inline void aa_assert_no_index(CGTarget* t, Operand addr,
const char* where) {
if (addr.kind == OPK_INDIRECT && addr.v.ind.index != REG_NONE) {
compiler_panic(t->c, impl_of(t)->loc,
- "aarch64 %s: OPK_INDIRECT with index unexpected", where);
+ "aarch64 %.*s: OPK_INDIRECT with index unexpected",
+ SLICE_ARG(slice_from_cstr(where)));
}
}
@@ -558,7 +560,7 @@ static void aa_tls_addr_of(CGTarget* t, Operand dst, ObjSymId sym, i64 addend) {
* SECREL fixups assume the merged .tls section is < 16 MiB; cfree
* panics with a clear diagnostic at link time if that ever fails. */
if (t->c->target.os == CFREE_OS_WINDOWS) {
- Sym idx_name = pool_intern_cstr(t->c->global, "_tls_index");
+ Sym idx_name = pool_intern_slice(t->c->global, SLICE_LIT("_tls_index"));
ObjSymId idx_sym = obj_symbol_find(t->obj, idx_name);
if (idx_sym == 0) {
idx_sym = obj_symbol(t->obj, idx_name, SB_GLOBAL, SK_UNDEF,
@@ -2467,8 +2469,9 @@ static void aa_intrinsic(CGTarget* t, IntrinKind kind, Operand* dsts, u32 nd,
Operand da = args[0], sa = args[1], nb = args[2];
if (da.kind != OPK_REG || sa.kind != OPK_REG || nb.kind != OPK_IMM) {
compiler_panic(t->c, a->loc,
- "aarch64 intrinsic: %s with non-const n or non-REG ptr",
- kind == INTRIN_MEMCPY ? "memcpy" : "memmove");
+ "aarch64 intrinsic: %.*s with non-const n or non-REG ptr",
+ SLICE_ARG(slice_from_cstr(
+ kind == INTRIN_MEMCPY ? "memcpy" : "memmove")));
}
u32 dr = reg_num(da);
u32 sr = reg_num(sa);
diff --git a/src/arch/aa64/regs.c b/src/arch/aa64/regs.c
@@ -16,6 +16,7 @@
#include "arch/aa64/regs.h"
#include "core/core.h"
+#include "core/slice.h"
typedef struct AA64Reg {
uint32_t dwarf_idx;
@@ -52,9 +53,11 @@ const char* aa64_register_name(uint32_t dwarf_idx) {
int aa64_register_index(const char* name, uint32_t* idx_out) {
uint32_t i;
+ Slice q;
if (!name) return 1;
+ q = slice_from_cstr(name);
for (i = 0; i < AA64_REGS_N; ++i) {
- if (!strcmp(AA64_REGS[i].name, name)) {
+ if (slice_eq_cstr(q, AA64_REGS[i].name)) {
if (idx_out) *idx_out = AA64_REGS[i].dwarf_idx;
return 0;
}
@@ -62,7 +65,7 @@ int aa64_register_index(const char* name, uint32_t* idx_out) {
/* Accept Wn alias for Xn (same DWARF index). */
if (name[0] == 'w' && name[1] != '\0') {
char buf[8];
- size_t n = strlen(name);
+ size_t n = q.len;
if (n < sizeof buf) {
buf[0] = 'x';
memcpy(buf + 1, name + 1, n);
@@ -70,7 +73,7 @@ int aa64_register_index(const char* name, uint32_t* idx_out) {
}
}
/* wzr / xzr aliases. */
- if (!strcmp(name, "wzr") || !strcmp(name, "xzr")) {
+ if (slice_eq_cstr(q, "wzr") || slice_eq_cstr(q, "xzr")) {
if (idx_out) *idx_out = 31u; /* shares SP encoding slot; v1 picks SP */
return 0;
}
diff --git a/src/arch/c_target/emit.c b/src/arch/c_target/emit.c
@@ -23,6 +23,7 @@
#include "core/core.h"
#include "core/heap.h"
#include "core/pool.h"
+#include "core/slice.h"
#include "obj/obj.h"
/* Forward decls. */
@@ -113,8 +114,8 @@ static const char* c_typedef_name(CTarget* t, CfreeCgTypeId tid) {
CfreeCgTypeId u = api_unalias_type(t->c, tid);
char buf[32];
int n = snprintf(buf, sizeof buf, "__ty_%u", (unsigned)u);
- Sym s = pool_intern(t->c->global, buf, (size_t)n);
- return pool_str(t->c->global, s, NULL);
+ Sym s = pool_intern_slice(t->c->global, (Slice){.s = buf, .len = (size_t)n});
+ return pool_slice(t->c->global, s).s;
}
/* Forward decl. */
@@ -472,7 +473,8 @@ static void c_assert_no_index(CTarget* t, Operand addr, const char* where) {
if (addr.v.ind.index == REG_NONE) return;
SrcLoc loc = t->cur_fn ? t->cur_fn->loc : (SrcLoc){0, 0, 0};
compiler_panic(t->c, loc,
- "C target: %s: indexed OPK_INDIRECT not allowed here", where);
+ "C target: %.*s: indexed OPK_INDIRECT not allowed here",
+ SLICE_ARG(slice_from_cstr(where)));
}
void c_emit_operand(CTarget* t, Operand op) {
@@ -905,8 +907,9 @@ const char* c_sym_name(CTarget* t, ObjSymId sym) {
compiler_panic(t->c, (SrcLoc){0, 0, 0}, "C target: unknown ObjSymId %u",
(unsigned)sym);
}
- size_t n = 0;
- const char* s = pool_str(t->c->global, os->name, &n);
+ Slice nm = pool_slice(t->c->global, os->name);
+ const char* s = nm.s;
+ size_t n = nm.len;
/* Mach-O linker symbols are mangled with a leading underscore; the host
* C compiler will re-add it on its own, so strip when re-emitting source. */
if (t->c->target.obj == CFREE_OBJ_MACHO && s && n > 0 && s[0] == '_') {
@@ -952,8 +955,8 @@ const char* c_sym_name(CTarget* t, ObjSymId sym) {
buf[out++] = ok ? ch : '_';
}
buf[out] = '\0';
- Sym interned = pool_intern(t->c->global, buf, out);
- return pool_str(t->c->global, interned, NULL);
+ Sym interned = pool_intern_slice(t->c->global, (Slice){.s = buf, .len = out});
+ return pool_slice(t->c->global, interned).s;
}
/* === Prologue / finalize === */
@@ -2913,7 +2916,7 @@ void c_asm_block(CGTarget* T, const char* tmpl, const AsmConstraint* outs,
if (i > 0) cbuf_puts(&t->body, ", ");
if (outs[i].name) {
cbuf_puts(&t->body, "[");
- cbuf_puts(&t->body, pool_str(t->c->global, outs[i].name, NULL));
+ cbuf_puts(&t->body, pool_slice(t->c->global, outs[i].name).s);
cbuf_puts(&t->body, "] ");
}
c_emit_c_string_literal(&t->body, outs[i].str ? outs[i].str : "");
@@ -2946,7 +2949,7 @@ void c_asm_block(CGTarget* T, const char* tmpl, const AsmConstraint* outs,
emitted_any = 1;
if (ins[i].name) {
cbuf_puts(&t->body, "[");
- cbuf_puts(&t->body, pool_str(t->c->global, ins[i].name, NULL));
+ cbuf_puts(&t->body, pool_slice(t->c->global, ins[i].name).s);
cbuf_puts(&t->body, "] ");
}
c_emit_c_string_literal(&t->body, cs);
@@ -2959,7 +2962,7 @@ void c_asm_block(CGTarget* T, const char* tmpl, const AsmConstraint* outs,
for (u32 i = 0; i < nc; ++i) {
if (i > 0) cbuf_puts(&t->body, ", ");
c_emit_c_string_literal(&t->body,
- pool_str(t->c->global, clobs[i], NULL));
+ pool_slice(t->c->global, clobs[i]).s);
}
cbuf_puts(&t->body, ");\n");
}
@@ -3168,11 +3171,12 @@ void c_fence(CGTarget* T, MemOrder o) {
/* === set_loc === */
-static void cbuf_put_line_filename(CBuf* b, const char* s) {
+static void cbuf_put_line_filename(CBuf* b, CfreeSlice s) {
+ size_t i;
cbuf_putc(b, '"');
- if (s) {
- while (*s) {
- unsigned char ch = (unsigned char)*s++;
+ for (i = 0; i < s.len; ++i) {
+ {
+ unsigned char ch = (unsigned char)s.s[i];
switch (ch) {
case '\\':
case '"':
@@ -3199,7 +3203,7 @@ static void cbuf_put_line_filename(CBuf* b, const char* s) {
void c_set_loc(CGTarget* T, SrcLoc l) {
CTarget* t = (CTarget*)T;
- const char* file;
+ CfreeSlice file;
if (!t->cur_fn || l.file_id == 0 || l.line == 0) return;
if (t->have_emitted_loc && t->emitted_loc.file_id == l.file_id &&
@@ -3208,7 +3212,7 @@ void c_set_loc(CGTarget* T, SrcLoc l) {
}
file = cfree_compiler_file_name(t->c, l.file_id);
- if (!file) return;
+ if (!file.len) return;
cbuf_puts(&t->body, "#line ");
cbuf_put_u64(&t->body, (u64)l.line);
@@ -3305,7 +3309,7 @@ static ObjSymId c_macho_tls_find_init(CTarget* t, ObjSecId desc_sec,
* on Mach-O). Compared by interned Sym id. */
static int c_sec_name_is_macho_tvars(CTarget* t, const Section* sec) {
if (!sec) return 0;
- Sym tvars = pool_intern_cstr(t->c->global, "__DATA,__thread_vars");
+ Sym tvars = pool_intern_slice(t->c->global, SLICE_LIT("__DATA,__thread_vars"));
return sec->name == tvars;
}
diff --git a/src/arch/mc.c b/src/arch/mc.c
@@ -803,9 +803,9 @@ void mc_emit_eh_frame(MCEmitter* m) {
* ".eh_frame". The Mach-O emitter splits on comma; the ELF emitter
* uses the literal as section name. */
if (m->c->target.obj == CFREE_OBJ_MACHO) {
- sec_name = pool_intern_cstr(m->c->global, "__TEXT,__eh_frame");
+ sec_name = pool_intern_slice(m->c->global, SLICE_LIT("__TEXT,__eh_frame"));
} else {
- sec_name = pool_intern_cstr(m->c->global, ".eh_frame");
+ sec_name = pool_intern_slice(m->c->global, SLICE_LIT(".eh_frame"));
}
eh_sec = obj_section(m->obj, sec_name, SEC_OTHER, SF_ALLOC, 8);
{
diff --git a/src/arch/rv64/arch.c b/src/arch/rv64/arch.c
@@ -32,8 +32,12 @@ static const ArchDwarfOps rv64_dwarf_ops = {
};
static int rv64_register_at_public(uint32_t idx, CfreeArchReg* out) {
+ const char* nm = NULL;
+ int rc;
if (!out) return 1;
- return rv64_register_iter_get(idx, &out->dwarf_idx, &out->name);
+ rc = rv64_register_iter_get(idx, &out->dwarf_idx, &nm);
+ if (rc == 0) out->name = cfree_slice_cstr(nm);
+ return rc;
}
static int rv64_apply_label_fixup(Compiler* c, const ArchLabelFixup* fx) {
@@ -112,26 +116,26 @@ static int rv64_apply_label_fixup(Compiler* c, const ArchLabelFixup* fx) {
* extensions outside scope (V, B, Zve*, Zfh, …) are deliberately
* absent. ABI variant is lp64d. */
static const CfreePredefinedMacro rv64_predefined_macros[] = {
- {"__riscv", "1"},
- {"__riscv_xlen", "64"},
- {"__riscv_float_abi_double", "1"},
- {"__riscv_atomic", "1"},
- {"__riscv_mul", "1"},
- {"__riscv_div", "1"},
- {"__riscv_muldiv", "1"},
- {"__riscv_compressed", "1"},
- {"__riscv_flen", "64"},
- {"__riscv_fdiv", "1"},
- {"__riscv_fsqrt", "1"},
- {"__riscv_zicsr", "1"},
- {"__riscv_zifencei", "1"},
- {"__riscv_arch_test", "1"},
- {"__LP64__", "1"},
- {"_LP64", "1"},
- {"__ORDER_LITTLE_ENDIAN__", "1234"},
- {"__ORDER_BIG_ENDIAN__", "4321"},
- {"__BYTE_ORDER__", "__ORDER_LITTLE_ENDIAN__"},
- {"__LITTLE_ENDIAN__", "1"},
+ {CFREE_SLICE_LIT("__riscv"), CFREE_SLICE_LIT("1")},
+ {CFREE_SLICE_LIT("__riscv_xlen"), CFREE_SLICE_LIT("64")},
+ {CFREE_SLICE_LIT("__riscv_float_abi_double"), CFREE_SLICE_LIT("1")},
+ {CFREE_SLICE_LIT("__riscv_atomic"), CFREE_SLICE_LIT("1")},
+ {CFREE_SLICE_LIT("__riscv_mul"), CFREE_SLICE_LIT("1")},
+ {CFREE_SLICE_LIT("__riscv_div"), CFREE_SLICE_LIT("1")},
+ {CFREE_SLICE_LIT("__riscv_muldiv"), CFREE_SLICE_LIT("1")},
+ {CFREE_SLICE_LIT("__riscv_compressed"), CFREE_SLICE_LIT("1")},
+ {CFREE_SLICE_LIT("__riscv_flen"), CFREE_SLICE_LIT("64")},
+ {CFREE_SLICE_LIT("__riscv_fdiv"), CFREE_SLICE_LIT("1")},
+ {CFREE_SLICE_LIT("__riscv_fsqrt"), CFREE_SLICE_LIT("1")},
+ {CFREE_SLICE_LIT("__riscv_zicsr"), CFREE_SLICE_LIT("1")},
+ {CFREE_SLICE_LIT("__riscv_zifencei"), CFREE_SLICE_LIT("1")},
+ {CFREE_SLICE_LIT("__riscv_arch_test"), CFREE_SLICE_LIT("1")},
+ {CFREE_SLICE_LIT("__LP64__"), CFREE_SLICE_LIT("1")},
+ {CFREE_SLICE_LIT("_LP64"), CFREE_SLICE_LIT("1")},
+ {CFREE_SLICE_LIT("__ORDER_LITTLE_ENDIAN__"), CFREE_SLICE_LIT("1234")},
+ {CFREE_SLICE_LIT("__ORDER_BIG_ENDIAN__"), CFREE_SLICE_LIT("4321")},
+ {CFREE_SLICE_LIT("__BYTE_ORDER__"), CFREE_SLICE_LIT("__ORDER_LITTLE_ENDIAN__")},
+ {CFREE_SLICE_LIT("__LITTLE_ENDIAN__"), CFREE_SLICE_LIT("1")},
};
static CGTarget* rv64_backend_make(Compiler* c, ObjBuilder* o,
diff --git a/src/arch/rv64/asm.c b/src/arch/rv64/asm.c
@@ -21,6 +21,7 @@
#include "asm/asm_helpers.h"
#include "core/arena.h"
#include "core/pool.h"
+#include "core/slice.h"
#include "core/strbuf.h"
struct Rv64Asm {
@@ -49,14 +50,18 @@ typedef struct Rv64Mem {
} Rv64Mem;
static int sym_to_cstr(AsmDriver* d, Sym s, char* out, size_t cap) {
- size_t n = 0;
- const char* p = pool_str(asm_driver_pool(d), s, &n);
- if (!p || n >= cap) return 0;
- memcpy(out, p, n);
- out[n] = '\0';
+ Slice sl = pool_slice(asm_driver_pool(d), s);
+ if (!sl.s || sl.len >= cap) return 0;
+ memcpy(out, sl.s, sl.len);
+ out[sl.len] = '\0';
return 1;
}
+/* True if `s` begins with the NUL-terminated literal `pfx` (length-explicit). */
+static bool slice_has_prefix_cstr(Slice s, const char* pfx, size_t n) {
+ return s.len >= n && memcmp(s.s, pfx, n) == 0;
+}
+
static int rv_reg_from_name(AsmDriver* d, Sym s, u32* reg_out, int* fp_out) {
char name[16];
uint32_t dwarf = 0;
@@ -305,23 +310,23 @@ static u32 assemble_one(AsmDriver* d, const Rv64InsnDesc* desc) {
case RV64_FMT_I:
/* Aliases first. */
if (desc->flags & RV64_ASMFL_ALIAS) {
- if (!strcmp(desc->mnemonic, "li")) {
+ if (slice_eq_cstr(desc->mnemonic, "li")) {
rd = parse_xreg(d); expect_comma(d);
imm = (i32)asm_driver_parse_const(d);
return enc_i(m, rd, 0u, imm);
}
- if (!strcmp(desc->mnemonic, "mv")) {
+ if (slice_eq_cstr(desc->mnemonic, "mv")) {
rd = parse_xreg(d); expect_comma(d);
rs1 = parse_xreg(d);
return enc_i(m, rd, rs1, 0);
}
- if (!strcmp(desc->mnemonic, "sext.w")) {
+ if (slice_eq_cstr(desc->mnemonic, "sext.w")) {
rd = parse_xreg(d); expect_comma(d);
rs1 = parse_xreg(d);
return enc_i(m, rd, rs1, 0);
}
- if (!strcmp(desc->mnemonic, "seqz") ||
- !strcmp(desc->mnemonic, "not")) {
+ if (slice_eq_cstr(desc->mnemonic, "seqz") ||
+ slice_eq_cstr(desc->mnemonic, "not")) {
rd = parse_xreg(d); expect_comma(d);
rs1 = parse_xreg(d);
/* match already has imm12 + funct3 + op pinned. */
@@ -351,7 +356,7 @@ static u32 assemble_one(AsmDriver* d, const Rv64InsnDesc* desc) {
return enc_u(m, rd, (u32)imm);
case RV64_FMT_J:
- if ((desc->flags & RV64_ASMFL_ALIAS) && !strcmp(desc->mnemonic, "j")) {
+ if ((desc->flags & RV64_ASMFL_ALIAS) && slice_eq_cstr(desc->mnemonic, "j")) {
imm = (i32)asm_driver_parse_const(d);
return enc_j(m, 0u, imm);
}
@@ -394,13 +399,13 @@ static u32 assemble_one(AsmDriver* d, const Rv64InsnDesc* desc) {
return enc_s(m, rs2, mem.base, mem.disp);
case RV64_FMT_JALR:
- if ((desc->flags & RV64_ASMFL_ALIAS) && !strcmp(desc->mnemonic, "jr")) {
+ if ((desc->flags & RV64_ASMFL_ALIAS) && slice_eq_cstr(desc->mnemonic, "jr")) {
rs1 = parse_xreg(d);
return enc_i(m, 0u, rs1, 0);
}
rd = parse_xreg(d);
if (!asm_driver_eat_comma(d)) {
- if (!strcmp(desc->mnemonic, "jalr"))
+ if (slice_eq_cstr(desc->mnemonic, "jalr"))
return enc_i(m, RV_RA, rd, 0);
asm_driver_panic(d, "rv64 asm: expected ','");
}
@@ -457,14 +462,14 @@ static u32 assemble_one(AsmDriver* d, const Rv64InsnDesc* desc) {
/* Source: integer reg for fcvt.s.w etc (no FP flag would
* indicate); but since we have ASMFL_FP set on dest, source may
* be either. Disambiguate by mnemonic. */
- if (!strncmp(desc->mnemonic, "fcvt.s.", 7) &&
- (desc->mnemonic[7] == 'w' || desc->mnemonic[7] == 'l')) {
+ if (slice_has_prefix_cstr(desc->mnemonic, "fcvt.s.", 7) &&
+ (desc->mnemonic.s[7] == 'w' || desc->mnemonic.s[7] == 'l')) {
rs1 = parse_xreg(d);
- } else if (!strncmp(desc->mnemonic, "fcvt.d.", 7) &&
- (desc->mnemonic[7] == 'w' || desc->mnemonic[7] == 'l')) {
+ } else if (slice_has_prefix_cstr(desc->mnemonic, "fcvt.d.", 7) &&
+ (desc->mnemonic.s[7] == 'w' || desc->mnemonic.s[7] == 'l')) {
rs1 = parse_xreg(d);
- } else if (!strcmp(desc->mnemonic, "fmv.w.x") ||
- !strcmp(desc->mnemonic, "fmv.d.x")) {
+ } else if (slice_eq_cstr(desc->mnemonic, "fmv.w.x") ||
+ slice_eq_cstr(desc->mnemonic, "fmv.d.x")) {
rs1 = parse_xreg(d);
} else {
rs1 = parse_freg(d);
@@ -508,8 +513,8 @@ static u32 assemble_one(AsmDriver* d, const Rv64InsnDesc* desc) {
}
case RV64_FMT_CR:
- if (!strcmp(desc->mnemonic, "c.jr") ||
- !strcmp(desc->mnemonic, "c.jalr")) {
+ if (slice_eq_cstr(desc->mnemonic, "c.jr") ||
+ slice_eq_cstr(desc->mnemonic, "c.jalr")) {
rs1 = parse_xreg(d);
return enc_c_cr(m, rs1, 0u);
}
@@ -518,22 +523,22 @@ static u32 assemble_one(AsmDriver* d, const Rv64InsnDesc* desc) {
return enc_c_cr(m, rd, rs2);
case RV64_FMT_CI:
- if (!strcmp(desc->mnemonic, "c.lwsp") ||
- !strcmp(desc->mnemonic, "c.ldsp") ||
- !strcmp(desc->mnemonic, "c.fldsp")) {
- rd = !strcmp(desc->mnemonic, "c.fldsp") ? parse_freg(d) : parse_xreg(d);
+ if (slice_eq_cstr(desc->mnemonic, "c.lwsp") ||
+ slice_eq_cstr(desc->mnemonic, "c.ldsp") ||
+ slice_eq_cstr(desc->mnemonic, "c.fldsp")) {
+ rd = slice_eq_cstr(desc->mnemonic, "c.fldsp") ? parse_freg(d) : parse_xreg(d);
expect_comma(d);
mem = parse_mem(d);
if (mem.base != RV_SP)
asm_driver_panic(d, "rv64 asm: compressed stack load needs sp base");
return enc_c_lwsp(m, rd, (u32)mem.disp,
- strcmp(desc->mnemonic, "c.lwsp") != 0);
+ !slice_eq_cstr(desc->mnemonic, "c.lwsp"));
}
rd = parse_xreg(d); expect_comma(d);
imm = (i32)asm_driver_parse_const(d);
- if (!strcmp(desc->mnemonic, "c.lui") && ((u32)imm & 0xfffu) == 0)
+ if (slice_eq_cstr(desc->mnemonic, "c.lui") && ((u32)imm & 0xfffu) == 0)
imm >>= 12;
- if (!strcmp(desc->mnemonic, "c.addi16sp")) {
+ if (slice_eq_cstr(desc->mnemonic, "c.addi16sp")) {
if (rd != RV_SP)
asm_driver_panic(d, "rv64 asm: c.addi16sp needs sp destination");
return enc_c_addi16sp(m, imm);
@@ -547,7 +552,7 @@ static u32 assemble_one(AsmDriver* d, const Rv64InsnDesc* desc) {
if (mem.base != RV_SP)
asm_driver_panic(d, "rv64 asm: compressed stack store needs sp base");
return enc_c_swsp(m, rs2, (u32)mem.disp,
- strcmp(desc->mnemonic, "c.swsp") != 0);
+ !slice_eq_cstr(desc->mnemonic, "c.swsp"));
case RV64_FMT_CIW:
rd = parse_xreg(d); expect_comma(d);
@@ -562,14 +567,14 @@ static u32 assemble_one(AsmDriver* d, const Rv64InsnDesc* desc) {
expect_comma(d);
mem = parse_mem(d);
return enc_c_lwld(m, c_reg3(d, rd), c_reg3(d, mem.base),
- (u32)mem.disp, strcmp(desc->mnemonic, "c.lw") != 0);
+ (u32)mem.disp, !slice_eq_cstr(desc->mnemonic, "c.lw"));
case RV64_FMT_CS:
rs2 = (desc->flags & RV64_ASMFL_FP) ? parse_freg(d) : parse_xreg(d);
expect_comma(d);
mem = parse_mem(d);
return enc_c_swld(m, c_reg3(d, rs2), c_reg3(d, mem.base),
- (u32)mem.disp, strcmp(desc->mnemonic, "c.sw") != 0);
+ (u32)mem.disp, !slice_eq_cstr(desc->mnemonic, "c.sw"));
case RV64_FMT_CA:
rd = parse_xreg(d); expect_comma(d);
@@ -579,8 +584,8 @@ static u32 assemble_one(AsmDriver* d, const Rv64InsnDesc* desc) {
case RV64_FMT_CB:
rs1 = parse_xreg(d); expect_comma(d);
imm = (i32)asm_driver_parse_const(d);
- if (!strcmp(desc->mnemonic, "c.beqz") ||
- !strcmp(desc->mnemonic, "c.bnez")) {
+ if (slice_eq_cstr(desc->mnemonic, "c.beqz") ||
+ slice_eq_cstr(desc->mnemonic, "c.bnez")) {
return enc_c_cb_imm(m, c_reg3(d, rs1), imm);
}
return enc_c_cb_alu_imm(m, c_reg3(d, rs1), imm);
@@ -599,13 +604,10 @@ static u32 assemble_one(AsmDriver* d, const Rv64InsnDesc* desc) {
static void rv64_arch_asm_insn(ArchAsm* base, AsmDriver* d, Sym mnemonic) {
MCEmitter* mc = asm_driver_mc(d);
- char name[24];
const Rv64InsnDesc* desc;
(void)base;
(void)asm_driver_cur_section(d);
- if (!sym_to_cstr(d, mnemonic, name, sizeof name))
- asm_driver_panic(d, "rv64 asm: mnemonic too long");
- desc = rv64_asm_find(name);
+ desc = rv64_asm_find(pool_slice(asm_driver_pool(d), mnemonic));
if (!desc) asm_driver_panic(d, "rv64 asm: unsupported instruction");
if (desc->flags & RV64_ASMFL_C16)
rv64_emit16(mc, assemble_one(d, desc));
@@ -665,7 +667,8 @@ void rv64_inline_bind(Rv64Asm* a,
_Noreturn static void inline_panic(Rv64Asm* a, const char* msg) {
SrcLoc loc = {0, 0, 0};
- compiler_panic(a->c, loc, "rv64 inline asm: %s", msg);
+ compiler_panic(a->c, loc, "rv64 inline asm: %.*s",
+ SLICE_ARG(slice_from_cstr(msg)));
}
/* Render a 5-bit integer register number using its canonical psABI name. */
@@ -825,16 +828,17 @@ static void run_one_line(Rv64Asm* a, MCEmitter* mc, const char* text,
AsmTok rest = asm_driver_next(d);
if (rest.kind != ASM_TOK_IDENT)
inline_panic(a, "composite mnemonic: expected ident after '.'");
- size_t hn = 0, rn = 0;
- const char* hp = pool_str(asm_driver_pool(d), mn, &hn);
- const char* rp = pool_str(asm_driver_pool(d), rest.v.ident, &rn);
+ Slice hsl = pool_slice(asm_driver_pool(d), mn);
+ Slice rsl = pool_slice(asm_driver_pool(d), rest.v.ident);
+ size_t hn = hsl.len, rn = rsl.len;
char buf[64];
if (hn + 1 + rn >= sizeof buf)
inline_panic(a, "composite mnemonic too long");
- for (size_t k = 0; k < hn; ++k) buf[k] = hp[k];
+ for (size_t k = 0; k < hn; ++k) buf[k] = hsl.s[k];
buf[hn] = '.';
- for (size_t k = 0; k < rn; ++k) buf[hn + 1 + k] = rp[k];
- mn = pool_intern(asm_driver_pool(d), buf, hn + 1 + rn);
+ for (size_t k = 0; k < rn; ++k) buf[hn + 1 + k] = rsl.s[k];
+ mn = pool_intern_slice(asm_driver_pool(d),
+ (Slice){.s = buf, .len = hn + 1 + rn});
dot = asm_driver_peek(d);
}
rv64_arch_asm_insn(&a->base, d, mn);
@@ -866,7 +870,8 @@ static void render_and_run_line(Rv64Asm* a, MCEmitter* mc, StrBuf* sb,
while (nend < end && *nend != ']') ++nend;
if (nend == end) inline_panic(a, "unterminated %[name]");
size_t nlen = (size_t)(nend - nbeg);
- Sym needle = pool_intern(a->c->global, nbeg, nlen);
+ Sym needle = pool_intern_slice(a->c->global,
+ (Slice){.s = nbeg, .len = nlen});
u32 idx = lookup_named(a, needle);
if (idx == (u32)-1)
inline_panic(a, "%[name] does not match any constraint");
@@ -887,7 +892,8 @@ static void render_and_run_line(Rv64Asm* a, MCEmitter* mc, StrBuf* sb,
while (nend < end && *nend != ']') ++nend;
if (nend == end) inline_panic(a, "unterminated %[name]");
size_t nlen = (size_t)(nend - nbeg);
- Sym needle = pool_intern(a->c->global, nbeg, nlen);
+ Sym needle = pool_intern_slice(a->c->global,
+ (Slice){.s = nbeg, .len = nlen});
u32 idx = lookup_named(a, needle);
if (idx == (u32)-1)
inline_panic(a, "%[name] does not match any constraint");
diff --git a/src/arch/rv64/disasm.c b/src/arch/rv64/disasm.c
@@ -65,7 +65,7 @@ static u32 rv_decode(ArchDisasm* base, const u8* bytes, size_t len, u64 vaddr,
const Rv64InsnDesc* desc = rv64_disasm_find_c(first_hw);
if (desc) {
strbuf_reset(&d->mnem);
- strbuf_puts(&d->mnem, desc->mnemonic);
+ strbuf_put_slice(&d->mnem, desc->mnemonic);
strbuf_reset(&d->ops);
rv64_print_operands(&d->ops, desc, first_hw, vaddr);
} else {
@@ -78,7 +78,7 @@ static u32 rv_decode(ArchDisasm* base, const u8* bytes, size_t len, u64 vaddr,
const Rv64InsnDesc* desc = rv64_disasm_find(word);
if (desc) {
strbuf_reset(&d->mnem);
- strbuf_puts(&d->mnem, desc->mnemonic);
+ strbuf_put_slice(&d->mnem, desc->mnemonic);
strbuf_reset(&d->ops);
rv64_print_operands(&d->ops, desc, word, vaddr);
} else {
@@ -91,9 +91,9 @@ static u32 rv_decode(ArchDisasm* base, const u8* bytes, size_t len, u64 vaddr,
out->vaddr = vaddr;
out->bytes = bytes;
out->nbytes = nbytes;
- out->mnemonic = strbuf_cstr(&d->mnem);
- out->operands = strbuf_cstr(&d->ops);
- out->annotation = strbuf_cstr(&d->ann);
+ out->mnemonic = strbuf_slice(&d->mnem);
+ out->operands = strbuf_slice(&d->ops);
+ out->annotation = strbuf_slice(&d->ann);
return nbytes;
}
diff --git a/src/arch/rv64/emit.c b/src/arch/rv64/emit.c
@@ -2,6 +2,7 @@
*/
#include "arch/rv64/internal.h"
+#include "core/slice.h"
static u32 collect_mask_regs(u32 mask, u32 first, u32 last, u32 *out) {
u32 n = 0;
@@ -62,7 +63,8 @@ void rv64_patch32(ObjBuilder *obj, u32 sec_id, u32 ofs, u32 word) {
_Noreturn void rv_panic(CGTarget *t, const char *what) {
SrcLoc loc = impl_of(t)->loc;
- compiler_panic(t->c, loc, "rv64: %s not implemented", what);
+ compiler_panic(t->c, loc, "rv64: %.*s not implemented",
+ SLICE_ARG(slice_from_cstr(what)));
}
int fits_signed32(i64 v) {
diff --git a/src/arch/rv64/isa.c b/src/arch/rv64/isa.c
@@ -14,8 +14,14 @@
#include <string.h>
+#include "core/slice.h"
#include "core/strbuf.h"
+/* True if `s` begins with the NUL-terminated literal `pfx` (length-explicit). */
+static bool slice_has_prefix_cstr(Slice s, const char* pfx, size_t n) {
+ return s.len >= n && memcmp(s.s, pfx, n) == 0;
+}
+
/* Family-match bit patterns. The opcode (bits 6:0) plus
* funct3/funct7/funct5 selectors narrow each match. For aliases we pin
* specific register fields (e.g. rs1=x0 for `li`, rd=x0 for `j`). */
@@ -94,102 +100,105 @@
* path which presents the halfword in low 16 bits. */
#define MATCH_C(w16) ((u32)(w16))
+/* Mnemonic Slice literal for a static table row (compile-time length). */
+#define MN(s) {{(s)}, sizeof(s) - 1}
+
const Rv64InsnDesc rv64_insn_table[] = {
/* =================================================================
* RV64I base — integer register ops (R-type, OP=0x33)
* ================================================================= */
- {"add", MATCH_R(0x00, 0x0, RV_OP), MASK_R, RV64_FMT_R, 0, {0, 0}},
- {"sub", MATCH_R(0x20, 0x0, RV_OP), MASK_R, RV64_FMT_R, 0, {0, 0}},
- {"sll", MATCH_R(0x00, 0x1, RV_OP), MASK_R, RV64_FMT_R, 0, {0, 0}},
- {"slt", MATCH_R(0x00, 0x2, RV_OP), MASK_R, RV64_FMT_R, 0, {0, 0}},
- {"sltu", MATCH_R(0x00, 0x3, RV_OP), MASK_R, RV64_FMT_R, 0, {0, 0}},
- {"xor", MATCH_R(0x00, 0x4, RV_OP), MASK_R, RV64_FMT_R, 0, {0, 0}},
- {"srl", MATCH_R(0x00, 0x5, RV_OP), MASK_R, RV64_FMT_R, 0, {0, 0}},
- {"sra", MATCH_R(0x20, 0x5, RV_OP), MASK_R, RV64_FMT_R, 0, {0, 0}},
- {"or", MATCH_R(0x00, 0x6, RV_OP), MASK_R, RV64_FMT_R, 0, {0, 0}},
- {"and", MATCH_R(0x00, 0x7, RV_OP), MASK_R, RV64_FMT_R, 0, {0, 0}},
+ {MN("add"), MATCH_R(0x00, 0x0, RV_OP), MASK_R, RV64_FMT_R, 0, {0, 0}},
+ {MN("sub"), MATCH_R(0x20, 0x0, RV_OP), MASK_R, RV64_FMT_R, 0, {0, 0}},
+ {MN("sll"), MATCH_R(0x00, 0x1, RV_OP), MASK_R, RV64_FMT_R, 0, {0, 0}},
+ {MN("slt"), MATCH_R(0x00, 0x2, RV_OP), MASK_R, RV64_FMT_R, 0, {0, 0}},
+ {MN("sltu"), MATCH_R(0x00, 0x3, RV_OP), MASK_R, RV64_FMT_R, 0, {0, 0}},
+ {MN("xor"), MATCH_R(0x00, 0x4, RV_OP), MASK_R, RV64_FMT_R, 0, {0, 0}},
+ {MN("srl"), MATCH_R(0x00, 0x5, RV_OP), MASK_R, RV64_FMT_R, 0, {0, 0}},
+ {MN("sra"), MATCH_R(0x20, 0x5, RV_OP), MASK_R, RV64_FMT_R, 0, {0, 0}},
+ {MN("or"), MATCH_R(0x00, 0x6, RV_OP), MASK_R, RV64_FMT_R, 0, {0, 0}},
+ {MN("and"), MATCH_R(0x00, 0x7, RV_OP), MASK_R, RV64_FMT_R, 0, {0, 0}},
/* 32-bit (W) variants — OP_32 = 0x3b */
- {"addw", MATCH_R(0x00, 0x0, RV_OP_32), MASK_R, RV64_FMT_R, 0, {0, 0}},
- {"subw", MATCH_R(0x20, 0x0, RV_OP_32), MASK_R, RV64_FMT_R, 0, {0, 0}},
- {"sllw", MATCH_R(0x00, 0x1, RV_OP_32), MASK_R, RV64_FMT_R, 0, {0, 0}},
- {"srlw", MATCH_R(0x00, 0x5, RV_OP_32), MASK_R, RV64_FMT_R, 0, {0, 0}},
- {"sraw", MATCH_R(0x20, 0x5, RV_OP_32), MASK_R, RV64_FMT_R, 0, {0, 0}},
+ {MN("addw"), MATCH_R(0x00, 0x0, RV_OP_32), MASK_R, RV64_FMT_R, 0, {0, 0}},
+ {MN("subw"), MATCH_R(0x20, 0x0, RV_OP_32), MASK_R, RV64_FMT_R, 0, {0, 0}},
+ {MN("sllw"), MATCH_R(0x00, 0x1, RV_OP_32), MASK_R, RV64_FMT_R, 0, {0, 0}},
+ {MN("srlw"), MATCH_R(0x00, 0x5, RV_OP_32), MASK_R, RV64_FMT_R, 0, {0, 0}},
+ {MN("sraw"), MATCH_R(0x20, 0x5, RV_OP_32), MASK_R, RV64_FMT_R, 0, {0, 0}},
/* ---- I-type immediate ALU (OP_IMM=0x13) ----
* Aliases: `li rd, imm` = ADDI rd, x0, imm (rs1=x0).
* `mv rd, rs1` = ADDI rd, rs1, 0 (imm=0).
* `nop` = ADDI x0, x0, 0 (full word fixed). */
- {"nop", 0x00000013u, 0xffffffffu, RV64_FMT_SYSTEM, RV64_ASMFL_ALIAS,
+ {MN("nop"), 0x00000013u, 0xffffffffu, RV64_FMT_SYSTEM, RV64_ASMFL_ALIAS,
{0, 0}},
- {"li", 0x00000013u, 0x000f807fu, RV64_FMT_I, RV64_ASMFL_ALIAS, {0, 0}},
+ {MN("li"), 0x00000013u, 0x000f807fu, RV64_FMT_I, RV64_ASMFL_ALIAS, {0, 0}},
/* mv: ADDI with imm=0. mask requires imm12=0 + funct3=0 + op. */
- {"mv", 0x00000013u, 0xfff0707fu, RV64_FMT_I, RV64_ASMFL_ALIAS, {0, 0}},
+ {MN("mv"), 0x00000013u, 0xfff0707fu, RV64_FMT_I, RV64_ASMFL_ALIAS, {0, 0}},
/* seqz: SLTIU rd, rs, 1 — funct3=3, imm12=1, op=OP_IMM. */
- {"seqz", 0x00103013u, 0xfff0707fu, RV64_FMT_I, RV64_ASMFL_ALIAS, {0, 0}},
+ {MN("seqz"), 0x00103013u, 0xfff0707fu, RV64_FMT_I, RV64_ASMFL_ALIAS, {0, 0}},
/* snez: SLTU rd, x0, rs2 — rs1=x0, funct3=3, op=OP. */
- {"snez", 0x00003033u, 0xfe0ff07fu, RV64_FMT_R, RV64_ASMFL_ALIAS, {0, 0}},
+ {MN("snez"), 0x00003033u, 0xfe0ff07fu, RV64_FMT_R, RV64_ASMFL_ALIAS, {0, 0}},
/* not: XORI rd, rs, -1 — imm12=0xfff, funct3=4, op=OP_IMM. */
- {"not", 0xfff04013u, 0xfff0707fu, RV64_FMT_I, RV64_ASMFL_ALIAS, {0, 0}},
+ {MN("not"), 0xfff04013u, 0xfff0707fu, RV64_FMT_I, RV64_ASMFL_ALIAS, {0, 0}},
/* neg: SUB rd, x0, rs2 — rs1=x0, funct7=0x20, funct3=0. */
- {"neg", 0x40000033u, 0xfe0ff07fu, RV64_FMT_R, RV64_ASMFL_ALIAS, {0, 0}},
+ {MN("neg"), 0x40000033u, 0xfe0ff07fu, RV64_FMT_R, RV64_ASMFL_ALIAS, {0, 0}},
/* negw: SUBW rd, x0, rs2. */
- {"negw", 0x4000003bu, 0xfe0ff07fu, RV64_FMT_R, RV64_ASMFL_ALIAS, {0, 0}},
- {"addi", MATCH_I(0x0, RV_OP_IMM), MASK_I, RV64_FMT_I, 0, {0, 0}},
- {"slti", MATCH_I(0x2, RV_OP_IMM), MASK_I, RV64_FMT_I, 0, {0, 0}},
- {"sltiu", MATCH_I(0x3, RV_OP_IMM), MASK_I, RV64_FMT_I, 0, {0, 0}},
- {"xori", MATCH_I(0x4, RV_OP_IMM), MASK_I, RV64_FMT_I, 0, {0, 0}},
- {"ori", MATCH_I(0x6, RV_OP_IMM), MASK_I, RV64_FMT_I, 0, {0, 0}},
- {"andi", MATCH_I(0x7, RV_OP_IMM), MASK_I, RV64_FMT_I, 0, {0, 0}},
+ {MN("negw"), 0x4000003bu, 0xfe0ff07fu, RV64_FMT_R, RV64_ASMFL_ALIAS, {0, 0}},
+ {MN("addi"), MATCH_I(0x0, RV_OP_IMM), MASK_I, RV64_FMT_I, 0, {0, 0}},
+ {MN("slti"), MATCH_I(0x2, RV_OP_IMM), MASK_I, RV64_FMT_I, 0, {0, 0}},
+ {MN("sltiu"), MATCH_I(0x3, RV_OP_IMM), MASK_I, RV64_FMT_I, 0, {0, 0}},
+ {MN("xori"), MATCH_I(0x4, RV_OP_IMM), MASK_I, RV64_FMT_I, 0, {0, 0}},
+ {MN("ori"), MATCH_I(0x6, RV_OP_IMM), MASK_I, RV64_FMT_I, 0, {0, 0}},
+ {MN("andi"), MATCH_I(0x7, RV_OP_IMM), MASK_I, RV64_FMT_I, 0, {0, 0}},
/* RV64I shift-imm: funct6 in bits 31:26, shamt in 25:20. */
- {"slli", MATCH_ISHIFT(0x00, 0x1, RV_OP_IMM), MASK_ISHIFT,
+ {MN("slli"), MATCH_ISHIFT(0x00, 0x1, RV_OP_IMM), MASK_ISHIFT,
RV64_FMT_I_SHIFT, 0, {0, 0}},
- {"srli", MATCH_ISHIFT(0x00, 0x5, RV_OP_IMM), MASK_ISHIFT,
+ {MN("srli"), MATCH_ISHIFT(0x00, 0x5, RV_OP_IMM), MASK_ISHIFT,
RV64_FMT_I_SHIFT, 0, {0, 0}},
- {"srai", MATCH_ISHIFT(0x10, 0x5, RV_OP_IMM), MASK_ISHIFT,
+ {MN("srai"), MATCH_ISHIFT(0x10, 0x5, RV_OP_IMM), MASK_ISHIFT,
RV64_FMT_I_SHIFT, 0, {0, 0}},
/* OP_IMM_32: ADDIW + word shifts. sext.w alias = ADDIW rd, rs, 0. */
- {"sext.w", 0x0000001bu, 0xfff0707fu, RV64_FMT_I, RV64_ASMFL_ALIAS,
+ {MN("sext.w"), 0x0000001bu, 0xfff0707fu, RV64_FMT_I, RV64_ASMFL_ALIAS,
{0, 0}},
- {"addiw", MATCH_I(0x0, RV_OP_IMM_32), MASK_I, RV64_FMT_I, 0, {0, 0}},
- {"slliw", MATCH_ISHIFTW(0x00, 0x1, RV_OP_IMM_32), MASK_ISHIFTW,
+ {MN("addiw"), MATCH_I(0x0, RV_OP_IMM_32), MASK_I, RV64_FMT_I, 0, {0, 0}},
+ {MN("slliw"), MATCH_ISHIFTW(0x00, 0x1, RV_OP_IMM_32), MASK_ISHIFTW,
RV64_FMT_I_SHIFTW, 0, {0, 0}},
- {"srliw", MATCH_ISHIFTW(0x00, 0x5, RV_OP_IMM_32), MASK_ISHIFTW,
+ {MN("srliw"), MATCH_ISHIFTW(0x00, 0x5, RV_OP_IMM_32), MASK_ISHIFTW,
RV64_FMT_I_SHIFTW, 0, {0, 0}},
- {"sraiw", MATCH_ISHIFTW(0x20, 0x5, RV_OP_IMM_32), MASK_ISHIFTW,
+ {MN("sraiw"), MATCH_ISHIFTW(0x20, 0x5, RV_OP_IMM_32), MASK_ISHIFTW,
RV64_FMT_I_SHIFTW, 0, {0, 0}},
/* ---- LUI / AUIPC ---- */
- {"lui", MATCH_U(RV_LUI), MASK_U, RV64_FMT_U, 0, {0, 0}},
- {"auipc", MATCH_U(RV_AUIPC), MASK_U, RV64_FMT_U, 0, {0, 0}},
+ {MN("lui"), MATCH_U(RV_LUI), MASK_U, RV64_FMT_U, 0, {0, 0}},
+ {MN("auipc"), MATCH_U(RV_AUIPC), MASK_U, RV64_FMT_U, 0, {0, 0}},
/* ---- Loads (I-type, op=LOAD=0x03) ---- */
- {"lb", MATCH_I(0x0, RV_LOAD), MASK_I, RV64_FMT_LOAD, 0, {0, 0}},
- {"lh", MATCH_I(0x1, RV_LOAD), MASK_I, RV64_FMT_LOAD, 0, {0, 0}},
- {"lw", MATCH_I(0x2, RV_LOAD), MASK_I, RV64_FMT_LOAD, 0, {0, 0}},
- {"ld", MATCH_I(0x3, RV_LOAD), MASK_I, RV64_FMT_LOAD, 0, {0, 0}},
- {"lbu", MATCH_I(0x4, RV_LOAD), MASK_I, RV64_FMT_LOAD, 0, {0, 0}},
- {"lhu", MATCH_I(0x5, RV_LOAD), MASK_I, RV64_FMT_LOAD, 0, {0, 0}},
- {"lwu", MATCH_I(0x6, RV_LOAD), MASK_I, RV64_FMT_LOAD, 0, {0, 0}},
+ {MN("lb"), MATCH_I(0x0, RV_LOAD), MASK_I, RV64_FMT_LOAD, 0, {0, 0}},
+ {MN("lh"), MATCH_I(0x1, RV_LOAD), MASK_I, RV64_FMT_LOAD, 0, {0, 0}},
+ {MN("lw"), MATCH_I(0x2, RV_LOAD), MASK_I, RV64_FMT_LOAD, 0, {0, 0}},
+ {MN("ld"), MATCH_I(0x3, RV_LOAD), MASK_I, RV64_FMT_LOAD, 0, {0, 0}},
+ {MN("lbu"), MATCH_I(0x4, RV_LOAD), MASK_I, RV64_FMT_LOAD, 0, {0, 0}},
+ {MN("lhu"), MATCH_I(0x5, RV_LOAD), MASK_I, RV64_FMT_LOAD, 0, {0, 0}},
+ {MN("lwu"), MATCH_I(0x6, RV_LOAD), MASK_I, RV64_FMT_LOAD, 0, {0, 0}},
/* ---- Stores (S-type, op=STORE=0x23) ---- */
- {"sb", MATCH_S(0x0, RV_STORE), MASK_S, RV64_FMT_STORE, 0, {0, 0}},
- {"sh", MATCH_S(0x1, RV_STORE), MASK_S, RV64_FMT_STORE, 0, {0, 0}},
- {"sw", MATCH_S(0x2, RV_STORE), MASK_S, RV64_FMT_STORE, 0, {0, 0}},
- {"sd", MATCH_S(0x3, RV_STORE), MASK_S, RV64_FMT_STORE, 0, {0, 0}},
+ {MN("sb"), MATCH_S(0x0, RV_STORE), MASK_S, RV64_FMT_STORE, 0, {0, 0}},
+ {MN("sh"), MATCH_S(0x1, RV_STORE), MASK_S, RV64_FMT_STORE, 0, {0, 0}},
+ {MN("sw"), MATCH_S(0x2, RV_STORE), MASK_S, RV64_FMT_STORE, 0, {0, 0}},
+ {MN("sd"), MATCH_S(0x3, RV_STORE), MASK_S, RV64_FMT_STORE, 0, {0, 0}},
/* ---- Branches (B-type, op=BRANCH=0x63) ----
* Aliases: `beqz rs, off` = BEQ rs, x0, off; `bnez rs, off` = BNE. */
- {"beqz", 0x00000063u, 0x01f0707fu, RV64_FMT_B, RV64_ASMFL_ALIAS, {0, 0}},
- {"bnez", 0x00001063u, 0x01f0707fu, RV64_FMT_B, RV64_ASMFL_ALIAS, {0, 0}},
- {"beq", MATCH_B(0x0, RV_BRANCH), MASK_B, RV64_FMT_B, 0, {0, 0}},
- {"bne", MATCH_B(0x1, RV_BRANCH), MASK_B, RV64_FMT_B, 0, {0, 0}},
- {"blt", MATCH_B(0x4, RV_BRANCH), MASK_B, RV64_FMT_B, 0, {0, 0}},
- {"bge", MATCH_B(0x5, RV_BRANCH), MASK_B, RV64_FMT_B, 0, {0, 0}},
- {"bltu", MATCH_B(0x6, RV_BRANCH), MASK_B, RV64_FMT_B, 0, {0, 0}},
- {"bgeu", MATCH_B(0x7, RV_BRANCH), MASK_B, RV64_FMT_B, 0, {0, 0}},
+ {MN("beqz"), 0x00000063u, 0x01f0707fu, RV64_FMT_B, RV64_ASMFL_ALIAS, {0, 0}},
+ {MN("bnez"), 0x00001063u, 0x01f0707fu, RV64_FMT_B, RV64_ASMFL_ALIAS, {0, 0}},
+ {MN("beq"), MATCH_B(0x0, RV_BRANCH), MASK_B, RV64_FMT_B, 0, {0, 0}},
+ {MN("bne"), MATCH_B(0x1, RV_BRANCH), MASK_B, RV64_FMT_B, 0, {0, 0}},
+ {MN("blt"), MATCH_B(0x4, RV_BRANCH), MASK_B, RV64_FMT_B, 0, {0, 0}},
+ {MN("bge"), MATCH_B(0x5, RV_BRANCH), MASK_B, RV64_FMT_B, 0, {0, 0}},
+ {MN("bltu"), MATCH_B(0x6, RV_BRANCH), MASK_B, RV64_FMT_B, 0, {0, 0}},
+ {MN("bgeu"), MATCH_B(0x7, RV_BRANCH), MASK_B, RV64_FMT_B, 0, {0, 0}},
/* ---- JAL / JALR ----
* `j off` = JAL x0, off (rd=x0).
@@ -197,200 +206,200 @@ const Rv64InsnDesc rv64_insn_table[] = {
* `ret` = JALR x0, 0(ra) (rd=x0 + rs1=ra + imm=0).
* `jr rs` = JALR x0, 0(rs) (rd=x0, imm=0).
* `jalr rs` = JALR ra, 0(rs) (rd=ra, imm=0). */
- {"ret", 0x00008067u, 0xffffffffu, RV64_FMT_SYSTEM, RV64_ASMFL_ALIAS,
+ {MN("ret"), 0x00008067u, 0xffffffffu, RV64_FMT_SYSTEM, RV64_ASMFL_ALIAS,
{0, 0}},
- {"jr", 0x00000067u, 0xfff07fffu, RV64_FMT_JALR, RV64_ASMFL_ALIAS,
+ {MN("jr"), 0x00000067u, 0xfff07fffu, RV64_FMT_JALR, RV64_ASMFL_ALIAS,
{0, 0}},
- {"j", 0x0000006fu, 0x00000fffu, RV64_FMT_J, RV64_ASMFL_ALIAS, {0, 0}},
- {"jal", MATCH_J(RV_JAL), MASK_J, RV64_FMT_J, 0, {0, 0}},
- {"jalr", MATCH_I(0x0, RV_JALR), MASK_I, RV64_FMT_JALR, 0, {0, 0}},
+ {MN("j"), 0x0000006fu, 0x00000fffu, RV64_FMT_J, RV64_ASMFL_ALIAS, {0, 0}},
+ {MN("jal"), MATCH_J(RV_JAL), MASK_J, RV64_FMT_J, 0, {0, 0}},
+ {MN("jalr"), MATCH_I(0x0, RV_JALR), MASK_I, RV64_FMT_JALR, 0, {0, 0}},
/* ---- FENCE ---- */
- {"fence", MATCH_I(0x0, RV_FENCE), MASK_I, RV64_FMT_FENCE, 0, {0, 0}},
- {"fence.i", MATCH_FULL(0x0000100fu), MASK_FULL, RV64_FMT_SYSTEM, 0,
+ {MN("fence"), MATCH_I(0x0, RV_FENCE), MASK_I, RV64_FMT_FENCE, 0, {0, 0}},
+ {MN("fence.i"), MATCH_FULL(0x0000100fu), MASK_FULL, RV64_FMT_SYSTEM, 0,
{0, 0}},
/* ---- System (ECALL/EBREAK) ---- */
- {"ecall", MATCH_FULL(0x00000073u), MASK_FULL, RV64_FMT_SYSTEM, 0,
+ {MN("ecall"), MATCH_FULL(0x00000073u), MASK_FULL, RV64_FMT_SYSTEM, 0,
{0, 0}},
- {"ebreak", MATCH_FULL(0x00100073u), MASK_FULL, RV64_FMT_SYSTEM, 0,
+ {MN("ebreak"), MATCH_FULL(0x00100073u), MASK_FULL, RV64_FMT_SYSTEM, 0,
{0, 0}},
/* =================================================================
* Zicsr (CSR access) — RV_SYSTEM with funct3 ∈ {1..3, 5..7}.
* ================================================================= */
- {"csrrw", MATCH_CSR(0x1), MASK_CSR, RV64_FMT_CSR, 0, {0, 0}},
- {"csrrs", MATCH_CSR(0x2), MASK_CSR, RV64_FMT_CSR, 0, {0, 0}},
- {"csrrc", MATCH_CSR(0x3), MASK_CSR, RV64_FMT_CSR, 0, {0, 0}},
- {"csrrwi", MATCH_CSR(0x5), MASK_CSR, RV64_FMT_CSRI, 0, {0, 0}},
- {"csrrsi", MATCH_CSR(0x6), MASK_CSR, RV64_FMT_CSRI, 0, {0, 0}},
- {"csrrci", MATCH_CSR(0x7), MASK_CSR, RV64_FMT_CSRI, 0, {0, 0}},
+ {MN("csrrw"), MATCH_CSR(0x1), MASK_CSR, RV64_FMT_CSR, 0, {0, 0}},
+ {MN("csrrs"), MATCH_CSR(0x2), MASK_CSR, RV64_FMT_CSR, 0, {0, 0}},
+ {MN("csrrc"), MATCH_CSR(0x3), MASK_CSR, RV64_FMT_CSR, 0, {0, 0}},
+ {MN("csrrwi"), MATCH_CSR(0x5), MASK_CSR, RV64_FMT_CSRI, 0, {0, 0}},
+ {MN("csrrsi"), MATCH_CSR(0x6), MASK_CSR, RV64_FMT_CSRI, 0, {0, 0}},
+ {MN("csrrci"), MATCH_CSR(0x7), MASK_CSR, RV64_FMT_CSRI, 0, {0, 0}},
/* =================================================================
* RV64M (multiply / divide) — funct7 = 0x01
* ================================================================= */
- {"mul", MATCH_R(0x01, 0x0, RV_OP), MASK_R, RV64_FMT_R, 0, {0, 0}},
- {"mulh", MATCH_R(0x01, 0x1, RV_OP), MASK_R, RV64_FMT_R, 0, {0, 0}},
- {"mulhsu", MATCH_R(0x01, 0x2, RV_OP), MASK_R, RV64_FMT_R, 0, {0, 0}},
- {"mulhu", MATCH_R(0x01, 0x3, RV_OP), MASK_R, RV64_FMT_R, 0, {0, 0}},
- {"div", MATCH_R(0x01, 0x4, RV_OP), MASK_R, RV64_FMT_R, 0, {0, 0}},
- {"divu", MATCH_R(0x01, 0x5, RV_OP), MASK_R, RV64_FMT_R, 0, {0, 0}},
- {"rem", MATCH_R(0x01, 0x6, RV_OP), MASK_R, RV64_FMT_R, 0, {0, 0}},
- {"remu", MATCH_R(0x01, 0x7, RV_OP), MASK_R, RV64_FMT_R, 0, {0, 0}},
- {"mulw", MATCH_R(0x01, 0x0, RV_OP_32), MASK_R, RV64_FMT_R, 0, {0, 0}},
- {"divw", MATCH_R(0x01, 0x4, RV_OP_32), MASK_R, RV64_FMT_R, 0, {0, 0}},
- {"divuw", MATCH_R(0x01, 0x5, RV_OP_32), MASK_R, RV64_FMT_R, 0, {0, 0}},
- {"remw", MATCH_R(0x01, 0x6, RV_OP_32), MASK_R, RV64_FMT_R, 0, {0, 0}},
- {"remuw", MATCH_R(0x01, 0x7, RV_OP_32), MASK_R, RV64_FMT_R, 0, {0, 0}},
+ {MN("mul"), MATCH_R(0x01, 0x0, RV_OP), MASK_R, RV64_FMT_R, 0, {0, 0}},
+ {MN("mulh"), MATCH_R(0x01, 0x1, RV_OP), MASK_R, RV64_FMT_R, 0, {0, 0}},
+ {MN("mulhsu"), MATCH_R(0x01, 0x2, RV_OP), MASK_R, RV64_FMT_R, 0, {0, 0}},
+ {MN("mulhu"), MATCH_R(0x01, 0x3, RV_OP), MASK_R, RV64_FMT_R, 0, {0, 0}},
+ {MN("div"), MATCH_R(0x01, 0x4, RV_OP), MASK_R, RV64_FMT_R, 0, {0, 0}},
+ {MN("divu"), MATCH_R(0x01, 0x5, RV_OP), MASK_R, RV64_FMT_R, 0, {0, 0}},
+ {MN("rem"), MATCH_R(0x01, 0x6, RV_OP), MASK_R, RV64_FMT_R, 0, {0, 0}},
+ {MN("remu"), MATCH_R(0x01, 0x7, RV_OP), MASK_R, RV64_FMT_R, 0, {0, 0}},
+ {MN("mulw"), MATCH_R(0x01, 0x0, RV_OP_32), MASK_R, RV64_FMT_R, 0, {0, 0}},
+ {MN("divw"), MATCH_R(0x01, 0x4, RV_OP_32), MASK_R, RV64_FMT_R, 0, {0, 0}},
+ {MN("divuw"), MATCH_R(0x01, 0x5, RV_OP_32), MASK_R, RV64_FMT_R, 0, {0, 0}},
+ {MN("remw"), MATCH_R(0x01, 0x6, RV_OP_32), MASK_R, RV64_FMT_R, 0, {0, 0}},
+ {MN("remuw"), MATCH_R(0x01, 0x7, RV_OP_32), MASK_R, RV64_FMT_R, 0, {0, 0}},
/* =================================================================
* RV32F / RV32D — single and double precision FP
* ================================================================= */
/* FP fused multiply-add/subtract — rm defaults to dyn in the assembler. */
- {"fmadd.s", MATCH_R4(RV_FMT_S, RV_MADD), MASK_R4, RV64_FMT_R4,
+ {MN("fmadd.s"), MATCH_R4(RV_FMT_S, RV_MADD), MASK_R4, RV64_FMT_R4,
RV64_ASMFL_FP, {0, 0}},
- {"fmsub.s", MATCH_R4(RV_FMT_S, RV_MSUB), MASK_R4, RV64_FMT_R4,
+ {MN("fmsub.s"), MATCH_R4(RV_FMT_S, RV_MSUB), MASK_R4, RV64_FMT_R4,
RV64_ASMFL_FP, {0, 0}},
- {"fnmsub.s", MATCH_R4(RV_FMT_S, RV_NMSUB), MASK_R4, RV64_FMT_R4,
+ {MN("fnmsub.s"), MATCH_R4(RV_FMT_S, RV_NMSUB), MASK_R4, RV64_FMT_R4,
RV64_ASMFL_FP, {0, 0}},
- {"fnmadd.s", MATCH_R4(RV_FMT_S, RV_NMADD), MASK_R4, RV64_FMT_R4,
+ {MN("fnmadd.s"), MATCH_R4(RV_FMT_S, RV_NMADD), MASK_R4, RV64_FMT_R4,
RV64_ASMFL_FP, {0, 0}},
- {"fmadd.d", MATCH_R4(RV_FMT_D, RV_MADD), MASK_R4, RV64_FMT_R4,
+ {MN("fmadd.d"), MATCH_R4(RV_FMT_D, RV_MADD), MASK_R4, RV64_FMT_R4,
RV64_ASMFL_FP, {0, 0}},
- {"fmsub.d", MATCH_R4(RV_FMT_D, RV_MSUB), MASK_R4, RV64_FMT_R4,
+ {MN("fmsub.d"), MATCH_R4(RV_FMT_D, RV_MSUB), MASK_R4, RV64_FMT_R4,
RV64_ASMFL_FP, {0, 0}},
- {"fnmsub.d", MATCH_R4(RV_FMT_D, RV_NMSUB), MASK_R4, RV64_FMT_R4,
+ {MN("fnmsub.d"), MATCH_R4(RV_FMT_D, RV_NMSUB), MASK_R4, RV64_FMT_R4,
RV64_ASMFL_FP, {0, 0}},
- {"fnmadd.d", MATCH_R4(RV_FMT_D, RV_NMADD), MASK_R4, RV64_FMT_R4,
+ {MN("fnmadd.d"), MATCH_R4(RV_FMT_D, RV_NMADD), MASK_R4, RV64_FMT_R4,
RV64_ASMFL_FP, {0, 0}},
/* FP arithmetic — rm field (funct3) is the rounding mode and prints
* as the DYN(=7) default suppressed. funct7 low bits select fmt. */
- {"fadd.s", MATCH_FP_RM(0x00, RV_OP_FP), MASK_FP_RM, RV64_FMT_FP_RM,
+ {MN("fadd.s"), MATCH_FP_RM(0x00, RV_OP_FP), MASK_FP_RM, RV64_FMT_FP_RM,
RV64_ASMFL_FP, {0, 0}},
- {"fsub.s", MATCH_FP_RM(0x04, RV_OP_FP), MASK_FP_RM, RV64_FMT_FP_RM,
+ {MN("fsub.s"), MATCH_FP_RM(0x04, RV_OP_FP), MASK_FP_RM, RV64_FMT_FP_RM,
RV64_ASMFL_FP, {0, 0}},
- {"fmul.s", MATCH_FP_RM(0x08, RV_OP_FP), MASK_FP_RM, RV64_FMT_FP_RM,
+ {MN("fmul.s"), MATCH_FP_RM(0x08, RV_OP_FP), MASK_FP_RM, RV64_FMT_FP_RM,
RV64_ASMFL_FP, {0, 0}},
- {"fdiv.s", MATCH_FP_RM(0x0c, RV_OP_FP), MASK_FP_RM, RV64_FMT_FP_RM,
+ {MN("fdiv.s"), MATCH_FP_RM(0x0c, RV_OP_FP), MASK_FP_RM, RV64_FMT_FP_RM,
RV64_ASMFL_FP, {0, 0}},
- {"fadd.d", MATCH_FP_RM(0x01, RV_OP_FP), MASK_FP_RM, RV64_FMT_FP_RM,
+ {MN("fadd.d"), MATCH_FP_RM(0x01, RV_OP_FP), MASK_FP_RM, RV64_FMT_FP_RM,
RV64_ASMFL_FP, {0, 0}},
- {"fsub.d", MATCH_FP_RM(0x05, RV_OP_FP), MASK_FP_RM, RV64_FMT_FP_RM,
+ {MN("fsub.d"), MATCH_FP_RM(0x05, RV_OP_FP), MASK_FP_RM, RV64_FMT_FP_RM,
RV64_ASMFL_FP, {0, 0}},
- {"fmul.d", MATCH_FP_RM(0x09, RV_OP_FP), MASK_FP_RM, RV64_FMT_FP_RM,
+ {MN("fmul.d"), MATCH_FP_RM(0x09, RV_OP_FP), MASK_FP_RM, RV64_FMT_FP_RM,
RV64_ASMFL_FP, {0, 0}},
- {"fdiv.d", MATCH_FP_RM(0x0d, RV_OP_FP), MASK_FP_RM, RV64_FMT_FP_RM,
+ {MN("fdiv.d"), MATCH_FP_RM(0x0d, RV_OP_FP), MASK_FP_RM, RV64_FMT_FP_RM,
RV64_ASMFL_FP, {0, 0}},
/* FP sqrt — funct7 = 0x2c (S) / 0x2d (D), rs2 must be 0. */
- {"fsqrt.s", MATCH_FP_CVT(0x2c, 0x0, RV_OP_FP), MASK_FP_CVT,
+ {MN("fsqrt.s"), MATCH_FP_CVT(0x2c, 0x0, RV_OP_FP), MASK_FP_CVT,
RV64_FMT_FP_CVT, RV64_ASMFL_FP, {0, 0}},
- {"fsqrt.d", MATCH_FP_CVT(0x2d, 0x0, RV_OP_FP), MASK_FP_CVT,
+ {MN("fsqrt.d"), MATCH_FP_CVT(0x2d, 0x0, RV_OP_FP), MASK_FP_CVT,
RV64_FMT_FP_CVT, RV64_ASMFL_FP, {0, 0}},
/* FP min/max — funct7 = 0x14/0x15, funct3 = 0 (min) / 1 (max). */
- {"fmin.s", MATCH_FP_R(0x14, 0x0, RV_OP_FP), MASK_FP_R, RV64_FMT_FP_R,
+ {MN("fmin.s"), MATCH_FP_R(0x14, 0x0, RV_OP_FP), MASK_FP_R, RV64_FMT_FP_R,
RV64_ASMFL_FP | RV64_ASMFL_NORM, {0, 0}},
- {"fmax.s", MATCH_FP_R(0x14, 0x1, RV_OP_FP), MASK_FP_R, RV64_FMT_FP_R,
+ {MN("fmax.s"), MATCH_FP_R(0x14, 0x1, RV_OP_FP), MASK_FP_R, RV64_FMT_FP_R,
RV64_ASMFL_FP | RV64_ASMFL_NORM, {0, 0}},
- {"fmin.d", MATCH_FP_R(0x15, 0x0, RV_OP_FP), MASK_FP_R, RV64_FMT_FP_R,
+ {MN("fmin.d"), MATCH_FP_R(0x15, 0x0, RV_OP_FP), MASK_FP_R, RV64_FMT_FP_R,
RV64_ASMFL_FP | RV64_ASMFL_NORM, {0, 0}},
- {"fmax.d", MATCH_FP_R(0x15, 0x1, RV_OP_FP), MASK_FP_R, RV64_FMT_FP_R,
+ {MN("fmax.d"), MATCH_FP_R(0x15, 0x1, RV_OP_FP), MASK_FP_R, RV64_FMT_FP_R,
RV64_ASMFL_FP | RV64_ASMFL_NORM, {0, 0}},
/* FP sign-injection — funct7 = 0x10/0x11, funct3 = 0/1/2 = J/JN/JX. */
- {"fsgnj.s", MATCH_FP_R(0x10, 0x0, RV_OP_FP), MASK_FP_R, RV64_FMT_FP_R,
+ {MN("fsgnj.s"), MATCH_FP_R(0x10, 0x0, RV_OP_FP), MASK_FP_R, RV64_FMT_FP_R,
RV64_ASMFL_FP | RV64_ASMFL_NORM, {0, 0}},
- {"fsgnjn.s", MATCH_FP_R(0x10, 0x1, RV_OP_FP), MASK_FP_R, RV64_FMT_FP_R,
+ {MN("fsgnjn.s"), MATCH_FP_R(0x10, 0x1, RV_OP_FP), MASK_FP_R, RV64_FMT_FP_R,
RV64_ASMFL_FP | RV64_ASMFL_NORM, {0, 0}},
- {"fsgnjx.s", MATCH_FP_R(0x10, 0x2, RV_OP_FP), MASK_FP_R, RV64_FMT_FP_R,
+ {MN("fsgnjx.s"), MATCH_FP_R(0x10, 0x2, RV_OP_FP), MASK_FP_R, RV64_FMT_FP_R,
RV64_ASMFL_FP | RV64_ASMFL_NORM, {0, 0}},
- {"fsgnj.d", MATCH_FP_R(0x11, 0x0, RV_OP_FP), MASK_FP_R, RV64_FMT_FP_R,
+ {MN("fsgnj.d"), MATCH_FP_R(0x11, 0x0, RV_OP_FP), MASK_FP_R, RV64_FMT_FP_R,
RV64_ASMFL_FP | RV64_ASMFL_NORM, {0, 0}},
- {"fsgnjn.d", MATCH_FP_R(0x11, 0x1, RV_OP_FP), MASK_FP_R, RV64_FMT_FP_R,
+ {MN("fsgnjn.d"), MATCH_FP_R(0x11, 0x1, RV_OP_FP), MASK_FP_R, RV64_FMT_FP_R,
RV64_ASMFL_FP | RV64_ASMFL_NORM, {0, 0}},
- {"fsgnjx.d", MATCH_FP_R(0x11, 0x2, RV_OP_FP), MASK_FP_R, RV64_FMT_FP_R,
+ {MN("fsgnjx.d"), MATCH_FP_R(0x11, 0x2, RV_OP_FP), MASK_FP_R, RV64_FMT_FP_R,
RV64_ASMFL_FP | RV64_ASMFL_NORM, {0, 0}},
/* FP compare — funct7 = 0x50 (S) / 0x51 (D), funct3 = 0/1/2 = LE/LT/EQ.
* rd is integer GPR (not FP). */
- {"fle.s", MATCH_FP_R(0x50, 0x0, RV_OP_FP), MASK_FP_R, RV64_FMT_FP_R,
+ {MN("fle.s"), MATCH_FP_R(0x50, 0x0, RV_OP_FP), MASK_FP_R, RV64_FMT_FP_R,
RV64_ASMFL_NORM, {0, 0}},
- {"flt.s", MATCH_FP_R(0x50, 0x1, RV_OP_FP), MASK_FP_R, RV64_FMT_FP_R,
+ {MN("flt.s"), MATCH_FP_R(0x50, 0x1, RV_OP_FP), MASK_FP_R, RV64_FMT_FP_R,
RV64_ASMFL_NORM, {0, 0}},
- {"feq.s", MATCH_FP_R(0x50, 0x2, RV_OP_FP), MASK_FP_R, RV64_FMT_FP_R,
+ {MN("feq.s"), MATCH_FP_R(0x50, 0x2, RV_OP_FP), MASK_FP_R, RV64_FMT_FP_R,
RV64_ASMFL_NORM, {0, 0}},
- {"fle.d", MATCH_FP_R(0x51, 0x0, RV_OP_FP), MASK_FP_R, RV64_FMT_FP_R,
+ {MN("fle.d"), MATCH_FP_R(0x51, 0x0, RV_OP_FP), MASK_FP_R, RV64_FMT_FP_R,
RV64_ASMFL_NORM, {0, 0}},
- {"flt.d", MATCH_FP_R(0x51, 0x1, RV_OP_FP), MASK_FP_R, RV64_FMT_FP_R,
+ {MN("flt.d"), MATCH_FP_R(0x51, 0x1, RV_OP_FP), MASK_FP_R, RV64_FMT_FP_R,
RV64_ASMFL_NORM, {0, 0}},
- {"feq.d", MATCH_FP_R(0x51, 0x2, RV_OP_FP), MASK_FP_R, RV64_FMT_FP_R,
+ {MN("feq.d"), MATCH_FP_R(0x51, 0x2, RV_OP_FP), MASK_FP_R, RV64_FMT_FP_R,
RV64_ASMFL_NORM, {0, 0}},
/* FP classification — rd is GPR, rs1 is FPR, rs2=0, rm/funct3=1. */
- {"fclass.s", MATCH_FP_R(0x70, 0x1, RV_OP_FP) | (0u << 20),
+ {MN("fclass.s"), MATCH_FP_R(0x70, 0x1, RV_OP_FP) | (0u << 20),
MASK_FP_CVT | (7u << 12), RV64_FMT_FP_CVT, 0, {0, 0}},
- {"fclass.d", MATCH_FP_R(0x71, 0x1, RV_OP_FP) | (0u << 20),
+ {MN("fclass.d"), MATCH_FP_R(0x71, 0x1, RV_OP_FP) | (0u << 20),
MASK_FP_CVT | (7u << 12), RV64_FMT_FP_CVT, 0, {0, 0}},
/* FP conversions — funct7 selects {direction, fmt}, rs2 selects
* integer width/signedness. */
- {"fcvt.w.s", MATCH_FP_CVT(0x60, 0x0, RV_OP_FP), MASK_FP_CVT,
+ {MN("fcvt.w.s"), MATCH_FP_CVT(0x60, 0x0, RV_OP_FP), MASK_FP_CVT,
RV64_FMT_FP_CVT, 0, {0, 0}},
- {"fcvt.wu.s", MATCH_FP_CVT(0x60, 0x1, RV_OP_FP), MASK_FP_CVT,
+ {MN("fcvt.wu.s"), MATCH_FP_CVT(0x60, 0x1, RV_OP_FP), MASK_FP_CVT,
RV64_FMT_FP_CVT, 0, {0, 0}},
- {"fcvt.l.s", MATCH_FP_CVT(0x60, 0x2, RV_OP_FP), MASK_FP_CVT,
+ {MN("fcvt.l.s"), MATCH_FP_CVT(0x60, 0x2, RV_OP_FP), MASK_FP_CVT,
RV64_FMT_FP_CVT, 0, {0, 0}},
- {"fcvt.lu.s", MATCH_FP_CVT(0x60, 0x3, RV_OP_FP), MASK_FP_CVT,
+ {MN("fcvt.lu.s"), MATCH_FP_CVT(0x60, 0x3, RV_OP_FP), MASK_FP_CVT,
RV64_FMT_FP_CVT, 0, {0, 0}},
- {"fcvt.w.d", MATCH_FP_CVT(0x61, 0x0, RV_OP_FP), MASK_FP_CVT,
+ {MN("fcvt.w.d"), MATCH_FP_CVT(0x61, 0x0, RV_OP_FP), MASK_FP_CVT,
RV64_FMT_FP_CVT, 0, {0, 0}},
- {"fcvt.wu.d", MATCH_FP_CVT(0x61, 0x1, RV_OP_FP), MASK_FP_CVT,
+ {MN("fcvt.wu.d"), MATCH_FP_CVT(0x61, 0x1, RV_OP_FP), MASK_FP_CVT,
RV64_FMT_FP_CVT, 0, {0, 0}},
- {"fcvt.l.d", MATCH_FP_CVT(0x61, 0x2, RV_OP_FP), MASK_FP_CVT,
+ {MN("fcvt.l.d"), MATCH_FP_CVT(0x61, 0x2, RV_OP_FP), MASK_FP_CVT,
RV64_FMT_FP_CVT, 0, {0, 0}},
- {"fcvt.lu.d", MATCH_FP_CVT(0x61, 0x3, RV_OP_FP), MASK_FP_CVT,
+ {MN("fcvt.lu.d"), MATCH_FP_CVT(0x61, 0x3, RV_OP_FP), MASK_FP_CVT,
RV64_FMT_FP_CVT, 0, {0, 0}},
- {"fcvt.s.w", MATCH_FP_CVT(0x68, 0x0, RV_OP_FP), MASK_FP_CVT,
+ {MN("fcvt.s.w"), MATCH_FP_CVT(0x68, 0x0, RV_OP_FP), MASK_FP_CVT,
RV64_FMT_FP_CVT, RV64_ASMFL_FP, {0, 0}},
- {"fcvt.s.wu", MATCH_FP_CVT(0x68, 0x1, RV_OP_FP), MASK_FP_CVT,
+ {MN("fcvt.s.wu"), MATCH_FP_CVT(0x68, 0x1, RV_OP_FP), MASK_FP_CVT,
RV64_FMT_FP_CVT, RV64_ASMFL_FP, {0, 0}},
- {"fcvt.s.l", MATCH_FP_CVT(0x68, 0x2, RV_OP_FP), MASK_FP_CVT,
+ {MN("fcvt.s.l"), MATCH_FP_CVT(0x68, 0x2, RV_OP_FP), MASK_FP_CVT,
RV64_FMT_FP_CVT, RV64_ASMFL_FP, {0, 0}},
- {"fcvt.s.lu", MATCH_FP_CVT(0x68, 0x3, RV_OP_FP), MASK_FP_CVT,
+ {MN("fcvt.s.lu"), MATCH_FP_CVT(0x68, 0x3, RV_OP_FP), MASK_FP_CVT,
RV64_FMT_FP_CVT, RV64_ASMFL_FP, {0, 0}},
- {"fcvt.d.w", MATCH_FP_CVT(0x69, 0x0, RV_OP_FP), MASK_FP_CVT,
+ {MN("fcvt.d.w"), MATCH_FP_CVT(0x69, 0x0, RV_OP_FP), MASK_FP_CVT,
RV64_FMT_FP_CVT, RV64_ASMFL_FP, {0, 0}},
- {"fcvt.d.wu", MATCH_FP_CVT(0x69, 0x1, RV_OP_FP), MASK_FP_CVT,
+ {MN("fcvt.d.wu"), MATCH_FP_CVT(0x69, 0x1, RV_OP_FP), MASK_FP_CVT,
RV64_FMT_FP_CVT, RV64_ASMFL_FP, {0, 0}},
- {"fcvt.d.l", MATCH_FP_CVT(0x69, 0x2, RV_OP_FP), MASK_FP_CVT,
+ {MN("fcvt.d.l"), MATCH_FP_CVT(0x69, 0x2, RV_OP_FP), MASK_FP_CVT,
RV64_FMT_FP_CVT, RV64_ASMFL_FP, {0, 0}},
- {"fcvt.d.lu", MATCH_FP_CVT(0x69, 0x3, RV_OP_FP), MASK_FP_CVT,
+ {MN("fcvt.d.lu"), MATCH_FP_CVT(0x69, 0x3, RV_OP_FP), MASK_FP_CVT,
RV64_FMT_FP_CVT, RV64_ASMFL_FP, {0, 0}},
- {"fcvt.s.d", MATCH_FP_CVT(0x20, 0x1, RV_OP_FP), MASK_FP_CVT,
+ {MN("fcvt.s.d"), MATCH_FP_CVT(0x20, 0x1, RV_OP_FP), MASK_FP_CVT,
RV64_FMT_FP_CVT, RV64_ASMFL_FP, {0, 0}},
- {"fcvt.d.s", MATCH_FP_CVT(0x21, 0x0, RV_OP_FP), MASK_FP_CVT,
+ {MN("fcvt.d.s"), MATCH_FP_CVT(0x21, 0x0, RV_OP_FP), MASK_FP_CVT,
RV64_FMT_FP_CVT, RV64_ASMFL_FP, {0, 0}},
/* FP bitcast moves — funct7 + rs2=0 + funct3=0 fixed. */
- {"fmv.x.w", MATCH_FP_CVT(0x70, 0x0, RV_OP_FP), MASK_FP_CVT,
+ {MN("fmv.x.w"), MATCH_FP_CVT(0x70, 0x0, RV_OP_FP), MASK_FP_CVT,
RV64_FMT_FP_CVT, 0, {0, 0}},
- {"fmv.w.x", MATCH_FP_CVT(0x78, 0x0, RV_OP_FP), MASK_FP_CVT,
+ {MN("fmv.w.x"), MATCH_FP_CVT(0x78, 0x0, RV_OP_FP), MASK_FP_CVT,
RV64_FMT_FP_CVT, RV64_ASMFL_FP, {0, 0}},
- {"fmv.x.d", MATCH_FP_CVT(0x71, 0x0, RV_OP_FP), MASK_FP_CVT,
+ {MN("fmv.x.d"), MATCH_FP_CVT(0x71, 0x0, RV_OP_FP), MASK_FP_CVT,
RV64_FMT_FP_CVT, 0, {0, 0}},
- {"fmv.d.x", MATCH_FP_CVT(0x79, 0x0, RV_OP_FP), MASK_FP_CVT,
+ {MN("fmv.d.x"), MATCH_FP_CVT(0x79, 0x0, RV_OP_FP), MASK_FP_CVT,
RV64_FMT_FP_CVT, RV64_ASMFL_FP, {0, 0}},
/* FP load/store */
- {"flw", MATCH_I(0x2, RV_LOAD_FP), MASK_I, RV64_FMT_FP_LOAD,
+ {MN("flw"), MATCH_I(0x2, RV_LOAD_FP), MASK_I, RV64_FMT_FP_LOAD,
RV64_ASMFL_FP, {0, 0}},
- {"fld", MATCH_I(0x3, RV_LOAD_FP), MASK_I, RV64_FMT_FP_LOAD,
+ {MN("fld"), MATCH_I(0x3, RV_LOAD_FP), MASK_I, RV64_FMT_FP_LOAD,
RV64_ASMFL_FP, {0, 0}},
- {"fsw", MATCH_S(0x2, RV_STORE_FP), MASK_S, RV64_FMT_FP_STORE,
+ {MN("fsw"), MATCH_S(0x2, RV_STORE_FP), MASK_S, RV64_FMT_FP_STORE,
RV64_ASMFL_FP, {0, 0}},
- {"fsd", MATCH_S(0x3, RV_STORE_FP), MASK_S, RV64_FMT_FP_STORE,
+ {MN("fsd"), MATCH_S(0x3, RV_STORE_FP), MASK_S, RV64_FMT_FP_STORE,
RV64_ASMFL_FP, {0, 0}},
/* =================================================================
@@ -399,36 +408,36 @@ const Rv64InsnDesc rv64_insn_table[] = {
* suffixes via the disassembler's annotation, but the row mnemonic
* itself is the bare form (e.g. "amoadd.w").
* ================================================================= */
- {"lr.w.aq", MATCH_AMO_ORDER(0x02, 1, 0, 0x2, RV_AMO),
+ {MN("lr.w.aq"), MATCH_AMO_ORDER(0x02, 1, 0, 0x2, RV_AMO),
MASK_AMO_ORDER | (0x1fu << 20), RV64_FMT_LR, 0, {0, 0}},
- {"lr.w.rl", MATCH_AMO_ORDER(0x02, 0, 1, 0x2, RV_AMO),
+ {MN("lr.w.rl"), MATCH_AMO_ORDER(0x02, 0, 1, 0x2, RV_AMO),
MASK_AMO_ORDER | (0x1fu << 20), RV64_FMT_LR, 0, {0, 0}},
- {"lr.w.aqrl", MATCH_AMO_ORDER(0x02, 1, 1, 0x2, RV_AMO),
+ {MN("lr.w.aqrl"), MATCH_AMO_ORDER(0x02, 1, 1, 0x2, RV_AMO),
MASK_AMO_ORDER | (0x1fu << 20), RV64_FMT_LR, 0, {0, 0}},
- {"lr.d.aq", MATCH_AMO_ORDER(0x02, 1, 0, 0x3, RV_AMO),
+ {MN("lr.d.aq"), MATCH_AMO_ORDER(0x02, 1, 0, 0x3, RV_AMO),
MASK_AMO_ORDER | (0x1fu << 20), RV64_FMT_LR, 0, {0, 0}},
- {"lr.d.rl", MATCH_AMO_ORDER(0x02, 0, 1, 0x3, RV_AMO),
+ {MN("lr.d.rl"), MATCH_AMO_ORDER(0x02, 0, 1, 0x3, RV_AMO),
MASK_AMO_ORDER | (0x1fu << 20), RV64_FMT_LR, 0, {0, 0}},
- {"lr.d.aqrl", MATCH_AMO_ORDER(0x02, 1, 1, 0x3, RV_AMO),
+ {MN("lr.d.aqrl"), MATCH_AMO_ORDER(0x02, 1, 1, 0x3, RV_AMO),
MASK_AMO_ORDER | (0x1fu << 20), RV64_FMT_LR, 0, {0, 0}},
- {"sc.w.aq", MATCH_AMO_ORDER(0x03, 1, 0, 0x2, RV_AMO),
+ {MN("sc.w.aq"), MATCH_AMO_ORDER(0x03, 1, 0, 0x2, RV_AMO),
MASK_AMO_ORDER, RV64_FMT_AMO, 0, {0, 0}},
- {"sc.w.rl", MATCH_AMO_ORDER(0x03, 0, 1, 0x2, RV_AMO),
+ {MN("sc.w.rl"), MATCH_AMO_ORDER(0x03, 0, 1, 0x2, RV_AMO),
MASK_AMO_ORDER, RV64_FMT_AMO, 0, {0, 0}},
- {"sc.w.aqrl", MATCH_AMO_ORDER(0x03, 1, 1, 0x2, RV_AMO),
+ {MN("sc.w.aqrl"), MATCH_AMO_ORDER(0x03, 1, 1, 0x2, RV_AMO),
MASK_AMO_ORDER, RV64_FMT_AMO, 0, {0, 0}},
- {"sc.d.aq", MATCH_AMO_ORDER(0x03, 1, 0, 0x3, RV_AMO),
+ {MN("sc.d.aq"), MATCH_AMO_ORDER(0x03, 1, 0, 0x3, RV_AMO),
MASK_AMO_ORDER, RV64_FMT_AMO, 0, {0, 0}},
- {"sc.d.rl", MATCH_AMO_ORDER(0x03, 0, 1, 0x3, RV_AMO),
+ {MN("sc.d.rl"), MATCH_AMO_ORDER(0x03, 0, 1, 0x3, RV_AMO),
MASK_AMO_ORDER, RV64_FMT_AMO, 0, {0, 0}},
- {"sc.d.aqrl", MATCH_AMO_ORDER(0x03, 1, 1, 0x3, RV_AMO),
+ {MN("sc.d.aqrl"), MATCH_AMO_ORDER(0x03, 1, 1, 0x3, RV_AMO),
MASK_AMO_ORDER, RV64_FMT_AMO, 0, {0, 0}},
#define RV64_AMO_ORDER_ROWS(mn, f5, f3) \
- {mn ".aq", MATCH_AMO_ORDER(f5, 1, 0, f3, RV_AMO), MASK_AMO_ORDER, \
+ {MN(mn ".aq"), MATCH_AMO_ORDER(f5, 1, 0, f3, RV_AMO), MASK_AMO_ORDER, \
RV64_FMT_AMO, 0, {0, 0}}, \
- {mn ".rl", MATCH_AMO_ORDER(f5, 0, 1, f3, RV_AMO), MASK_AMO_ORDER, \
+ {MN(mn ".rl"), MATCH_AMO_ORDER(f5, 0, 1, f3, RV_AMO), MASK_AMO_ORDER, \
RV64_FMT_AMO, 0, {0, 0}}, \
- {mn ".aqrl", MATCH_AMO_ORDER(f5, 1, 1, f3, RV_AMO), MASK_AMO_ORDER, \
+ {MN(mn ".aqrl"), MATCH_AMO_ORDER(f5, 1, 1, f3, RV_AMO), MASK_AMO_ORDER, \
RV64_FMT_AMO, 0, {0, 0}}
RV64_AMO_ORDER_ROWS("amoswap.w", RV_AMO_SWAP, 0x2),
RV64_AMO_ORDER_ROWS("amoadd.w", RV_AMO_ADD, 0x2),
@@ -448,101 +457,101 @@ const Rv64InsnDesc rv64_insn_table[] = {
RV64_AMO_ORDER_ROWS("amomax.d", RV_AMO_MAX, 0x3),
RV64_AMO_ORDER_ROWS("amominu.d", RV_AMO_MINU, 0x3),
RV64_AMO_ORDER_ROWS("amomaxu.d", RV_AMO_MAXU, 0x3),
- {"lr.w", MATCH_AMO(0x02, 0x2, RV_AMO), MASK_AMO | (0x1fu << 20),
+ {MN("lr.w"), MATCH_AMO(0x02, 0x2, RV_AMO), MASK_AMO | (0x1fu << 20),
RV64_FMT_LR, 0, {0, 0}},
- {"lr.d", MATCH_AMO(0x02, 0x3, RV_AMO), MASK_AMO | (0x1fu << 20),
+ {MN("lr.d"), MATCH_AMO(0x02, 0x3, RV_AMO), MASK_AMO | (0x1fu << 20),
RV64_FMT_LR, 0, {0, 0}},
- {"sc.w", MATCH_AMO(0x03, 0x2, RV_AMO), MASK_AMO, RV64_FMT_AMO, 0,
+ {MN("sc.w"), MATCH_AMO(0x03, 0x2, RV_AMO), MASK_AMO, RV64_FMT_AMO, 0,
{0, 0}},
- {"sc.d", MATCH_AMO(0x03, 0x3, RV_AMO), MASK_AMO, RV64_FMT_AMO, 0,
+ {MN("sc.d"), MATCH_AMO(0x03, 0x3, RV_AMO), MASK_AMO, RV64_FMT_AMO, 0,
{0, 0}},
- {"amoswap.w", MATCH_AMO(RV_AMO_SWAP, 0x2, RV_AMO), MASK_AMO,
+ {MN("amoswap.w"), MATCH_AMO(RV_AMO_SWAP, 0x2, RV_AMO), MASK_AMO,
RV64_FMT_AMO, 0, {0, 0}},
- {"amoadd.w", MATCH_AMO(RV_AMO_ADD, 0x2, RV_AMO), MASK_AMO,
+ {MN("amoadd.w"), MATCH_AMO(RV_AMO_ADD, 0x2, RV_AMO), MASK_AMO,
RV64_FMT_AMO, 0, {0, 0}},
- {"amoxor.w", MATCH_AMO(RV_AMO_XOR, 0x2, RV_AMO), MASK_AMO,
+ {MN("amoxor.w"), MATCH_AMO(RV_AMO_XOR, 0x2, RV_AMO), MASK_AMO,
RV64_FMT_AMO, 0, {0, 0}},
- {"amoand.w", MATCH_AMO(RV_AMO_AND, 0x2, RV_AMO), MASK_AMO,
+ {MN("amoand.w"), MATCH_AMO(RV_AMO_AND, 0x2, RV_AMO), MASK_AMO,
RV64_FMT_AMO, 0, {0, 0}},
- {"amoor.w", MATCH_AMO(RV_AMO_OR, 0x2, RV_AMO), MASK_AMO,
+ {MN("amoor.w"), MATCH_AMO(RV_AMO_OR, 0x2, RV_AMO), MASK_AMO,
RV64_FMT_AMO, 0, {0, 0}},
- {"amomin.w", MATCH_AMO(RV_AMO_MIN, 0x2, RV_AMO), MASK_AMO,
+ {MN("amomin.w"), MATCH_AMO(RV_AMO_MIN, 0x2, RV_AMO), MASK_AMO,
RV64_FMT_AMO, 0, {0, 0}},
- {"amomax.w", MATCH_AMO(RV_AMO_MAX, 0x2, RV_AMO), MASK_AMO,
+ {MN("amomax.w"), MATCH_AMO(RV_AMO_MAX, 0x2, RV_AMO), MASK_AMO,
RV64_FMT_AMO, 0, {0, 0}},
- {"amominu.w", MATCH_AMO(RV_AMO_MINU, 0x2, RV_AMO), MASK_AMO,
+ {MN("amominu.w"), MATCH_AMO(RV_AMO_MINU, 0x2, RV_AMO), MASK_AMO,
RV64_FMT_AMO, 0, {0, 0}},
- {"amomaxu.w", MATCH_AMO(RV_AMO_MAXU, 0x2, RV_AMO), MASK_AMO,
+ {MN("amomaxu.w"), MATCH_AMO(RV_AMO_MAXU, 0x2, RV_AMO), MASK_AMO,
RV64_FMT_AMO, 0, {0, 0}},
- {"amoswap.d", MATCH_AMO(RV_AMO_SWAP, 0x3, RV_AMO), MASK_AMO,
+ {MN("amoswap.d"), MATCH_AMO(RV_AMO_SWAP, 0x3, RV_AMO), MASK_AMO,
RV64_FMT_AMO, 0, {0, 0}},
- {"amoadd.d", MATCH_AMO(RV_AMO_ADD, 0x3, RV_AMO), MASK_AMO,
+ {MN("amoadd.d"), MATCH_AMO(RV_AMO_ADD, 0x3, RV_AMO), MASK_AMO,
RV64_FMT_AMO, 0, {0, 0}},
- {"amoxor.d", MATCH_AMO(RV_AMO_XOR, 0x3, RV_AMO), MASK_AMO,
+ {MN("amoxor.d"), MATCH_AMO(RV_AMO_XOR, 0x3, RV_AMO), MASK_AMO,
RV64_FMT_AMO, 0, {0, 0}},
- {"amoand.d", MATCH_AMO(RV_AMO_AND, 0x3, RV_AMO), MASK_AMO,
+ {MN("amoand.d"), MATCH_AMO(RV_AMO_AND, 0x3, RV_AMO), MASK_AMO,
RV64_FMT_AMO, 0, {0, 0}},
- {"amoor.d", MATCH_AMO(RV_AMO_OR, 0x3, RV_AMO), MASK_AMO,
+ {MN("amoor.d"), MATCH_AMO(RV_AMO_OR, 0x3, RV_AMO), MASK_AMO,
RV64_FMT_AMO, 0, {0, 0}},
- {"amomin.d", MATCH_AMO(RV_AMO_MIN, 0x3, RV_AMO), MASK_AMO,
+ {MN("amomin.d"), MATCH_AMO(RV_AMO_MIN, 0x3, RV_AMO), MASK_AMO,
RV64_FMT_AMO, 0, {0, 0}},
- {"amomax.d", MATCH_AMO(RV_AMO_MAX, 0x3, RV_AMO), MASK_AMO,
+ {MN("amomax.d"), MATCH_AMO(RV_AMO_MAX, 0x3, RV_AMO), MASK_AMO,
RV64_FMT_AMO, 0, {0, 0}},
- {"amominu.d", MATCH_AMO(RV_AMO_MINU, 0x3, RV_AMO), MASK_AMO,
+ {MN("amominu.d"), MATCH_AMO(RV_AMO_MINU, 0x3, RV_AMO), MASK_AMO,
RV64_FMT_AMO, 0, {0, 0}},
- {"amomaxu.d", MATCH_AMO(RV_AMO_MAXU, 0x3, RV_AMO), MASK_AMO,
+ {MN("amomaxu.d"), MATCH_AMO(RV_AMO_MAXU, 0x3, RV_AMO), MASK_AMO,
RV64_FMT_AMO, 0, {0, 0}},
/* =================================================================
* RV64C compressed — assembler rows. The disassembler uses the
* dynamic C decoder below, so 32-bit decode skips these rows.
* ================================================================= */
- {"c.nop", 0x0001u, 0xffffu, RV64_FMT_C_NONE, RV64_ASMFL_C16,
+ {MN("c.nop"), 0x0001u, 0xffffu, RV64_FMT_C_NONE, RV64_ASMFL_C16,
{0, 0}},
- {"c.ebreak", 0x9002u, 0xffffu, RV64_FMT_C_NONE, RV64_ASMFL_C16,
+ {MN("c.ebreak"), 0x9002u, 0xffffu, RV64_FMT_C_NONE, RV64_ASMFL_C16,
{0, 0}},
- {"c.jr", 0x8002u, 0xf07fu, RV64_FMT_CR, RV64_ASMFL_C16, {0, 0}},
- {"c.jalr", 0x9002u, 0xf07fu, RV64_FMT_CR, RV64_ASMFL_C16, {0, 0}},
- {"c.mv", 0x8002u, 0xf003u, RV64_FMT_CR, RV64_ASMFL_C16, {0, 0}},
- {"c.add", 0x9002u, 0xf003u, RV64_FMT_CR, RV64_ASMFL_C16, {0, 0}},
- {"c.li", 0x4001u, 0xe003u, RV64_FMT_CI, RV64_ASMFL_C16, {0, 0}},
- {"c.addi", 0x0001u, 0xe003u, RV64_FMT_CI, RV64_ASMFL_C16, {0, 0}},
- {"c.addiw", 0x2001u, 0xe003u, RV64_FMT_CI, RV64_ASMFL_C16, {0, 0}},
- {"c.slli", 0x0002u, 0xe003u, RV64_FMT_CI, RV64_ASMFL_C16, {0, 0}},
- {"c.lui", 0x6001u, 0xe003u, RV64_FMT_CI, RV64_ASMFL_C16, {0, 0}},
- {"c.addi16sp", 0x6101u, 0xef83u, RV64_FMT_CI, RV64_ASMFL_C16, {0, 0}},
- {"c.lwsp", 0x4002u, 0xe003u, RV64_FMT_CI, RV64_ASMFL_C16, {0, 0}},
- {"c.ldsp", 0x6002u, 0xe003u, RV64_FMT_CI, RV64_ASMFL_C16, {0, 0}},
- {"c.fldsp", 0x2002u, 0xe003u, RV64_FMT_CI,
+ {MN("c.jr"), 0x8002u, 0xf07fu, RV64_FMT_CR, RV64_ASMFL_C16, {0, 0}},
+ {MN("c.jalr"), 0x9002u, 0xf07fu, RV64_FMT_CR, RV64_ASMFL_C16, {0, 0}},
+ {MN("c.mv"), 0x8002u, 0xf003u, RV64_FMT_CR, RV64_ASMFL_C16, {0, 0}},
+ {MN("c.add"), 0x9002u, 0xf003u, RV64_FMT_CR, RV64_ASMFL_C16, {0, 0}},
+ {MN("c.li"), 0x4001u, 0xe003u, RV64_FMT_CI, RV64_ASMFL_C16, {0, 0}},
+ {MN("c.addi"), 0x0001u, 0xe003u, RV64_FMT_CI, RV64_ASMFL_C16, {0, 0}},
+ {MN("c.addiw"), 0x2001u, 0xe003u, RV64_FMT_CI, RV64_ASMFL_C16, {0, 0}},
+ {MN("c.slli"), 0x0002u, 0xe003u, RV64_FMT_CI, RV64_ASMFL_C16, {0, 0}},
+ {MN("c.lui"), 0x6001u, 0xe003u, RV64_FMT_CI, RV64_ASMFL_C16, {0, 0}},
+ {MN("c.addi16sp"), 0x6101u, 0xef83u, RV64_FMT_CI, RV64_ASMFL_C16, {0, 0}},
+ {MN("c.lwsp"), 0x4002u, 0xe003u, RV64_FMT_CI, RV64_ASMFL_C16, {0, 0}},
+ {MN("c.ldsp"), 0x6002u, 0xe003u, RV64_FMT_CI, RV64_ASMFL_C16, {0, 0}},
+ {MN("c.fldsp"), 0x2002u, 0xe003u, RV64_FMT_CI,
RV64_ASMFL_C16 | RV64_ASMFL_FP, {0, 0}},
- {"c.swsp", 0xc002u, 0xe003u, RV64_FMT_CSS, RV64_ASMFL_C16,
+ {MN("c.swsp"), 0xc002u, 0xe003u, RV64_FMT_CSS, RV64_ASMFL_C16,
{0, 0}},
- {"c.sdsp", 0xe002u, 0xe003u, RV64_FMT_CSS, RV64_ASMFL_C16,
+ {MN("c.sdsp"), 0xe002u, 0xe003u, RV64_FMT_CSS, RV64_ASMFL_C16,
{0, 0}},
- {"c.fsdsp", 0xa002u, 0xe003u, RV64_FMT_CSS,
+ {MN("c.fsdsp"), 0xa002u, 0xe003u, RV64_FMT_CSS,
RV64_ASMFL_C16 | RV64_ASMFL_FP, {0, 0}},
- {"c.addi4spn", 0x0000u, 0xe003u, RV64_FMT_CIW, RV64_ASMFL_C16,
+ {MN("c.addi4spn"), 0x0000u, 0xe003u, RV64_FMT_CIW, RV64_ASMFL_C16,
{0, 0}},
- {"c.lw", 0x4000u, 0xe003u, RV64_FMT_CL, RV64_ASMFL_C16, {0, 0}},
- {"c.ld", 0x6000u, 0xe003u, RV64_FMT_CL, RV64_ASMFL_C16, {0, 0}},
- {"c.fld", 0x2000u, 0xe003u, RV64_FMT_CL,
+ {MN("c.lw"), 0x4000u, 0xe003u, RV64_FMT_CL, RV64_ASMFL_C16, {0, 0}},
+ {MN("c.ld"), 0x6000u, 0xe003u, RV64_FMT_CL, RV64_ASMFL_C16, {0, 0}},
+ {MN("c.fld"), 0x2000u, 0xe003u, RV64_FMT_CL,
RV64_ASMFL_C16 | RV64_ASMFL_FP, {0, 0}},
- {"c.sw", 0xc000u, 0xe003u, RV64_FMT_CS, RV64_ASMFL_C16, {0, 0}},
- {"c.sd", 0xe000u, 0xe003u, RV64_FMT_CS, RV64_ASMFL_C16, {0, 0}},
- {"c.fsd", 0xa000u, 0xe003u, RV64_FMT_CS,
+ {MN("c.sw"), 0xc000u, 0xe003u, RV64_FMT_CS, RV64_ASMFL_C16, {0, 0}},
+ {MN("c.sd"), 0xe000u, 0xe003u, RV64_FMT_CS, RV64_ASMFL_C16, {0, 0}},
+ {MN("c.fsd"), 0xa000u, 0xe003u, RV64_FMT_CS,
RV64_ASMFL_C16 | RV64_ASMFL_FP, {0, 0}},
- {"c.srli", 0x8001u, 0xec03u, RV64_FMT_CB, RV64_ASMFL_C16, {0, 0}},
- {"c.srai", 0x8401u, 0xec03u, RV64_FMT_CB, RV64_ASMFL_C16, {0, 0}},
- {"c.andi", 0x8801u, 0xec03u, RV64_FMT_CB, RV64_ASMFL_C16, {0, 0}},
- {"c.sub", 0x8c01u, 0xfc63u, RV64_FMT_CA, RV64_ASMFL_C16, {0, 0}},
- {"c.xor", 0x8c21u, 0xfc63u, RV64_FMT_CA, RV64_ASMFL_C16, {0, 0}},
- {"c.or", 0x8c41u, 0xfc63u, RV64_FMT_CA, RV64_ASMFL_C16, {0, 0}},
- {"c.and", 0x8c61u, 0xfc63u, RV64_FMT_CA, RV64_ASMFL_C16, {0, 0}},
- {"c.subw", 0x9c01u, 0xfc63u, RV64_FMT_CA, RV64_ASMFL_C16, {0, 0}},
- {"c.addw", 0x9c21u, 0xfc63u, RV64_FMT_CA, RV64_ASMFL_C16, {0, 0}},
- {"c.j", 0xa001u, 0xe003u, RV64_FMT_CJ, RV64_ASMFL_C16, {0, 0}},
- {"c.beqz", 0xc001u, 0xe003u, RV64_FMT_CB, RV64_ASMFL_C16, {0, 0}},
- {"c.bnez", 0xe001u, 0xe003u, RV64_FMT_CB, RV64_ASMFL_C16, {0, 0}},
+ {MN("c.srli"), 0x8001u, 0xec03u, RV64_FMT_CB, RV64_ASMFL_C16, {0, 0}},
+ {MN("c.srai"), 0x8401u, 0xec03u, RV64_FMT_CB, RV64_ASMFL_C16, {0, 0}},
+ {MN("c.andi"), 0x8801u, 0xec03u, RV64_FMT_CB, RV64_ASMFL_C16, {0, 0}},
+ {MN("c.sub"), 0x8c01u, 0xfc63u, RV64_FMT_CA, RV64_ASMFL_C16, {0, 0}},
+ {MN("c.xor"), 0x8c21u, 0xfc63u, RV64_FMT_CA, RV64_ASMFL_C16, {0, 0}},
+ {MN("c.or"), 0x8c41u, 0xfc63u, RV64_FMT_CA, RV64_ASMFL_C16, {0, 0}},
+ {MN("c.and"), 0x8c61u, 0xfc63u, RV64_FMT_CA, RV64_ASMFL_C16, {0, 0}},
+ {MN("c.subw"), 0x9c01u, 0xfc63u, RV64_FMT_CA, RV64_ASMFL_C16, {0, 0}},
+ {MN("c.addw"), 0x9c21u, 0xfc63u, RV64_FMT_CA, RV64_ASMFL_C16, {0, 0}},
+ {MN("c.j"), 0xa001u, 0xe003u, RV64_FMT_CJ, RV64_ASMFL_C16, {0, 0}},
+ {MN("c.beqz"), 0xc001u, 0xe003u, RV64_FMT_CB, RV64_ASMFL_C16, {0, 0}},
+ {MN("c.bnez"), 0xe001u, 0xe003u, RV64_FMT_CB, RV64_ASMFL_C16, {0, 0}},
};
#undef RV64_AMO_ORDER_ROWS
@@ -558,20 +567,20 @@ const Rv64InsnDesc* rv64_disasm_find(u32 word) {
return NULL;
}
-const Rv64InsnDesc* rv64_asm_find(const char* mnemonic) {
+const Rv64InsnDesc* rv64_asm_find(Slice mnemonic) {
/* Prefer canonical (non-alias) rows when both spellings exist; the
* caller can still write the alias and we'll match it on a second
* pass. Aliases share encoding with the canonical row so the choice
* is purely for diagnostics. */
- if (!mnemonic) return NULL;
+ if (!mnemonic.s) return NULL;
for (u32 i = 0; i < rv64_insn_table_n; ++i) {
const Rv64InsnDesc* d = &rv64_insn_table[i];
if ((d->flags & RV64_ASMFL_ALIAS)) continue;
- if (!strcmp(d->mnemonic, mnemonic)) return d;
+ if (slice_eq(d->mnemonic, mnemonic)) return d;
}
for (u32 i = 0; i < rv64_insn_table_n; ++i) {
const Rv64InsnDesc* d = &rv64_insn_table[i];
- if (!strcmp(d->mnemonic, mnemonic)) return d;
+ if (slice_eq(d->mnemonic, mnemonic)) return d;
}
return NULL;
}
@@ -601,11 +610,13 @@ static u32 rv64c_lookup_simple(u32 w) {
* with custom operand printers. */
static const Rv64InsnDesc rv64_c_table[] = {
/* index 0 reserved (no match). */
- {"c.unknown", 0, 0xffffu, RV64_FMT_C_NONE, RV64_ASMFL_C16, {0, 0}},
- {"c.nop", 0x0001u, 0xffffu, RV64_FMT_C_NONE, RV64_ASMFL_C16, {0, 0}},
- {"c.ebreak", 0x9002u, 0xffffu, RV64_FMT_C_NONE, RV64_ASMFL_C16, {0, 0}},
+ {MN("c.unknown"), 0, 0xffffu, RV64_FMT_C_NONE, RV64_ASMFL_C16, {0, 0}},
+ {MN("c.nop"), 0x0001u, 0xffffu, RV64_FMT_C_NONE, RV64_ASMFL_C16, {0, 0}},
+ {MN("c.ebreak"), 0x9002u, 0xffffu, RV64_FMT_C_NONE, RV64_ASMFL_C16, {0, 0}},
};
+#undef MN
+
const Rv64InsnDesc* rv64_disasm_find_c(u32 word) {
u32 hw = word & 0xffffu;
u32 idx = rv64c_lookup_simple(hw);
@@ -623,7 +634,7 @@ const Rv64InsnDesc* rv64_disasm_find_c(u32 word) {
u32 rd_rs1 = (hw >> 7) & 0x1fu;
u32 rs2 = (hw >> 2) & 0x1fu;
if (funct4 == 0x8u) {
- dyn = (Rv64InsnDesc){rs2 == 0 ? "c.jr" : "c.mv", hw,
+ dyn = (Rv64InsnDesc){slice_from_cstr(rs2 == 0 ? "c.jr" : "c.mv"), hw,
0xffffu, RV64_FMT_CR, RV64_ASMFL_C16, {0, 0}};
return rd_rs1 == 0 ? NULL : &dyn;
}
@@ -632,30 +643,30 @@ const Rv64InsnDesc* rv64_disasm_find_c(u32 word) {
dyn = rv64_c_table[2]; /* c.ebreak */
return &dyn;
}
- dyn = (Rv64InsnDesc){rs2 == 0 ? "c.jalr" : "c.add", hw,
+ dyn = (Rv64InsnDesc){slice_from_cstr(rs2 == 0 ? "c.jalr" : "c.add"), hw,
0xffffu, RV64_FMT_CR, RV64_ASMFL_C16, {0, 0}};
return &dyn;
}
}
/* C.LI / C.ADDI / C.LUI — quadrant 1 */
if (op == 1u && f3 == 2u) {
- dyn = (Rv64InsnDesc){"c.li", hw, 0xffffu, RV64_FMT_CI,
+ dyn = (Rv64InsnDesc){slice_from_cstr("c.li"), hw, 0xffffu, RV64_FMT_CI,
RV64_ASMFL_C16, {0, 0}};
return &dyn;
}
if (op == 1u && f3 == 1u) {
- dyn = (Rv64InsnDesc){"c.addiw", hw, 0xffffu, RV64_FMT_CI,
+ dyn = (Rv64InsnDesc){slice_from_cstr("c.addiw"), hw, 0xffffu, RV64_FMT_CI,
RV64_ASMFL_C16, {0, 0}};
return &dyn;
}
if (op == 1u && f3 == 0u) {
- dyn = (Rv64InsnDesc){"c.addi", hw, 0xffffu, RV64_FMT_CI,
+ dyn = (Rv64InsnDesc){slice_from_cstr("c.addi"), hw, 0xffffu, RV64_FMT_CI,
RV64_ASMFL_C16, {0, 0}};
return &dyn;
}
if (op == 1u && f3 == 3u) {
u32 rd = (hw >> 7) & 0x1fu;
- dyn = (Rv64InsnDesc){rd == 2u ? "c.addi16sp" : "c.lui", hw,
+ dyn = (Rv64InsnDesc){slice_from_cstr(rd == 2u ? "c.addi16sp" : "c.lui"), hw,
0xffffu, RV64_FMT_CI, RV64_ASMFL_C16, {0, 0}};
return &dyn;
}
@@ -663,7 +674,7 @@ const Rv64InsnDesc* rv64_disasm_find_c(u32 word) {
u32 top = (hw >> 10) & 0x3u;
if (top == 0u || top == 1u || top == 2u) {
static const char* const names[3] = {"c.srli", "c.srai", "c.andi"};
- dyn = (Rv64InsnDesc){names[top], hw, 0xffffu, RV64_FMT_CB,
+ dyn = (Rv64InsnDesc){slice_from_cstr(names[top]), hw, 0xffffu, RV64_FMT_CB,
RV64_ASMFL_C16, {0, 0}};
return &dyn;
}
@@ -674,97 +685,97 @@ const Rv64InsnDesc* rv64_disasm_find_c(u32 word) {
static const char* const ca1[4] = {"c.subw", "c.addw", NULL, NULL};
const char* name = bit12 ? ca1[subop] : ca0[subop];
if (!name) return NULL;
- dyn = (Rv64InsnDesc){name, hw, 0xffffu, RV64_FMT_CA,
+ dyn = (Rv64InsnDesc){slice_from_cstr(name), hw, 0xffffu, RV64_FMT_CA,
RV64_ASMFL_C16, {0, 0}};
return &dyn;
}
}
if (op == 1u && f3 == 5u) {
- dyn = (Rv64InsnDesc){"c.j", hw, 0xffffu, RV64_FMT_CJ,
+ dyn = (Rv64InsnDesc){slice_from_cstr("c.j"), hw, 0xffffu, RV64_FMT_CJ,
RV64_ASMFL_C16, {0, 0}};
return &dyn;
}
if (op == 1u && f3 == 6u) {
- dyn = (Rv64InsnDesc){"c.beqz", hw, 0xffffu, RV64_FMT_CB,
+ dyn = (Rv64InsnDesc){slice_from_cstr("c.beqz"), hw, 0xffffu, RV64_FMT_CB,
RV64_ASMFL_C16, {0, 0}};
return &dyn;
}
if (op == 1u && f3 == 7u) {
- dyn = (Rv64InsnDesc){"c.bnez", hw, 0xffffu, RV64_FMT_CB,
+ dyn = (Rv64InsnDesc){slice_from_cstr("c.bnez"), hw, 0xffffu, RV64_FMT_CB,
RV64_ASMFL_C16, {0, 0}};
return &dyn;
}
/* C.LWSP / C.LDSP — quadrant 2, funct3=010/011 */
if (op == 2u && f3 == 2u) {
- dyn = (Rv64InsnDesc){"c.lwsp", hw, 0xffffu, RV64_FMT_CI,
+ dyn = (Rv64InsnDesc){slice_from_cstr("c.lwsp"), hw, 0xffffu, RV64_FMT_CI,
RV64_ASMFL_C16, {0, 0}};
return &dyn;
}
if (op == 2u && f3 == 3u) {
- dyn = (Rv64InsnDesc){"c.ldsp", hw, 0xffffu, RV64_FMT_CI,
+ dyn = (Rv64InsnDesc){slice_from_cstr("c.ldsp"), hw, 0xffffu, RV64_FMT_CI,
RV64_ASMFL_C16, {0, 0}};
return &dyn;
}
if (op == 2u && f3 == 0u) {
- dyn = (Rv64InsnDesc){"c.slli", hw, 0xffffu, RV64_FMT_CI,
+ dyn = (Rv64InsnDesc){slice_from_cstr("c.slli"), hw, 0xffffu, RV64_FMT_CI,
RV64_ASMFL_C16, {0, 0}};
return &dyn;
}
if (op == 2u && f3 == 1u) {
- dyn = (Rv64InsnDesc){"c.fldsp", hw, 0xffffu, RV64_FMT_CI,
+ dyn = (Rv64InsnDesc){slice_from_cstr("c.fldsp"), hw, 0xffffu, RV64_FMT_CI,
RV64_ASMFL_C16 | RV64_ASMFL_FP, {0, 0}};
return &dyn;
}
/* C.SWSP / C.SDSP — quadrant 2, funct3=110/111 */
if (op == 2u && f3 == 6u) {
- dyn = (Rv64InsnDesc){"c.swsp", hw, 0xffffu, RV64_FMT_CSS,
+ dyn = (Rv64InsnDesc){slice_from_cstr("c.swsp"), hw, 0xffffu, RV64_FMT_CSS,
RV64_ASMFL_C16, {0, 0}};
return &dyn;
}
if (op == 2u && f3 == 7u) {
- dyn = (Rv64InsnDesc){"c.sdsp", hw, 0xffffu, RV64_FMT_CSS,
+ dyn = (Rv64InsnDesc){slice_from_cstr("c.sdsp"), hw, 0xffffu, RV64_FMT_CSS,
RV64_ASMFL_C16, {0, 0}};
return &dyn;
}
if (op == 2u && f3 == 5u) {
- dyn = (Rv64InsnDesc){"c.fsdsp", hw, 0xffffu, RV64_FMT_CSS,
+ dyn = (Rv64InsnDesc){slice_from_cstr("c.fsdsp"), hw, 0xffffu, RV64_FMT_CSS,
RV64_ASMFL_C16 | RV64_ASMFL_FP, {0, 0}};
return &dyn;
}
/* C.ADDI4SPN — quadrant 0, funct3=000 */
if (op == 0u && f3 == 0u) {
- dyn = (Rv64InsnDesc){"c.addi4spn", hw, 0xffffu, RV64_FMT_CIW,
+ dyn = (Rv64InsnDesc){slice_from_cstr("c.addi4spn"), hw, 0xffffu, RV64_FMT_CIW,
RV64_ASMFL_C16, {0, 0}};
return &dyn;
}
/* C.LW / C.LD — quadrant 0, funct3=010/011 */
if (op == 0u && f3 == 2u) {
- dyn = (Rv64InsnDesc){"c.lw", hw, 0xffffu, RV64_FMT_CL,
+ dyn = (Rv64InsnDesc){slice_from_cstr("c.lw"), hw, 0xffffu, RV64_FMT_CL,
RV64_ASMFL_C16, {0, 0}};
return &dyn;
}
if (op == 0u && f3 == 3u) {
- dyn = (Rv64InsnDesc){"c.ld", hw, 0xffffu, RV64_FMT_CL,
+ dyn = (Rv64InsnDesc){slice_from_cstr("c.ld"), hw, 0xffffu, RV64_FMT_CL,
RV64_ASMFL_C16, {0, 0}};
return &dyn;
}
if (op == 0u && f3 == 1u) {
- dyn = (Rv64InsnDesc){"c.fld", hw, 0xffffu, RV64_FMT_CL,
+ dyn = (Rv64InsnDesc){slice_from_cstr("c.fld"), hw, 0xffffu, RV64_FMT_CL,
RV64_ASMFL_C16 | RV64_ASMFL_FP, {0, 0}};
return &dyn;
}
if (op == 0u && f3 == 6u) {
- dyn = (Rv64InsnDesc){"c.sw", hw, 0xffffu, RV64_FMT_CS,
+ dyn = (Rv64InsnDesc){slice_from_cstr("c.sw"), hw, 0xffffu, RV64_FMT_CS,
RV64_ASMFL_C16, {0, 0}};
return &dyn;
}
if (op == 0u && f3 == 7u) {
- dyn = (Rv64InsnDesc){"c.sd", hw, 0xffffu, RV64_FMT_CS,
+ dyn = (Rv64InsnDesc){slice_from_cstr("c.sd"), hw, 0xffffu, RV64_FMT_CS,
RV64_ASMFL_C16, {0, 0}};
return &dyn;
}
if (op == 0u && f3 == 5u) {
- dyn = (Rv64InsnDesc){"c.fsd", hw, 0xffffu, RV64_FMT_CS,
+ dyn = (Rv64InsnDesc){slice_from_cstr("c.fsd"), hw, 0xffffu, RV64_FMT_CS,
RV64_ASMFL_C16 | RV64_ASMFL_FP, {0, 0}};
return &dyn;
}
@@ -830,23 +841,23 @@ static void print_i(StrBuf* sb, u32 w, const Rv64InsnDesc* d) {
Rv64I f = rv64_i_unpack(w);
i64 imm = rv64_sext((u64)f.imm12, 12);
/* Alias: `li rd, imm` — print rd, imm. */
- if ((d->flags & RV64_ASMFL_ALIAS) && !strcmp(d->mnemonic, "li")) {
+ if ((d->flags & RV64_ASMFL_ALIAS) && slice_eq_cstr(d->mnemonic, "li")) {
p_xreg(sb, f.rd); p_sep(sb); strbuf_put_i64(sb, imm);
return;
}
/* Alias: `mv rd, rs1` — print rd, rs1. */
- if ((d->flags & RV64_ASMFL_ALIAS) && !strcmp(d->mnemonic, "mv")) {
+ if ((d->flags & RV64_ASMFL_ALIAS) && slice_eq_cstr(d->mnemonic, "mv")) {
p_xreg(sb, f.rd); p_sep(sb); p_xreg(sb, f.rs1);
return;
}
/* Alias: `sext.w rd, rs1` — print rd, rs1. */
- if ((d->flags & RV64_ASMFL_ALIAS) && !strcmp(d->mnemonic, "sext.w")) {
+ if ((d->flags & RV64_ASMFL_ALIAS) && slice_eq_cstr(d->mnemonic, "sext.w")) {
p_xreg(sb, f.rd); p_sep(sb); p_xreg(sb, f.rs1);
return;
}
/* Alias: `seqz rd, rs` / `not rd, rs` — print rd, rs (drop imm). */
if ((d->flags & RV64_ASMFL_ALIAS) &&
- (!strcmp(d->mnemonic, "seqz") || !strcmp(d->mnemonic, "not"))) {
+ (slice_eq_cstr(d->mnemonic, "seqz") || slice_eq_cstr(d->mnemonic, "not"))) {
p_xreg(sb, f.rd); p_sep(sb); p_xreg(sb, f.rs1);
return;
}
@@ -902,7 +913,7 @@ static void print_b(StrBuf* sb, u32 w, u64 vaddr, const Rv64InsnDesc* d) {
Rv64B f = rv64_b_unpack(w);
i64 off = rv64_sext((u64)f.imm13, 13);
if ((d->flags & RV64_ASMFL_ALIAS) &&
- (!strcmp(d->mnemonic, "beqz") || !strcmp(d->mnemonic, "bnez"))) {
+ (slice_eq_cstr(d->mnemonic, "beqz") || slice_eq_cstr(d->mnemonic, "bnez"))) {
p_xreg(sb, f.rs1); p_sep(sb); p_rel(sb, vaddr, off);
return;
}
@@ -914,7 +925,7 @@ static void print_b(StrBuf* sb, u32 w, u64 vaddr, const Rv64InsnDesc* d) {
static void print_j(StrBuf* sb, u32 w, u64 vaddr, const Rv64InsnDesc* d) {
Rv64J f = rv64_j_unpack(w);
i64 off = rv64_sext((u64)f.imm21, 21);
- if ((d->flags & RV64_ASMFL_ALIAS) && !strcmp(d->mnemonic, "j")) {
+ if ((d->flags & RV64_ASMFL_ALIAS) && slice_eq_cstr(d->mnemonic, "j")) {
p_rel(sb, vaddr, off);
return;
}
@@ -925,7 +936,7 @@ static void print_j(StrBuf* sb, u32 w, u64 vaddr, const Rv64InsnDesc* d) {
static void print_jalr(StrBuf* sb, u32 w, const Rv64InsnDesc* d) {
Rv64I f = rv64_i_unpack(w);
i64 imm = rv64_sext((u64)f.imm12, 12);
- if ((d->flags & RV64_ASMFL_ALIAS) && !strcmp(d->mnemonic, "jr")) {
+ if ((d->flags & RV64_ASMFL_ALIAS) && slice_eq_cstr(d->mnemonic, "jr")) {
p_xreg(sb, f.rs1);
return;
}
@@ -1005,12 +1016,12 @@ static void print_fp_cvt(StrBuf* sb, u32 w, const Rv64InsnDesc* d) {
/* rs1: FP if mnemonic is fcvt.X.{S,D} or fsqrt or fmv.x.{w,d};
* GPR if mnemonic is fcvt.{S,D}.{w,wu,l,lu} or fmv.{w,d}.x. */
int rs1_is_fp = 1;
- if (!strcmp(d->mnemonic, "fmv.w.x") || !strcmp(d->mnemonic, "fmv.d.x") ||
- !strncmp(d->mnemonic, "fcvt.s.", 7) ||
- !strncmp(d->mnemonic, "fcvt.d.", 7)) {
+ if (slice_eq_cstr(d->mnemonic, "fmv.w.x") || slice_eq_cstr(d->mnemonic, "fmv.d.x") ||
+ slice_has_prefix_cstr(d->mnemonic, "fcvt.s.", 7) ||
+ slice_has_prefix_cstr(d->mnemonic, "fcvt.d.", 7)) {
/* These have rs1 as integer GPR (source is integer). Exception:
* fcvt.s.d / fcvt.d.s have rs1 as FP. */
- if (!strcmp(d->mnemonic, "fcvt.s.d") || !strcmp(d->mnemonic, "fcvt.d.s"))
+ if (slice_eq_cstr(d->mnemonic, "fcvt.s.d") || slice_eq_cstr(d->mnemonic, "fcvt.d.s"))
rs1_is_fp = 1;
else
rs1_is_fp = 0;
@@ -1041,7 +1052,7 @@ static void print_cr(StrBuf* sb, u32 w, const Rv64InsnDesc* d) {
u32 hw = w & 0xffffu;
u32 rd_rs1 = (hw >> 7) & 0x1fu;
u32 rs2 = (hw >> 2) & 0x1fu;
- if (!strcmp(d->mnemonic, "c.jr") || !strcmp(d->mnemonic, "c.jalr")) {
+ if (slice_eq_cstr(d->mnemonic, "c.jr") || slice_eq_cstr(d->mnemonic, "c.jalr")) {
p_xreg(sb, rd_rs1);
} else {
/* c.mv / c.add */
@@ -1056,7 +1067,7 @@ static void print_ci(StrBuf* sb, u32 w, const Rv64InsnDesc* d) {
u32 imm5 = (hw >> 12) & 1u;
u32 imm4_0 = (hw >> 2) & 0x1fu;
i64 imm;
- if (!strcmp(d->mnemonic, "c.lui")) {
+ if (slice_eq_cstr(d->mnemonic, "c.lui")) {
/* nzimm[17:12] = bits 12, 6:2 — signed extended to 18 bits. */
u64 raw = (u64)((imm5 << 5) | imm4_0);
imm = rv64_sext(raw, 6) << 12;
@@ -1064,7 +1075,7 @@ static void print_ci(StrBuf* sb, u32 w, const Rv64InsnDesc* d) {
strbuf_put_hex_u64(sb, (u64)imm);
return;
}
- if (!strcmp(d->mnemonic, "c.addi16sp")) {
+ if (slice_eq_cstr(d->mnemonic, "c.addi16sp")) {
/* nzimm[9|4|6|8:7|5] (scrambled). Just decode for print. */
u32 b9 = (hw >> 12) & 1u;
u32 b4 = (hw >> 6) & 1u;
@@ -1078,7 +1089,7 @@ static void print_ci(StrBuf* sb, u32 w, const Rv64InsnDesc* d) {
strbuf_put_i64(sb, imm);
return;
}
- if (!strcmp(d->mnemonic, "c.lwsp")) {
+ if (slice_eq_cstr(d->mnemonic, "c.lwsp")) {
/* offset[5|4:2|7:6] scaled by 4. */
u32 b5 = imm5;
u32 b4_2 = (imm4_0 >> 2) & 7u;
@@ -1088,7 +1099,7 @@ static void print_ci(StrBuf* sb, u32 w, const Rv64InsnDesc* d) {
p_mem(sb, (i64)off, 2u);
return;
}
- if (!strcmp(d->mnemonic, "c.ldsp") || !strcmp(d->mnemonic, "c.fldsp")) {
+ if (slice_eq_cstr(d->mnemonic, "c.ldsp") || slice_eq_cstr(d->mnemonic, "c.fldsp")) {
/* offset[5|4:3|8:6] scaled by 8. */
u32 b5 = imm5;
u32 b4_3 = (imm4_0 >> 3) & 3u;
@@ -1100,7 +1111,7 @@ static void print_ci(StrBuf* sb, u32 w, const Rv64InsnDesc* d) {
p_mem(sb, (i64)off, 2u);
return;
}
- if (!strcmp(d->mnemonic, "c.slli")) {
+ if (slice_eq_cstr(d->mnemonic, "c.slli")) {
u32 shamt = (imm5 << 5) | imm4_0;
p_xreg(sb, rd_rs1); p_sep(sb);
strbuf_put_u64(sb, (u64)shamt);
@@ -1117,7 +1128,7 @@ static void print_css(StrBuf* sb, u32 w, const Rv64InsnDesc* d) {
u32 rs2 = (hw >> 2) & 0x1fu;
u32 imm6 = (hw >> 7) & 0x3fu;
u32 off;
- if (!strcmp(d->mnemonic, "c.swsp")) {
+ if (slice_eq_cstr(d->mnemonic, "c.swsp")) {
/* offset[5:2|7:6] scaled by 4. */
u32 b5_2 = (imm6 >> 2) & 0xfu;
u32 b7_6 = imm6 & 3u;
@@ -1160,7 +1171,7 @@ static void print_cl(StrBuf* sb, u32 w, const Rv64InsnDesc* d) {
u32 b5_3 = (hw >> 10) & 7u;
u32 lo = (hw >> 5) & 3u;
u32 off;
- if (!strcmp(d->mnemonic, "c.lw")) {
+ if (slice_eq_cstr(d->mnemonic, "c.lw")) {
/* offset[5:3|2|6] scaled by 4. */
u32 b2 = (lo >> 1) & 1u;
u32 b6 = lo & 1u;
@@ -1182,7 +1193,7 @@ static void print_cs(StrBuf* sb, u32 w, const Rv64InsnDesc* d) {
u32 b5_3 = (hw >> 10) & 7u;
u32 lo = (hw >> 5) & 3u;
u32 off;
- if (!strcmp(d->mnemonic, "c.sw")) {
+ if (slice_eq_cstr(d->mnemonic, "c.sw")) {
u32 b2 = (lo >> 1) & 1u;
u32 b6 = lo & 1u;
off = (b6 << 6) | (b5_3 << 3) | (b2 << 2);
@@ -1206,11 +1217,11 @@ static void print_ca(StrBuf* sb, u32 w) {
static void print_cb(StrBuf* sb, u32 w, u64 vaddr, const Rv64InsnDesc* d) {
u32 hw = w & 0xffffu;
u32 rs1_3 = (hw >> 7) & 7u;
- if (!strcmp(d->mnemonic, "c.srli") || !strcmp(d->mnemonic, "c.srai") ||
- !strcmp(d->mnemonic, "c.andi")) {
+ if (slice_eq_cstr(d->mnemonic, "c.srli") || slice_eq_cstr(d->mnemonic, "c.srai") ||
+ slice_eq_cstr(d->mnemonic, "c.andi")) {
u32 imm = (((hw >> 12) & 1u) << 5) | ((hw >> 2) & 0x1fu);
p_xreg(sb, RVC_REG3(rs1_3)); p_sep(sb);
- if (!strcmp(d->mnemonic, "c.andi"))
+ if (slice_eq_cstr(d->mnemonic, "c.andi"))
strbuf_put_i64(sb, rv64_sext((u64)imm, 6));
else
strbuf_put_u64(sb, (u64)imm);
diff --git a/src/arch/rv64/isa.h b/src/arch/rv64/isa.h
@@ -10,6 +10,7 @@
#define CFREE_RV64_ISA_H
#include "core/core.h"
+#include "core/slice.h"
#include "core/strbuf.h"
/* ---- Named registers (DWARF / psABI numbering matches HW) ---- */
@@ -485,7 +486,7 @@ typedef struct Rv64C { u32 word; } Rv64C; /* 16-bit halfword in low 16 bits */
* =================================================================== */
typedef struct Rv64InsnDesc {
- const char* mnemonic;
+ Slice mnemonic;
u32 match;
u32 mask;
u8 fmt; /* Rv64Format */
@@ -508,7 +509,7 @@ const Rv64InsnDesc* rv64_disasm_find_c(u32 word);
/* Mnemonic → descriptor for the assembler. Returns NULL if not found.
* Ignores ALIAS-only rows when those would produce ambiguous parses
* (the canonical form is always reachable). */
-const Rv64InsnDesc* rv64_asm_find(const char* mnemonic);
+const Rv64InsnDesc* rv64_asm_find(Slice mnemonic);
/* ===================================================================
* Operand print / parse dispatch.
diff --git a/src/arch/rv64/ops.c b/src/arch/rv64/ops.c
@@ -5,6 +5,7 @@
#include "arch/rv64/asm.h"
#include "arch/rv64/regs.h"
#include "core/pool.h"
+#include "core/slice.h"
/* ---- For a memory access of `nbytes`, pick the right store opcode. ---- */
u32 enc_int_store(u32 nbytes, u32 src, u32 base, i32 off) {
@@ -36,7 +37,7 @@ static void rv_load_const(CGTarget* t, Operand dst, ConstBytes cb) {
if (dst.cls != RC_FP) {
compiler_panic(t->c, a->loc, "rv64 load_const: only FP supported in v1");
}
- Sym ro_name = pool_intern_cstr(t->c->global, ".rodata");
+ Sym ro_name = pool_intern_slice(t->c->global, SLICE_LIT(".rodata"));
ObjSecId ro = obj_section(t->obj, ro_name, SEC_RODATA, SF_ALLOC, 1u);
u32 cur_section = t->mc->section_id;
@@ -60,7 +61,7 @@ static void rv_load_const(CGTarget* t, Operand dst, ConstBytes cb) {
for (int i = tn - 1; i >= 0; --i) namebuf[len++] = tmp[i];
namebuf[len] = 0;
}
- Sym sname = pool_intern_cstr(t->c->global, namebuf);
+ Sym sname = pool_intern_slice(t->c->global, slice_from_cstr(namebuf));
ObjSymId sym = obj_symbol(t->obj, sname, SB_LOCAL, SK_OBJ, ro, (u64)ro_off,
(u64)cb.size);
t->mc->set_section(t->mc, cur_section);
@@ -87,7 +88,7 @@ static void rv_load_const(CGTarget* t, Operand dst, ConstBytes cb) {
for (int i = tn - 1; i >= 0; --i) anchor_buf[al++] = tmp[i];
anchor_buf[al] = 0;
}
- Sym aname = pool_intern_cstr(t->c->global, anchor_buf);
+ Sym aname = pool_intern_slice(t->c->global, slice_from_cstr(anchor_buf));
ObjSymId anchor = obj_symbol(t->obj, aname, SB_LOCAL, SK_OBJ, sec,
(u64)auipc_pos, 0);
u32 lpos = t->mc->pos(t->mc);
@@ -201,7 +202,7 @@ ObjSymId emit_pcrel_anchor(CGTarget* t, u32 sec, u32 auipc_pos) {
else { while (v) { tmp[tn++] = '0' + (char)(v % 10); v /= 10; } }
for (int i = tn - 1; i >= 0; --i) buf[len++] = tmp[i];
buf[len] = 0;
- Sym n = pool_intern_cstr(t->c->global, buf);
+ Sym n = pool_intern_slice(t->c->global, slice_from_cstr(buf));
return obj_symbol(t->obj, n, SB_LOCAL, SK_OBJ, sec, (u64)auipc_pos, 0);
}
@@ -2327,14 +2328,13 @@ static void rv_asm_block(CGTarget* t, const char* tmpl,
* named in the clobber list (psABI: s0..s11 are CS for integers, fs0..
* fs11 for FP). Same accounting the prologue uses for bound regs. */
for (u32 i = 0; i < nc; ++i) {
- size_t len = 0;
- const char* s = pool_str(t->c->global, clobs[i], &len);
+ Slice cs = pool_slice(t->c->global, clobs[i]);
char buf[16];
uint32_t dwarf;
- if (!s || !len) continue;
- if (len >= sizeof buf) continue;
- memcpy(buf, s, len);
- buf[len] = '\0';
+ if (!cs.s || !cs.len) continue;
+ if (cs.len >= sizeof buf) continue;
+ memcpy(buf, cs.s, cs.len);
+ buf[cs.len] = '\0';
if (rv64_register_index(buf, &dwarf) != 0) continue;
if (dwarf <= 31u) {
/* Integer reg: s0=x8, s1=x9, s2..s11=x18..x27. */
diff --git a/src/arch/rv64/regs.c b/src/arch/rv64/regs.c
@@ -7,9 +7,9 @@
#include "arch/rv64/regs.h"
#include <stdint.h>
-#include <string.h>
#include "core/core.h"
+#include "core/slice.h"
typedef struct Rv64Reg {
uint32_t dwarf_idx;
@@ -64,9 +64,11 @@ const char* rv64_register_name(uint32_t dwarf_idx) {
int rv64_register_index(const char* name, uint32_t* idx_out) {
uint32_t i;
uint32_t n;
+ Slice q;
if (!name) return 1;
+ q = slice_from_cstr(name);
for (i = 0; i < RV64_REGS_N; ++i) {
- if (!strcmp(RV64_REGS[i].name, name)) {
+ if (slice_eq_cstr(q, RV64_REGS[i].name)) {
if (idx_out) *idx_out = RV64_REGS[i].dwarf_idx;
return 0;
}
@@ -79,7 +81,7 @@ int rv64_register_index(const char* name, uint32_t* idx_out) {
if (idx_out) *idx_out = 32u + n;
return 0;
}
- if (!strcmp(name, "fp")) {
+ if (slice_eq_cstr(q, "fp")) {
if (idx_out) *idx_out = 8u;
return 0;
}
diff --git a/src/arch/x64/alloc.c b/src/arch/x64/alloc.c
@@ -8,6 +8,7 @@
#include <string.h>
#include "arch/arch.h"
+#include "core/slice.h"
#include "arch/x64/internal.h"
#include "arch/x64/isa.h"
#include "arch/x64/regs.h"
@@ -20,29 +21,29 @@
* Registers / frame */
int x_resolve_reg_name(CGTarget* t, Sym name, Reg* out, RegClass* cls_out) {
- size_t len = 0;
- const char* s = pool_str(t->c->global, name, &len);
+ Slice ns = pool_slice(t->c->global, name);
char buf[16];
u32 idx;
- if (!s || !len || len >= sizeof buf) return 1;
- memcpy(buf, s, len);
- buf[len] = '\0';
- if (!strcmp(buf, "ah")) {
+ if (!ns.s || !ns.len || ns.len >= sizeof buf) return 1;
+ memcpy(buf, ns.s, ns.len);
+ buf[ns.len] = '\0';
+ Slice q = slice_from_cstr(buf);
+ if (slice_eq_cstr(q, "ah")) {
if (out) *out = X64_RAX;
if (cls_out) *cls_out = RC_INT;
return 0;
}
- if (!strcmp(buf, "ch")) {
+ if (slice_eq_cstr(q, "ch")) {
if (out) *out = X64_RCX;
if (cls_out) *cls_out = RC_INT;
return 0;
}
- if (!strcmp(buf, "dh")) {
+ if (slice_eq_cstr(q, "dh")) {
if (out) *out = X64_RDX;
if (cls_out) *cls_out = RC_INT;
return 0;
}
- if (!strcmp(buf, "bh")) {
+ if (slice_eq_cstr(q, "bh")) {
if (out) *out = X64_RBX;
if (cls_out) *cls_out = RC_INT;
return 0;
diff --git a/src/arch/x64/arch.c b/src/arch/x64/arch.c
@@ -66,20 +66,24 @@ static int x64_apply_label_fixup(Compiler* c, const ArchLabelFixup* fx) {
}
static const CfreePredefinedMacro x64_predefined_macros[] = {
- {"__x86_64", "1"},
- {"__x86_64__", "1"},
- {"__amd64", "1"},
- {"__amd64__", "1"},
- {"__LP64__", "1"},
- {"__ORDER_LITTLE_ENDIAN__", "1234"},
- {"__ORDER_BIG_ENDIAN__", "4321"},
- {"__BYTE_ORDER__", "__ORDER_LITTLE_ENDIAN__"},
- {"__LITTLE_ENDIAN__", "1"},
+ {CFREE_SLICE_LIT("__x86_64"), CFREE_SLICE_LIT("1")},
+ {CFREE_SLICE_LIT("__x86_64__"), CFREE_SLICE_LIT("1")},
+ {CFREE_SLICE_LIT("__amd64"), CFREE_SLICE_LIT("1")},
+ {CFREE_SLICE_LIT("__amd64__"), CFREE_SLICE_LIT("1")},
+ {CFREE_SLICE_LIT("__LP64__"), CFREE_SLICE_LIT("1")},
+ {CFREE_SLICE_LIT("__ORDER_LITTLE_ENDIAN__"), CFREE_SLICE_LIT("1234")},
+ {CFREE_SLICE_LIT("__ORDER_BIG_ENDIAN__"), CFREE_SLICE_LIT("4321")},
+ {CFREE_SLICE_LIT("__BYTE_ORDER__"), CFREE_SLICE_LIT("__ORDER_LITTLE_ENDIAN__")},
+ {CFREE_SLICE_LIT("__LITTLE_ENDIAN__"), CFREE_SLICE_LIT("1")},
};
static int x64_register_at_public(uint32_t idx, CfreeArchReg* out) {
+ const char* nm = NULL;
+ int rc;
if (!out) return 1;
- return x64_register_iter_get(idx, &out->dwarf_idx, &out->name);
+ rc = x64_register_iter_get(idx, &out->dwarf_idx, &nm);
+ if (rc == 0) out->name = cfree_slice_cstr(nm);
+ return rc;
}
static CGTarget* x64_backend_make(Compiler* c, ObjBuilder* o,
diff --git a/src/arch/x64/asm.c b/src/arch/x64/asm.c
@@ -7,6 +7,7 @@
#include "asm/asm_helpers.h"
#include "core/arena.h"
#include "core/pool.h"
+#include "core/slice.h"
#include "core/strbuf.h"
struct X64Asm {
@@ -46,16 +47,17 @@ typedef struct X64AsmOperand {
static int x64_reg_from_name(AsmDriver* d, Sym s, u32* reg_out,
u32* width_out, u32* high8_out) {
- size_t n = 0;
- const char* p = pool_str(asm_driver_pool(d), s, &n);
+ Slice sl = pool_slice(asm_driver_pool(d), s);
char buf[16];
u32 reg;
u32 width = 8;
- if (!p || n < 2 || n >= sizeof buf) return 0;
- memcpy(buf, p, n);
- buf[n] = '\0';
- if (!strcmp(buf, "ah") || !strcmp(buf, "ch") || !strcmp(buf, "dh") ||
- !strcmp(buf, "bh")) {
+ Slice q;
+ if (!sl.s || sl.len < 2 || sl.len >= sizeof buf) return 0;
+ memcpy(buf, sl.s, sl.len);
+ buf[sl.len] = '\0';
+ q = slice_from_cstr(buf);
+ if (slice_eq_cstr(q, "ah") || slice_eq_cstr(q, "ch") ||
+ slice_eq_cstr(q, "dh") || slice_eq_cstr(q, "bh")) {
static const u32 high_map[4] = {4u, 5u, 6u, 7u};
const char* names = "acdb";
for (u32 i = 0; i < 4u; ++i) {
@@ -69,17 +71,19 @@ static int x64_reg_from_name(AsmDriver* d, Sym s, u32* reg_out,
}
if (x64_register_hw_index(buf, ®) != 0) return 0;
if (reg > 15u) return 0;
- if (!strcmp(buf, "al") || !strcmp(buf, "cl") || !strcmp(buf, "dl") ||
- !strcmp(buf, "bl") || !strcmp(buf, "spl") || !strcmp(buf, "bpl") ||
- !strcmp(buf, "sil") || !strcmp(buf, "dil") || buf[n - 1] == 'b') {
+ if (slice_eq_cstr(q, "al") || slice_eq_cstr(q, "cl") ||
+ slice_eq_cstr(q, "dl") || slice_eq_cstr(q, "bl") ||
+ slice_eq_cstr(q, "spl") || slice_eq_cstr(q, "bpl") ||
+ slice_eq_cstr(q, "sil") || slice_eq_cstr(q, "dil") ||
+ buf[sl.len - 1] == 'b') {
width = 1;
- } else if (!strcmp(buf, "ax") || !strcmp(buf, "cx") ||
- !strcmp(buf, "dx") || !strcmp(buf, "bx") ||
- !strcmp(buf, "sp") || !strcmp(buf, "bp") ||
- !strcmp(buf, "si") || !strcmp(buf, "di") ||
- buf[n - 1] == 'w') {
+ } else if (slice_eq_cstr(q, "ax") || slice_eq_cstr(q, "cx") ||
+ slice_eq_cstr(q, "dx") || slice_eq_cstr(q, "bx") ||
+ slice_eq_cstr(q, "sp") || slice_eq_cstr(q, "bp") ||
+ slice_eq_cstr(q, "si") || slice_eq_cstr(q, "di") ||
+ buf[sl.len - 1] == 'w') {
width = 2;
- } else if (buf[n - 1] == 'd' || buf[0] == 'e') {
+ } else if (buf[sl.len - 1] == 'd' || buf[0] == 'e') {
width = 4;
}
if (reg_out) *reg_out = reg;
@@ -89,8 +93,9 @@ static int x64_reg_from_name(AsmDriver* d, Sym s, u32* reg_out,
}
static int x64_xmm_from_name(AsmDriver* d, Sym s, u32* reg_out) {
- size_t n = 0;
- const char* p = pool_str(asm_driver_pool(d), s, &n);
+ Slice sl = pool_slice(asm_driver_pool(d), s);
+ const char* p = sl.s;
+ size_t n = sl.len;
u32 reg = 0;
if (!p || n < 4 || n > 5) return 0;
if (p[0] != 'x' || p[1] != 'm' || p[2] != 'm') return 0;
@@ -104,8 +109,9 @@ static int x64_xmm_from_name(AsmDriver* d, Sym s, u32* reg_out) {
}
static int x64_segment_prefix_from_name(AsmDriver* d, Sym s, u8* prefix_out) {
- size_t n = 0;
- const char* p = pool_str(asm_driver_pool(d), s, &n);
+ Slice sl = pool_slice(asm_driver_pool(d), s);
+ const char* p = sl.s;
+ size_t n = sl.len;
if (!p || n != 2) return 0;
if (p[0] == 'f' && p[1] == 's') {
if (prefix_out) *prefix_out = 0x64;
@@ -480,10 +486,9 @@ static int parse_mnemonic(const char* s, size_t n, X64MnInfo* out) {
tail = n - 1;
}
if (tail > after) {
- size_t cc_n = tail - after;
+ Slice cc = {{s + after}, tail - after};
for (size_t i = 0; i < sizeof kCC / sizeof kCC[0]; ++i) {
- size_t kn = strlen(kCC[i].name);
- if (cc_n == kn && memcmp(s + after, kCC[i].name, kn) == 0) {
+ if (slice_eq_cstr(cc, kCC[i].name)) {
out->cc = kCC[i].cc;
memcpy(out->base, "cmov", 4);
out->base[4] = '\0';
@@ -496,10 +501,9 @@ static int parse_mnemonic(const char* s, size_t n, X64MnInfo* out) {
/* SETcc: set<cc>. */
if (n > 3 && memcmp(s, "set", 3) == 0) {
- size_t cc_n = n - 3;
+ Slice cc = {{s + 3}, n - 3};
for (size_t i = 0; i < sizeof kCC / sizeof kCC[0]; ++i) {
- size_t kn = strlen(kCC[i].name);
- if (cc_n == kn && memcmp(s + 3, kCC[i].name, kn) == 0) {
+ if (slice_eq_cstr(cc, kCC[i].name)) {
out->cc = kCC[i].cc;
memcpy(out->base, "set", 3);
out->base[3] = '\0';
@@ -511,10 +515,9 @@ static int parse_mnemonic(const char* s, size_t n, X64MnInfo* out) {
/* Jcc: j<cc> — but NOT "jmp" / "jmpq" (handled above). */
if (n > 1 && s[0] == 'j' && !(n >= 3 && s[1] == 'm' && s[2] == 'p')) {
- size_t cc_n = n - 1;
+ Slice cc = {{s + 1}, n - 1};
for (size_t i = 0; i < sizeof kCC / sizeof kCC[0]; ++i) {
- size_t kn = strlen(kCC[i].name);
- if (cc_n == kn && memcmp(s + 1, kCC[i].name, kn) == 0) {
+ if (slice_eq_cstr(cc, kCC[i].name)) {
out->cc = kCC[i].cc;
out->base[0] = 'j';
out->base[1] = '\0';
@@ -556,11 +559,10 @@ static u32 row_implied_width(const X64InsnDesc* d) {
* AND whose width filter is compatible. Returns NULL on miss. */
static const X64InsnDesc* find_mnemonic_row(const X64MnInfo* info) {
u32 want_w = info->width; /* 0 = any */
+ Slice base = {{info->base}, info->base_len};
for (u32 i = 0; i < x64_insn_table_n; ++i) {
const X64InsnDesc* d = &x64_insn_table[i];
- size_t mn = strlen(d->mnemonic);
- if (mn != info->base_len) continue;
- if (memcmp(d->mnemonic, info->base, mn) != 0) continue;
+ if (!slice_eq(d->mnemonic, base)) continue;
if (want_w != 0) {
u32 rw = row_implied_width(d);
if (rw != 0 && rw != want_w) continue;
@@ -608,12 +610,11 @@ static void parse_br_rm(X64ParseCtx* p) {
/* Look up the ALU_RM_IMM8 row for a given mnemonic root; the /digit
* picks the operation (0=add, 1=or, 4=and, 5=sub, 6=xor, 7=cmp). */
-static const X64InsnDesc* find_alu_imm_row(const char* root, u32 root_len) {
+static const X64InsnDesc* find_alu_imm_row(Slice root) {
for (u32 i = 0; i < x64_insn_table_n; ++i) {
const X64InsnDesc* d = &x64_insn_table[i];
if (d->fmt != X64_FMT_ALU_RM_IMM8) continue;
- if (strlen(d->mnemonic) != root_len) continue;
- if (memcmp(d->mnemonic, root, root_len) != 0) continue;
+ if (!slice_eq(d->mnemonic, root)) continue;
return d;
}
return NULL;
@@ -633,9 +634,7 @@ static void parse_alu_rr(X64ParseCtx* p) {
/* Immediate source → not an ALU_RR encoding. Redirect to the
* ALU_RM_IMM row for this mnemonic. */
if (src.kind == X64_ASM_OP_IMM && dst.kind == X64_ASM_OP_REG) {
- const X64InsnDesc* imm_row =
- find_alu_imm_row(p->desc->mnemonic,
- (u32)strlen(p->desc->mnemonic));
+ const X64InsnDesc* imm_row = find_alu_imm_row(p->desc->mnemonic);
if (!imm_row) asm_driver_panic(p->d, "x64 asm: no alu-imm row");
if (imm_fits_i8(src.imm))
emit_alu_imm8(p->mc, width_to_w(p->width), imm_row->modrm_reg, dst.reg,
@@ -1013,15 +1012,15 @@ static void parse_sse_rr(X64ParseCtx* p) {
}
if (dst.kind == X64_ASM_OP_MEM && src.kind == X64_ASM_OP_XMM &&
p->desc->opc[1] == 0x10u &&
- (!strcmp(p->desc->mnemonic, "movsd") ||
- !strcmp(p->desc->mnemonic, "movss"))) {
+ (slice_eq_cstr(p->desc->mnemonic, "movsd") ||
+ slice_eq_cstr(p->desc->mnemonic, "movss"))) {
emit_sse_store(p->mc, p->desc->leg_pfx, 0x11, src.reg, dst.base,
dst.disp);
return;
}
if (dst.kind == X64_ASM_OP_MEM && src.kind == X64_ASM_OP_XMM &&
p->desc->opc[1] == 0x28u &&
- !strcmp(p->desc->mnemonic, "movaps")) {
+ slice_eq_cstr(p->desc->mnemonic, "movaps")) {
emit_sse_store(p->mc, p->desc->leg_pfx, 0x29, src.reg, dst.base,
dst.disp);
return;
@@ -1179,8 +1178,9 @@ static u32 width_from_info(const X64MnInfo* info, const X64InsnDesc* d) {
static void x64_arch_asm_insn(ArchAsm* base, AsmDriver* d, Sym mnemonic) {
X64Asm* a = (X64Asm*)base;
MCEmitter* mc = asm_driver_mc(d);
- size_t n = 0;
- const char* p = pool_str(asm_driver_pool(d), mnemonic, &n);
+ Slice mnsl = pool_slice(asm_driver_pool(d), mnemonic);
+ const char* p = mnsl.s;
+ size_t n = mnsl.len;
X64MnInfo info;
const X64InsnDesc* desc;
X64ParseCtx ctx;
@@ -1214,8 +1214,7 @@ static void x64_arch_asm_insn(ArchAsm* base, AsmDriver* d, Sym mnemonic) {
for (u32 i = 0; i < x64_insn_table_n; ++i) {
const X64InsnDesc* dr = &x64_insn_table[i];
if (dr->fmt == X64_FMT_MOV_RI &&
- strlen(dr->mnemonic) == 3 &&
- memcmp(dr->mnemonic, "mov", 3) == 0) {
+ slice_eq_cstr(dr->mnemonic, "mov")) {
ctx.d = d;
ctx.mc = mc;
ctx.desc = dr;
@@ -1275,8 +1274,7 @@ static void x64_arch_asm_insn(ArchAsm* base, AsmDriver* d, Sym mnemonic) {
for (u32 i = 0; i < x64_insn_table_n; ++i) {
const X64InsnDesc* dr = &x64_insn_table[i];
if (dr->fmt != X64_FMT_BR_RM) continue;
- if (strlen(dr->mnemonic) != info.base_len) continue;
- if (memcmp(dr->mnemonic, info.base, info.base_len) != 0) continue;
+ if (!slice_eq(dr->mnemonic, (Slice){{info.base}, info.base_len})) continue;
desc = dr;
break;
}
@@ -1325,7 +1323,8 @@ void x64_inline_bind(X64Asm* a, const AsmConstraint* outs, u32 nout,
_Noreturn static void inline_panic(X64Asm* a, const char* msg) {
SrcLoc loc = {0, 0, 0};
- compiler_panic(a->c, loc, "x64 inline asm: %s", msg);
+ compiler_panic(a->c, loc, "x64 inline asm: %.*s",
+ SLICE_ARG(slice_from_cstr(msg)));
}
/* Width selector for x64_reg_spelling: matches the operand-modifier
@@ -1464,7 +1463,7 @@ static void render_operand(X64Asm* a, StrBuf* sb, u32 idx, int form) {
}
static u32 find_named_operand(X64Asm* a, const char* name, size_t len) {
- Sym needle = pool_intern(a->c->global, name, len);
+ Sym needle = pool_intern_slice(a->c->global, (Slice){.s = name, .len = len});
u32 i;
for (i = 0; i < a->nout; ++i) {
if (a->outs[i].name == needle) return i;
diff --git a/src/arch/x64/disasm.c b/src/arch/x64/disasm.c
@@ -36,7 +36,7 @@ typedef struct X64Disasm {
static void emit_mnemonic(StrBuf* sb, const X64InsnDesc* d,
const X64DecodeCtx* ctx, const u8* bytes) {
if (ctx->has_lock) strbuf_puts(sb, "lock ");
- strbuf_puts(sb, d->mnemonic);
+ strbuf_put_slice(sb, d->mnemonic);
/* Jcc / SETcc / CMOVcc: the table stores the bare prefix ("j", "set",
* "cmov") and we append the condition suffix from the opcode byte. */
if (d->fmt == X64_FMT_JCC_REL32 || d->fmt == X64_FMT_SETCC_RM ||
@@ -81,9 +81,9 @@ static u32 x64_decode(ArchDisasm* base, const u8* bytes, size_t len, u64 vaddr,
out->vaddr = vaddr;
out->bytes = bytes;
out->nbytes = 1;
- out->mnemonic = strbuf_cstr(&d->mnem);
- out->operands = strbuf_cstr(&d->ops);
- out->annotation = strbuf_cstr(&d->ann);
+ out->mnemonic = strbuf_slice(&d->mnem);
+ out->operands = strbuf_slice(&d->ops);
+ out->annotation = strbuf_slice(&d->ann);
return 1;
}
@@ -93,9 +93,9 @@ static u32 x64_decode(ArchDisasm* base, const u8* bytes, size_t len, u64 vaddr,
out->vaddr = vaddr;
out->bytes = bytes;
out->nbytes = 1;
- out->mnemonic = strbuf_cstr(&d->mnem);
- out->operands = strbuf_cstr(&d->ops);
- out->annotation = strbuf_cstr(&d->ann);
+ out->mnemonic = strbuf_slice(&d->mnem);
+ out->operands = strbuf_slice(&d->ops);
+ out->annotation = strbuf_slice(&d->ann);
return 1;
}
@@ -107,18 +107,18 @@ static u32 x64_decode(ArchDisasm* base, const u8* bytes, size_t len, u64 vaddr,
out->vaddr = vaddr;
out->bytes = bytes;
out->nbytes = 1;
- out->mnemonic = strbuf_cstr(&d->mnem);
- out->operands = strbuf_cstr(&d->ops);
- out->annotation = strbuf_cstr(&d->ann);
+ out->mnemonic = strbuf_slice(&d->mnem);
+ out->operands = strbuf_slice(&d->ops);
+ out->annotation = strbuf_slice(&d->ann);
return 1;
}
out->vaddr = vaddr;
out->bytes = bytes;
out->nbytes = total;
- out->mnemonic = strbuf_cstr(&d->mnem);
- out->operands = strbuf_cstr(&d->ops);
- out->annotation = strbuf_cstr(&d->ann);
+ out->mnemonic = strbuf_slice(&d->mnem);
+ out->operands = strbuf_slice(&d->ops);
+ out->annotation = strbuf_slice(&d->ann);
return total;
}
diff --git a/src/arch/x64/emit.c b/src/arch/x64/emit.c
@@ -11,6 +11,7 @@
#include "arch/x64/x64.h"
#include "core/arena.h"
#include "core/pool.h"
+#include "core/slice.h"
#include "obj/obj.h"
#include "arch/x64/internal.h"
@@ -832,7 +833,7 @@ static u32 x_compute_frame_size(const XImpl *a, u32 cs_used, u32 cs_fp_used) {
* cfree references it on demand from the prologue and lets the linker
* resolve it. */
static ObjSymId x_chkstk_sym(CGTarget *t) {
- Sym name = pool_intern_cstr(t->c->global, "__chkstk");
+ Sym name = pool_intern_slice(t->c->global, SLICE_LIT("__chkstk"));
ObjSymId s = obj_symbol_find(t->obj, name);
if (s != 0) return s;
return obj_symbol(t->obj, name, SB_GLOBAL, SK_UNDEF, OBJ_SEC_NONE, 0, 0);
diff --git a/src/arch/x64/internal.h b/src/arch/x64/internal.h
@@ -17,6 +17,7 @@
#include "arch/x64/x64.h"
#include "core/arena.h"
#include "core/pool.h"
+#include "core/slice.h"
#include "obj/obj.h"
/* Prologue placeholder budget for the unplanned-regs path (the C
@@ -185,7 +186,8 @@ static inline int type_is_signed(CfreeCgTypeId t) {
static inline _Noreturn void x_panic(CGTarget* t, const char* what) {
SrcLoc loc = impl_of(t)->loc;
- compiler_panic(t->c, loc, "x64: %s not implemented", what);
+ compiler_panic(t->c, loc, "x64: %.*s not implemented",
+ SLICE_ARG(slice_from_cstr(what)));
}
/* ============================================================
diff --git a/src/arch/x64/isa.c b/src/arch/x64/isa.c
@@ -28,7 +28,7 @@
* ==================================================================== */
#define ROW(mn, lp, ol, b0, b1, b2, lm, mr, wr, f, fl) \
- {mn, lp, ol, {b0, b1, b2}, lm, mr, wr, f, fl}
+ {{{(mn)}, sizeof(mn) - 1}, lp, ol, {b0, b1, b2}, lm, mr, wr, f, fl}
#define NO_MODRM 0xFFu
const X64InsnDesc x64_insn_table[] = {
diff --git a/src/arch/x64/isa.h b/src/arch/x64/isa.h
@@ -30,6 +30,7 @@
#include "core/bytes.h"
#include "core/core.h"
+#include "core/slice.h"
#include "core/strbuf.h"
/* ---- GPR numbering (DWARF / ABI matches HW encoding 0..15) ---- */
@@ -307,7 +308,7 @@ typedef enum X64Format {
* ==================================================================== */
typedef struct X64InsnDesc {
- const char* mnemonic; /* AT&T mnemonic without size suffix; printer adds
+ Slice mnemonic; /* AT&T mnemonic without size suffix; printer adds
a size letter (b/w/l/q) based on fmt + ctx. */
u8 leg_pfx; /* X64_PFX_NONE / 0x66 / 0xF2 / 0xF3 */
u8 opc_len; /* 1..3 */
diff --git a/src/arch/x64/ops.c b/src/arch/x64/ops.c
@@ -19,6 +19,7 @@
#include "arch/x64/x64.h"
#include "core/arena.h"
#include "core/pool.h"
+#include "core/slice.h"
#include "obj/obj.h"
/* ============================================================
@@ -36,7 +37,7 @@ static void x_load_const(CGTarget* t, Operand dst, ConstBytes cb) {
if (dst.cls != RC_FP)
compiler_panic(t->c, a->loc, "x64 load_const: only FP supported in v1");
- Sym ro_name = pool_intern_cstr(t->c->global, ".rodata");
+ Sym ro_name = pool_intern_slice(t->c->global, SLICE_LIT(".rodata"));
ObjSecId ro = obj_section(t->obj, ro_name, SEC_RODATA, SF_ALLOC, 1u);
u32 cur_section = t->mc->section_id;
@@ -62,7 +63,7 @@ static void x_load_const(CGTarget* t, Operand dst, ConstBytes cb) {
for (int i = tn - 1; i >= 0; --i) namebuf[len++] = tmp[i];
namebuf[len] = 0;
- Sym sname = pool_intern_cstr(t->c->global, namebuf);
+ Sym sname = pool_intern_slice(t->c->global, slice_from_cstr(namebuf));
ObjSymId sym = obj_symbol(t->obj, sname, SB_LOCAL, SK_OBJ, ro, (u64)ro_off,
(u64)cb.size);
t->mc->set_section(t->mc, cur_section);
@@ -450,7 +451,7 @@ static void x_tls_addr_of_win64(CGTarget* t, Operand dst, ObjSymId sym,
emit_u32le(mc, 0x58u);
/* (2) mov r11d, [rip + _tls_index]: 44 8B 1D disp32. */
- Sym idx_name = pool_intern_cstr(t->c->global, "_tls_index");
+ Sym idx_name = pool_intern_slice(t->c->global, SLICE_LIT("_tls_index"));
ObjSymId idx_sym = obj_symbol_find(t->obj, idx_name);
if (idx_sym == 0) {
idx_sym = obj_symbol(t->obj, idx_name, SB_GLOBAL, SK_UNDEF,
@@ -2578,8 +2579,9 @@ static void x_intrinsic(CGTarget* t, IntrinKind kind, Operand* dsts, u32 nd,
Operand da = args[0], sa = args[1], nb = args[2];
if (da.kind != OPK_REG || sa.kind != OPK_REG || nb.kind != OPK_IMM) {
compiler_panic(t->c, a->loc,
- "x64 intrinsic: %s with non-const n or non-REG ptr",
- kind == INTRIN_MEMCPY ? "memcpy" : "memmove");
+ "x64 intrinsic: %.*s with non-const n or non-REG ptr",
+ SLICE_ARG(slice_from_cstr(
+ kind == INTRIN_MEMCPY ? "memcpy" : "memmove")));
}
u32 dr = da.v.reg & 0xFu;
u32 sr = sa.v.reg & 0xFu;
diff --git a/src/arch/x64/regs.c b/src/arch/x64/regs.c
@@ -2,7 +2,7 @@
#include "arch/x64/regs.h"
-#include <string.h>
+#include "core/slice.h"
typedef struct X64Reg {
uint32_t dwarf_idx;
@@ -43,11 +43,13 @@ static int gpr_alias_index(const char* name, const uint32_t* map,
{"r15", "r15d", "r15w", "r15b", NULL},
};
uint32_t i;
+ Slice q;
if (!name) return 1;
+ q = slice_from_cstr(name);
for (i = 0; i < 16u; ++i) {
uint32_t j;
for (j = 0; aliases[i][j]; ++j) {
- if (!strcmp(name, aliases[i][j])) {
+ if (slice_eq_cstr(q, aliases[i][j])) {
if (idx_out) *idx_out = map[i];
return 0;
}
@@ -71,10 +73,13 @@ int x64_register_index(const char* name, uint32_t* idx_out) {
};
if (!name) return 1;
if (name[0] == '%') ++name;
- for (i = 0; i < X64_REGS_N; ++i) {
- if (!strcmp(X64_REGS[i].name, name)) {
- if (idx_out) *idx_out = X64_REGS[i].dwarf_idx;
- return 0;
+ {
+ Slice q = slice_from_cstr(name);
+ for (i = 0; i < X64_REGS_N; ++i) {
+ if (slice_eq_cstr(q, X64_REGS[i].name)) {
+ if (idx_out) *idx_out = X64_REGS[i].dwarf_idx;
+ return 0;
+ }
}
}
return gpr_alias_index(name, dwarf, idx_out);
diff --git a/src/asm/asm.c b/src/asm/asm.c
@@ -30,6 +30,7 @@
#include "core/hashmap.h"
#include "core/heap.h"
#include "core/pool.h"
+#include "core/slice.h"
#include "obj/obj.h"
HASHMAP_DEFINE(SymSecMap, Sym, ObjSecId, hash_u32);
@@ -111,7 +112,9 @@ _Noreturn static void d_panicf(AsmDriver* d, const char* fmt, ...) {
/* ---- spelling helpers ---- */
static const char* asm_str(AsmDriver* d, Sym s, size_t* nout) {
- return pool_str(d->pool, s, nout);
+ Slice sl = pool_slice(d->pool, s);
+ if (nout) *nout = sl.len;
+ return sl.s;
}
static int sym_eq(AsmDriver* d, Sym s, const char* lit) {
@@ -422,7 +425,7 @@ ObjSymId asm_driver_intern_sym(AsmDriver* d, Sym name) {
ObjSecId asm_driver_cur_section(AsmDriver* d) {
if (d->cur_sec == OBJ_SEC_NONE) {
- if (!d->n_text) d->n_text = pool_intern_cstr(d->pool, ".text");
+ if (!d->n_text) d->n_text = pool_intern_slice(d->pool, SLICE_LIT(".text"));
d->cur_sec =
ensure_section(d, d->n_text, SEC_TEXT, (u16)(SF_ALLOC | SF_EXEC), 4);
d->mc->set_section(d->mc, d->cur_sec);
@@ -456,7 +459,8 @@ int asm_driver_eat_punct(AsmDriver* d, u32 p) {
void asm_driver_expect_punct(AsmDriver* d, u32 p, const char* what) {
if (!asm_driver_eat_punct(d, p))
- d_panicf(d, "asm: expected '%s' (%s)", "punct", what);
+ d_panicf(d, "asm: expected '%.*s' (%.*s)", SLICE_ARG(SLICE_LIT("punct")),
+ SLICE_ARG(slice_from_cstr(what)));
}
i64 asm_driver_parse_const(AsmDriver* d) {
@@ -584,7 +588,7 @@ static void decode_string(AsmDriver* d, Sym spelling, u8** out, u32* nout) {
static Sym expect_ident(AsmDriver* d, const char* what) {
AsmTok t = d_peek(d);
if (t.kind != ASM_TOK_IDENT)
- d_panicf(d, "asm: %s: expected identifier", what);
+ d_panicf(d, "asm: %.*s: expected identifier", SLICE_ARG(slice_from_cstr(what)));
(void)d_next(d);
return t.v.ident;
}
@@ -621,25 +625,25 @@ static void emit_int_directive(AsmDriver* d, u32 width) {
static void do_directive(AsmDriver* d, Sym name) {
if (sym_eq(d, name, "text")) {
- if (!d->n_text) d->n_text = pool_intern_cstr(d->pool, ".text");
+ if (!d->n_text) d->n_text = pool_intern_slice(d->pool, SLICE_LIT(".text"));
set_section(d, d->n_text, SEC_TEXT, (u16)(SF_ALLOC | SF_EXEC), 4);
d_skip_to_eol(d);
return;
}
if (sym_eq(d, name, "data")) {
- if (!d->n_data) d->n_data = pool_intern_cstr(d->pool, ".data");
+ if (!d->n_data) d->n_data = pool_intern_slice(d->pool, SLICE_LIT(".data"));
set_section(d, d->n_data, SEC_DATA, (u16)(SF_ALLOC | SF_WRITE), 8);
d_skip_to_eol(d);
return;
}
if (sym_eq(d, name, "rodata")) {
- if (!d->n_rodata) d->n_rodata = pool_intern_cstr(d->pool, ".rodata");
+ if (!d->n_rodata) d->n_rodata = pool_intern_slice(d->pool, SLICE_LIT(".rodata"));
set_section(d, d->n_rodata, SEC_RODATA, (u16)SF_ALLOC, 8);
d_skip_to_eol(d);
return;
}
if (sym_eq(d, name, "bss")) {
- if (!d->n_bss) d->n_bss = pool_intern_cstr(d->pool, ".bss");
+ if (!d->n_bss) d->n_bss = pool_intern_slice(d->pool, SLICE_LIT(".bss"));
set_section(d, d->n_bss, SEC_BSS, (u16)(SF_ALLOC | SF_WRITE), 8);
d_skip_to_eol(d);
return;
@@ -653,7 +657,8 @@ static void do_directive(AsmDriver* d, Sym name) {
} else if (t.kind == ASM_TOK_STR) {
size_t n = 0;
const char* p = asm_str(d, t.spelling, &n);
- if (n >= 2 && p[0] == '"') sname = pool_intern(d->pool, p + 1, n - 2);
+ if (n >= 2 && p[0] == '"')
+ sname = pool_intern_slice(d->pool, (Slice){ .s = p + 1, .len = n - 2 });
(void)d_next(d);
} else if (tok_is_punct(t, '.')) {
(void)d_next(d);
@@ -665,7 +670,7 @@ static void do_directive(AsmDriver* d, Sym name) {
if (ni + 1 >= sizeof buf) d_panicf(d, "asm: .section: name too long");
buf[0] = '.';
for (size_t i = 0; i < ni; ++i) buf[i + 1] = nm[i];
- sname = pool_intern(d->pool, buf, ni + 1);
+ sname = pool_intern_slice(d->pool, (Slice){ .s = buf, .len = ni + 1 });
} else {
d_panicf(d, "asm: .section: expected name");
}
@@ -747,7 +752,7 @@ static void do_directive(AsmDriver* d, Sym name) {
size_t sn = 0;
const char* sp = asm_str(d, t.spelling, &sn);
if (sn >= 2 && sp[0] == '"' && sp[sn - 1] == '"')
- tag = pool_intern(d->pool, sp + 1, sn - 2);
+ tag = pool_intern_slice(d->pool, (Slice){ .s = sp + 1, .len = sn - 2 });
} else {
d_panicf(d, "asm: .type: tag");
}
@@ -945,7 +950,7 @@ static Sym maybe_compose_mnemonic(AsmDriver* d, Sym head) {
for (size_t i = 0; i < hn; ++i) buf[i] = hp[i];
buf[hn] = '.';
for (size_t i = 0; i < rn; ++i) buf[hn + 1 + i] = rp[i];
- head = pool_intern(d->pool, buf, n);
+ head = pool_intern_slice(d->pool, (Slice){ .s = buf, .len = n });
}
}
diff --git a/src/asm/asm_lex.c b/src/asm/asm_lex.c
@@ -15,6 +15,7 @@
#include "core/heap.h"
#include "core/pool.h"
+#include "core/slice.h"
struct AsmLexer {
Compiler* c;
@@ -129,7 +130,8 @@ AsmLexer* asm_lex_open_mem(Compiler* c, const char* name, const char* src,
l->src = src ? src : "";
l->len = src ? len : 0;
l->pos = 0;
- if (source_add_memory(c->sources, name, &l->file_id) != CFREE_OK) {
+ if (source_add_memory(c->sources, slice_from_cstr(name), &l->file_id) !=
+ CFREE_OK) {
h->free(h, l, sizeof(*l));
return NULL;
}
@@ -168,7 +170,9 @@ static Sym intern_spliced(AsmLexer* l, size_t start, size_t end) {
break;
}
}
- if (!has_splice) return pool_intern(l->pool, l->src + start, end - start);
+ if (!has_splice)
+ return pool_intern_slice(
+ l->pool, (Slice){ .s = l->src + start, .len = end - start });
buf = (char*)l->heap->alloc(l->heap, end - start, 1);
k = 0;
@@ -179,7 +183,7 @@ static Sym intern_spliced(AsmLexer* l, size_t start, size_t end) {
}
buf[k++] = l->src[i++];
}
- sym = pool_intern(l->pool, buf, k);
+ sym = pool_intern_slice(l->pool, (Slice){ .s = buf, .len = k });
l->heap->free(l->heap, buf, end - start);
return sym;
}
@@ -474,7 +478,7 @@ AsmTok asm_lex_next(AsmLexer* l) {
break;
}
}
- t.spelling = pool_intern(l->pool, pbuf, k);
+ t.spelling = pool_intern_slice(l->pool, (Slice){ .s = pbuf, .len = k });
l->heap->free(l->heap, pbuf, plen ? plen : 1);
return t;
}
diff --git a/src/cg/arith.c b/src/cg/arith.c
@@ -949,7 +949,8 @@ CfreeCgTypeId api_atomic_pointee(CfreeCg* g, CfreeCgTypeId pty,
const char* who) {
CfreeCgTypeId pointee = cg_type_pointee(g->c, pty);
if (!pointee) {
- compiler_panic(g->c, g->cur_loc, "%s: operand is not a pointer", who);
+ compiler_panic(g->c, g->cur_loc, "%.*s: operand is not a pointer",
+ SLICE_ARG(slice_from_cstr(who)));
return builtin_id(CFREE_CG_BUILTIN_I32);
}
return pointee;
diff --git a/src/cg/asm.c b/src/cg/asm.c
@@ -1,11 +1,9 @@
#include "cg/internal.h"
const char* api_sym_cstr(CfreeCg* g, CfreeSym sym) {
- size_t len;
const char* s;
if (!sym) return "";
- s = pool_str(g->c->global, (Sym)sym, &len);
- (void)len;
+ s = pool_slice(g->c->global, (Sym)sym).s;
return s ? s : "";
}
@@ -240,7 +238,7 @@ void cfree_cg_inline_asm(CfreeCg* g, CfreeCgInlineAsm asm_block) {
out_reg_owned[i] = 1;
}
- sym_memory = pool_intern_cstr(g->c->global, "memory");
+ sym_memory = pool_intern_slice(g->c->global, SLICE_LIT("memory"));
has_memory_clobber = 0;
for (u32 i = 0; i < nclobbers; ++i) {
if (clobs[i] == sym_memory) has_memory_clobber = 1;
@@ -304,10 +302,9 @@ void cfree_cg_inline_asm(CfreeCg* g, CfreeCgInlineAsm asm_block) {
if (out_reg_owned) h->free(h, out_reg_owned, noutputs);
}
-void cfree_cg_file_scope_asm(CfreeCg* g, const char* asm_source,
- size_t asm_source_len) {
+void cfree_cg_file_scope_asm(CfreeCg* g, CfreeSlice asm_source) {
AsmLexer* lex;
- if (!g || !asm_source) return;
+ if (!g || !asm_source.s) return;
/* The C-source backend bypasses MCEmitter entirely; file-scope asm has
* no portable C source equivalent (Phase 4 territory — see
* doc/CBACKEND.md). Panic with the same shape as other unimplemented
@@ -317,7 +314,8 @@ void cfree_cg_file_scope_asm(CfreeCg* g, const char* asm_source,
"C target: file-scope asm not yet supported");
}
api_local_const_memory_boundary(g);
- lex = asm_lex_open_mem(g->c, "<file-scope asm>", asm_source, asm_source_len);
+ lex = asm_lex_open_mem(g->c, "<file-scope asm>", asm_source.s,
+ asm_source.len);
if (!lex)
compiler_panic(g->c, api_no_loc(), "CfreeCg: file-scope asm out of memory");
asm_parse(g->c, lex, g->mc);
diff --git a/src/cg/control.c b/src/cg/control.c
@@ -404,21 +404,25 @@ ApiCgScope* api_scope_from_handle(CfreeCg* g, CfreeCgScope scope,
slot = ((u32)scope & 0xffu);
generation = ((u32)scope >> 8);
if (slot == 0 || slot > API_CG_MAX_SCOPES) {
- compiler_panic(g->c, g->cur_loc, "%s: invalid scope handle", who);
+ compiler_panic(g->c, g->cur_loc, "%.*s: invalid scope handle",
+ SLICE_ARG(slice_from_cstr(who)));
return NULL;
}
slot--;
if (slot >= g->nscopes) {
- compiler_panic(g->c, g->cur_loc, "%s: stale scope handle", who);
+ compiler_panic(g->c, g->cur_loc, "%.*s: stale scope handle",
+ SLICE_ARG(slice_from_cstr(who)));
return NULL;
}
if (require_top && slot + 1u != g->nscopes) {
- compiler_panic(g->c, g->cur_loc, "%s: non-LIFO scope end", who);
+ compiler_panic(g->c, g->cur_loc, "%.*s: non-LIFO scope end",
+ SLICE_ARG(slice_from_cstr(who)));
return NULL;
}
s = &g->scopes[slot];
if (!s->active || s->generation != generation) {
- compiler_panic(g->c, g->cur_loc, "%s: stale scope handle", who);
+ compiler_panic(g->c, g->cur_loc, "%.*s: stale scope handle",
+ SLICE_ARG(slice_from_cstr(who)));
return NULL;
}
return s;
diff --git a/src/cg/data.c b/src/cg/data.c
@@ -122,8 +122,9 @@ void cfree_cg_data_begin(CfreeCg* g, CfreeCgSym cg_sym,
} else if (attrs.flags & CFREE_CG_DATADEF_ZERO_FILL) {
sec_kind = SEC_BSS;
sec_flags = SF_ALLOC | SF_WRITE;
- sec_name_sym = attrs.section ? (Sym)attrs.section
- : pool_intern_cstr(c->global, ".bss");
+ sec_name_sym = attrs.section
+ ? (Sym)attrs.section
+ : pool_intern_slice(c->global, SLICE_LIT(".bss"));
} else if (attrs.section) {
sec_name_sym = (Sym)attrs.section;
if (attrs.flags & CFREE_CG_DATADEF_READONLY) {
@@ -137,7 +138,7 @@ void cfree_cg_data_begin(CfreeCg* g, CfreeCgSym cg_sym,
(decl_attrs.as.object.flags & CFREE_CG_OBJ_READONLY)) {
sec_kind = SEC_RODATA;
sec_flags = SF_ALLOC;
- sec_name_sym = pool_intern_cstr(c->global, ".rodata");
+ sec_name_sym = pool_intern_slice(c->global, SLICE_LIT(".rodata"));
} else if (decl_attrs.as.object.flags & CFREE_CG_OBJ_TLS) {
sec_kind = SEC_DATA;
sec_flags = SF_ALLOC | SF_WRITE | SF_TLS;
@@ -145,7 +146,7 @@ void cfree_cg_data_begin(CfreeCg* g, CfreeCgSym cg_sym,
} else {
sec_kind = SEC_DATA;
sec_flags = SF_ALLOC | SF_WRITE;
- sec_name_sym = pool_intern_cstr(c->global, ".data");
+ sec_name_sym = pool_intern_slice(c->global, SLICE_LIT(".data"));
}
if (attrs.flags & CFREE_CG_DATADEF_RETAIN) sec_flags |= SF_RETAIN;
if (attrs.flags & CFREE_CG_DATADEF_MERGE) sec_flags |= SF_MERGE;
@@ -630,6 +631,7 @@ ObjSymId api_emit_label_table(CfreeCg* g, const Label* labels, u32 n) {
RelocKind rk;
u8 pad[8];
char name_buf[40];
+ StrBuf name_sb;
Sym anon;
ObjSymId sym;
u32 i;
@@ -659,7 +661,7 @@ ObjSymId api_emit_label_table(CfreeCg* g, const Label* labels, u32 n) {
(unsigned)ptrsz);
return OBJ_SYM_NONE;
}
- sec_name = pool_intern_cstr(c->global, ".rodata");
+ sec_name = pool_intern_slice(c->global, SLICE_LIT(".rodata"));
sec = obj_section(ob, sec_name, SEC_RODATA, SF_ALLOC, ptral);
base = obj_align_to(ob, sec, ptral);
/* Write `n` placeholder slots first; emit_label_data_reloc later
@@ -680,8 +682,12 @@ ObjSymId api_emit_label_table(CfreeCg* g, const Label* labels, u32 n) {
mc->emit_label_data_reloc(mc, sec, base + i * ptrsz, ml, rk, ptrsz,
/*extra_addend=*/0);
}
- snprintf(name_buf, sizeof name_buf, ".Lcfree_jt.%u", g->rodata_counter++);
- anon = pool_intern_cstr(c->global, name_buf);
+ strbuf_init(&name_sb, name_buf, sizeof name_buf);
+ strbuf_put_slice(&name_sb, SLICE_LIT(".Lcfree_jt."));
+ strbuf_put_u64(&name_sb, g->rodata_counter++);
+ anon = pool_intern_slice(
+ c->global,
+ (Slice){.s = strbuf_cstr(&name_sb), .len = strbuf_len(&name_sb)});
sym = obj_symbol(ob, anon, SB_LOCAL, SK_OBJ, sec, base, (u64)n * ptrsz);
return sym;
}
diff --git a/src/cg/debug.c b/src/cg/debug.c
@@ -9,7 +9,8 @@ DebugTypeId api_debug_type(CfreeCg* g, CfreeCgTypeId id) {
case CFREE_CG_TYPE_VOID:
return debug_type_void(g->debug);
case CFREE_CG_TYPE_BOOL:
- return debug_type_base(g->debug, pool_intern_cstr(g->c->global, "_Bool"),
+ return debug_type_base(g->debug,
+ pool_intern_slice(g->c->global, SLICE_LIT("_Bool")),
DEBUG_BE_BOOL, 1);
case CFREE_CG_TYPE_INT: {
const char* name = "long long";
@@ -19,14 +20,15 @@ DebugTypeId api_debug_type(CfreeCg* g, CfreeCgTypeId id) {
name = "short";
else if (ty->integer.width <= 32)
name = "int";
- return debug_type_base(g->debug, pool_intern_cstr(g->c->global, name),
- DEBUG_BE_SIGNED,
- (u32)((ty->integer.width + 7u) / 8u));
+ return debug_type_base(
+ g->debug, pool_intern_slice(g->c->global, slice_from_cstr(name)),
+ DEBUG_BE_SIGNED, (u32)((ty->integer.width + 7u) / 8u));
}
case CFREE_CG_TYPE_FLOAT: {
const char* name = ty->fp.width <= 32 ? "float" : "double";
- return debug_type_base(g->debug, pool_intern_cstr(g->c->global, name),
- DEBUG_BE_FLOAT, (u32)((ty->fp.width + 7u) / 8u));
+ return debug_type_base(
+ g->debug, pool_intern_slice(g->c->global, slice_from_cstr(name)),
+ DEBUG_BE_FLOAT, (u32)((ty->fp.width + 7u) / 8u));
}
case CFREE_CG_TYPE_PTR: {
DebugTypeId pointee = api_debug_type(g, ty->ptr.pointee);
@@ -68,7 +70,8 @@ DebugTypeId api_debug_type(CfreeCg* g, CfreeCgTypeId id) {
return debug_type_record_end(b);
}
case CFREE_CG_TYPE_ENUM:
- return debug_type_base(g->debug, pool_intern_cstr(g->c->global, "int"),
+ return debug_type_base(g->debug,
+ pool_intern_slice(g->c->global, SLICE_LIT("int")),
DEBUG_BE_SIGNED, ty->size ? (u32)ty->size : 4u);
case CFREE_CG_TYPE_ALIAS: {
DebugTypeId base = api_debug_type(g, ty->alias.base);
diff --git a/src/cg/internal.h b/src/cg/internal.h
@@ -17,6 +17,8 @@
#include "core/heap.h"
#include "core/pool.h"
#include "core/segvec.h"
+#include "core/slice.h"
+#include "core/strbuf.h"
#include "debug/debug.h"
#include "obj/obj.h"
#include "opt/opt.h"
@@ -221,8 +223,7 @@ const char* api_asm_constraint_body(const char* s);
int api_asm_is_early_clobber(const char* s);
void api_asm_spill_sv(CfreeCg* g, ApiSValue* sv, Reg phys, RegClass cls);
void cfree_cg_inline_asm(CfreeCg* g, CfreeCgInlineAsm asm_block);
-void cfree_cg_file_scope_asm(CfreeCg* g, const char* asm_source,
- size_t asm_source_len);
+void cfree_cg_file_scope_asm(CfreeCg* g, CfreeSlice asm_source);
MemAccess api_mem_for_atomic(CfreeCg* g, CfreeCgTypeId val_ty);
int cfree_cg_atomic_is_legal(CfreeCompiler* c, CfreeCgMemAccess access,
CfreeCgMemOrder order);
diff --git a/src/cg/memory.c b/src/cg/memory.c
@@ -58,6 +58,7 @@ CfreeCgSym cfree_cg_const_data(CfreeCg* g, const uint8_t* data, size_t len,
ObjSecId sec;
u32 base;
char name_buf[32];
+ StrBuf name_sb;
Sym anon_name;
ObjSymId sym;
CfreeCgDecl attrs;
@@ -66,14 +67,18 @@ CfreeCgSym cfree_cg_const_data(CfreeCg* g, const uint8_t* data, size_t len,
ob = g->obj;
pty = resolve_type(c, pointee_type);
if (!pty) return CFREE_CG_SYM_NONE;
- sec_name = pool_intern_cstr(c->global, ".rodata");
+ sec_name = pool_intern_slice(c->global, SLICE_LIT(".rodata"));
sec = obj_section(ob, sec_name, SEC_RODATA, SF_ALLOC,
align ? align : (u32)abi_cg_alignof(c->abi, pointee_type));
base = obj_align_to(
ob, sec, align ? align : (u32)abi_cg_alignof(c->abi, pointee_type));
obj_write(ob, sec, data, len);
- snprintf(name_buf, sizeof(name_buf), ".Lcfree_ro.%u", g->rodata_counter++);
- anon_name = pool_intern_cstr(c->global, name_buf);
+ strbuf_init(&name_sb, name_buf, sizeof(name_buf));
+ strbuf_put_slice(&name_sb, SLICE_LIT(".Lcfree_ro."));
+ strbuf_put_u64(&name_sb, g->rodata_counter++);
+ anon_name = pool_intern_slice(
+ c->global,
+ (Slice){.s = strbuf_cstr(&name_sb), .len = strbuf_len(&name_sb)});
sym = obj_symbol(ob, anon_name, SB_LOCAL, SK_OBJ, sec, base, (u64)len);
memset(&attrs, 0, sizeof(attrs));
attrs.kind = CFREE_CG_DECL_OBJECT;
diff --git a/src/cg/session.c b/src/cg/session.c
@@ -232,7 +232,8 @@ void cfree_cg_func_begin_attrs(CfreeCg* g, CfreeCgSym cg_sym,
attrs = api_sym_attrs(g, cg_sym);
abi = abi_cg_func_info(c->abi, fty);
- text_sec = obj_section(ob, pool_intern_cstr(c->global, ".text"), SEC_TEXT,
+ text_sec = obj_section(ob, pool_intern_slice(c->global, SLICE_LIT(".text")),
+ SEC_TEXT,
SF_EXEC | SF_ALLOC, 4);
if (sym != OBJ_SYM_NONE) {
diff --git a/src/cg/value.c b/src/cg/value.c
@@ -433,7 +433,8 @@ CfreeCgTypeId api_mem_access_type(CfreeCg* g, CfreeCgMemAccess access,
CfreeCgTypeId ty = resolve_type(g->c, access.type);
if (!ty) ty = resolve_type(g->c, fallback);
if (!ty) {
- compiler_panic(g->c, g->cur_loc, "CfreeCg: %s has no value type", who);
+ compiler_panic(g->c, g->cur_loc, "CfreeCg: %.*s has no value type",
+ SLICE_ARG(slice_from_cstr(who)));
}
return ty;
}
@@ -441,10 +442,12 @@ CfreeCgTypeId api_mem_access_type(CfreeCg* g, CfreeCgMemAccess access,
u32 api_mem_type_size(CfreeCg* g, CfreeCgTypeId ty, const char* who) {
ty = resolve_type(g->c, ty);
if (!ty) {
- compiler_panic(g->c, g->cur_loc, "CfreeCg: %s has invalid type", who);
+ compiler_panic(g->c, g->cur_loc, "CfreeCg: %.*s has invalid type",
+ SLICE_ARG(slice_from_cstr(who)));
}
if (cg_type_is_void(g->c, ty)) {
- compiler_panic(g->c, g->cur_loc, "CfreeCg: %s uses void type", who);
+ compiler_panic(g->c, g->cur_loc, "CfreeCg: %.*s uses void type",
+ SLICE_ARG(slice_from_cstr(who)));
}
return abi_cg_sizeof(g->c->abi, ty);
}
@@ -453,17 +456,18 @@ void api_require_scalar_mem_type(CfreeCg* g, const char* who,
CfreeCgTypeId ty) {
if (cg_type_is_aggregate(g->c, ty)) {
compiler_panic(g->c, g->cur_loc,
- "CfreeCg: %s cannot use aggregate value type (size %u); "
+ "CfreeCg: %.*s cannot use aggregate value type (size %u); "
"copy fields or use byte memory operations",
- who, (unsigned)api_mem_type_size(g, ty, who));
+ SLICE_ARG(slice_from_cstr(who)),
+ (unsigned)api_mem_type_size(g, ty, who));
}
(void)api_mem_type_size(g, ty, who);
}
void api_require_pointer_value(CfreeCg* g, const char* who, CfreeCgTypeId ty) {
if (!cg_type_pointee(g->c, ty)) {
- compiler_panic(g->c, g->cur_loc, "CfreeCg: %s operand must be a pointer",
- who);
+ compiler_panic(g->c, g->cur_loc, "CfreeCg: %.*s operand must be a pointer",
+ SLICE_ARG(slice_from_cstr(who)));
}
}
@@ -476,22 +480,25 @@ void api_validate_memory_value(CfreeCg* g, const char* who,
value_ty = resolve_type(g->c, value_ty);
api_require_scalar_mem_type(g, who, access_ty);
if (!value_ty) {
- compiler_panic(g->c, g->cur_loc, "CfreeCg: %s value has no type", who);
+ compiler_panic(g->c, g->cur_loc, "CfreeCg: %.*s value has no type",
+ SLICE_ARG(slice_from_cstr(who)));
}
if (cg_type_is_aggregate(g->c, value_ty)) {
compiler_panic(g->c, g->cur_loc,
- "CfreeCg: %s value is aggregate (size %u); copy fields or "
+ "CfreeCg: %.*s value is aggregate (size %u); copy fields or "
"use byte memory operations",
- who, (unsigned)api_mem_type_size(g, value_ty, who));
+ SLICE_ARG(slice_from_cstr(who)),
+ (unsigned)api_mem_type_size(g, value_ty, who));
}
access_size = api_mem_type_size(g, access_ty, who);
value_size = api_mem_type_size(g, value_ty, who);
if (access_size != value_size ||
api_type_class(access_ty) != api_type_class(value_ty)) {
compiler_panic(g->c, g->cur_loc,
- "CfreeCg: %s value type/size mismatch: access size %u, "
+ "CfreeCg: %.*s value type/size mismatch: access size %u, "
"value size %u",
- who, (unsigned)access_size, (unsigned)value_size);
+ SLICE_ARG(slice_from_cstr(who)), (unsigned)access_size,
+ (unsigned)value_size);
}
}
diff --git a/src/cg/wide.c b/src/cg/wide.c
@@ -171,7 +171,8 @@ CfreeCgSym api_runtime_helper(CfreeCg* g, const char* name, CfreeCgTypeId ret,
decl.kind = CFREE_CG_DECL_FUNC;
decl.linkage_name =
cfree_cg_c_linkage_name((CfreeCompiler*)g->c,
- pool_intern_cstr(g->c->global, name));
+ pool_intern_slice(g->c->global,
+ slice_from_cstr(name)));
decl.display_name = decl.linkage_name;
decl.type = cfree_cg_type_func((CfreeCompiler*)g->c, sig);
decl.sym.bind = CFREE_SB_GLOBAL;
diff --git a/src/core/core.h b/src/core/core.h
@@ -87,8 +87,8 @@ void source_free(SourceManager*);
CfreeStatus source_add_file(SourceManager*, const char* path, int system_header,
u32* id_out);
-CfreeStatus source_add_memory(SourceManager*, const char* name, u32* id_out);
-CfreeStatus source_add_builtin(SourceManager*, const char* name, u32* id_out);
+CfreeStatus source_add_memory(SourceManager*, CfreeSlice name, u32* id_out);
+CfreeStatus source_add_builtin(SourceManager*, CfreeSlice name, u32* id_out);
CfreeStatus source_add_include(SourceManager*, u32 includer_file_id,
u32 included_file_id, SrcLoc include_loc,
int system);
diff --git a/src/core/pool.c b/src/core/pool.c
@@ -95,7 +95,9 @@ void pool_fini(Pool* p) {
p->entries = NULL;
}
-Sym pool_intern(Pool* p, const char* s, size_t len) {
+Sym pool_intern_slice(Pool* p, Slice in) {
+ const char* s = in.s;
+ size_t len = in.len;
u32 h, mask, i;
Sym sym;
@@ -110,12 +112,11 @@ Sym pool_intern(Pool* p, const char* s, size_t len) {
if (sym_eq(&p->entries[sym], s, len, h)) return sym;
i = (i + 1) & mask;
}
- /* Not found: allocate a new entry. The stored buffer carries a
- * trailing NUL byte that callers may rely on (so `pool_str` can be
- * fed straight to strcmp / printf %s); the recorded `len` is still
- * the logical string length, exclusive of the terminator. The
- * strtab content itself can carry embedded NULs, so consumers that
- * care about exact bytes should compare via (len, memcmp). */
+ /* Not found: allocate a new entry. The stored buffer carries a trailing
+ * NUL so a returned slice's pointer can be handed to a NUL-terminated
+ * boundary API; the recorded `len` is the logical length, exclusive of the
+ * terminator. The strtab content may carry embedded NULs, so exact-byte
+ * consumers compare via (len, memcmp). */
if (entries_grow(p)) return 0;
{
char* dst = (char*)arena_alloc(&p->arena, len + 1, 1);
@@ -132,18 +133,7 @@ Sym pool_intern(Pool* p, const char* s, size_t len) {
return sym;
}
-Sym pool_intern_cstr(Pool* p, const char* s) {
- size_t n = 0;
- if (!s) return 0;
- while (s[n]) ++n;
- return pool_intern(p, s, n);
-}
-
-const char* pool_str(Pool* p, Sym sym, size_t* len_out) {
- if (sym == 0 || sym >= p->nentries) {
- if (len_out) *len_out = 0;
- return NULL;
- }
- if (len_out) *len_out = p->entries[sym].len;
- return p->entries[sym].data;
+Slice pool_slice(Pool* p, Sym sym) {
+ if (sym == 0 || sym >= p->nentries) return SLICE_NULL;
+ return (Slice){ .s = p->entries[sym].data, .len = p->entries[sym].len };
}
diff --git a/src/core/pool.h b/src/core/pool.h
@@ -4,6 +4,7 @@
#include "core/arena.h"
#include "core/core.h"
#include "core/heap.h"
+#include "core/slice.h"
typedef struct PoolEntry {
const char* data;
@@ -32,9 +33,11 @@ struct Pool {
void pool_init(Pool*, Heap*);
void pool_fini(Pool*);
-/* Strings. Returns canonical id; equal strings → equal ids. */
-Sym pool_intern(Pool*, const char* s, size_t len);
-Sym pool_intern_cstr(Pool*, const char* s);
-const char* pool_str(Pool*, Sym, size_t* len_out);
+/* Interning. Returns the canonical id; equal byte sequences → equal ids
+ * (Sym 0 for the empty slice). pool_slice returns the interned bytes as a
+ * slice (SLICE_NULL for Sym 0); its pointer is NUL-terminated as a boundary
+ * convenience, with the NUL excluded from len. */
+Sym pool_intern_slice(Pool*, Slice);
+Slice pool_slice(Pool*, Sym);
#endif
diff --git a/src/core/slice.c b/src/core/slice.c
@@ -0,0 +1,28 @@
+#include "core/slice.h"
+
+#include <string.h>
+
+Slice slice_from_cstr(const char* z) {
+ if (!z) return SLICE_NULL;
+ return (Slice){ .s = z, .len = strlen(z) };
+}
+
+bool slice_eq(Slice a, Slice b) {
+ if (a.len != b.len) return false;
+ if (a.len == 0) return true;
+ return memcmp(a.s, b.s, a.len) == 0;
+}
+
+bool slice_eq_cstr(Slice a, const char* z) {
+ size_t i;
+ if (!z) return a.len == 0;
+ for (i = 0; i < a.len; ++i) {
+ if (z[i] == '\0' || z[i] != a.s[i]) return false;
+ }
+ return z[a.len] == '\0';
+}
+
+Slice slice_dup(Arena* arena, Slice in) {
+ char* dst = arena_strdup(arena, in.s, in.len);
+ return (Slice){ .s = dst, .len = in.len };
+}
diff --git a/src/core/slice.h b/src/core/slice.h
@@ -0,0 +1,40 @@
+#ifndef CFREE_SLICE_H
+#define CFREE_SLICE_H
+
+/*
+ * Internal fat-pointer string/byte view. `Slice` is the internal alias of the
+ * public CfreeSlice: a borrowed (ptr, len) pair, readable as text (`s`) or
+ * bytes (`data`). `len` never counts a trailing NUL.
+ *
+ * cfree carries lengths everywhere; NUL termination is only a boundary
+ * convenience. slice_from_cstr() is the single sanctioned place that scans a
+ * NUL terminator, used to lift OS/argv strings into slices at the boundary.
+ */
+
+#include "core/arena.h"
+#include "core/core.h"
+
+typedef CfreeSlice Slice;
+
+/* Build a slice from a string literal (length is compile-time, no strlen). */
+#define SLICE_LIT(lit) ((Slice){ .s = (lit), .len = sizeof(lit) - 1 })
+/* The empty slice. */
+#define SLICE_NULL ((Slice){ .s = NULL, .len = 0 })
+/* Spread a slice into printf "%.*s" arguments. */
+#define SLICE_ARG(x) CFREE_SLICE_ARG(x)
+
+/* Boundary helper: lift a NUL-terminated C string into a slice. The only
+ * sanctioned NUL scan; use exclusively where a string arrives from the OS
+ * (argv, getenv) or another NUL-terminated foreign API. NULL yields SLICE_NULL. */
+Slice slice_from_cstr(const char* z);
+
+/* Byte-exact equality. */
+bool slice_eq(Slice a, Slice b);
+/* Equality against a NUL-terminated literal/string (compares bytes, no NUL). */
+bool slice_eq_cstr(Slice a, const char* z);
+
+/* Copy into the arena with a trailing NUL (so the result is also usable at a
+ * boundary). The trailing NUL is not counted in the returned length. */
+Slice slice_dup(Arena*, Slice);
+
+#endif
diff --git a/src/core/source.c b/src/core/source.c
@@ -7,6 +7,7 @@
#include "core/core.h"
#include "core/heap.h"
#include "core/pool.h"
+#include "core/slice.h"
typedef struct SrcMgrFile {
SourceFile info;
@@ -90,13 +91,13 @@ void source_free(SourceManager* sm) {
sm->heap->free(sm->heap, sm, sizeof(*sm));
}
-static CfreeStatus file_register(SourceManager* sm, const char* name,
+static CfreeStatus file_register(SourceManager* sm, Slice name,
SourceFileKind kind, int system_header,
u32* id_out) {
Sym sym;
u32 id;
if (files_grow(sm, sm->nfiles + 1)) return CFREE_NOMEM;
- sym = pool_intern_cstr(sm->c->global, name ? name : "");
+ sym = pool_intern_slice(sm->c->global, name);
id = sm->nfiles++;
memset(&sm->files[id], 0, sizeof(sm->files[id]));
sm->files[id].info.id = id;
@@ -110,15 +111,16 @@ static CfreeStatus file_register(SourceManager* sm, const char* name,
CfreeStatus source_add_file(SourceManager* sm, const char* path,
int system_header, u32* id_out) {
- return file_register(sm, path, SRC_FILE_REAL, system_header, id_out);
+ return file_register(sm, slice_from_cstr(path ? path : ""), SRC_FILE_REAL,
+ system_header, id_out);
}
-CfreeStatus source_add_memory(SourceManager* sm, const char* name,
+CfreeStatus source_add_memory(SourceManager* sm, CfreeSlice name,
u32* id_out) {
return file_register(sm, name, SRC_FILE_MEMORY, 0, id_out);
}
-CfreeStatus source_add_builtin(SourceManager* sm, const char* name,
+CfreeStatus source_add_builtin(SourceManager* sm, CfreeSlice name,
u32* id_out) {
return file_register(sm, name, SRC_FILE_BUILTIN, 0, id_out);
}
diff --git a/src/core/strbuf.h b/src/core/strbuf.h
@@ -12,6 +12,7 @@
#include <stddef.h>
#include "core/core.h"
+#include "core/slice.h"
typedef struct StrBuf {
char* base; /* start of buffer (caller owned) */
@@ -43,6 +44,13 @@ static inline size_t strbuf_len(const StrBuf* sb) {
static inline const char* strbuf_cstr(const StrBuf* sb) { return sb->base; }
+/* View the accumulated bytes as a Slice. The backing buffer stays
+ * NUL-terminated, so the slice's `.s` is safe to hand to NUL-requiring
+ * boundaries while `.len` carries the exact length. */
+static inline Slice strbuf_slice(const StrBuf* sb) {
+ return (Slice){ .s = sb->base, .len = strbuf_len(sb) };
+}
+
static inline void strbuf_putc(StrBuf* sb, char c) {
if (sb->p < sb->end) {
*sb->p++ = c;
@@ -63,6 +71,11 @@ static inline void strbuf_putn(StrBuf* sb, const char* s, size_t n) {
for (size_t i = 0; i < n; ++i) strbuf_putc(sb, s[i]);
}
+/* Append a slice's bytes verbatim (length-explicit, no NUL scan). */
+static inline void strbuf_put_slice(StrBuf* sb, Slice s) {
+ strbuf_putn(sb, s.s, s.len);
+}
+
void strbuf_put_u64(StrBuf*, u64 v);
void strbuf_put_i64(StrBuf*, i64 v);
void strbuf_put_hex_u64(StrBuf*, u64 v); /* "0x" + hex, no padding */
diff --git a/src/dbg/step.c b/src/dbg/step.c
@@ -9,6 +9,8 @@
#include <string.h>
+#include "core/slice.h"
+
#define DBG_STEP_LINE_INSN_CAP 1024u
/* DWARF line/CFI tables are authored in image-relative vaddrs (cfree's
@@ -46,9 +48,9 @@ static int stop_is_internal_completion(const CfreeJitSession* s) {
}
static CfreeStatus dwarf_line_for(CfreeJitSession* s, uint64_t pc,
- const char** file, uint32_t* line) {
+ CfreeSlice* file, uint32_t* line) {
uint32_t col = 0;
- *file = NULL;
+ *file = CFREE_SLICE_NULL;
*line = 0;
return cfree_dwarf_addr_to_line(s->dwarf, step_rt_to_img(s, pc), file, line,
&col);
@@ -60,20 +62,20 @@ static CfreeStatus dwarf_sub_for(CfreeJitSession* s, uint64_t pc,
return cfree_dwarf_subprogram_at(s->dwarf, step_rt_to_img(s, pc), out);
}
-static int line_changed(const char* base_file, uint32_t base_line,
- const char* new_file, uint32_t new_line) {
+static int line_changed(CfreeSlice base_file, uint32_t base_line,
+ CfreeSlice new_file, uint32_t new_line) {
if (new_line == 0) return 0;
if (base_line == 0) return 1;
if (new_line != base_line) return 1;
- if (base_file != new_file) {
- if (!base_file || !new_file) return 1;
- if (strcmp(base_file, new_file) != 0) return 1;
+ if (base_file.s != new_file.s) {
+ if (!base_file.s || !new_file.s) return 1;
+ if (!slice_eq(base_file, new_file)) return 1;
}
return 0;
}
static CfreeStatus run_step_line_loop(CfreeJitSession* s) {
- const char* base_file = NULL;
+ CfreeSlice base_file = CFREE_SLICE_NULL;
uint32_t base_line = 0;
CfreeDwarfSubprogram base_sub;
int have_sub;
@@ -83,7 +85,7 @@ static CfreeStatus run_step_line_loop(CfreeJitSession* s) {
have_sub = (dwarf_sub_for(s, s->stop.regs.pc, &base_sub) == CFREE_OK);
for (i = 0; i < DBG_STEP_LINE_INSN_CAP; ++i) {
- const char* new_file = NULL;
+ CfreeSlice new_file = CFREE_SLICE_NULL;
uint32_t new_line = 0;
CfreeDwarfSubprogram new_sub;
int have_new_sub;
diff --git a/src/debug/debug.c b/src/debug/debug.c
@@ -6,6 +6,7 @@
#include "core/core.h"
#include "core/heap.h"
#include "core/pool.h"
+#include "core/slice.h"
#include "core/vec.h"
#include "debug/debug_internal.h"
@@ -13,7 +14,7 @@
static _Noreturn void debug_oom(Debug* d, const char* what) {
SrcLoc nl = {0, 0, 0};
- compiler_panic(d->c, nl, "debug: oom (%s)", what);
+ compiler_panic(d->c, nl, "debug: oom (%.*s)", SLICE_ARG(slice_from_cstr(what)));
}
static DebugTypeId type_alloc(Debug* d) {
@@ -93,25 +94,27 @@ void debug_free(Debug* d) {
/* ---- file table ---- */
static void split_path(Pool* p, Sym path, Sym* dir_out, Sym* base_out) {
- size_t len = 0;
- const char* s = pool_str(p, path, &len);
+ Slice sl = pool_slice(p, path);
+ const char* s = sl.s;
+ size_t len = sl.len;
size_t i;
size_t slash = (size_t)-1;
if (!s || len == 0) {
- *dir_out = pool_intern_cstr(p, "");
- *base_out = path ? path : pool_intern_cstr(p, "");
+ *dir_out = pool_intern_slice(p, SLICE_LIT(""));
+ *base_out = path ? path : pool_intern_slice(p, SLICE_LIT(""));
return;
}
for (i = 0; i < len; ++i) {
if (s[i] == '/') slash = i;
}
if (slash == (size_t)-1) {
- *dir_out = pool_intern_cstr(p, "");
+ *dir_out = pool_intern_slice(p, SLICE_LIT(""));
*base_out = path;
return;
}
- *dir_out = pool_intern(p, s, slash);
- *base_out = pool_intern(p, s + slash + 1, len - slash - 1);
+ *dir_out = pool_intern_slice(p, (Slice){ .s = s, .len = slash });
+ *base_out =
+ pool_intern_slice(p, (Slice){ .s = s + slash + 1, .len = len - slash - 1 });
}
u32 debug_file(Debug* d, u32 source_file_id) {
@@ -122,7 +125,7 @@ u32 debug_file(Debug* d, u32 source_file_id) {
DebugFile* slot;
Sym path = 0, dir, base;
if (sf) path = sf->path ? sf->path : sf->name;
- if (!path) path = pool_intern_cstr(d->c->global, "");
+ if (!path) path = pool_intern_slice(d->c->global, SLICE_LIT(""));
split_path(d->c->global, path, &dir, &base);
if (VEC_GROW(d->heap, d->files, d->files_cap, d->nfiles + 1))
debug_oom(d, "file table");
diff --git a/src/debug/debug_emit.c b/src/debug/debug_emit.c
@@ -20,6 +20,7 @@
#include "core/core.h"
#include "core/heap.h"
#include "core/pool.h"
+#include "core/slice.h"
#include "core/vec.h"
#include "debug/debug_internal.h"
@@ -61,12 +62,16 @@ static u32 str_intern(StrTab *s, Heap *h, Pool *pool, Sym sym) {
size_t len;
const char *str;
if (sym == 0)
- sym = pool_intern_cstr(pool, "");
+ sym = pool_intern_slice(pool, SLICE_LIT(""));
found = SymToU32_get(&s->by_sym, sym);
if (found)
return *found;
ofs = buf_pos(&s->buf);
- str = pool_str(pool, sym, &len);
+ {
+ Slice sl = pool_slice(pool, sym);
+ str = sl.s;
+ len = sl.len;
+ }
if (str && len)
buf_write(&s->buf, str, len);
{
@@ -263,7 +268,7 @@ static void add_rng_reloc(EmitCtx *e, u32 buf_offset, ObjSymId sym) {
static void emit_strx4(EmitCtx *e, Buf *b, Sym name) {
str_intern(&e->str, e->heap, e->pool, name);
{
- Sym key = name ? name : pool_intern_cstr(e->pool, "");
+ Sym key = name ? name : pool_intern_slice(e->pool, SLICE_LIT(""));
u32 idx = str_index_of(&e->str, key);
form_u32(b, idx);
}
@@ -711,7 +716,7 @@ static void emit_subprogram_die(EmitCtx *e, DebugFunc *f) {
/* Section flushing. */
static ObjSecId mk_section(EmitCtx *e, const char *name) {
- Sym n = pool_intern_cstr(e->pool, name);
+ Sym n = pool_intern_slice(e->pool, slice_from_cstr(name));
return obj_section(e->ob, n, SEC_DEBUG, 0, 1);
}
@@ -948,7 +953,7 @@ static void emit_section_line(EmitCtx *e) {
dirs[ndirs++] = e->d->files[0].dir;
} else {
if (!VEC_GROW(e->heap, dirs, dirs_cap, ndirs + 1))
- dirs[ndirs++] = pool_intern_cstr(pool, "");
+ dirs[ndirs++] = pool_intern_slice(pool, SLICE_LIT(""));
}
for (i = 1; i < e->d->nfiles; ++i) {
Sym dir = e->d->files[i].dir;
@@ -990,7 +995,7 @@ static void emit_section_line(EmitCtx *e) {
u32 ofs;
form_uleb(&hdr_body, 1);
at = buf_pos(&hdr_body);
- ofs = line_str_offset(e, pool_intern_cstr(pool, ""));
+ ofs = line_str_offset(e, pool_intern_slice(pool, SLICE_LIT("")));
form_u32(&hdr_body, ofs);
if (!VEC_GROW(e->heap, lsp_slots, lsp_cap, nlsp + 1)) {
lsp_slots[nlsp].at = at;
@@ -1309,13 +1314,13 @@ void debug_emit(Debug *d) {
ec.ssym_line_str = mk_section_sym(&ec, ec.sec_line_str);
ec.ssym_str_off = mk_section_sym(&ec, ec.sec_str_off);
- producer_sym = pool_intern_cstr(pool, "cfree 0.1");
+ producer_sym = pool_intern_slice(pool, SLICE_LIT("cfree 0.1"));
if (d->nfiles > 0) {
primary_dir = d->files[0].dir;
primary_base = d->files[0].base;
} else {
- primary_dir = pool_intern_cstr(pool, "");
- primary_base = pool_intern_cstr(pool, "");
+ primary_dir = pool_intern_slice(pool, SLICE_LIT(""));
+ primary_base = pool_intern_slice(pool, SLICE_LIT(""));
}
/* CU root DIE */
diff --git a/src/debug/dwarf_line.c b/src/debug/dwarf_line.c
@@ -12,6 +12,7 @@
#include "core/core.h"
#include "core/heap.h"
+#include "core/slice.h"
#include "core/util.h"
#include "debug/dwarf_internal.h"
@@ -183,8 +184,8 @@ static const char* build_file_norm(CfreeDebugInfo* d, DwLineProgram* lp,
if (!path) path = "";
dir_idx = lp->files[idx].dir_index;
dir = (dir_idx < lp->ndirs) ? lp->dirs[dir_idx] : "";
- plen = strlen(path);
- dlen = strlen(dir);
+ plen = slice_from_cstr(path).len;
+ dlen = slice_from_cstr(dir).len;
/* If path is already absolute (starts with /), return as-is. */
if (plen > 0 && path[0] == '/') return path;
if (dlen > 0) {
@@ -441,14 +442,14 @@ void dw_build_line(CfreeDebugInfo* d, u32 cu_idx) {
/* Lookup helpers. Build all CU line tables on demand, walk each. */
CfreeStatus cfree_dwarf_addr_to_line(CfreeDebugInfo* d, uint64_t pc,
- const char** file_out, uint32_t* line_out,
+ CfreeSlice* file_out, uint32_t* line_out,
uint32_t* col_out) {
/* Status codes:
* CFREE_OK — PC has a line entry; outputs filled.
* CFREE_NOT_FOUND — PC has no line entry (either inside a CU's
* coverage with no row, or outside every CU). */
u32 i;
- if (file_out) *file_out = NULL;
+ if (file_out) *file_out = CFREE_SLICE_NULL;
if (line_out) *line_out = 0;
if (col_out) *col_out = 0;
if (!d) return CFREE_INVALID;
@@ -468,7 +469,7 @@ CfreeStatus cfree_dwarf_addr_to_line(CfreeDebugInfo* d, uint64_t pc,
const char* f = "";
if (best->file_index < lp->nfile_norm && lp->file_norm)
f = lp->file_norm[best->file_index];
- if (file_out) *file_out = f;
+ if (file_out) *file_out = cfree_slice_cstr(f);
if (line_out) *line_out = best->line;
if (col_out) *col_out = best->column;
return CFREE_OK;
@@ -484,13 +485,13 @@ static int dw_file_matches(const char* file_norm, const char* user, size_t ulen)
size_t flen;
if (!file_norm) return 0;
if (dw_streq(file_norm, user)) return 1;
- flen = strlen(file_norm);
+ flen = slice_from_cstr(file_norm).len;
if (flen <= ulen) return 0;
if (file_norm[flen - ulen - 1] != '/') return 0;
return memcmp(file_norm + flen - ulen, user, ulen) == 0;
}
-CfreeStatus cfree_dwarf_line_to_addr(CfreeDebugInfo* d, const char* file,
+CfreeStatus cfree_dwarf_line_to_addr(CfreeDebugInfo* d, CfreeSlice file,
uint32_t line, uint64_t* pc_out) {
/* Status:
* CFREE_OK — unique match; *pc_out filled.
@@ -505,8 +506,8 @@ CfreeStatus cfree_dwarf_line_to_addr(CfreeDebugInfo* d, const char* file,
const char* alt_path = NULL;
int line_hits = 0;
if (pc_out) *pc_out = 0;
- if (!d || !file) return CFREE_INVALID;
- ulen = strlen(file);
+ if (!d || !file.s) return CFREE_INVALID;
+ ulen = file.len;
if (ulen == 0) return CFREE_INVALID;
for (i = 0; i < d->ncus; ++i) {
DwLineProgram* lp;
@@ -519,7 +520,7 @@ CfreeStatus cfree_dwarf_line_to_addr(CfreeDebugInfo* d, const char* file,
if (r->end_sequence) continue;
if (r->file_index >= lp->nfile_norm || !lp->file_norm) continue;
f = lp->file_norm[r->file_index];
- if (!dw_file_matches(f, file, ulen)) continue;
+ if (!dw_file_matches(f, file.s, ulen)) continue;
if (r->line != line) continue;
++line_hits;
if (!first_path) {
@@ -542,7 +543,7 @@ CfreeStatus cfree_dwarf_line_to_addr(CfreeDebugInfo* d, const char* file,
* which case only the first `cap` are written). Returns 0 on success
* (including 0 candidates), 1 on invalid args. Intended for REPL
* disambiguation after cfree_dwarf_line_to_addr returns 3. */
-CfreeStatus cfree_dwarf_line_to_addr_all(CfreeDebugInfo* d, const char* file,
+CfreeStatus cfree_dwarf_line_to_addr_all(CfreeDebugInfo* d, CfreeSlice file,
uint32_t line,
CfreeDwarfLineMatch* out, uint32_t cap,
uint32_t* n_out) {
@@ -553,8 +554,8 @@ CfreeStatus cfree_dwarf_line_to_addr_all(CfreeDebugInfo* d, const char* file,
size_t ulen;
uint32_t total = 0;
if (n_out) *n_out = 0;
- if (!d || !file) return CFREE_INVALID;
- ulen = strlen(file);
+ if (!d || !file.s) return CFREE_INVALID;
+ ulen = file.len;
if (ulen == 0) return CFREE_INVALID;
for (i = 0; i < d->ncus; ++i) {
DwLineProgram* lp;
@@ -570,13 +571,14 @@ CfreeStatus cfree_dwarf_line_to_addr_all(CfreeDebugInfo* d, const char* file,
if (r->line != line) continue;
if (r->file_index >= lp->nfile_norm || !lp->file_norm) continue;
f = lp->file_norm[r->file_index];
- if (!dw_file_matches(f, file, ulen)) continue;
+ if (!dw_file_matches(f, file.s, ulen)) continue;
/* Dedupe by file_norm path so the candidate list is one entry per
* source file even if the line has many per-instruction rows. */
if (out) {
uint32_t lim = total < cap ? total : cap;
for (k = 0; k < lim; ++k) {
- if (out[k].file == f || (out[k].file && dw_streq(out[k].file, f))) {
+ if (out[k].file.s == f ||
+ (out[k].file.s && dw_streq(out[k].file.s, f))) {
dup = 1;
break;
}
@@ -585,7 +587,7 @@ CfreeStatus cfree_dwarf_line_to_addr_all(CfreeDebugInfo* d, const char* file,
if (dup) continue;
if (out && total < cap) {
out[total].pc = r->address;
- out[total].file = f;
+ out[total].file = cfree_slice_cstr(f);
}
++total;
}
diff --git a/src/debug/dwarf_open.c b/src/debug/dwarf_open.c
@@ -15,6 +15,7 @@
#include "core/core.h"
#include "core/heap.h"
#include "core/pool.h"
+#include "core/slice.h"
#include "core/util.h"
#include "core/vec.h"
#include "debug/dwarf_internal.h"
@@ -31,7 +32,7 @@ void dw_find_section(CfreeDebugInfo* d, const char* name, DwSection* out) {
for (i = 0; i < n; ++i) {
CfreeObjSecInfo info;
if (cfree_obj_section(d->obj, i, &info) != CFREE_OK) continue;
- if (info.name && dw_streq(info.name, name)) {
+ if (info.name.len && cfree_slice_eq_cstr(info.name, name)) {
size_t len = 0;
const uint8_t* p = NULL;
if (cfree_obj_section_data(d->obj, i, &p, &len) != CFREE_OK) continue;
@@ -136,8 +137,8 @@ const char* dw_cstr(const u8* base, u32 size, u32* off) {
/* ---- string interning ------------------------------------------------- */
const char* dw_intern(CfreeDebugInfo* d, const char* s, size_t len) {
- Sym sym = pool_intern(d->strs, s, len);
- return pool_str(d->strs, sym, NULL);
+ Sym sym = pool_intern_slice(d->strs, (Slice){ .s = s, .len = len });
+ return pool_slice(d->strs, sym).s;
}
/* Resolve a .debug_str offset. */
diff --git a/src/debug/dwarf_query.c b/src/debug/dwarf_query.c
@@ -18,10 +18,11 @@
static void fill_subprogram(CfreeDebugInfo *d, DwSubprog *sp,
CfreeDwarfSubprogram *out) {
memset(out, 0, sizeof(*out));
- out->name = sp->name ? sp->name : "";
+ out->name = sp->name ? cfree_slice_cstr(sp->name) : CFREE_SLICE_NULL;
out->low_pc = sp->low_pc;
out->high_pc = sp->high_pc;
- out->decl_file = sp->decl_file ? sp->decl_file : "";
+ out->decl_file =
+ sp->decl_file ? cfree_slice_cstr(sp->decl_file) : CFREE_SLICE_NULL;
out->decl_line = sp->decl_line;
out->return_type = sp->type_die_offset
? dw_type_from_die(d, sp->cu_idx, sp->type_die_offset)
@@ -65,12 +66,12 @@ static DwSubprog *dw_find_subprog_named(CfreeDebugInfo *d, const char *name) {
return NULL;
}
-CfreeStatus cfree_dwarf_subprogram_named(CfreeDebugInfo *d, const char *name,
+CfreeStatus cfree_dwarf_subprogram_named(CfreeDebugInfo *d, CfreeSlice name,
CfreeDwarfSubprogram *out) {
DwSubprog *sp;
- if (!d || !name || !out)
+ if (!d || !name.s || !out)
return CFREE_INVALID;
- sp = dw_find_subprog_named(d, name);
+ sp = dw_find_subprog_named(d, name.s);
if (!sp)
return CFREE_NOT_FOUND;
fill_subprogram(d, sp, out);
@@ -78,7 +79,7 @@ CfreeStatus cfree_dwarf_subprogram_named(CfreeDebugInfo *d, const char *name,
}
CfreeStatus cfree_dwarf_func_at(CfreeDebugInfo *d, uint64_t pc,
- const char **name_out, uint64_t *low_out,
+ CfreeSlice *name_out, uint64_t *low_out,
uint64_t *high_out) {
CfreeDwarfSubprogram sp;
CfreeStatus st = cfree_dwarf_subprogram_at(d, pc, &sp);
@@ -171,7 +172,7 @@ static void fill_varloc(CfreeDebugInfo *d, u32 cu_idx, const DwLocal *v, u64 pc,
out->v.expr.len = 0;
}
-CfreeStatus cfree_dwarf_var_at(CfreeDebugInfo *d, uint64_t pc, const char *name,
+CfreeStatus cfree_dwarf_var_at(CfreeDebugInfo *d, uint64_t pc, CfreeSlice name,
CfreeDwarfVarLoc *out) {
/* Status codes:
* CFREE_OK — found; *out filled.
@@ -181,7 +182,7 @@ CfreeStatus cfree_dwarf_var_at(CfreeDebugInfo *d, uint64_t pc, const char *name,
*/
DwSubprog *sp;
u32 i;
- if (!d || !name || !out)
+ if (!d || !name.s || !out)
return CFREE_INVALID;
memset(out, 0, sizeof(*out));
sp = dw_find_subprog(d, pc);
@@ -191,7 +192,7 @@ CfreeStatus cfree_dwarf_var_at(CfreeDebugInfo *d, uint64_t pc, const char *name,
* after enclosing). */
for (i = sp->nlocals; i > 0; --i) {
DwLocal *v = &sp->locals[i - 1];
- if (!v->name || !dw_streq(v->name, name))
+ if (!v->name || !dw_streq(v->name, name.s))
continue;
if (v->has_scope && (pc < v->scope_lo || pc >= v->scope_hi))
continue;
@@ -201,7 +202,7 @@ CfreeStatus cfree_dwarf_var_at(CfreeDebugInfo *d, uint64_t pc, const char *name,
/* Then params. */
for (i = 0; i < sp->nparams; ++i) {
DwLocal *v = &sp->params[i];
- if (!v->name || !dw_streq(v->name, name))
+ if (!v->name || !dw_streq(v->name, name.s))
continue;
fill_varloc(d, sp->cu_idx, v, pc, out);
return CFREE_OK;
@@ -211,7 +212,7 @@ CfreeStatus cfree_dwarf_var_at(CfreeDebugInfo *d, uint64_t pc, const char *name,
dw_build_globals(d);
for (i = 0; i < d->nglobals; ++i) {
DwLocal *v = &d->globals[i];
- if (!v->name || !dw_streq(v->name, name))
+ if (!v->name || !dw_streq(v->name, name.s))
continue;
fill_varloc(d, 0, v, pc, out);
return CFREE_OK;
@@ -361,7 +362,7 @@ CfreeIterResult cfree_dwarf_vars_at_next(CfreeDwarfVarIter *it,
DwLocal *v = &it->sp->locals[--it->idx];
if (v->has_scope && (it->pc < v->scope_lo || it->pc >= v->scope_hi))
break;
- out->name = v->name ? v->name : "";
+ out->name = v->name ? cfree_slice_cstr(v->name) : CFREE_SLICE_NULL;
out->role = CFREE_DVR_LOCAL;
fill_varloc(it->d, it->sp->cu_idx, v, it->pc, &out->loc);
return CFREE_ITER_ITEM;
@@ -380,7 +381,7 @@ CfreeIterResult cfree_dwarf_vars_at_next(CfreeDwarfVarIter *it,
}
{
DwLocal *v = &it->sp->params[it->idx++];
- out->name = v->name ? v->name : "";
+ out->name = v->name ? cfree_slice_cstr(v->name) : CFREE_SLICE_NULL;
out->role = CFREE_DVR_ARG;
fill_varloc(it->d, it->sp->cu_idx, v, it->pc, &out->loc);
return CFREE_ITER_ITEM;
@@ -398,7 +399,7 @@ CfreeIterResult cfree_dwarf_vars_at_next(CfreeDwarfVarIter *it,
}
{
DwLocal *v = &it->d->globals[it->idx++];
- out->name = v->name ? v->name : "";
+ out->name = v->name ? cfree_slice_cstr(v->name) : CFREE_SLICE_NULL;
out->role = CFREE_DVR_GLOBAL;
fill_varloc(it->d, 0, v, it->pc, &out->loc);
return CFREE_ITER_ITEM;
@@ -451,16 +452,16 @@ CfreeStatus cfree_dwarf_param_iter_new(CfreeDebugInfo *d, uint64_t pc,
}
CfreeStatus cfree_dwarf_param_iter_new_named(CfreeDebugInfo *d,
- const char *name,
+ CfreeSlice name,
CfreeDwarfParamIter **out) {
CfreeDwarfParamIter *it;
DwSubprog *sp;
if (!out)
return CFREE_INVALID;
*out = NULL;
- if (!d || !name)
+ if (!d || !name.s)
return CFREE_INVALID;
- sp = dw_find_subprog_named(d, name);
+ sp = dw_find_subprog_named(d, name.s);
if (!sp)
return CFREE_NOT_FOUND;
dw_build_locals(d, sp);
@@ -484,7 +485,7 @@ CfreeIterResult cfree_dwarf_param_iter_next(CfreeDwarfParamIter *it,
return CFREE_ITER_END;
{
DwLocal *v = &it->sp->params[it->idx++];
- out->name = v->name ? v->name : "";
+ out->name = v->name ? cfree_slice_cstr(v->name) : CFREE_SLICE_NULL;
out->role = CFREE_DVR_ARG;
fill_varloc(it->d, it->sp->cu_idx, v, it->pc, &out->loc);
}
diff --git a/src/debug/dwarf_type.c b/src/debug/dwarf_type.c
@@ -387,14 +387,14 @@ static CfreeDwarfTypeKind map_kind(const CfreeDwarfType* t) {
CfreeDwarfTypeInfo cfree_dwarf_type_info(const CfreeDwarfType* t) {
CfreeDwarfTypeInfo info;
memset(&info, 0, sizeof(info));
- info.name = "";
+ info.name = CFREE_SLICE_NULL;
if (!t) {
info.kind = CFREE_DT_VOID;
return info;
}
info.kind = map_kind(t);
info.byte_size = t->byte_size;
- info.name = t->name ? t->name : "";
+ info.name = t->name ? cfree_slice_cstr(t->name) : CFREE_SLICE_NULL;
info.element_count = t->element_count;
/* For TYPEDEF/PTR/ARRAY: expose inner. For BASE_CHAR map signedness. */
switch (t->kind) {
@@ -462,7 +462,7 @@ CfreeIterResult cfree_dwarf_field_iter_next(CfreeDwarfFieldIter* it,
if (it->idx >= t->nfields) return CFREE_ITER_END;
{
DwField* f = &t->fields[it->idx++];
- out->name = f->name ? f->name : "";
+ out->name = f->name ? cfree_slice_cstr(f->name) : CFREE_SLICE_NULL;
out->byte_offset = f->byte_offset;
out->bit_offset = f->bit_offset;
out->bit_size = f->bit_size;
@@ -509,7 +509,8 @@ CfreeIterResult cfree_dwarf_enum_iter_next(CfreeDwarfEnumIter* it,
t = it->t;
if (t->kind != DTK_ENUM) return CFREE_ITER_END;
if (it->idx >= t->nevals) return CFREE_ITER_END;
- out->name = t->evals[it->idx].name ? t->evals[it->idx].name : "";
+ out->name = t->evals[it->idx].name ? cfree_slice_cstr(t->evals[it->idx].name)
+ : CFREE_SLICE_NULL;
out->value = t->evals[it->idx].value;
it->idx++;
return CFREE_ITER_ITEM;
diff --git a/src/emu/elf_load.c b/src/emu/elf_load.c
@@ -26,6 +26,7 @@
#include <string.h>
#include "core/core.h"
+#include "core/slice.h"
#include "emu/emu.h"
#include "emu/rv64_ops.h"
#include "obj/elf.h"
@@ -364,13 +365,13 @@ int emu_load_elf(Compiler* c, CfreeEmuArch arch, const u8* bytes, size_t len,
}
for (i = 0; i < (u32)argc; ++i) {
- size_t slen = strlen(argv[i]) + 1u;
+ size_t slen = slice_from_cstr(argv[i]).len + 1u;
cursor -= slen;
memcpy(guest_base + (cursor - lo_va), argv[i], slen);
argv_addrs[i] = cursor;
}
for (i = 0; i < (u32)envc; ++i) {
- size_t slen = strlen(envp[i]) + 1u;
+ size_t slen = slice_from_cstr(envp[i]).len + 1u;
cursor -= slen;
memcpy(guest_base + (cursor - lo_va), envp[i], slen);
envp_addrs[i] = cursor;
diff --git a/src/emu/emu.c b/src/emu/emu.c
@@ -14,6 +14,7 @@
#include <string.h>
#include "core/pool.h"
+#include "core/slice.h"
#include "link/link.h"
#include "obj/obj.h"
@@ -383,5 +384,5 @@ Sym emu_block_sym_name(Compiler* c, u64 guest_pc) {
guest_pc >>= 4;
}
buf[26] = '\0';
- return pool_intern_cstr(c->global, buf);
+ return pool_intern_slice(c->global, slice_from_cstr(buf));
}
diff --git a/src/emu/emu.h b/src/emu/emu.h
@@ -171,7 +171,7 @@ Sym emu_block_sym_name(Compiler*, u64 guest_pc);
/* External resolver passed to link_set_extern_resolver. `user` is
* the CfreeEmu*. Returns NULL for unrecognized names — the linker
* promotes that to a fatal undefined-symbol diagnostic. */
-void* emu_runtime_extern_resolver(void* user, const char* name);
+void* emu_runtime_extern_resolver(void* user, CfreeSlice name);
/* Memory helpers; called from JITted blocks. The host process owns
* the guest AS, so loads/stores bounds-check against the EmuCPUState's
diff --git a/src/emu/runtime.c b/src/emu/runtime.c
@@ -490,31 +490,23 @@ void emu_syscall(EmuCPUState* s) {
* (or the running emu's CPUState). Returning NULL surfaces as a
* fatal "undefined reference" diagnostic from link_resolve_extend. */
-static int streq(const char* a, const char* b) {
- while (*a && *a == *b) {
- ++a;
- ++b;
- }
- return *a == 0 && *b == 0;
-}
-
-void* emu_runtime_extern_resolver(void* user, const char* name) {
- if (!name) return NULL;
+void* emu_runtime_extern_resolver(void* user, CfreeSlice name) {
+ if (!name.s) return NULL;
- if (streq(name, EMU_SYM_CPU_STATE)) {
+ if (cfree_slice_eq_cstr(name, EMU_SYM_CPU_STATE)) {
CfreeEmu* e = (CfreeEmu*)user;
return (void*)emu_internal_cpu(e);
}
- if (streq(name, EMU_SYM_LOAD8)) return (void*)emu_mem_load8;
- if (streq(name, EMU_SYM_LOAD16)) return (void*)emu_mem_load16;
- if (streq(name, EMU_SYM_LOAD32)) return (void*)emu_mem_load32;
- if (streq(name, EMU_SYM_LOAD64)) return (void*)emu_mem_load64;
- if (streq(name, EMU_SYM_STORE8)) return (void*)emu_mem_store8;
- if (streq(name, EMU_SYM_STORE16)) return (void*)emu_mem_store16;
- if (streq(name, EMU_SYM_STORE32)) return (void*)emu_mem_store32;
- if (streq(name, EMU_SYM_STORE64)) return (void*)emu_mem_store64;
- if (streq(name, EMU_SYM_SYSCALL)) return (void*)emu_syscall;
+ if (cfree_slice_eq_cstr(name, EMU_SYM_LOAD8)) return (void*)emu_mem_load8;
+ if (cfree_slice_eq_cstr(name, EMU_SYM_LOAD16)) return (void*)emu_mem_load16;
+ if (cfree_slice_eq_cstr(name, EMU_SYM_LOAD32)) return (void*)emu_mem_load32;
+ if (cfree_slice_eq_cstr(name, EMU_SYM_LOAD64)) return (void*)emu_mem_load64;
+ if (cfree_slice_eq_cstr(name, EMU_SYM_STORE8)) return (void*)emu_mem_store8;
+ if (cfree_slice_eq_cstr(name, EMU_SYM_STORE16)) return (void*)emu_mem_store16;
+ if (cfree_slice_eq_cstr(name, EMU_SYM_STORE32)) return (void*)emu_mem_store32;
+ if (cfree_slice_eq_cstr(name, EMU_SYM_STORE64)) return (void*)emu_mem_store64;
+ if (cfree_slice_eq_cstr(name, EMU_SYM_SYSCALL)) return (void*)emu_syscall;
/* EMU_SYM_DISPATCH is the cross-block tail-call helper; it shares
* the host address of the dispatcher entry. The dispatcher loop
diff --git a/src/link/link.c b/src/link/link.c
@@ -19,6 +19,7 @@
#include "core/heap.h"
#include "core/pool.h"
+#include "core/slice.h"
#include "core/vec.h"
#include "link/link_internal.h"
@@ -79,7 +80,7 @@ Linker* link_new(Compiler* c) {
* so the on-disk symbol is `_main` (the mangled form of `main`).
* Format choice lives in obj_format_default_entry_name. */
l->entry_name =
- pool_intern_cstr(c->global, obj_format_default_entry_name(c));
+ pool_intern_slice(c->global, slice_from_cstr(obj_format_default_entry_name(c)));
/* Match the rest of libcfree's lifetime story: the new'd Linker is
* registered for cleanup in case a panic fires before link_free. */
l->deferred = compiler_defer(c, linker_cleanup, l);
@@ -146,17 +147,21 @@ LinkInputId link_add_obj_bytes(Linker* l, const char* name, const u8* data,
default:
compiler_panic(l->c, no_loc(),
"link_add_obj_bytes: unsupported object format "
- "(fmt=%u) for '%s'",
- (u32)fmt, name ? name : "(unnamed)");
+ "(fmt=%u) for '%.*s'",
+ (u32)fmt,
+ SLICE_ARG(name ? slice_from_cstr(name)
+ : SLICE_LIT("(unnamed)")));
}
if (!ob)
compiler_panic(l->c, no_loc(),
- "link_add_obj_bytes: %s returned NULL for '%s'",
- reader_name, name ? name : "(unnamed)");
+ "link_add_obj_bytes: %.*s returned NULL for '%.*s'",
+ SLICE_ARG(slice_from_cstr(reader_name)),
+ SLICE_ARG(name ? slice_from_cstr(name)
+ : SLICE_LIT("(unnamed)")));
in = inputs_push(l, &id);
in->order = l->next_input_order++;
in->obj = ob; /* re-uses the ObjBuilder slot for ownership */
- in->name = name ? pool_intern_cstr(l->c->global, name) : 0;
+ in->name = name ? pool_intern_slice(l->c->global, slice_from_cstr(name)) : 0;
/* PE/COFF short-import: read_coff_short_import stashes the providing
* DLL name on the builder. Reclassify the input as a DSO so the
* resolver treats its symbols as exports (matching the .lib archive
@@ -216,19 +221,23 @@ LinkInputId link_add_dso_bytes(Linker* l, const char* name, const u8* data,
default:
compiler_panic(l->c, no_loc(),
"link_add_dso_bytes: unsupported DSO format "
- "(fmt=%u) for '%s'",
- (u32)fmt, name ? name : "(unnamed)");
+ "(fmt=%u) for '%.*s'",
+ (u32)fmt,
+ SLICE_ARG(name ? slice_from_cstr(name)
+ : SLICE_LIT("(unnamed)")));
}
}
if (!ob)
compiler_panic(l->c, no_loc(),
- "link_add_dso_bytes: %s returned NULL for '%s'",
- reader_name, name ? name : "(unnamed)");
+ "link_add_dso_bytes: %.*s returned NULL for '%.*s'",
+ SLICE_ARG(slice_from_cstr(reader_name)),
+ SLICE_ARG(name ? slice_from_cstr(name)
+ : SLICE_LIT("(unnamed)")));
in = inputs_push(l, &id);
in->kind = LINK_INPUT_DSO_BYTES;
in->order = l->next_input_order++;
in->obj = ob;
- in->name = name ? pool_intern_cstr(l->c->global, name) : 0;
+ in->name = name ? pool_intern_slice(l->c->global, slice_from_cstr(name)) : 0;
/* DT_SONAME wins; fall back to the file's basename if the DSO has
* no SONAME (matches GNU ld's behaviour for hand-rolled libraries
* that forgot to set DT_SONAME). */
@@ -239,7 +248,7 @@ LinkInputId link_add_dso_bytes(Linker* l, const char* name, const u8* data,
const char* p;
for (p = name; *p; ++p)
if (*p == '/') base = p + 1;
- in->soname = pool_intern_cstr(l->c->global, base);
+ in->soname = pool_intern_slice(l->c->global, slice_from_cstr(base));
} else {
in->soname = 0;
}
@@ -312,7 +321,7 @@ static Sym derive_dll_name_from_archive_path(Compiler* c, const char* path) {
base = path;
for (p = path; *p; ++p)
if (*p == '/' || *p == '\\') base = p + 1;
- n = strlen(base);
+ n = slice_from_cstr(base).len;
/* Strip trailing ".dll.a" / ".a" / ".lib" (case-sensitive — mingw
* uses lowercase, MSVC uses .lib). */
if (n >= 6 && memcmp(base + n - 6, ".dll.a", 6) == 0) n -= 6;
@@ -329,7 +338,7 @@ static Sym derive_dll_name_from_archive_path(Compiler* c, const char* path) {
out = (char*)arena_array(c->scratch, char, out_len);
memcpy(out, base, n);
memcpy(out + n, ".dll", 4);
- sym = pool_intern(c->global, out, (u32)out_len);
+ sym = pool_intern_slice(c->global, (Slice){ .s = out, .len = (u32)out_len });
return sym;
}
@@ -343,11 +352,11 @@ static Sym derive_dll_name_from_archive_member(Compiler* c,
base = member_name;
for (p = member_name; *p; ++p)
if (*p == '/' || *p == '\\') base = p + 1;
- n = strlen(base);
+ n = slice_from_cstr(base).len;
if (n >= 4 && memcmp(base + n - 4, ".dll", 4) == 0)
- return pool_intern(c->global, base, (u32)n);
+ return pool_intern_slice(c->global, (Slice){ .s = base, .len = (u32)n });
if (n >= 4 && memcmp(base + n - 4, ".DLL", 4) == 0)
- return pool_intern(c->global, base, (u32)n);
+ return pool_intern_slice(c->global, (Slice){ .s = base, .len = (u32)n });
return fallback;
}
@@ -474,7 +483,7 @@ static CoffArMemberClass classify_coff_archive_member_bytes(
if (imp_bare_name == 0) {
const char* tail = nm + kCoffImpPrefixLen_;
u32 tail_len = nlen - kCoffImpPrefixLen_;
- imp_bare_name = pool_intern(c->global, tail, tail_len);
+ imp_bare_name = pool_intern_slice(c->global, (Slice){ .s = tail, .len = tail_len });
}
} else if (nlen > kCoffHeadPrefixLen_ &&
memcmp(nm, kCoffHeadPrefix_, kCoffHeadPrefixLen_) == 0) {
@@ -511,7 +520,11 @@ static ObjBuilder* build_coff_long_import_shim(Compiler* c, Sym bare_name,
ObjSymId id;
ObjSymId imp_id;
if (bare_name == 0 || dll_name == 0) return NULL;
- bare = pool_str(c->global, bare_name, &bare_len);
+ {
+ Slice bare_s = pool_slice(c->global, bare_name);
+ bare = bare_s.s;
+ bare_len = bare_s.len;
+ }
if (!bare || bare_len == 0) return NULL;
ob = obj_new(c);
if (!ob) return NULL;
@@ -522,7 +535,7 @@ static ObjBuilder* build_coff_long_import_shim(Compiler* c, Sym bare_name,
imp_buf = (char*)arena_array(c->scratch, char, imp_len);
memcpy(imp_buf, kCoffImpPrefix_, kCoffImpPrefixLen_);
memcpy(imp_buf + kCoffImpPrefixLen_, bare, bare_len);
- imp_sn = pool_intern(c->global, imp_buf, imp_len);
+ imp_sn = pool_intern_slice(c->global, (Slice){ .s = imp_buf, .len = imp_len });
imp_id = obj_symbol_ex(ob, imp_sn, SB_GLOBAL, SV_DEFAULT, SK_OBJ,
OBJ_SEC_NONE, 0, 0, 0);
obj_sym_mark_referenced(ob, imp_id);
@@ -535,7 +548,11 @@ static int coff_skip_long_import_shim_bare(Compiler* c, Sym bare_name) {
const char* s;
size_t n = 0;
if (!bare_name) return 0;
- s = pool_str(c->global, bare_name, &n);
+ {
+ Slice s_s = pool_slice(c->global, bare_name);
+ s = s_s.s;
+ n = s_s.len;
+ }
if (!s) return 0;
/* llvm-mingw's UCRT libmsvcrt.a intentionally provides these legacy
* CRT entry helpers as regular archive members later in the same
@@ -548,7 +565,7 @@ static int coff_skip_long_import_shim_bare(Compiler* c, Sym bare_name) {
LinkInputId link_add_archive_bytes(Linker* l, const char* name, const u8* data,
size_t len, u8 whole_archive, u8 link_mode,
u8 group_id) {
- CfreeBytes in_arc;
+ CfreeSlice in_arc;
CfreeArIter* it = NULL;
CfreeArMember mem;
LinkArchive* ar;
@@ -560,13 +577,13 @@ LinkInputId link_add_archive_bytes(Linker* l, const char* name, const u8* data,
if (is_coff_target)
archive_dll_name = derive_dll_name_from_archive_path(l->c, name);
- in_arc.name = name;
in_arc.data = data;
in_arc.len = len;
if (cfree_ar_iter_new(cfree_compiler_context(l->c), &in_arc, &it) != CFREE_OK || !it)
compiler_panic(l->c, no_loc(),
- "link_add_archive_bytes: '%s' is not a valid ar archive",
- name ? name : "(unnamed)");
+ "link_add_archive_bytes: '%.*s' is not a valid ar archive",
+ SLICE_ARG(name ? slice_from_cstr(name)
+ : SLICE_LIT("(unnamed)")));
/* Two-pass: count members so we allocate the member array exactly
* once. The linker_release path frees by nmembers, so we need
@@ -579,7 +596,7 @@ LinkInputId link_add_archive_bytes(Linker* l, const char* name, const u8* data,
ar = LinkArchives_push(&l->archives, NULL);
if (!ar)
compiler_panic(l->c, no_loc(), "link: out of memory growing archives");
- ar->name = name ? pool_intern_cstr(l->c->global, name) : 0;
+ ar->name = name ? pool_intern_slice(l->c->global, slice_from_cstr(name)) : 0;
ar->order = l->next_input_order++;
ar->whole_archive = whole_archive;
ar->link_mode = link_mode;
@@ -600,9 +617,10 @@ LinkInputId link_add_archive_bytes(Linker* l, const char* name, const u8* data,
* principle hold mixed formats (in practice it never does). */
if (cfree_ar_iter_new(cfree_compiler_context(l->c), &in_arc, &it) != CFREE_OK || !it)
compiler_panic(l->c, no_loc(),
- "link_add_archive_bytes: ar_iter_init failed on '%s' "
+ "link_add_archive_bytes: ar_iter_init failed on '%.*s' "
"second pass",
- name ? name : "(unnamed)");
+ SLICE_ARG(name ? slice_from_cstr(name)
+ : SLICE_LIT("(unnamed)")));
n = 0;
while (cfree_ar_iter_next(it, &mem) == CFREE_ITER_ITEM && n < ar->nmembers) {
ObjBuilder* ob = NULL;
@@ -621,7 +639,7 @@ LinkInputId link_add_archive_bytes(Linker* l, const char* name, const u8* data,
ob = NULL;
} else {
Sym member_dll =
- derive_dll_name_from_archive_member(l->c, mem.name,
+ derive_dll_name_from_archive_member(l->c, mem.name.s,
archive_dll_name);
ob = build_coff_long_import_shim(l->c, bare, member_dll);
}
@@ -630,7 +648,7 @@ LinkInputId link_add_archive_bytes(Linker* l, const char* name, const u8* data,
}
if (cls != COFF_AR_KEEP) {
ar->members[n].name =
- mem.name ? pool_intern_cstr(l->c->global, mem.name) : 0;
+ mem.name.len ? pool_intern_slice(l->c->global, mem.name) : 0;
ar->members[n].obj = ob;
++n;
continue;
@@ -638,30 +656,34 @@ LinkInputId link_add_archive_bytes(Linker* l, const char* name, const u8* data,
}
switch (mfmt) {
case CFREE_BIN_ELF:
- ob = read_elf(l->c, mem.name, mem.data, mem.size);
+ ob = read_elf(l->c, mem.name.s, mem.data, mem.size);
break;
case CFREE_BIN_MACHO:
- ob = read_macho(l->c, mem.name, mem.data, mem.size);
+ ob = read_macho(l->c, mem.name.s, mem.data, mem.size);
break;
case CFREE_BIN_COFF:
- ob = read_coff(l->c, mem.name, mem.data, mem.size);
+ ob = read_coff(l->c, mem.name.s, mem.data, mem.size);
break;
default:
compiler_panic(l->c, no_loc(),
"link_add_archive_bytes: unsupported member "
- "format (fmt=%u) for '%s' in archive '%s'",
+ "format (fmt=%u) for '%.*s' in archive '%.*s'",
(u32)mfmt,
- mem.name ? mem.name : "(unnamed)",
- name ? name : "(unnamed)");
+ SLICE_ARG(mem.name.len ? mem.name
+ : SLICE_LIT("(unnamed)")),
+ SLICE_ARG(name ? slice_from_cstr(name)
+ : SLICE_LIT("(unnamed)")));
}
if (!ob)
compiler_panic(l->c, no_loc(),
"link_add_archive_bytes: object read failed for "
- "member '%s' of archive '%s'",
- mem.name ? mem.name : "(unnamed)",
- name ? name : "(unnamed)");
+ "member '%.*s' of archive '%.*s'",
+ SLICE_ARG(mem.name.len ? mem.name
+ : SLICE_LIT("(unnamed)")),
+ SLICE_ARG(name ? slice_from_cstr(name)
+ : SLICE_LIT("(unnamed)")));
ar->members[n].name =
- mem.name ? pool_intern_cstr(l->c->global, mem.name) : 0;
+ mem.name.len ? pool_intern_slice(l->c->global, mem.name) : 0;
ar->members[n].obj = ob;
++n;
}
@@ -678,9 +700,11 @@ Sym link_intern_c_name(Linker* l, const char* name) {
return obj_format_c_mangle(l->c, name);
}
-void link_set_entry(Linker* l, const char* name) {
- if (!l || !name) return;
- l->entry_name = link_intern_c_name(l, name);
+void link_set_entry(Linker* l, CfreeSlice name) {
+ if (!l || !name.s || name.len == 0) return;
+ /* entry names from the API/script are interned arena/pool slices and
+ * thus NUL-terminated; the mangler scans a C string. */
+ l->entry_name = link_intern_c_name(l, name.s);
}
void link_clear_entry(Linker* l) {
@@ -691,7 +715,8 @@ void link_clear_entry(Linker* l) {
void link_set_script(Linker* l, const CfreeLinkScript* script) {
if (!l || !script) return;
l->script = script;
- if (script->entry) l->entry_name = link_intern_c_name(l, script->entry);
+ if (script->entry.s && script->entry.len)
+ l->entry_name = link_intern_c_name(l, script->entry.s);
}
void link_set_extern_resolver(Linker* l, LinkExternResolver fn, void* user) {
@@ -732,9 +757,10 @@ void link_set_jit_host(Linker* l, const CfreeJitHost* host) {
l->jit_host = host;
}
-void link_set_interp_path(Linker* l, const char* path) {
+void link_set_interp_path(Linker* l, CfreeSlice path) {
if (!l) return;
- l->interp_path = (path && path[0]) ? pool_intern_cstr(l->c->global, path) : 0;
+ l->interp_path =
+ (path.s && path.len) ? pool_intern_slice(l->c->global, path) : 0;
}
/* ---- debug-input capture ----
diff --git a/src/link/link.h b/src/link/link.h
@@ -164,7 +164,7 @@ LinkInputId link_add_archive_bytes(Linker*, const char* name, const u8* data,
size_t len, u8 whole_archive, u8 link_mode,
u8 group_id);
-void link_set_entry(Linker*, const char* name);
+void link_set_entry(Linker*, CfreeSlice name);
void link_clear_entry(Linker*);
/* Borrowed reference; the script and every sub-object must outlive
* link_resolve. The linker accepts only the structured form — there is no
@@ -204,7 +204,7 @@ void link_set_pe_subsystem(Linker*, u16 subsystem);
/* Runtime loader path written into PT_INTERP / .interp. NULL leaves the
* default ("/lib/ld-musl-aarch64.so.1" for aarch64-linux). Only
* consulted when -pie is enabled (or any DSO input is present). */
-void link_set_interp_path(Linker*, const char* path);
+void link_set_interp_path(Linker*, CfreeSlice path);
/* Borrowed JIT host. The layout passes read execmem->page_size; the JIT
* mapper reads the full host (execmem reserve/protect, tls). NULL on
diff --git a/src/link/link_coff.c b/src/link/link_coff.c
@@ -45,6 +45,7 @@
#include "core/core.h"
#include "core/heap.h"
#include "core/pool.h"
+#include "core/slice.h"
#include "core/util.h"
#include "core/vec.h"
#include "link/link.h"
@@ -217,7 +218,7 @@ typedef struct CoffTlsLayout {
} CoffTlsLayout;
static LinkSymId coff_find_sym(LinkImage* img, const char* name) {
- Sym sym = pool_intern_cstr(img->c->global, name);
+ Sym sym = pool_intern_slice(img->c->global, slice_from_cstr(name));
u32 n = LinkSyms_count(&img->syms);
u32 i;
for (i = 0; i < n; ++i) {
@@ -238,8 +239,9 @@ static LinkSymId coff_find_tls_index_sym(LinkImage* img) {
static const LinkSection* coff_symbol_section(const LinkImage* img,
const LinkSymbol* s) {
if (s->name) {
- size_t n = 0;
- const char* nm = pool_str(img->c->global, s->name, &n);
+ Slice nm_s = pool_slice(img->c->global, s->name);
+ const char* nm = nm_s.s;
+ size_t n = nm_s.len;
const char* sec_name = NULL;
if (nm && n == 6 && memcmp(nm, "__xd_a", 6) == 0)
sec_name = ".CRT$XDA";
@@ -255,13 +257,10 @@ static const LinkSection* coff_symbol_section(const LinkImage* img,
sec_name = ".CRT$XLZ";
if (sec_name) {
u32 i;
- size_t sn = strlen(sec_name);
for (i = 0; i < img->nsections; ++i) {
const LinkSection* ls = &img->sections[i];
- size_t ln = 0;
- const char* lname =
- ls->name ? pool_str(img->c->global, ls->name, &ln) : NULL;
- if (lname && ln == sn && memcmp(lname, sec_name, sn) == 0)
+ if (ls->name &&
+ slice_eq_cstr(pool_slice(img->c->global, ls->name), sec_name))
return ls;
}
}
@@ -279,14 +278,15 @@ static u64 coff_symbol_final_va(const LinkImage* img,
const LinkSymbol* s = LinkSyms_at(&img->syms, id - 1);
if (!s->defined || s->kind == SK_ABS) {
compiler_panic(img->c, no_loc(),
- "link_emit_coff: `%s` is not a defined section-bound "
+ "link_emit_coff: `%.*s` is not a defined section-bound "
"symbol",
- what);
+ SLICE_ARG(slice_from_cstr(what)));
}
const LinkSection* sec = coff_symbol_section(img, s);
if (!sec) {
compiler_panic(img->c, no_loc(),
- "link_emit_coff: `%s` has no containing section", what);
+ "link_emit_coff: `%.*s` has no containing section",
+ SLICE_ARG(slice_from_cstr(what)));
}
u8 b = map[sec->id - 1].bucket;
return PE_IMAGE_BASE + (u64)out[b].rva +
@@ -457,8 +457,9 @@ static int coff_import_cmp(const void* a, const void* b) {
static const char* coff_import_lookup_name(Compiler* c, const LinkSymbol* s,
size_t* nlen_out) {
- size_t nlen = 0;
- const char* nm = s->name ? pool_str(c->global, s->name, &nlen) : NULL;
+ Slice nm_s = s->name ? pool_slice(c->global, s->name) : SLICE_NULL;
+ const char* nm = nm_s.s;
+ size_t nlen = nm_s.len;
static const char kImpPrefix[] = "__imp_";
const size_t kImpPrefixLen = sizeof(kImpPrefix) - 1u;
if (nm && nlen > kImpPrefixLen &&
@@ -478,8 +479,9 @@ static const char* coff_import_lookup_name(Compiler* c, const LinkSymbol* s,
* IAT-routed call). */
static int coff_import_is_func(Compiler* c, const LinkSymbol* s) {
if (s->name) {
- size_t nlen = 0;
- const char* nm = pool_str(c->global, s->name, &nlen);
+ Slice nm_s = pool_slice(c->global, s->name);
+ const char* nm = nm_s.s;
+ size_t nlen = nm_s.len;
if (nm && nlen > 6u && memcmp(nm, "__imp_", 6u) == 0) return 0;
}
if (s->kind == SK_FUNC || s->kind == SK_IFUNC) return 1;
@@ -646,8 +648,9 @@ static void coff_plan_idata_layout(LinkImage* img, CoffImportTable* it) {
/* Block 5: DLL name strings (NUL-terminated). */
it->name_base = off;
for (u32 d = 0; d < it->ndlls; ++d) {
- size_t nlen = 0;
- const char* nm = pool_str(c->global, it->dlls[d].soname, &nlen);
+ Slice nm_s = pool_slice(c->global, it->dlls[d].soname);
+ const char* nm = nm_s.s;
+ size_t nlen = nm_s.len;
if (!nm || nlen == 0)
compiler_panic(c, no_loc(),
"link_emit_coff: providing DSO has empty soname");
@@ -786,8 +789,9 @@ static void coff_emit_idata(LinkImage* img, const CoffImportTable* it,
/* Block 5: DLL name strings. */
for (u32 d = 0; d < it->ndlls; ++d) {
- size_t nlen = 0;
- const char* nm = pool_str(c->global, it->dlls[d].soname, &nlen);
+ Slice nm_s = pool_slice(c->global, it->dlls[d].soname);
+ const char* nm = nm_s.s;
+ size_t nlen = nm_s.len;
memcpy(buf + it->dlls[d].name_off, nm, nlen);
/* NUL already zero. */
}
@@ -865,17 +869,20 @@ static u16 coff_machine_or_panic(Compiler* c) {
static int coff_section_name_starts(Compiler* c, const LinkSection* ls,
const char* prefix) {
- size_t n = 0;
- size_t pn = strlen(prefix);
- const char* s = ls->name ? pool_str(c->global, ls->name, &n) : NULL;
+ size_t pn = slice_from_cstr(prefix).len;
+ Slice s_s = ls->name ? pool_slice(c->global, ls->name) : SLICE_NULL;
+ const char* s = s_s.s;
+ size_t n = s_s.len;
return s && n >= pn && memcmp(s, prefix, pn) == 0;
}
static int coff_section_name_cmp(Compiler* c, const LinkSection* a,
const LinkSection* b) {
- size_t an = 0, bn = 0;
- const char* as = a->name ? pool_str(c->global, a->name, &an) : "";
- const char* bs = b->name ? pool_str(c->global, b->name, &bn) : "";
+ Slice as_s = a->name ? pool_slice(c->global, a->name) : SLICE_NULL;
+ Slice bs_s = b->name ? pool_slice(c->global, b->name) : SLICE_NULL;
+ const char* as = as_s.s ? as_s.s : "";
+ const char* bs = bs_s.s ? bs_s.s : "";
+ size_t an = as_s.len, bn = bs_s.len;
size_t n = an < bn ? an : bn;
int cmp = n ? memcmp(as, bs, n) : 0;
if (cmp) return cmp;
@@ -1466,7 +1473,7 @@ static void coff_write_section_header(Writer* w, const char* name,
u32 file_offset,
u32 characteristics) {
u8 nm[8] = {0, 0, 0, 0, 0, 0, 0, 0};
- size_t n = strlen(name);
+ size_t n = slice_from_cstr(name).len;
if (n > 8) n = 8;
memcpy(nm, name, n);
cfree_writer_write(w, nm, 8);
diff --git a/src/link/link_dyn.c b/src/link/link_dyn.c
@@ -36,6 +36,7 @@
#include "core/bytes.h"
#include "core/heap.h"
#include "core/pool.h"
+#include "core/slice.h"
#include "core/util.h"
#include "core/vec.h"
#include "link/link.h"
@@ -339,8 +340,9 @@ static void build_dynsym(LinkImage* img, LinkDynState* dyn,
LinkSymId lsid = il->funcs[i];
LinkSymbol* s = LinkSyms_at(&img->syms, lsid - 1);
DynSymRec* r = &dyn->dynsym[idx];
- size_t namelen = 0;
- const char* nm = pool_str(img->c->global, s->name, &namelen);
+ Slice nm_s = pool_slice(img->c->global, s->name);
+ const char* nm = nm_s.s;
+ size_t namelen = nm_s.len;
r->st_name = bb_append_str(dynstr, nm, (u32)namelen);
r->st_info = ELF64_ST_INFO(STB_GLOBAL, STT_FUNC);
r->st_other = STV_DEFAULT;
@@ -354,8 +356,9 @@ static void build_dynsym(LinkImage* img, LinkDynState* dyn,
LinkSymId lsid = il->datas[i];
LinkSymbol* s = LinkSyms_at(&img->syms, lsid - 1);
DynSymRec* r = &dyn->dynsym[idx];
- size_t namelen = 0;
- const char* nm = pool_str(img->c->global, s->name, &namelen);
+ Slice nm_s = pool_slice(img->c->global, s->name);
+ const char* nm = nm_s.s;
+ size_t namelen = nm_s.len;
u8 elf_type = STT_OBJECT;
if (s->kind == SK_TLS)
elf_type = STT_TLS;
@@ -419,7 +422,7 @@ static void build_gnu_hash(Heap* h, LinkImage* img, LinkDynState* dyn,
for (i = 0; i < hashed; ++i) {
const DynSymRec* r = &dyn->dynsym[sym_offset + i];
const char* name = (const char*)dynstr->data + r->st_name;
- size_t n = name ? strlen(name) : 0;
+ size_t n = name ? slice_from_cstr(name).len : 0;
hashes[i] = gnu_hash_name(name, (u32)n);
}
@@ -526,7 +529,7 @@ void layout_dyn(Linker* l, LinkImage* img) {
dyn->interp_path =
l->interp_path
? l->interp_path
- : pool_intern_cstr(l->c->global, arch->default_musl_interp);
+ : pool_intern_slice(l->c->global, slice_from_cstr(arch->default_musl_interp));
/* Step 1: enumerate imports + DT_NEEDED. */
collect_imports(l, img, h, &imports);
@@ -541,8 +544,9 @@ void layout_dyn(Linker* l, LinkImage* img) {
{
u32 ni;
for (ni = 0; ni < dyn->nneeded; ++ni) {
- size_t slen = 0;
- const char* s = pool_str(l->c->global, dyn->needed[ni], &slen);
+ Slice s_s = pool_slice(l->c->global, dyn->needed[ni]);
+ const char* s = s_s.s;
+ size_t slen = s_s.len;
if (s && slen) (void)bb_append_str(&dynstr, s, (u32)slen);
}
}
@@ -604,8 +608,9 @@ void layout_dyn(Linker* l, LinkImage* img) {
compiler_panic(img->c, no_loc(), "link: oom on rela_dyn");
dyn->nrela_dyn = 0;
- size_t namelen;
- const char* interp_str = pool_str(l->c->global, dyn->interp_path, &namelen);
+ Slice interp_s = pool_slice(l->c->global, dyn->interp_path);
+ const char* interp_str = interp_s.s;
+ size_t namelen = interp_s.len;
u64 interp_bytes = (u64)namelen + 1u;
u64 dynsym_bytes = (u64)dyn->ndynsym * ELF64_SYM_SIZE;
u64 dynstr_bytes = (u64)dyn->dynstr_len;
@@ -785,15 +790,15 @@ void layout_dyn(Linker* l, LinkImage* img) {
/* helper: populate a fresh LinkSection for a segment-internal range */
/* Inline because the args differ enough (sem, name) per slot. */
- Sym name_interp = pool_intern_cstr(l->c->global, ".interp");
- Sym name_dynsym = pool_intern_cstr(l->c->global, ".dynsym");
- Sym name_dynstr = pool_intern_cstr(l->c->global, ".dynstr");
- Sym name_gnu_hash = pool_intern_cstr(l->c->global, ".gnu.hash");
- Sym name_rela_dyn = pool_intern_cstr(l->c->global, ".rela.dyn");
- Sym name_rela_plt = pool_intern_cstr(l->c->global, ".rela.plt");
- Sym name_dynamic = pool_intern_cstr(l->c->global, ".dynamic");
- Sym name_plt = pool_intern_cstr(l->c->global, ".plt");
- Sym name_got_plt = pool_intern_cstr(l->c->global, ".got.plt");
+ Sym name_interp = pool_intern_slice(l->c->global, SLICE_LIT(".interp"));
+ Sym name_dynsym = pool_intern_slice(l->c->global, SLICE_LIT(".dynsym"));
+ Sym name_dynstr = pool_intern_slice(l->c->global, SLICE_LIT(".dynstr"));
+ Sym name_gnu_hash = pool_intern_slice(l->c->global, SLICE_LIT(".gnu.hash"));
+ Sym name_rela_dyn = pool_intern_slice(l->c->global, SLICE_LIT(".rela.dyn"));
+ Sym name_rela_plt = pool_intern_slice(l->c->global, SLICE_LIT(".rela.plt"));
+ Sym name_dynamic = pool_intern_slice(l->c->global, SLICE_LIT(".dynamic"));
+ Sym name_plt = pool_intern_slice(l->c->global, SLICE_LIT(".plt"));
+ Sym name_got_plt = pool_intern_slice(l->c->global, SLICE_LIT(".got.plt"));
#define INIT_SEC(IDX, NAME, SEG_IDX, OFF_IN_SEG, SIZE, ALIGN, FLAGS, SEM) \
do { \
diff --git a/src/link/link_elf.c b/src/link/link_elf.c
@@ -49,6 +49,7 @@
#include "core/heap.h"
#include "core/pool.h"
+#include "core/slice.h"
#include "core/util.h"
#include "core/vec.h"
#include "link/link.h"
@@ -256,7 +257,8 @@ static void emit_dyn_record(LinkImage* img, u64 site_vaddr, u32 reloc_type,
static const LinkArchDesc* elf_arch_or_panic(Compiler* c, const char* where) {
const LinkArchDesc* arch = link_arch_desc_for(c);
if (!arch || !arch->e_machine)
- compiler_panic(c, no_loc(), "%s: no ELF arch descriptor", where);
+ compiler_panic(c, no_loc(), "%.*s: no ELF arch descriptor",
+ SLICE_ARG(slice_from_cstr(where)));
return arch;
}
@@ -403,9 +405,10 @@ static void apply_all_relocs(LinkImage* img, u64 img_base) {
continue;
}
{
- size_t nl = 0;
- const char* nm =
- tgt->name ? pool_str(img->c->global, tgt->name, &nl) : "";
+ Slice nm_s = tgt->name ? pool_slice(img->c->global, tgt->name)
+ : SLICE_NULL;
+ const char* nm = nm_s.s ? nm_s.s : "";
+ size_t nl = nm_s.len;
compiler_panic(
img->c, no_loc(),
"link: unhandled reloc kind %u against imported symbol '%.*s'",
@@ -482,7 +485,7 @@ static u32 strb_add(StrBuilder* s, const char* str, u32 slen) {
}
static u32 strb_add_cstr(StrBuilder* s, const char* str) {
- return strb_add(s, str, (u32)strlen(str));
+ return strb_add(s, str, (u32)slice_from_cstr(str).len);
}
/* ---- symtab builder ---- */
@@ -723,8 +726,9 @@ void link_emit_elf(LinkImage* img, Writer* w) {
u32 ni;
for (ni = 0; ni < dyn->nneeded; ++ni) {
Sym soname = dyn->needed[ni];
- size_t namelen = 0;
- const char* nm = pool_str(c->global, soname, &namelen);
+ Slice nm_s = pool_slice(c->global, soname);
+ const char* nm = nm_s.s;
+ size_t namelen = nm_s.len;
/* Linear search dynstr for this name. */
u32 off = 0;
if (nm && namelen) {
@@ -928,8 +932,9 @@ void link_emit_elf(LinkImage* img, Writer* w) {
for (i = 0; i < noutshdr; ++i) {
const OutShdr* o = &outshdrs[i];
if (o->name) {
- size_t nlen;
- const char* nm = pool_str(c->global, o->name, &nlen);
+ Slice nm_s = pool_slice(c->global, o->name);
+ const char* nm = nm_s.s;
+ size_t nlen = nm_s.len;
outshdr_name_off[i] =
nm && nlen ? strb_add(&shstrtab, nm, (u32)nlen) : 0;
} else {
@@ -989,7 +994,11 @@ void link_emit_elf(LinkImage* img, Writer* w) {
LinkSymId canonical = symhash_get(&img->globals, s->name);
if (canonical != LINK_SYM_NONE && canonical != s->id) continue;
}
- nm = s->name ? pool_str(c->global, s->name, &namelen) : "";
+ {
+ Slice nm_s = s->name ? pool_slice(c->global, s->name) : SLICE_NULL;
+ nm = nm_s.s ? nm_s.s : "";
+ namelen = nm_s.len;
+ }
shndx = sym_shndx_for(s, outshdrs, noutshdr);
/* st_value: in ET_EXEC, defined non-ABS symbols carry
* absolute virtual addresses (IMAGE_BASE + image
@@ -1285,13 +1294,13 @@ void link_emit_elf(LinkImage* img, Writer* w) {
Sym n_reladyn = 0, n_relaplt = 0, n_dynamic = 0;
Sym n_gotplt = 0;
if (pie && img->dyn) {
- n_dynsym = pool_intern_cstr(c->global, ".dynsym");
- n_dynstr = pool_intern_cstr(c->global, ".dynstr");
- n_gnuhash = pool_intern_cstr(c->global, ".gnu.hash");
- n_reladyn = pool_intern_cstr(c->global, ".rela.dyn");
- n_relaplt = pool_intern_cstr(c->global, ".rela.plt");
- n_dynamic = pool_intern_cstr(c->global, ".dynamic");
- n_gotplt = pool_intern_cstr(c->global, ".got.plt");
+ n_dynsym = pool_intern_slice(c->global, SLICE_LIT(".dynsym"));
+ n_dynstr = pool_intern_slice(c->global, SLICE_LIT(".dynstr"));
+ n_gnuhash = pool_intern_slice(c->global, SLICE_LIT(".gnu.hash"));
+ n_reladyn = pool_intern_slice(c->global, SLICE_LIT(".rela.dyn"));
+ n_relaplt = pool_intern_slice(c->global, SLICE_LIT(".rela.plt"));
+ n_dynamic = pool_intern_slice(c->global, SLICE_LIT(".dynamic"));
+ n_gotplt = pool_intern_slice(c->global, SLICE_LIT(".got.plt"));
}
/* Two-pass: first find dynsym/dynstr/gotplt indices for sh_link
* fixups, then emit. */
diff --git a/src/link/link_jit.c b/src/link/link_jit.c
@@ -18,6 +18,7 @@
#include "core/heap.h"
#include "core/metrics.h"
#include "core/pool.h"
+#include "core/slice.h"
#include "core/util.h"
#include "jit/tlv_thunk.h"
#include "link/link.h"
@@ -283,7 +284,7 @@ static void jit_patch_tlv_descriptors(CfreeJit* jit) {
* marks a descriptor's +0 slot.
*
* Bitmap over LinkSymId so the inner reloc test is O(1). */
- Sym tlv_name = pool_intern_cstr(c->global, "__tlv_bootstrap");
+ Sym tlv_name = pool_intern_slice(c->global, SLICE_LIT("__tlv_bootstrap"));
u32 nsyms = LinkSyms_count(&img->syms);
Heap* h = (Heap*)c->ctx->heap;
u8* is_tlv_bootstrap = (u8*)h->alloc(h, nsyms + 1u, 1u);
@@ -681,8 +682,8 @@ CfreeJit* cfree_jit_from_image(LinkImage* img) {
/* Run .init_array constructors in forward order. */
{
typedef void (*VoidFn)(void);
- void* p_start = cfree_jit_lookup(jit, "__init_array_start");
- void* p_end = cfree_jit_lookup(jit, "__init_array_end");
+ void* p_start = cfree_jit_lookup(jit, CFREE_SLICE_LIT("__init_array_start"));
+ void* p_end = cfree_jit_lookup(jit, CFREE_SLICE_LIT("__init_array_end"));
if (p_start && p_end) {
VoidFn* fn = (VoidFn*)p_start;
VoidFn* end = (VoidFn*)p_end;
@@ -742,14 +743,15 @@ void cfree_jit_free(CfreeJit* jit) {
heap->free(heap, jit, sizeof(*jit));
}
-void* cfree_jit_lookup(CfreeJit* jit, const char* name) {
+void* cfree_jit_lookup(CfreeJit* jit, CfreeSlice name) {
Sym sym;
LinkSymId id;
const LinkSymbol* s;
- if (!jit || !name) return NULL;
+ if (!jit || !name.s) return NULL;
/* C-symbol mangling lives in obj_format_c_mangle so JIT lookups by
- * source-level name find the symbol regardless of target format. */
- sym = obj_format_c_mangle(jit->c, name);
+ * source-level name find the symbol regardless of target format.
+ * name.s is NUL-terminated (CFREE_SLICE_LIT / cfree_slice_cstr / interned). */
+ sym = obj_format_c_mangle(jit->c, name.s);
id = symhash_get(&jit->image->globals, sym);
if (id == LINK_SYM_NONE) return NULL;
s = LinkSyms_at(&jit->image->syms, id - 1);
@@ -958,8 +960,9 @@ static void jit_append_obj_inner(CfreeJit* jit, ObjBuilder* ob) {
if (prev && prev->defined &&
jit_bind_strength((u8)s->bind) == jit_bind_strength(SB_GLOBAL) &&
jit_bind_strength(prev->bind) == jit_bind_strength(SB_GLOBAL)) {
- size_t namelen;
- const char* nm = pool_str(jit->c->global, s->name, &namelen);
+ Slice nm_s = pool_slice(jit->c->global, s->name);
+ const char* nm = nm_s.s;
+ size_t namelen = nm_s.len;
obj_format_demangle_c(jit->c, &nm, &namelen);
obj_symiter_free(it);
compiler_panic(jit->c, no_loc(),
@@ -988,15 +991,14 @@ static void jit_append_obj_inner(CfreeJit* jit, ObjBuilder* ob) {
obj_symiter_free(it2);
}
if (!ok && jit->linker->resolver) {
- size_t namelen;
- const char* nm = pool_str(jit->c->global, s->name, &namelen);
- (void)namelen;
- if (jit->linker->resolver(jit->linker->resolver_user, nm)) ok = 1;
+ Slice nm_s = pool_slice(jit->c->global, s->name);
+ if (jit->linker->resolver(jit->linker->resolver_user, nm_s)) ok = 1;
}
if (!ok && s->bind == SB_WEAK) ok = 1;
if (!ok) {
- size_t nlen;
- const char* nm = pool_str(jit->c->global, s->name, &nlen);
+ Slice nm_s = pool_slice(jit->c->global, s->name);
+ const char* nm = nm_s.s;
+ size_t nlen = nm_s.len;
if (nm && nlen == 15u && memcmp(nm, "__tlv_bootstrap", 15u) == 0)
ok = 1;
if (!ok) {
@@ -1070,8 +1072,9 @@ static void jit_append_obj_inner(CfreeJit* jit, ObjBuilder* ob) {
if (prev && prev->defined &&
jit_bind_strength((u8)s->bind) == jit_bind_strength(SB_GLOBAL) &&
jit_bind_strength(prev->bind) == jit_bind_strength(SB_GLOBAL)) {
- size_t namelen;
- const char* nm = pool_str(jit->c->global, s->name, &namelen);
+ Slice nm_s = pool_slice(jit->c->global, s->name);
+ const char* nm = nm_s.s;
+ size_t namelen = nm_s.len;
obj_format_demangle_c(jit->c, &nm, &namelen);
obj_symiter_free(it);
compiler_panic(jit->c, no_loc(),
@@ -1149,10 +1152,8 @@ static void jit_append_obj_inner(CfreeJit* jit, ObjBuilder* ob) {
}
}
if (jit->linker->resolver && s->name != 0) {
- size_t namelen;
- const char* nm = pool_str(jit->c->global, s->name, &namelen);
- void* p = jit->linker->resolver(jit->linker->resolver_user, nm);
- (void)namelen;
+ Slice nm_s = pool_slice(jit->c->global, s->name);
+ void* p = jit->linker->resolver(jit->linker->resolver_user, nm_s);
if (p) {
s->kind = SK_ABS;
s->vaddr = (u64)(uintptr_t)p;
@@ -1167,8 +1168,9 @@ static void jit_append_obj_inner(CfreeJit* jit, ObjBuilder* ob) {
continue;
}
if (s->name != 0) {
- size_t nlen;
- const char* nm = pool_str(jit->c->global, s->name, &nlen);
+ Slice nm_s = pool_slice(jit->c->global, s->name);
+ const char* nm = nm_s.s;
+ size_t nlen = nm_s.len;
if (nm && nlen == 15u && memcmp(nm, "__tlv_bootstrap", 15u) == 0) {
s->kind = SK_ABS;
s->vaddr = 0;
@@ -1431,7 +1433,7 @@ static int jit_view_input_has_debug(CfreeJit* jit, u32 ii) {
const Section* s = obj_section_get(ob, (ObjSecId)(k + 1));
const char* nm;
if (!s || !s->name) continue;
- nm = pool_str(in_pool, s->name, NULL);
+ nm = pool_slice(in_pool, s->name).s;
if (jit_view_is_debug_name(nm)) return 1;
}
return 0;
@@ -1477,7 +1479,7 @@ static ViewSec* view_sec_for(CfreeJit* jit, ViewSec* tab, u32* ntab,
ViewSec** tab_out) {
Heap* h = (Heap*)jit->c->ctx->heap;
Pool* view_pool = obj_compiler(view_ob)->global;
- Sym vn = pool_intern_cstr(view_pool, name);
+ Sym vn = pool_intern_slice(view_pool, slice_from_cstr(name));
u32 i;
for (i = 0; i < *ntab; ++i) {
if (tab[i].view_name == vn) {
@@ -1563,11 +1565,11 @@ static void jit_view_copy_debug_section(CfreeJit* jit, u32 ii,
if (ts && ts->kind == SK_SECTION && ts->section_id != OBJ_SEC_NONE) {
const Section* tsec = obj_section_get(in_ob, ts->section_id);
if (tsec && tsec->kind == SEC_DEBUG && tsec->name) {
- size_t tnlen = 0;
- const char* tnm =
- pool_str(obj_compiler(in_ob)->global, tsec->name, &tnlen);
+ Slice tnm_s = pool_slice(obj_compiler(in_ob)->global, tsec->name);
+ const char* tnm = tnm_s.s;
+ size_t tnlen = tnm_s.len;
if (tnm) {
- Sym v_tn = pool_intern(view_pool, tnm, tnlen);
+ Sym v_tn = pool_intern_slice(view_pool, (Slice){ .s = tnm, .len = tnlen });
ViewSec* tgt = view_sec_find(tab, ntab, v_tn);
if (tgt) {
S = (u64)tgt->snap;
@@ -1637,10 +1639,9 @@ static CfreeObjFile* jit_view_build(CfreeJit* jit) {
for (k = 0; k < nsec; ++k) {
const Section* s = obj_section_get(in_ob, (ObjSecId)(k + 1));
const char* nm;
- size_t nlen = 0;
ViewSec* vs;
if (!s || !s->name) continue;
- nm = pool_str(obj_compiler(in_ob)->global, s->name, &nlen);
+ nm = pool_slice(obj_compiler(in_ob)->global, s->name).s;
if (!nm || !jit_view_is_debug_name(nm)) continue;
vs = view_sec_for(jit, tab, &ntab, &cap, nm, s->flags,
s->align ? s->align : 1u, s->entsize, view_ob, &tab);
@@ -1659,9 +1660,14 @@ static CfreeObjFile* jit_view_build(CfreeJit* jit) {
Sym v_nm;
ViewSec* vs;
if (!s || !s->name) continue;
- nm = pool_str(obj_compiler(in_ob)->global, s->name, &nlen);
+ {
+ Slice nm_s = pool_slice(obj_compiler(in_ob)->global, s->name);
+ nm = nm_s.s;
+ nlen = nm_s.len;
+ }
if (!nm || !jit_view_is_debug_name(nm)) continue;
- v_nm = pool_intern(obj_compiler(view_ob)->global, nm, nlen);
+ v_nm = pool_intern_slice(obj_compiler(view_ob)->global,
+ (Slice){ .s = nm, .len = nlen });
vs = view_sec_find(tab, ntab, v_nm);
if (!vs) continue;
jit_view_copy_debug_section(jit, ii, (ObjSecId)(k + 1), view_ob, tab,
@@ -1693,12 +1699,15 @@ static int jit_sym_kind_visible(u8 k) {
/* Resolve a LinkSymbol's interned name to a stable C string, stripping
* the target format's C-mangling prefix (Mach-O's leading `_`) so the
* user sees the source-level name. */
-static const char* jit_sym_name_cstr(CfreeJit* jit, const LinkSymbol* s) {
- size_t len = 0;
- const char* nm = pool_str(jit->c->global, s->name, &len);
- if (!nm) return NULL;
+static Slice jit_sym_name_slice(CfreeJit* jit, const LinkSymbol* s) {
+ Slice nm_s = pool_slice(jit->c->global, s->name);
+ const char* nm = nm_s.s;
+ size_t len = nm_s.len;
+ if (!nm) return CFREE_SLICE_NULL;
obj_format_demangle_c(jit->c, &nm, &len);
- return nm;
+ nm_s.s = nm;
+ nm_s.len = len;
+ return nm_s;
}
static uint64_t jit_sym_runtime_addr(CfreeJit* jit, const LinkSymbol* s) {
@@ -1707,13 +1716,13 @@ static uint64_t jit_sym_runtime_addr(CfreeJit* jit, const LinkSymbol* s) {
}
CfreeStatus cfree_jit_addr_to_sym(CfreeJit* jit, uint64_t addr,
- const char** name_out, uint64_t* off_out) {
+ CfreeSlice* name_out, uint64_t* off_out) {
u32 n;
u32 i;
const LinkSymbol* best = NULL;
uint64_t best_base = 0;
uint64_t best_off = (uint64_t)-1;
- if (name_out) *name_out = NULL;
+ if (name_out) *name_out = CFREE_SLICE_NULL;
if (off_out) *off_out = 0;
if (!jit) return CFREE_INVALID;
n = LinkSyms_count(&jit->image->syms);
@@ -1735,7 +1744,7 @@ CfreeStatus cfree_jit_addr_to_sym(CfreeJit* jit, uint64_t addr,
}
}
if (best) {
- if (name_out) *name_out = jit_sym_name_cstr(jit, best);
+ if (name_out) *name_out = jit_sym_name_slice(jit, best);
if (off_out) *off_out = addr - best_base;
return CFREE_OK;
}
@@ -1770,7 +1779,7 @@ CfreeIterResult cfree_jit_sym_iter_next(CfreeJitSymIter* it, CfreeJitSym* out) {
LinkSymbol* s = LinkSyms_at(&it->jit->image->syms, it->next++);
if (!s || !s->defined) continue;
if (!jit_sym_kind_visible(s->kind)) continue;
- out->name = jit_sym_name_cstr(it->jit, s);
+ out->name = jit_sym_name_slice(it->jit, s);
out->addr = jit_sym_runtime_addr(it->jit, s);
out->size = s->size;
out->kind = (CfreeSymKind)s->kind;
@@ -1855,8 +1864,8 @@ void cfree_jit_run_dtors(CfreeJit* jit) {
void* p_start;
void* p_end;
if (!jit) return;
- p_start = cfree_jit_lookup(jit, "__fini_array_start");
- p_end = cfree_jit_lookup(jit, "__fini_array_end");
+ p_start = cfree_jit_lookup(jit, CFREE_SLICE_LIT("__fini_array_start"));
+ p_end = cfree_jit_lookup(jit, CFREE_SLICE_LIT("__fini_array_end"));
if (p_start && p_end) {
VoidFn* begin = (VoidFn*)p_start;
VoidFn* fn = (VoidFn*)p_end;
diff --git a/src/link/link_layout.c b/src/link/link_layout.c
@@ -18,6 +18,7 @@
#include "core/heap.h"
#include "core/metrics.h"
#include "core/pool.h"
+#include "core/slice.h"
#include "core/util.h"
#include "core/vec.h"
#include "link/link.h"
@@ -413,8 +414,8 @@ void link_layout_sections(Linker* l, LinkImage* img, const GcLive* g) {
static int match_glob(const char* pat, const char* name) {
size_t plen, nlen;
if (!pat || !name) return 0;
- plen = strlen(pat);
- nlen = strlen(name);
+ plen = slice_from_cstr(pat).len;
+ nlen = slice_from_cstr(name).len;
if (plen == 1 && pat[0] == '*') return 1;
if (plen >= 2 && pat[plen - 1] == '*') {
if (nlen + 1 < plen) return 0;
@@ -439,12 +440,12 @@ static u64 eval_link_expr(Linker* l, LinkImage* img, u64 dot,
case CFREE_LE_DOT:
return dot;
case CFREE_LE_SYM: {
- Sym name = pool_intern_cstr(l->c->global, e->v.name);
+ Sym name = pool_intern_slice(l->c->global, e->v.name);
LinkSymId id = symhash_get(&img->globals, name);
if (id == LINK_SYM_NONE) {
compiler_panic(l->c, no_loc(),
- "linker script: undefined symbol '%s' in expression",
- e->v.name);
+ "linker script: undefined symbol '%.*s' in expression",
+ SLICE_ARG(pool_slice(l->c->global, name)));
}
return LinkSyms_at(&img->syms, id - 1)->vaddr;
}
@@ -513,8 +514,8 @@ void link_emit_boundary_sym(Linker* l, LinkImage* img, const char* name,
u8 kind = SK_OBJ;
u32 i, n;
if (l->c->target.obj == CFREE_OBJ_COFF &&
- (strcmp(name, "__ImageBase") == 0 ||
- strcmp(name, "_tls_used") == 0)) {
+ (slice_eq_cstr(slice_from_cstr(name), "__ImageBase") ||
+ slice_eq_cstr(slice_from_cstr(name), "_tls_used"))) {
kind = SK_ABS;
}
memset(&rec, 0, sizeof(rec));
@@ -552,9 +553,11 @@ void link_define_boundary(Linker* l, LinkImage* img, const char* name,
}
/* Upsert a global symbol (mirror of emit_boundary_sym, used by apply_asn). */
-static void upsert_global_sym(Linker* l, LinkImage* img, const char* name,
+static void upsert_global_sym(Linker* l, LinkImage* img, CfreeSlice name,
u64 vaddr) {
- link_emit_boundary_sym(l, img, name, vaddr);
+ /* Script sym slices are arena-interned and NUL-terminated; the boundary
+ * emitter mangles via obj_format_c_mangle which needs a C string. */
+ link_emit_boundary_sym(l, img, name.s, vaddr);
}
/* Apply one CfreeLinkAssignment. */
@@ -573,13 +576,15 @@ static void apply_asn(Linker* l, LinkImage* img, u64* dot,
break;
case CFREE_LAS_SYM:
case CFREE_LAS_PROVIDE:
- if (asn->sym) upsert_global_sym(l, img, asn->sym, v);
+ if (asn->sym.s) upsert_global_sym(l, img, asn->sym, v);
break;
}
}
static int input_match_section(const CfreeLinkInputMatch* m, const char* nm) {
- return match_glob(m->section_pattern, nm);
+ /* section_pattern is an arena-interned, NUL-terminated span of the
+ * script text; match_glob scans it as a C string. */
+ return match_glob(m->section_pattern.s, nm);
}
static void link_layout_sections_scripted(Linker* l, LinkImage* img,
@@ -630,7 +635,8 @@ static void link_layout_sections_scripted(Linker* l, LinkImage* img,
u32 nseg_max = 0;
for (si = 0; si < script->nsections; ++si)
- if (strcmp(script->sections[si].name, "/DISCARD/") != 0) ++nseg_max;
+ if (!slice_eq_cstr(script->sections[si].name, "/DISCARD/"))
+ ++nseg_max;
img->segments =
nseg_max ? (LinkSegment*)h->alloc(h, sizeof(*img->segments) * nseg_max,
_Alignof(LinkSegment))
@@ -655,7 +661,7 @@ static void link_layout_sections_scripted(Linker* l, LinkImage* img,
for (si = 0; si < script->nsections; ++si) {
const CfreeLinkOutputSection* os = &script->sections[si];
- int is_discard = (strcmp(os->name, "/DISCARD/") == 0);
+ int is_discard = slice_eq_cstr(os->name, "/DISCARD/");
if (is_discard) {
u32 mi;
@@ -666,11 +672,12 @@ static void link_layout_sections_scripted(Linker* l, LinkImage* img,
for (j = 1; j < obj_section_count(ob); ++j) {
const Section* s;
const char* nm;
- size_t nl;
if (claimed[ii][j]) continue;
s = obj_section_get(ob, j);
if (!s) continue;
- nm = pool_str(l->c->global, s->name, &nl);
+ {
+ nm = pool_slice(l->c->global, s->name).s;
+ }
if (!nm) continue;
if (input_match_section(im, nm)) claimed[ii][j] = 1;
}
@@ -704,7 +711,6 @@ static void link_layout_sections_scripted(Linker* l, LinkImage* img,
for (j = 1; j < obj_section_count(ob); ++j) {
const Section* s;
const char* nm;
- size_t nl;
u32 align;
u64 ofs;
LinkSection* ls;
@@ -713,7 +719,9 @@ static void link_layout_sections_scripted(Linker* l, LinkImage* img,
if (!link_gc_live_get(g, ii, j)) continue;
s = obj_section_get(ob, j);
if (!s || !link_section_kept(s)) continue;
- nm = pool_str(l->c->global, s->name, &nl);
+ {
+ nm = pool_slice(l->c->global, s->name).s;
+ }
if (!nm) continue;
if (!input_match_section(im, nm)) continue;
@@ -910,7 +918,7 @@ void link_layout_commons(Linker* l, LinkImage* img) {
commsec->size = bss_cursor - bss_start;
commsec->flags = SF_ALLOC | SF_WRITE;
commsec->align = max_align;
- commsec->name = pool_intern_cstr(img->c->global, ".bss.common");
+ commsec->name = pool_intern_slice(img->c->global, SLICE_LIT(".bss.common"));
commsec->sem = SSEM_NOBITS;
img->nsections++;
diff --git a/src/link/link_macho.c b/src/link/link_macho.c
@@ -43,6 +43,7 @@
#include "core/heap.h"
#include "core/pool.h"
#include "core/sha256.h"
+#include "core/slice.h"
#include "core/util.h"
#include "core/vec.h"
#include "link/link.h"
@@ -433,7 +434,7 @@ static void collect_imports(MCtx* x) {
if (in->kind == LINK_INPUT_DSO_BYTES) install = in->soname;
}
if (install == 0)
- install = pool_intern_cstr(x->c->global, "/usr/lib/libSystem.B.dylib");
+ install = pool_intern_slice(x->c->global, SLICE_LIT("/usr/lib/libSystem.B.dylib"));
u32 ord = dylib_ordinal_of(x, install);
if (!ord) {
if (VEC_GROW(h, x->dylibs, cap_d, x->ndylibs + 1u))
@@ -637,8 +638,9 @@ static int sec_needs_data_const(const LinkImage* img, const LinkSection* ls) {
* a previous version used a shared static buffer which aliased all
* sections to whichever name was set last. */
static void pick_macho_names(const LinkSection* ls, Compiler* c, MSec* m) {
- size_t nlen;
- const char* nm = pool_str(c->global, ls->name, &nlen);
+ Slice nm_s = pool_slice(c->global, ls->name);
+ const char* nm = nm_s.s;
+ size_t nlen = nm_s.len;
if (nm) {
/* Comma-form: "__SEG,__sect" round-tripped from a Mach-O input. */
for (size_t i = 0; i < nlen; ++i) {
@@ -732,7 +734,8 @@ static void plan_layout(MCtx* x) {
m->link_sec_id = ls->id;
pick_macho_names(ls, x->c, m);
/* Force into __TEXT. */
- if (strcmp(m->segname, "__TEXT") != 0) m->segname = "__TEXT";
+ if (!slice_eq_cstr(slice_from_cstr(m->segname), "__TEXT"))
+ m->segname = "__TEXT";
m->align = ls->align ? ls->align : 1u;
m->size = ls->size;
m->segidx = 1;
@@ -809,7 +812,8 @@ static void plan_layout(MCtx* x) {
memset(m, 0, sizeof(*m));
m->link_sec_id = ls->id;
pick_macho_names(ls, x->c, m);
- if (strcmp(m->segname, "__DATA") != 0) m->segname = "__DATA";
+ if (!slice_eq_cstr(slice_from_cstr(m->segname), "__DATA"))
+ m->segname = "__DATA";
m->align = ls->align ? ls->align : 1u;
m->size = ls->size;
m->segidx = 3;
@@ -819,9 +823,9 @@ static void plan_layout(MCtx* x) {
* __mod_init_func / __mod_term_func sections must carry the
* S_MOD_INIT_FUNC_POINTERS / S_MOD_TERM_FUNC_POINTERS type or dyld
* skips them entirely — leaving constructors unrun at startup. */
- if (strcmp(m->sectname, "__mod_init_func") == 0)
+ if (slice_eq_cstr(slice_from_cstr(m->sectname), "__mod_init_func"))
m->flags = 0x00000009u /*S_MOD_INIT_FUNC_POINTERS*/;
- else if (strcmp(m->sectname, "__mod_term_func") == 0)
+ else if (slice_eq_cstr(slice_from_cstr(m->sectname), "__mod_term_func"))
m->flags = 0x0000000au /*S_MOD_TERM_FUNC_POINTERS*/;
else if (ls->flags & SF_TLS) {
/* TLV sections: dyld dispatches by section type, not name. Map
@@ -830,7 +834,7 @@ static void plan_layout(MCtx* x) {
* __thread_bss → S_THREAD_LOCAL_ZEROFILL (zero-init data). Done
* by sectname so per-TU inputs without a Mach-O ext_type still
* get the right section type. */
- if (strcmp(m->sectname, "__thread_vars") == 0) {
+ if (slice_eq_cstr(slice_from_cstr(m->sectname), "__thread_vars")) {
m->flags = S_THREAD_LOCAL_VARIABLES;
/* Each descriptor is three pointers (24B) whose first word is
* dyld's _tlv_bootstrap thunk pointer. Clang/llvm emit
@@ -889,8 +893,10 @@ static void plan_layout(MCtx* x) {
u32 j = a;
while (j > 0) {
MSec* prev = &x->secs[base + j - 1];
- int cmp = strcmp(prev->segname, key.segname);
- if (cmp == 0) cmp = strcmp(prev->sectname, key.sectname);
+ /* Ordering compare for stable sort: slices don't order, keep strcmp. */
+ int cmp = strcmp(prev->segname, key.segname); /* ordering */
+ if (cmp == 0)
+ cmp = strcmp(prev->sectname, key.sectname); /* ordering */
if (cmp <= 0) break;
x->secs[base + j] = x->secs[base + j - 1];
msec_repair_name_ptrs(&x->secs[base + j]);
@@ -910,8 +916,10 @@ static void plan_layout(MCtx* x) {
for (u32 a = sg->first_sec; a < sg->first_sec + sg->nsects; ++a) {
int seen = 0;
for (u32 b = sg->first_sec; b < a; ++b) {
- if (strcmp(x->secs[a].sectname, x->secs[b].sectname) == 0 &&
- strcmp(x->secs[a].segname, x->secs[b].segname) == 0) {
+ if (slice_eq_cstr(slice_from_cstr(x->secs[a].sectname),
+ x->secs[b].sectname) &&
+ slice_eq_cstr(slice_from_cstr(x->secs[a].segname),
+ x->secs[b].segname)) {
seen = 1;
break;
}
@@ -955,15 +963,14 @@ static void plan_layout(MCtx* x) {
sizeofcmds += MACHO_SYMTAB_CMD_SIZE + MACHO_DYSYMTAB_CMD_SIZE;
/* LC_LOAD_DYLINKER */
{
- u32 ld_size = 12u + (u32)strlen("/usr/lib/dyld") + 1u;
+ u32 ld_size = 12u + (u32)(sizeof("/usr/lib/dyld") - 1u) + 1u;
sizeofcmds += (u32)ALIGN_UP((u64)ld_size, 8u);
}
/* LC_UUID + LC_BUILD_VERSION + LC_MAIN */
sizeofcmds += 24u + 24u + 24u;
/* LC_LOAD_DYLIB per dylib */
for (u32 i = 0; i < x->ndylibs; ++i) {
- size_t nl;
- pool_str(x->c->global, x->dylibs[i].install, &nl);
+ size_t nl = pool_slice(x->c->global, x->dylibs[i].install).len;
u32 sz = 24u + (u32)nl + 1u;
sizeofcmds += (u32)ALIGN_UP((u64)sz, 8u);
}
@@ -1026,14 +1033,16 @@ static void plan_layout(MCtx* x) {
x->stubs_vaddr = 0;
for (u32 j = 0; j < sg->nsects; ++j) {
MSec* m = &x->secs[sg->first_sec + j];
- if (strcmp(m->sectname, "__stubs") == 0) x->stubs_vaddr = m->vaddr;
+ if (slice_eq_cstr(slice_from_cstr(m->sectname), "__stubs"))
+ x->stubs_vaddr = m->vaddr;
}
x->text_filesz = sg->filesize;
}
if (i == 2) {
for (u32 j = 0; j < sg->nsects; ++j) {
MSec* m = &x->secs[sg->first_sec + j];
- if (strcmp(m->sectname, "__got") == 0) x->got_vaddr = m->vaddr;
+ if (slice_eq_cstr(slice_from_cstr(m->sectname), "__got"))
+ x->got_vaddr = m->vaddr;
}
x->data_const_vaddr = sg->vmaddr;
x->data_const_filesz = sg->filesize;
@@ -1041,14 +1050,14 @@ static void plan_layout(MCtx* x) {
if (i == 3) {
for (u32 j = 0; j < sg->nsects; ++j) {
MSec* m = &x->secs[sg->first_sec + j];
- if (strcmp(m->sectname, "__thread_ptrs") == 0)
+ if (slice_eq_cstr(slice_from_cstr(m->sectname), "__thread_ptrs"))
x->tlv_ptrs_vaddr = m->vaddr;
/* TLS storage image base: min vaddr across __thread_data and
* __thread_bss sections. __thread_vars is excluded — it holds
* the descriptors, not the data that maps into the per-thread
* block. */
- if ((strcmp(m->sectname, "__thread_data") == 0 ||
- strcmp(m->sectname, "__thread_bss") == 0) &&
+ if ((slice_eq_cstr(slice_from_cstr(m->sectname), "__thread_data") ||
+ slice_eq_cstr(slice_from_cstr(m->sectname), "__thread_bss")) &&
(!x->has_tls_image || m->vaddr < x->tls_image_vaddr)) {
x->tls_image_vaddr = m->vaddr;
x->has_tls_image = 1;
@@ -1124,14 +1133,16 @@ static void plan_layout(MCtx* x) {
MSec* m = &x->secs[order[i]];
OutSec* tail = x->nouts ? &x->outs[x->nouts - 1] : NULL;
int merge = tail && tail->segidx == m->segidx &&
- strcmp(tail->sectname, m->sectname) == 0 &&
- strcmp(tail->segname, m->segname) == 0;
+ slice_eq_cstr(slice_from_cstr(tail->sectname),
+ m->sectname) &&
+ slice_eq_cstr(slice_from_cstr(tail->segname), m->segname);
if (merge) {
if (tail->flags != m->flags || tail->is_zerofill != m->is_zerofill)
compiler_panic(
x->c, no_loc(),
- "link_macho: coalesce mismatch on %s,%s (flags/zerofill)",
- m->segname, m->sectname);
+ "link_macho: coalesce mismatch on %.*s,%.*s (flags/zerofill)",
+ SLICE_ARG(slice_from_cstr(m->segname)),
+ SLICE_ARG(slice_from_cstr(m->sectname)));
u64 end = m->vaddr + m->size;
u64 prev_end = tail->vaddr + tail->size;
if (end > prev_end) tail->size = end - tail->vaddr;
@@ -1764,8 +1775,9 @@ static void build_chained_fixups(MCtx* x, FixList* fl) {
mbuf_u8(out, 0);
for (u32 i = 0; i < x->nimports_real; ++i) {
MachImp* mi = &x->imports[i];
- size_t nl;
- const char* nm = pool_str(x->c->global, mi->name, &nl);
+ Slice nm_s = pool_slice(x->c->global, mi->name);
+ const char* nm = nm_s.s;
+ size_t nl = nm_s.len;
if (!nm || !nl || mi->dylib_ord == 0 || mi->dylib_ord > x->ndylibs) {
compiler_panic(x->c, no_loc(),
"link_macho: invalid chained import %u "
@@ -1820,8 +1832,9 @@ static void build_exports_trie(MCtx* x) {
mbuf_u8(out, 0); /* children 0 */
return;
}
- size_t nl;
- const char* nm = pool_str(x->c->global, esym->name, &nl);
+ Slice nm_s = pool_slice(x->c->global, esym->name);
+ const char* nm = nm_s.s;
+ size_t nl = nm_s.len;
if (!nm || nl == 0) {
mbuf_u8(out, 0);
mbuf_u8(out, 0);
@@ -1950,8 +1963,9 @@ static void build_symtab(MCtx* x) {
break;
}
}
- size_t nl;
- const char* nm = pool_str(x->c->global, s->name, &nl);
+ Slice nm_s = pool_slice(x->c->global, s->name);
+ const char* nm = nm_s.s;
+ size_t nl = nm_s.len;
u32 strx = x->strtab.len;
if (nm && nl) mbuf_str(&x->strtab, nm, (u32)nl);
@@ -1974,8 +1988,9 @@ static void build_symtab(MCtx* x) {
u32 imp_first_symtab_idx = n_extdef;
for (u32 i = 0; i < x->nimports_real; ++i) {
MachImp* mi = &x->imports[i];
- size_t nl;
- const char* nm = pool_str(x->c->global, mi->name, &nl);
+ Slice nm_s = pool_slice(x->c->global, mi->name);
+ const char* nm = nm_s.s;
+ size_t nl = nm_s.len;
u32 strx = x->strtab.len;
if (nm && nl) mbuf_str(&x->strtab, nm, (u32)nl);
@@ -2002,7 +2017,7 @@ static void build_symtab(MCtx* x) {
* so a sectname match identifies them unambiguously. */
for (u32 i = 0; i < x->nouts; ++i) {
OutSec* o = &x->outs[i];
- if (strcmp(o->sectname, "__stubs") == 0 && o->size) {
+ if (slice_eq_cstr(slice_from_cstr(o->sectname), "__stubs") && o->size) {
o->reserved1 = indirect_start;
for (u32 k = 0; k < x->nimports; ++k) {
MachImp* mi = &x->imports[k];
@@ -2015,7 +2030,7 @@ static void build_symtab(MCtx* x) {
}
for (u32 i = 0; i < x->nouts; ++i) {
OutSec* o = &x->outs[i];
- if (strcmp(o->sectname, "__got") == 0 && o->size) {
+ if (slice_eq_cstr(slice_from_cstr(o->sectname), "__got") && o->size) {
o->reserved1 = indirect_start;
for (u32 k = 0; k < x->nimports; ++k) {
MachImp* mi = &x->imports[k];
@@ -2136,7 +2151,7 @@ static void build_codesig_skeleton(MCtx* x, u32 code_limit, const char* ident) {
* identifier (ident_len + 1)
* hashes (nslots * 32)
*/
- u32 ident_len = (u32)strlen(ident) + 1u;
+ u32 ident_len = (u32)slice_from_cstr(ident).len + 1u;
u32 cd_hdr = 88u;
u32 cd_size = cd_hdr + ident_len + nslots * CS_SHA256_LEN;
/* SuperBlob: 12 hdr + 8 slot + cd. */
@@ -2191,7 +2206,7 @@ static void compute_codesig(MCtx* x, const u8* full_file, u32 file_len_excl_cs,
const char* ident) {
u32 code_page = 1u << CS_PAGE_SIZE_LOG2;
u32 nslots = (file_len_excl_cs + code_page - 1u) / code_page;
- u32 ident_len = (u32)strlen(ident) + 1u;
+ u32 ident_len = (u32)slice_from_cstr(ident).len + 1u;
u8* cd = x->codesig.data + 12 + 8;
u8* hashes = cd + 88u + ident_len;
@@ -2220,7 +2235,7 @@ static void emit_load_command_segment(MByte* lc, MCtx* x, u32 segidx) {
/* segname: 16 bytes zero-padded */
u8 nm[16];
memset(nm, 0, 16);
- size_t nlen = strlen(sg->name);
+ size_t nlen = slice_from_cstr(sg->name).len;
if (nlen > 16) nlen = 16;
memcpy(nm, sg->name, nlen);
mbuf_append(lc, nm, 16);
@@ -2238,10 +2253,10 @@ static void emit_load_command_segment(MByte* lc, MCtx* x, u32 segidx) {
u8 sname[16], gname[16];
memset(sname, 0, 16);
memset(gname, 0, 16);
- size_t sl = o->sectname ? strlen(o->sectname) : 0;
+ size_t sl = o->sectname ? slice_from_cstr(o->sectname).len : 0;
if (sl > 16) sl = 16;
if (sl) memcpy(sname, o->sectname, sl);
- size_t gl = strlen(sg->name); /* segname must match */
+ size_t gl = slice_from_cstr(sg->name).len; /* segname must match */
if (gl > 16) gl = 16;
memcpy(gname, sg->name, gl);
mbuf_append(lc, sname, 16);
@@ -2384,11 +2399,12 @@ void link_emit_macho(LinkImage* img, Writer* w) {
/* LC_LOAD_DYLINKER */
{
const char* dyld = "/usr/lib/dyld";
- u32 cmd_size = (u32)ALIGN_UP((u64)(12u + (u32)strlen(dyld) + 1u), 8u);
+ u32 dyld_len = (u32)slice_from_cstr(dyld).len;
+ u32 cmd_size = (u32)ALIGN_UP((u64)(12u + dyld_len + 1u), 8u);
mbuf_u32(&lc, LC_LOAD_DYLINKER);
mbuf_u32(&lc, cmd_size);
mbuf_u32(&lc, 12u); /* name offset within cmd */
- u32 wrote = mbuf_str(&lc, dyld, (u32)strlen(dyld));
+ u32 wrote = mbuf_str(&lc, dyld, dyld_len);
(void)wrote;
/* Pad to cmd_size. */
while (lc.len < (u32)((u64)mbuf_align(&lc, 1) + 0)) {
@@ -2398,7 +2414,7 @@ void link_emit_macho(LinkImage* img, Writer* w) {
/* Re-align to cmd_size. */
u32 want = (u32)(lc.len);
/* Walk back: lc grew by 12 + (strlen+1). Pad to cmd_size. */
- u32 cmd_start_back = lc.len - (12u + (u32)strlen(dyld) + 1u);
+ u32 cmd_start_back = lc.len - (12u + dyld_len + 1u);
u32 pad_needed = cmd_size - (lc.len - cmd_start_back);
while (pad_needed-- > 0) mbuf_u8(&lc, 0);
(void)want;
@@ -2426,8 +2442,9 @@ void link_emit_macho(LinkImage* img, Writer* w) {
/* LC_LOAD_DYLIB per dylib. */
for (u32 i = 0; i < x.ndylibs; ++i) {
- size_t nl;
- const char* nm = pool_str(x.c->global, x.dylibs[i].install, &nl);
+ Slice nm_s = pool_slice(x.c->global, x.dylibs[i].install);
+ const char* nm = nm_s.s;
+ size_t nl = nm_s.len;
u32 cmd_size = (u32)ALIGN_UP((u64)(24u + (u32)nl + 1u), 8u);
u32 cmd_start = lc.len;
mbuf_u32(&lc, LC_LOAD_DYLIB);
diff --git a/src/link/link_reloc_layout.c b/src/link/link_reloc_layout.c
@@ -17,6 +17,7 @@
#include "core/bytes.h"
#include "core/heap.h"
#include "core/pool.h"
+#include "core/slice.h"
#include "core/util.h"
#include "core/vec.h"
#include "link/link.h"
@@ -173,7 +174,7 @@ void link_emit_tls_boundaries(Linker* l, LinkImage* img) {
u64 tdata_start = img->tls_vaddr;
u64 tdata_end = img->tls_vaddr + img->tls_filesz;
u64 tbss_size = img->tls_memsz - img->tls_filesz;
- Sym sym_size = pool_intern_cstr(l->c->global, "__tbss_size");
+ Sym sym_size = pool_intern_slice(l->c->global, SLICE_LIT("__tbss_size"));
LinkSymId id;
LinkSymbol rec;
@@ -209,10 +210,14 @@ void link_emit_encoding_section_boundaries(Linker* l, LinkImage* img) {
int found = 0;
if (sym->defined) continue;
if (sym->name == 0) continue;
- nm = pool_str(l->c->global, sym->name, &namelen);
+ {
+ Slice nm_s = pool_slice(l->c->global, sym->name);
+ nm = nm_s.s;
+ namelen = nm_s.len;
+ }
if (!link_gc_split_start_stop(nm, namelen, &off, &ilen, &is_start))
continue;
- secname = pool_intern(l->c->global, nm + off, ilen);
+ secname = pool_intern_slice(l->c->global, (Slice){ .s = nm + off, .len = ilen });
for (ii = 0; ii < LinkInputs_count(&l->inputs); ++ii) {
ObjBuilder* ob = LinkInputs_at(&l->inputs, ii)->obj;
InputMap* m = &img->input_maps[ii];
@@ -520,7 +525,7 @@ void link_layout_jit_stubs(Linker* l, LinkImage* img, u32 map_size,
stubs_sec->size = stubs_size;
stubs_sec->flags = SF_ALLOC | SF_EXEC;
stubs_sec->align = 4;
- stubs_sec->name = pool_intern_cstr(l->c->global, ".cfree_jit_call_stubs");
+ stubs_sec->name = pool_intern_slice(l->c->global, SLICE_LIT(".cfree_jit_call_stubs"));
stubs_sec->sem = SSEM_PROGBITS;
slots_sec = &img->sections[sec_base + 1u];
@@ -535,7 +540,7 @@ void link_layout_jit_stubs(Linker* l, LinkImage* img, u32 map_size,
slots_sec->size = slots_size;
slots_sec->flags = SF_ALLOC | SF_WRITE;
slots_sec->align = 8;
- slots_sec->name = pool_intern_cstr(l->c->global, ".cfree_jit_call_slots");
+ slots_sec->name = pool_intern_slice(l->c->global, SLICE_LIT(".cfree_jit_call_slots"));
slots_sec->sem = SSEM_PROGBITS;
img->nsections += 2u;
@@ -741,7 +746,7 @@ void link_layout_got(Linker* l, LinkImage* img, u32 map_size,
gotsec->size = got_size;
gotsec->flags = SF_ALLOC | SF_WRITE;
gotsec->align = 8;
- gotsec->name = pool_intern_cstr(img->c->global, ".got");
+ gotsec->name = pool_intern_slice(img->c->global, SLICE_LIT(".got"));
gotsec->sem = SSEM_PROGBITS;
img->nsections++;
@@ -842,7 +847,7 @@ void link_layout_iplt(Linker* l, LinkImage* img) {
pairs_size = (u64)nifunc * 16u;
if (emit_init_array) {
- ifunc_init_name = pool_intern_cstr(l->c->global, "__cfree_ifunc_init");
+ ifunc_init_name = pool_intern_slice(l->c->global, SLICE_LIT("__cfree_ifunc_init"));
ifunc_init_sym = symhash_get(&img->globals, ifunc_init_name);
if (ifunc_init_sym == LINK_SYM_NONE ||
!LinkSyms_at(&img->syms, ifunc_init_sym - 1)->defined) {
@@ -936,7 +941,7 @@ void link_layout_iplt(Linker* l, LinkImage* img) {
sec_base = link_iplt_alloc_sections(img, nsec);
}
- pairs_section_name = pool_intern_cstr(l->c->global, ".iplt.pairs");
+ pairs_section_name = pool_intern_slice(l->c->global, SLICE_LIT(".iplt.pairs"));
init_section_name = obj_secname_preinit_array(l->c);
iplt_sec = &img->sections[sec_base + 0u];
@@ -951,7 +956,7 @@ void link_layout_iplt(Linker* l, LinkImage* img) {
iplt_sec->size = iplt_size;
iplt_sec->flags = SF_ALLOC | SF_EXEC;
iplt_sec->align = 4;
- iplt_sec->name = pool_intern_cstr(l->c->global, ".iplt");
+ iplt_sec->name = pool_intern_slice(l->c->global, SLICE_LIT(".iplt"));
iplt_sec->sem = SSEM_PROGBITS;
igot_sec = &img->sections[sec_base + 1u];
@@ -966,7 +971,7 @@ void link_layout_iplt(Linker* l, LinkImage* img) {
igot_sec->size = igot_size;
igot_sec->flags = SF_ALLOC | SF_WRITE;
igot_sec->align = 8;
- igot_sec->name = pool_intern_cstr(l->c->global, ".igot.plt");
+ igot_sec->name = pool_intern_slice(l->c->global, SLICE_LIT(".igot.plt"));
igot_sec->sem = SSEM_PROGBITS;
pairs_sec = &img->sections[sec_base + 2u];
@@ -1170,15 +1175,17 @@ void link_resolve_entry(Linker* l, LinkImage* img) {
if (l->entry_name == 0) return;
id = symhash_get(&img->globals, l->entry_name);
if (id == LINK_SYM_NONE) {
- size_t namelen;
- const char* nm = pool_str(l->c->global, l->entry_name, &namelen);
+ Slice nm_s = pool_slice(l->c->global, l->entry_name);
+ const char* nm = nm_s.s;
+ size_t namelen = nm_s.len;
compiler_panic(l->c, no_loc(), "link: entry symbol '%.*s' not defined",
(int)namelen, nm);
}
s = LinkSyms_at(&img->syms, id - 1);
if (!s->defined) {
- size_t namelen;
- const char* nm = pool_str(l->c->global, l->entry_name, &namelen);
+ Slice nm_s = pool_slice(l->c->global, l->entry_name);
+ const char* nm = nm_s.s;
+ size_t namelen = nm_s.len;
compiler_panic(l->c, no_loc(), "link: entry symbol '%.*s' is undefined",
(int)namelen, nm);
}
diff --git a/src/link/link_relocatable.c b/src/link/link_relocatable.c
@@ -12,6 +12,7 @@
#include "core/buf.h"
#include "core/heap.h"
#include "core/pool.h"
+#include "core/slice.h"
#include "core/vec.h"
#include "link/link.h"
#include "link/link_internal.h"
@@ -171,8 +172,9 @@ static void rel_record_global(Linker* l, RelGlobal** globals, u32* nglobals,
g->def_sym = id;
} else if (new_strength == old_strength &&
new_strength == rel_bind_strength(SB_GLOBAL)) {
- size_t namelen;
- const char* nm = pool_str(l->c->global, s->name, &namelen);
+ Slice nm_s = pool_slice(l->c->global, s->name);
+ const char* nm = nm_s.s;
+ size_t namelen = nm_s.len;
obj_format_demangle_c(l->c, &nm, &namelen);
compiler_panic(l->c, no_loc(),
"link -r: duplicate definition of global symbol '%.*s'",
diff --git a/src/link/link_resolve.c b/src/link/link_resolve.c
@@ -15,6 +15,7 @@
#include "core/bytes.h"
#include "core/heap.h"
#include "core/pool.h"
+#include "core/slice.h"
#include "core/util.h"
#include "core/vec.h"
#include "link/link.h"
@@ -177,8 +178,9 @@ void link_resolve_symbols(Linker* l, LinkImage* img) {
if (s->section_id < m->nsection)
m->comdat_discarded[s->section_id] = 1;
} else {
- size_t namelen;
- const char* nm = pool_str(l->c->global, s->name, &namelen);
+ Slice nm_s = pool_slice(l->c->global, s->name);
+ const char* nm = nm_s.s;
+ size_t namelen = nm_s.len;
compiler_panic(l->c, no_loc(),
"link: duplicate definition of "
"global symbol '%.*s'",
@@ -248,10 +250,8 @@ void link_resolve_undefs(Linker* l, LinkImage* img) {
}
}
if (l->resolver && s->name != 0) {
- size_t namelen;
- const char* nm = pool_str(l->c->global, s->name, &namelen);
- (void)namelen;
- void* p = l->resolver(l->resolver_user, nm);
+ Slice nm_s = pool_slice(l->c->global, s->name);
+ void* p = l->resolver(l->resolver_user, nm_s);
if (p) {
s->kind = SK_ABS;
s->vaddr = (u64)(uintptr_t)p;
@@ -274,19 +274,20 @@ void link_resolve_undefs(Linker* l, LinkImage* img) {
* the mingw CRT — losing the aux TagIndex means we can't tell
* which side is the alias declarator. */
if (l->c->target.obj == CFREE_OBJ_COFF && s->name != 0) {
- size_t nlen;
- const char* nm = pool_str(l->c->global, s->name, &nlen);
+ Slice nm_s = pool_slice(l->c->global, s->name);
+ const char* nm = nm_s.s;
+ size_t nlen = nm_s.len;
Sym candidates[2] = {0, 0};
u32 ncand = 0;
if (nm && nlen >= 2 && nm[0] == '_') {
candidates[ncand++] =
- pool_intern(l->c->global, nm + 1, (u32)(nlen - 1u));
+ pool_intern_slice(l->c->global, (Slice){ .s = nm + 1, .len = (u32)(nlen - 1u) });
}
if (nm && nlen > 0) {
char* buf = (char*)arena_array(l->c->scratch, char, nlen + 1u);
buf[0] = '_';
memcpy(buf + 1, nm, nlen);
- candidates[ncand++] = pool_intern(l->c->global, buf, (u32)(nlen + 1u));
+ candidates[ncand++] = pool_intern_slice(l->c->global, (Slice){ .s = buf, .len = (u32)(nlen + 1u) });
}
int resolved = 0;
for (u32 ci = 0; !resolved && ci < ncand; ++ci) {
@@ -338,8 +339,9 @@ void link_resolve_undefs(Linker* l, LinkImage* img) {
* (vaddr = 0, SK_ABS) in JIT mode only; AOT lanes keep the strict
* "undefined external" semantics. */
if (l->jit_mode && s->name != 0) {
- size_t nlen;
- const char* nm = pool_str(l->c->global, s->name, &nlen);
+ Slice nm_s = pool_slice(l->c->global, s->name);
+ const char* nm = nm_s.s;
+ size_t nlen = nm_s.len;
if (nm && nlen == 15u && memcmp(nm, "__tlv_bootstrap", 15u) == 0) {
s->kind = SK_ABS;
s->vaddr = 0;
@@ -348,9 +350,9 @@ void link_resolve_undefs(Linker* l, LinkImage* img) {
}
}
{
- size_t namelen;
- const char* nm = s->name ? pool_str(l->c->global, s->name, &namelen)
- : (namelen = 0, "");
+ Slice nm_s = s->name ? pool_slice(l->c->global, s->name) : SLICE_NULL;
+ const char* nm = nm_s.s ? nm_s.s : "";
+ size_t namelen = nm_s.len;
obj_format_demangle_c(l->c, &nm, &namelen);
compiler_panic(l->c, no_loc(), "link: undefined reference to '%.*s'",
(int)namelen, nm);
@@ -558,10 +560,12 @@ void link_gc_compute(Linker* l, LinkImage* img, GcLive* g) {
tsym = LinkSyms_at(&img->syms, target - 1);
if (tsym->name != 0) {
- size_t namelen, off, ilen;
- const char* nm = pool_str(l->c->global, tsym->name, &namelen);
+ size_t off, ilen;
+ Slice nm_s = pool_slice(l->c->global, tsym->name);
+ const char* nm = nm_s.s;
+ size_t namelen = nm_s.len;
if (link_gc_split_start_stop(nm, namelen, &off, &ilen, NULL)) {
- Sym secname = pool_intern(l->c->global, nm + off, ilen);
+ Sym secname = pool_intern_slice(l->c->global, (Slice){ .s = nm + off, .len = ilen });
gc_promote_by_section_name(l, g, &q, h, secname);
}
}
@@ -749,28 +753,28 @@ void link_synth_coff_ctor_dtor_list(Linker* l) {
if (!l || l->c->target.obj != CFREE_OBJ_COFF) return;
ob = obj_new(l->c);
if (!ob) return;
- sid = obj_section_ex(ob, pool_intern_cstr(l->c->global, ".rdata$ctors"),
+ sid = obj_section_ex(ob, pool_intern_slice(l->c->global, SLICE_LIT(".rdata$ctors")),
SEC_RODATA, SSEM_PROGBITS, SF_ALLOC | SF_RETAIN, 16,
0u, 0u, 0u);
obj_section_replace_bytes(ob, sid, kZeros, sizeof(kZeros));
- obj_symbol_ex(ob, pool_intern_cstr(l->c->global, "__CTOR_LIST__"),
+ obj_symbol_ex(ob, pool_intern_slice(l->c->global, SLICE_LIT("__CTOR_LIST__")),
SB_GLOBAL, SV_DEFAULT, SK_OBJ, sid, 0, 0, 0);
- obj_symbol_ex(ob, pool_intern_cstr(l->c->global, "__CTOR_END__"),
+ obj_symbol_ex(ob, pool_intern_slice(l->c->global, SLICE_LIT("__CTOR_END__")),
SB_GLOBAL, SV_DEFAULT, SK_OBJ, sid, 0, 0, 0);
- obj_symbol_ex(ob, pool_intern_cstr(l->c->global, "__DTOR_LIST__"),
+ obj_symbol_ex(ob, pool_intern_slice(l->c->global, SLICE_LIT("__DTOR_LIST__")),
SB_GLOBAL, SV_DEFAULT, SK_OBJ, sid, 0, 0, 0);
- obj_symbol_ex(ob, pool_intern_cstr(l->c->global, "__DTOR_END__"),
+ obj_symbol_ex(ob, pool_intern_slice(l->c->global, SLICE_LIT("__DTOR_END__")),
SB_GLOBAL, SV_DEFAULT, SK_OBJ, sid, 0, 0, 0);
/* __chkstk: only the aa64 variant is synthesized here; x64 codegen
* already emits inline probes (or links libmingwex's __chkstk
* which is a plain object, not an ARM64EC alias). */
if (l->c->target.arch == CFREE_ARCH_ARM_64) {
ObjSecId tsid =
- obj_section_ex(ob, pool_intern_cstr(l->c->global, ".text$chkstk"),
+ obj_section_ex(ob, pool_intern_slice(l->c->global, SLICE_LIT(".text$chkstk")),
SEC_TEXT, SSEM_PROGBITS,
SF_ALLOC | SF_EXEC | SF_RETAIN, 4, 0u, 0u, 0u);
obj_section_replace_bytes(ob, tsid, kAa64Chkstk, sizeof(kAa64Chkstk));
- obj_symbol_ex(ob, pool_intern_cstr(l->c->global, "__chkstk"), SB_GLOBAL,
+ obj_symbol_ex(ob, pool_intern_slice(l->c->global, SLICE_LIT("__chkstk")), SB_GLOBAL,
SV_DEFAULT, SK_FUNC, tsid, 0, sizeof(kAa64Chkstk), 0);
}
obj_finalize(ob);
@@ -780,7 +784,7 @@ void link_synth_coff_ctor_dtor_list(Linker* l) {
in->kind = LINK_INPUT_OBJ_BYTES;
in->order = l->next_input_order++;
in->obj = ob;
- in->name = pool_intern_cstr(l->c->global, "<cfree-synth-coff-runtime>");
+ in->name = pool_intern_slice(l->c->global, SLICE_LIT("<cfree-synth-coff-runtime>"));
in->soname = 0;
}
@@ -804,7 +808,7 @@ void link_ingest_archives(Linker* l) {
Sym want_ifunc_init = 0;
if (ar->whole_archive) continue;
if (l->emit_static_exe && inputs_have_defined_ifunc_before(l, ar->order))
- want_ifunc_init = pool_intern_cstr(l->c->global, "__cfree_ifunc_init");
+ want_ifunc_init = pool_intern_slice(l->c->global, SLICE_LIT("__cfree_ifunc_init"));
for (;;) {
SymHash defined, undefs;
int changed = 0;
diff --git a/src/link/link_script.c b/src/link/link_script.c
@@ -26,7 +26,7 @@
* - An output section's `: ALIGN(N)` header is encoded as the first
* entry in its asns[]: a dot-assignment whose expr is ALIGN(., N).
* - `*(p1 p2 ...)` produces one CfreeLinkInputMatch per pattern with
- * file_pattern = NULL (implicit `*`) and section_pattern set.
+ * file_pattern = empty slice (implicit `*`) and section_pattern set.
* COMMON is parsed as a literal pattern "COMMON".
*
* Allocation: every node and string is owned by the compiler's tu arena.
@@ -48,6 +48,7 @@
#include "core/core.h"
#include "core/diag.h"
#include "core/heap.h"
+#include "core/slice.h"
/* The public CfreeLinkScript has no place to carry its backing-arena
* pointer, so we allocate a fixed-shape owner block via heap and arena-
@@ -111,6 +112,16 @@ static char* lsp_strdup(LSP* p, const char* s, size_t n) {
return arena_strdup(p->arena, s, n);
}
+/* Arena-copy a span of the script text and return a CfreeSlice over the
+ * copy. The copy is NUL-terminated (arena_strdup), so consumers that hit
+ * a host boundary can use .s directly. */
+static CfreeSlice lsp_slice(LSP* p, const char* s, size_t n) {
+ CfreeSlice out;
+ out.s = lsp_strdup(p, s, n);
+ out.len = out.s ? n : 0;
+ return out;
+}
+
static CfreeLinkExpr* lsp_new_expr(LSP* p) {
return arena_znew(p->arena, CfreeLinkExpr);
}
@@ -235,7 +246,7 @@ static int lex_ident(LSP* p, const char** out, size_t* out_len) {
/* Match a literal keyword. Caller must have already peeked. */
static int match_kw(LSP* p, const char* kw) {
- size_t klen = strlen(kw);
+ size_t klen = slice_from_cstr(kw).len;
size_t save;
skip_ws(p);
if (p->err) return 0;
@@ -377,7 +388,7 @@ static CfreeLinkExpr* parse_atom(LSP* p) {
e = lsp_new_expr(p);
if (!e) return NULL;
e->kind = CFREE_LE_SYM;
- e->v.name = lsp_strdup(p, s, n);
+ e->v.name = lsp_slice(p, s, n);
return e;
}
}
@@ -497,7 +508,7 @@ static int push_dot_align(LSP* p, VecAsn* asns, CfreeLinkExpr* align_n) {
aln->v.align.val = dot;
aln->v.align.align = align_n;
a.kind = CFREE_LAS_DOT;
- a.sym = NULL;
+ a.sym = CFREE_SLICE_NULL;
a.expr = aln;
return VEC_PUSH(p, *asns, a);
}
@@ -540,8 +551,8 @@ static int parse_input_matchers(LSP* p, VecMatch* out) {
return 1;
}
s = p->src + start;
- m.file_pattern = NULL;
- m.section_pattern = lsp_strdup(p, s, n);
+ m.file_pattern = CFREE_SLICE_NULL;
+ m.section_pattern = lsp_slice(p, s, n);
m.keep = 0;
if (VEC_PUSH(p, *out, m)) return 1;
}
@@ -585,7 +596,7 @@ static int parse_section_body(LSP* p, VecMatch* inputs, VecAsn* asns) {
if (!match_ch(p, ';')) { /* ; is optional but encouraged */
}
a.kind = CFREE_LAS_DOT;
- a.sym = NULL;
+ a.sym = CFREE_SLICE_NULL;
a.expr = e;
if (VEC_PUSH(p, *asns, a)) return 1;
}
@@ -612,7 +623,7 @@ static int parse_section_body(LSP* p, VecMatch* inputs, VecAsn* asns) {
if (!e) return 1;
(void)match_ch(p, ';');
a.kind = CFREE_LAS_SYM;
- a.sym = lsp_strdup(p, s, n);
+ a.sym = lsp_slice(p, s, n);
a.expr = e;
if (VEC_PUSH(p, *asns, a)) return 1;
continue;
@@ -679,7 +690,7 @@ static int parse_output_section(LSP* p, const char* name_buf, size_t name_len,
memcpy(arr_as, asns.p, sizeof(*arr_as) * asns.n);
}
memset(&sec, 0, sizeof(sec));
- sec.name = lsp_strdup(p, name_buf, name_len);
+ sec.name = lsp_slice(p, name_buf, name_len);
sec.inputs = arr_in;
sec.ninputs = inputs.n;
sec.asns = arr_as;
@@ -749,7 +760,7 @@ static int parse_sections_block(LSP* p, VecAsn* top_asns, VecSec* sections) {
if (!e) return 1;
(void)match_ch(p, ';');
a.kind = CFREE_LAS_DOT;
- a.sym = NULL;
+ a.sym = CFREE_SLICE_NULL;
a.expr = e;
if (VEC_PUSH(p, *top_asns, a)) return 1;
}
@@ -781,7 +792,7 @@ static int parse_sections_block(LSP* p, VecAsn* top_asns, VecSec* sections) {
if (!e) return 1;
(void)match_ch(p, ';');
a.kind = CFREE_LAS_SYM;
- a.sym = lsp_strdup(p, s, n);
+ a.sym = lsp_slice(p, s, n);
a.expr = e;
if (VEC_PUSH(p, *top_asns, a)) return 1;
continue;
@@ -802,7 +813,7 @@ static int parse_sections_block(LSP* p, VecAsn* top_asns, VecSec* sections) {
static int parse_top(LSP* p, CfreeLinkScript* out) {
VecAsn top_asns = {0};
VecSec sections = {0};
- const char* entry_name = NULL;
+ CfreeSlice entry_name = CFREE_SLICE_NULL;
int saw_sections = 0;
int rc = 1;
@@ -821,8 +832,8 @@ static int parse_top(LSP* p, CfreeLinkScript* out) {
if (lex_ident(p, &s, &n)) goto done;
if (expect_ch(p, ')')) goto done;
(void)match_ch(p, ';');
- entry_name = lsp_strdup(p, s, n);
- if (!entry_name) goto done;
+ entry_name = lsp_slice(p, s, n);
+ if (!entry_name.s) goto done;
continue;
}
if (match_kw(p, "SECTIONS")) {
@@ -886,8 +897,8 @@ done:
/* ---- public API ---- */
-CfreeStatus cfree_link_script_parse(const CfreeContext* ctx, const char* text,
- size_t len, CfreeLinkScript** out) {
+CfreeStatus cfree_link_script_parse(const CfreeContext* ctx, CfreeSlice text,
+ CfreeLinkScript** out) {
ScriptOwner* owner;
LSP p;
int rc;
@@ -895,7 +906,7 @@ CfreeStatus cfree_link_script_parse(const CfreeContext* ctx, const char* text,
if (!out) return CFREE_INVALID;
*out = NULL;
- if (!ctx || !ctx->heap || !text) return CFREE_INVALID;
+ if (!ctx || !ctx->heap || !text.s) return CFREE_INVALID;
h = ctx->heap;
owner = (ScriptOwner*)h->alloc(h, sizeof(*owner), _Alignof(ScriptOwner));
@@ -909,8 +920,8 @@ CfreeStatus cfree_link_script_parse(const CfreeContext* ctx, const char* text,
p.arena = &owner->arena;
p.heap = h;
p.diag = ctx->diag;
- p.src = text;
- p.len = len;
+ p.src = text.s;
+ p.len = text.len;
rc = parse_top(&p, &owner->script);
if (rc != 0 || p.err) {
diff --git a/src/obj/coff_emit.c b/src/obj/coff_emit.c
@@ -40,6 +40,7 @@
#include "core/buf.h"
#include "core/heap.h"
#include "core/pool.h"
+#include "core/slice.h"
#include "core/util.h"
#include "obj/coff.h"
@@ -240,13 +241,13 @@ static void wr_aux_weak(u8* dst, u32 TagIndex, u32 Characteristics) {
/* Look up the pool-interned string for a Sym. */
static const char* sym_to_str(Compiler* c, Sym n, u32* len_out) {
- size_t len;
- const char* s = pool_str(c->global, n, &len);
+ Slice sl = pool_slice(c->global, n);
+ const char* s = sl.s;
if (!s) {
*len_out = 0;
return "";
}
- *len_out = (u32)len;
+ *len_out = (u32)sl.len;
return s;
}
diff --git a/src/obj/coff_read.c b/src/obj/coff_read.c
@@ -20,6 +20,7 @@
#include "core/arena.h"
#include "core/heap.h"
#include "core/pool.h"
+#include "core/slice.h"
#include "obj/coff.h"
static SrcLoc no_loc(void) {
@@ -205,10 +206,11 @@ static ObjBuilder* read_coff_short_import(Compiler* c, const char* name,
if (name_type == IMPORT_OBJECT_ORDINAL)
compiler_panic(c, no_loc(),
"read_coff: short-import by ordinal not implemented "
- "(archive member \"%s\", ordinal %u). cfree links "
+ "(archive member \"%.*s\", ordinal %u). cfree links "
"imports by name only; rebuild the consumer to import "
"by name, or omit this archive from the link.",
- name ? name : "<unnamed>",
+ SLICE_ARG(name ? slice_from_cstr(name)
+ : SLICE_LIT("<unnamed>")),
(unsigned)ordinal_or_hint);
/* Symbol name: NUL-terminated starting at data + 20. */
@@ -243,7 +245,8 @@ static ObjBuilder* read_coff_short_import(Compiler* c, const char* name,
* shape read_coff_dso would produce for a DLL export. */
SymKind k = (import_type == IMPORT_OBJECT_CODE) ? SK_FUNC : SK_OBJ;
- Sym sn = pool_intern(c->global, (const char*)body, sym_name_len);
+ Sym sn = pool_intern_slice(
+ c->global, (Slice){ .s = (const char*)body, .len = sym_name_len });
ObjSymId id = obj_symbol_ex(ob, sn, SB_GLOBAL, SV_DEFAULT, k, OBJ_SEC_NONE,
0, 0, 0);
obj_sym_mark_referenced(ob, id);
@@ -257,14 +260,16 @@ static ObjBuilder* read_coff_short_import(Compiler* c, const char* name,
char* imp_buf = arena_array(c->scratch, char, imp_len);
memcpy(imp_buf, kImpPrefix, sizeof kImpPrefix - 1u);
memcpy(imp_buf + (sizeof kImpPrefix - 1u), body, sym_name_len);
- Sym imp_sn = pool_intern(c->global, imp_buf, imp_len);
+ Sym imp_sn =
+ pool_intern_slice(c->global, (Slice){ .s = imp_buf, .len = imp_len });
ObjSymId imp_id = obj_symbol_ex(ob, imp_sn, SB_GLOBAL, SV_DEFAULT, SK_OBJ,
OBJ_SEC_NONE, 0, 0, 0);
obj_sym_mark_referenced(ob, imp_id);
/* Stash the DLL name so the archive-ingestion layer (Phase 4.3) can
* route this builder as a DSO with the DLL as soname. */
- Sym dll_sn = pool_intern(c->global, (const char*)dll_p, dll_name_len);
+ Sym dll_sn = pool_intern_slice(
+ c->global, (Slice){ .s = (const char*)dll_p, .len = dll_name_len });
obj_set_coff_import_dll(ob, dll_sn);
(void)name_type;
@@ -361,7 +366,7 @@ ObjBuilder* read_coff(Compiler* c, const char* name, const u8* data,
const char* nm;
u32 nlen;
resolve_section_name(s->raw_name, strtab, strtab_size, &nm, &nlen);
- Sym sn = pool_intern(c->global, nm, nlen);
+ Sym sn = pool_intern_slice(c->global, (Slice){ .s = nm, .len = nlen });
u16 kind = coff_sec_kind(nm, nlen, s->characteristics);
u16 flags = coff_sec_flags(nm, nlen, s->characteristics);
@@ -448,7 +453,9 @@ ObjBuilder* read_coff(Compiler* c, const char* name, const u8* data,
fnm = (const char*)aux;
fnlen = n;
}
- Sym fsn = fnlen ? pool_intern(c->global, fnm, fnlen) : 0;
+ Sym fsn = fnlen ? pool_intern_slice(
+ c->global, (Slice){ .s = fnm, .len = fnlen })
+ : 0;
ObjSymId id = obj_symbol_ex(ob, fsn, SB_LOCAL, SV_DEFAULT, SK_FILE,
OBJ_SEC_NONE, 0, 0, 0);
obj_sym_mark_referenced(ob, id);
@@ -561,7 +568,8 @@ ObjBuilder* read_coff(Compiler* c, const char* name, const u8* data,
* resolution by name and we drop the explicit index. */
if (sclass == IMAGE_SYM_CLASS_WEAK_EXTERNAL) bind = SB_WEAK;
- Sym sn = nlen ? pool_intern(c->global, nm, nlen) : 0;
+ Sym sn = nlen ? pool_intern_slice(c->global, (Slice){ .s = nm, .len = nlen })
+ : 0;
ObjSymId id = obj_symbol_ex(ob, sn, bind, vis, kind, target_sec, sym_value,
sym_size, cmnalign);
obj_sym_mark_referenced(ob, id);
diff --git a/src/obj/coff_read_dso.c b/src/obj/coff_read_dso.c
@@ -24,6 +24,7 @@
#include "core/arena.h"
#include "core/heap.h"
#include "core/pool.h"
+#include "core/slice.h"
#include "obj/coff.h"
static SrcLoc no_loc(void) {
@@ -180,7 +181,7 @@ ObjBuilder* read_coff_dso(Compiler* c, const char* name, const u8* data,
const char* dll_name;
u32 nlen = read_cstr(data, len, name_off, &dll_name);
if (nlen && soname_out)
- *soname_out = pool_intern(c->global, dll_name, nlen);
+ *soname_out = pool_intern_slice(c->global, (Slice){ .s = dll_name, .len = nlen });
}
/* ---- resolve EAT / ENT / ordinal table once ---- */
@@ -224,7 +225,7 @@ ObjBuilder* read_coff_dso(Compiler* c, const char* name, const u8* data,
u32 nlen = read_cstr(data, len, name_off, &nm);
if (!nlen) continue;
- Sym sn = pool_intern(c->global, nm, nlen);
+ Sym sn = pool_intern_slice(c->global, (Slice){ .s = nm, .len = nlen });
ObjSymId id = obj_symbol(ob, sn, SB_GLOBAL, SK_FUNC,
OBJ_SEC_NONE, 0, 0);
obj_sym_mark_referenced(ob, id);
diff --git a/src/obj/elf_emit.c b/src/obj/elf_emit.c
@@ -32,6 +32,7 @@
#include "core/buf.h"
#include "core/heap.h"
#include "core/pool.h"
+#include "core/slice.h"
#include "core/util.h"
#include "obj/elf.h"
@@ -187,13 +188,13 @@ static u16 sym_shndx(const ObjSym* s, const u32* obj_to_elf, u32 nsec) {
}
static const char* sym_to_str(Compiler* c, Sym n, u32* len_out) {
- size_t len;
- const char* s = pool_str(c->global, n, &len);
+ Slice sl = pool_slice(c->global, n);
+ const char* s = sl.s;
if (!s) {
*len_out = 0;
return "";
}
- *len_out = (u32)len;
+ *len_out = (u32)sl.len;
return s;
}
diff --git a/src/obj/elf_read.c b/src/obj/elf_read.c
@@ -13,6 +13,7 @@
#include "arch/arch.h"
#include "core/heap.h"
#include "core/pool.h"
+#include "core/slice.h"
#include "obj/elf.h"
static SrcLoc no_loc(void) {
@@ -181,7 +182,7 @@ static u8 elf_other_to_vis(u32 other) {
/* Bounds-checked C-string slice from a strtab section. Returns "" on
* out-of-range so callers don't have to special-case it. `len_out` is
- * set to strlen(result). */
+ * set to the result's byte length. */
static const char* strtab_lookup(const u8* tab, u64 tab_size, u32 off,
u32* len_out) {
if (off >= tab_size) {
@@ -286,7 +287,7 @@ ObjBuilder* read_elf(Compiler* c, const char* name, const u8* data,
u32 nlen;
const char* nm = strtab_lookup(shstrtab, shstrtab_sz, sh->sh_name, &nlen);
- Sym sym = pool_intern(c->global, nm, nlen);
+ Sym sym = pool_intern_slice(c->global, (Slice){ .s = nm, .len = nlen });
u16 sec_kind = elf_kind_from_name(nm, nlen, sh->sh_flags, sh->sh_type);
int type_known;
@@ -298,8 +299,8 @@ ObjBuilder* read_elf(Compiler* c, const char* name, const u8* data,
obj_section_ex(ob, sym, (SecKind)sec_kind, (SecSem)sec_sem, flags,
align, (u32)sh->sh_entsize, sh->sh_link, sh->sh_info);
if (id == OBJ_SEC_NONE)
- compiler_panic(c, no_loc(), "read_elf: obj_section_ex failed for '%s'",
- nm);
+ compiler_panic(c, no_loc(), "read_elf: obj_section_ex failed for '%.*s'",
+ SLICE_ARG(((Slice){.s = nm, .len = nlen})));
elf_to_obj[i] = id;
/* Preserve format-specific bits the canonical SecSem/SecFlag
@@ -317,8 +318,9 @@ ObjBuilder* read_elf(Compiler* c, const char* name, const u8* data,
obj_reserve_bss(ob, id, (u32)sh->sh_size, align);
} else if (sh->sh_size) {
if (sh->sh_offset + sh->sh_size > len)
- compiler_panic(c, no_loc(), "read_elf: section '%s' bytes out of range",
- nm);
+ compiler_panic(c, no_loc(),
+ "read_elf: section '%.*s' bytes out of range",
+ SLICE_ARG(((Slice){.s = nm, .len = nlen})));
/* For SYMTAB/STRTAB/RELA we still copy the raw bytes — the
* post-finalize shape contract says these sections are
* present; emit_elf will regenerate them on re-emit, so the
@@ -375,7 +377,7 @@ ObjBuilder* read_elf(Compiler* c, const char* name, const u8* data,
u32 nlen;
const char* nm = strtab_lookup(strtab, strtab_sz, st_name, &nlen);
- Sym sn = nlen ? pool_intern(c->global, nm, nlen) : 0;
+ Sym sn = nlen ? pool_intern_slice(c->global, (Slice){ .s = nm, .len = nlen }) : 0;
u32 e_bind = ELF64_ST_BIND(st_info);
u32 e_type = ELF64_ST_TYPE(st_info);
@@ -468,7 +470,7 @@ ObjBuilder* read_elf(Compiler* c, const char* name, const u8* data,
u32 nm_len;
const char* gnm =
strtab_lookup(shstrtab, shstrtab_sz, sh->sh_name, &nm_len);
- Sym gname = pool_intern(c->global, gnm, nm_len);
+ Sym gname = pool_intern_slice(c->global, (Slice){ .s = gnm, .len = nm_len });
ObjSymId signature = OBJ_SYM_NONE;
if (sym_elf_to_obj && sh->sh_info < nsyms)
@@ -607,7 +609,7 @@ ObjBuilder* read_elf_dso(Compiler* c, const char* name, const u8* data,
if (tag == DT_SONAME) {
u32 nlen;
const char* nm = strtab_lookup(dynstr, dynstr_sz, (u32)val, &nlen);
- if (nlen) soname = pool_intern(c->global, nm, nlen);
+ if (nlen) soname = pool_intern_slice(c->global, (Slice){ .s = nm, .len = nlen });
break;
}
}
@@ -660,7 +662,7 @@ ObjBuilder* read_elf_dso(Compiler* c, const char* name, const u8* data,
u32 nlen;
const char* nm = strtab_lookup(strtab, strtab_sz, st_name, &nlen);
if (!nlen) continue;
- Sym sn = pool_intern(c->global, nm, nlen);
+ Sym sn = pool_intern_slice(c->global, (Slice){ .s = nm, .len = nlen });
u32 e_type_field = ELF64_ST_TYPE(st_info);
u16 bind = elf_bind_to_obj(e_bind);
diff --git a/src/obj/macho_emit.c b/src/obj/macho_emit.c
@@ -31,6 +31,7 @@
#include "core/bytes.h"
#include "core/heap.h"
#include "core/pool.h"
+#include "core/slice.h"
#include "core/util.h"
#include "obj/macho.h"
@@ -122,7 +123,8 @@ static void name_to_seg_sect(const char* name, u32 nlen, u16 sec_kind,
/* Strip a leading `.` from the input name (".debug_info" →
* "__debug_info") so the dwarf section names round-trip. */
sect = (nlen && name[0] == '.') ? name + 1 : name;
- copy_fixed16(out->segname, &out->seg_len, seg, (u32)strlen(seg));
+ copy_fixed16(out->segname, &out->seg_len, seg,
+ (u32)slice_from_cstr(seg).len);
copy_fixed16(out->sectname, &out->sect_len, sect,
(u32)((nlen && name[0] == '.') ? nlen - 1 : nlen));
return;
@@ -131,8 +133,9 @@ static void name_to_seg_sect(const char* name, u32 nlen, u16 sec_kind,
sect = "__data";
break;
}
- copy_fixed16(out->segname, &out->seg_len, seg, (u32)strlen(seg));
- copy_fixed16(out->sectname, &out->sect_len, sect, (u32)strlen(sect));
+ copy_fixed16(out->segname, &out->seg_len, seg, (u32)slice_from_cstr(seg).len);
+ copy_fixed16(out->sectname, &out->sect_len, sect,
+ (u32)slice_from_cstr(sect).len);
}
/* ---- per-section plan ---- */
@@ -265,8 +268,9 @@ void emit_macho(Compiler* c, ObjBuilder* ob, Writer* w) {
s->sem == SSEM_GROUP) {
continue;
}
- size_t nlen;
- const char* nm = pool_str(c->global, s->name, &nlen);
+ Slice nm_s = pool_slice(c->global, s->name);
+ const char* nm = nm_s.s;
+ size_t nlen = nm_s.len;
MSec* m = &secs[nsecs];
name_to_seg_sect(nm ? nm : "", (u32)nlen, s->kind, &m->ns);
m->obj_sec = i;
@@ -369,8 +373,9 @@ void emit_macho(Compiler* c, ObjBuilder* ob, Writer* w) {
MSym* ms = &msyms[nmsyms];
ms->obj_id = e.id;
- size_t nlen;
- const char* nm = pool_str(c->global, s->name, &nlen);
+ Slice nm_s = pool_slice(c->global, s->name);
+ const char* nm = nm_s.s;
+ size_t nlen = nm_s.len;
/* Mach-O symbol names are stored on disk verbatim — including
* the leading `_` Apple toolchains use for C-source-level
* symbols ("_main" for `int main()`). cfree treats the prefix
diff --git a/src/obj/macho_read.c b/src/obj/macho_read.c
@@ -16,6 +16,7 @@
#include "core/bytes.h"
#include "core/heap.h"
#include "core/pool.h"
+#include "core/slice.h"
#include "core/util.h"
#include "obj/macho.h"
@@ -194,7 +195,7 @@ ObjBuilder* read_macho(Compiler* c, const char* name, const u8* data,
nmbuf[nlen++] = ',';
memcpy(nmbuf + nlen, m->sectname, m->sect_len);
nlen += m->sect_len;
- Sym sn = pool_intern(c->global, nmbuf, nlen);
+ Sym sn = pool_intern_slice(c->global, (Slice){ .s = nmbuf, .len = nlen });
u16 kind = sec_kind_from_seg_sect(m->segname, m->seg_len, m->sectname,
m->sect_len, m->flags);
@@ -249,7 +250,7 @@ ObjBuilder* read_macho(Compiler* c, const char* name, const u8* data,
* `test_main` ↔ `_test_main` mapping for API callers) happens
* one layer up at the linker API boundary (link_c_name_intern
* in link.c); the on-disk shape stays byte-for-byte stable. */
- Sym sn = nlen ? pool_intern(c->global, nm, nlen) : 0;
+ Sym sn = nlen ? pool_intern_slice(c->global, (Slice){ .s = nm, .len = nlen }) : 0;
u8 type_field = (u8)(n_type & N_TYPE);
u8 ext = (u8)(n_type & N_EXT);
@@ -473,7 +474,7 @@ ObjBuilder* read_macho(Compiler* c, const char* name, const u8* data,
} while (v);
for (u32 k = 0; k < dn; ++k) nmbuf[nlen + k] = dec[dn - 1 - k];
nlen += dn;
- Sym sn = pool_intern(c->global, nmbuf, nlen);
+ Sym sn = pool_intern_slice(c->global, (Slice){ .s = nmbuf, .len = nlen });
u16 sk = (tm->flags & S_ATTR_PURE_INSTRUCTIONS) ? SK_FUNC : SK_OBJ;
sec_start_sym[sec_idx] = obj_symbol(ob, sn, SB_LOCAL, (SymKind)sk,
tm->obj_sec, 0, 0);
@@ -573,7 +574,7 @@ ObjBuilder* read_macho_dso(Compiler* c, const char* name, const u8* data,
u32 maxlen = cmdsize - nm_off;
u32 nlen = 0;
while (nlen < maxlen && p[nlen]) ++nlen;
- if (nlen) install_name = pool_intern(c->global, p, nlen);
+ if (nlen) install_name = pool_intern_slice(c->global, (Slice){ .s = p, .len = nlen });
} else if (cmd == LC_SYMTAB) {
symoff = rd_u32_le(data + pos + 8);
nsyms = rd_u32_le(data + pos + 12);
@@ -614,7 +615,7 @@ ObjBuilder* read_macho_dso(Compiler* c, const char* name, const u8* data,
u32 nlen = 0;
while (strx + nlen < strsize && nm[nlen]) ++nlen;
if (!nlen) continue;
- Sym sn = pool_intern(c->global, nm, nlen);
+ Sym sn = pool_intern_slice(c->global, (Slice){ .s = nm, .len = nlen });
SymBind bind = (n_desc & (N_WEAK_DEF | N_WEAK_REF)) ? SB_WEAK : SB_GLOBAL;
SymKind kind = SK_NOTYPE;
diff --git a/src/obj/obj_secnames.c b/src/obj/obj_secnames.c
@@ -24,26 +24,27 @@
#include "core/core.h"
#include "core/heap.h"
#include "core/pool.h"
+#include "core/slice.h"
static Sym secname_panic_unimpl(Compiler* c, const char* which) {
SrcLoc l = {0, 0, 0};
compiler_panic(c, l,
- "obj section name '%s' for target obj=%u not yet "
+ "obj section name '%.*s' for target obj=%u not yet "
"implemented",
- which, (unsigned)c->target.obj);
+ SLICE_ARG(slice_from_cstr(which)), (unsigned)c->target.obj);
return 0;
}
Sym obj_secname_init_array(Compiler* c) {
switch (c->target.obj) {
case CFREE_OBJ_ELF:
- return pool_intern_cstr(c->global, ".init_array");
+ return pool_intern_slice(c->global, SLICE_LIT(".init_array"));
case CFREE_OBJ_MACHO:
- return pool_intern_cstr(c->global, "__DATA,__mod_init_func");
+ return pool_intern_slice(c->global, SLICE_LIT("__DATA,__mod_init_func"));
case CFREE_OBJ_COFF:
/* CRT runtime scans `.CRT$X[A-Z]` for ctor/dtor tables; XCU is
* the user-constructor bucket. See doc/WINDOWS.md §1.6. */
- return pool_intern_cstr(c->global, ".CRT$XCU");
+ return pool_intern_slice(c->global, SLICE_LIT(".CRT$XCU"));
default:
return secname_panic_unimpl(c, ".init_array");
}
@@ -52,13 +53,13 @@ Sym obj_secname_init_array(Compiler* c) {
Sym obj_secname_fini_array(Compiler* c) {
switch (c->target.obj) {
case CFREE_OBJ_ELF:
- return pool_intern_cstr(c->global, ".fini_array");
+ return pool_intern_slice(c->global, SLICE_LIT(".fini_array"));
case CFREE_OBJ_MACHO:
- return pool_intern_cstr(c->global, "__DATA,__mod_term_func");
+ return pool_intern_slice(c->global, SLICE_LIT("__DATA,__mod_term_func"));
case CFREE_OBJ_COFF:
/* `.CRT$XPA`/`XPZ` are markers; XPU is the user-destructor
* bucket. See doc/WINDOWS.md §1.6. */
- return pool_intern_cstr(c->global, ".CRT$XPU");
+ return pool_intern_slice(c->global, SLICE_LIT(".CRT$XPU"));
default:
return secname_panic_unimpl(c, ".fini_array");
}
@@ -67,7 +68,7 @@ Sym obj_secname_fini_array(Compiler* c) {
Sym obj_secname_preinit_array(Compiler* c) {
switch (c->target.obj) {
case CFREE_OBJ_ELF:
- return pool_intern_cstr(c->global, ".preinit_array");
+ return pool_intern_slice(c->global, SLICE_LIT(".preinit_array"));
case CFREE_OBJ_MACHO:
/* Mach-O has no direct `.preinit_array` analogue — dyld runs
* S_MOD_INIT_FUNC_POINTERS only. Phase 3 of the linker will
@@ -78,7 +79,7 @@ Sym obj_secname_preinit_array(Compiler* c) {
case CFREE_OBJ_COFF:
/* CRT's own setup runs in `.CRT$XI*`; user pre-init lives at
* XIA just after the CRT. See doc/WINDOWS.md §1.6. */
- return pool_intern_cstr(c->global, ".CRT$XIA");
+ return pool_intern_slice(c->global, SLICE_LIT(".CRT$XIA"));
default:
return secname_panic_unimpl(c, ".preinit_array");
}
@@ -87,13 +88,13 @@ Sym obj_secname_preinit_array(Compiler* c) {
Sym obj_secname_tdata(Compiler* c) {
switch (c->target.obj) {
case CFREE_OBJ_ELF:
- return pool_intern_cstr(c->global, ".tdata");
+ return pool_intern_slice(c->global, SLICE_LIT(".tdata"));
case CFREE_OBJ_MACHO:
- return pool_intern_cstr(c->global, "__DATA,__thread_data");
+ return pool_intern_slice(c->global, SLICE_LIT("__DATA,__thread_data"));
case CFREE_OBJ_COFF:
/* MSVC `.tls$` convention; linker concatenates `.tls$*` sorted
* by suffix. See doc/WINDOWS.md §1.6. */
- return pool_intern_cstr(c->global, ".tls$");
+ return pool_intern_slice(c->global, SLICE_LIT(".tls$"));
default:
return secname_panic_unimpl(c, ".tdata");
}
@@ -102,13 +103,13 @@ Sym obj_secname_tdata(Compiler* c) {
Sym obj_secname_tbss(Compiler* c) {
switch (c->target.obj) {
case CFREE_OBJ_ELF:
- return pool_intern_cstr(c->global, ".tbss");
+ return pool_intern_slice(c->global, SLICE_LIT(".tbss"));
case CFREE_OBJ_MACHO:
- return pool_intern_cstr(c->global, "__DATA,__thread_bss");
+ return pool_intern_slice(c->global, SLICE_LIT("__DATA,__thread_bss"));
case CFREE_OBJ_COFF:
/* sorted-alphabetically-last so it falls at the tail of the TLS
* image's zero-fill region. See doc/WINDOWS.md §1.6. */
- return pool_intern_cstr(c->global, ".tls$ZZZ");
+ return pool_intern_slice(c->global, SLICE_LIT(".tls$ZZZ"));
default:
return secname_panic_unimpl(c, ".tbss");
}
@@ -155,16 +156,17 @@ Sym obj_format_c_mangle(Compiler* c, const char* name) {
SrcLoc loc = {0, 0, 0};
if (!c || !name) return 0;
if (c->target.obj != CFREE_OBJ_MACHO)
- return pool_intern_cstr(c->global, name);
- n = strlen(name);
+ return pool_intern_slice(c->global, slice_from_cstr(name));
+ n = slice_from_cstr(name).len;
h = (Heap*)c->ctx->heap;
buf = (char*)h->alloc(h, n + 2u, 1);
if (!buf)
- compiler_panic(c, loc, "obj_format_c_mangle: oom prefixing '%s'", name);
+ compiler_panic(c, loc, "obj_format_c_mangle: oom prefixing '%.*s'",
+ SLICE_ARG(slice_from_cstr(name)));
buf[0] = '_';
memcpy(buf + 1, name, n);
buf[n + 1] = 0;
- s = pool_intern(c->global, buf, (u32)(n + 1u));
+ s = pool_intern_slice(c->global, (Slice){ .s = buf, .len = (u32)(n + 1u) });
h->free(h, buf, n + 2u);
return s;
}
diff --git a/src/obj/obj_tls.c b/src/obj/obj_tls.c
@@ -35,6 +35,7 @@
#include "core/core.h"
#include "core/heap.h"
#include "core/pool.h"
+#include "core/slice.h"
/* ObjBuilder is opaque outside obj.c; obj_tls.c reaches the bootstrap
* cache via these accessors defined in obj.c. Declared here to avoid
@@ -80,15 +81,16 @@ static ObjSymId tlv_bootstrap(ObjBuilder* ob, Compiler* c) {
if (s != OBJ_SYM_NONE) return s;
/* On-disk name carries the Mach-O leading underscore: source-level
* `_tlv_bootstrap` becomes `__tlv_bootstrap`. */
- Sym name = pool_intern_cstr(c->global, "__tlv_bootstrap");
+ Sym name = pool_intern_slice(c->global, SLICE_LIT("__tlv_bootstrap"));
s = obj_symbol(ob, name, SB_GLOBAL, SK_UNDEF, OBJ_SEC_NONE, 0, 0);
obj_tlv_bootstrap_set(ob, s);
return s;
}
static ObjSymId mint_init_sym(ObjBuilder* ob, Compiler* c, Sym desc_name) {
- size_t nlen = 0;
- const char* nm = pool_str(c->global, desc_name, &nlen);
+ Slice nm_s = pool_slice(c->global, desc_name);
+ const char* nm = nm_s.s;
+ size_t nlen = nm_s.len;
static const char suffix[] = "$tlv$init";
size_t slen = sizeof(suffix) - 1u;
Heap* h = (Heap*)c->ctx->heap;
@@ -98,7 +100,7 @@ static ObjSymId mint_init_sym(ObjBuilder* ob, Compiler* c, Sym desc_name) {
if (nlen) memcpy(buf, nm, nlen);
memcpy(buf + nlen, suffix, slen);
buf[nlen + slen] = 0;
- Sym n = pool_intern(c->global, buf, (u32)(nlen + slen));
+ Sym n = pool_intern_slice(c->global, (Slice){ .s = buf, .len = (u32)(nlen + slen) });
h->free(h, buf, nlen + slen + 1u);
return obj_symbol(ob, n, SB_LOCAL, SK_TLS, OBJ_SEC_NONE, 0, 0);
}
@@ -143,7 +145,7 @@ static void define_tls_macho(ObjBuilder* ob, Compiler* c, ObjSymId sym,
/* Descriptor in __DATA,__thread_vars: 24 bytes aligned 8.
* The user-visible `sym` lives here; the TLVP relocs in code target
* this symbol so the linker can route them through __thread_ptrs. */
- Sym vars_name = pool_intern_cstr(c->global, "__DATA,__thread_vars");
+ Sym vars_name = pool_intern_slice(c->global, SLICE_LIT("__DATA,__thread_vars"));
ObjSecId vars_sec = obj_section(ob, vars_name, SEC_DATA,
SF_ALLOC | SF_WRITE | SF_TLS, 8u);
u32 desc_base = obj_align_to(ob, vars_sec, 8u);
diff --git a/src/obj/tbd_read.c b/src/obj/tbd_read.c
@@ -41,6 +41,7 @@
#include "core/heap.h"
#include "core/pool.h"
+#include "core/slice.h"
#include "obj/obj.h"
static SrcLoc no_loc(void) {
@@ -84,8 +85,7 @@ static Sym extract_install_name(Compiler* c, const u8* data, size_t len) {
--end;
}
if (end > start)
- return pool_intern(c->global, (const char*)(data + start),
- (u32)(end - start));
+ return pool_intern_slice(c->global, (Slice){ .s = (const char*)(data + start), .len = (u32)(end - start) });
return 0;
}
return 0;
@@ -140,7 +140,7 @@ ObjBuilder* read_tbd(Compiler* c, const char* name, const u8* data, size_t len,
* keep tokens of length >= 2. Single `_` is the throwaway-name
* convention and never an exported symbol. */
if (tlen < 2u) continue;
- Sym sn = pool_intern(c->global, (const char*)(data + start), (u32)tlen);
+ Sym sn = pool_intern_slice(c->global, (Slice){ .s = (const char*)(data + start), .len = (u32)tlen });
obj_symbol_ex(ob, sn, SB_GLOBAL, SV_DEFAULT, SK_NOTYPE, OBJ_SEC_NONE, 0,
0, 0);
}
diff --git a/src/opt/ir_print.c b/src/opt/ir_print.c
@@ -1,10 +1,25 @@
-#include <stdio.h>
-#include <string.h>
-
+#include "core/slice.h"
+#include "core/strbuf.h"
#include "opt/opt.h"
static void dump_write(Writer* w, const char* s) {
- cfree_writer_write(w, s, strlen(s));
+ cfree_writer_write(w, s, slice_from_cstr(s).len);
+}
+
+static void dump_sb(Writer* w, const StrBuf* sb) {
+ cfree_writer_write(w, strbuf_cstr(sb), strbuf_len(sb));
+}
+
+/* Append a signed value with an explicit leading sign, matching printf's
+ * "%+lld"/"%+d" formatting (forced '+' on non-negative values). */
+static void strbuf_put_i64_plus(StrBuf* sb, i64 v) {
+ if (v < 0) {
+ strbuf_putc(sb, '-');
+ strbuf_put_u64(sb, (u64)(-(v + 1)) + 1u);
+ } else {
+ strbuf_putc(sb, '+');
+ strbuf_put_u64(sb, (u64)v);
+ }
}
static const char* op_name(IROp op) {
@@ -125,23 +140,29 @@ static const char* alias_name(u8 kind) {
static void dump_alias(Writer* w, const AliasRoot* a) {
char buf[64];
+ StrBuf sb;
dump_write(w, alias_name(a->kind));
+ strbuf_init(&sb, buf, sizeof buf);
switch ((AliasKind)a->kind) {
case ALIAS_LOCAL:
- snprintf(buf, sizeof buf, "#%d", (int)a->v.local_id);
- dump_write(w, buf);
+ strbuf_putc(&sb, '#');
+ strbuf_put_i64(&sb, (i64)(int)a->v.local_id);
+ dump_sb(w, &sb);
break;
case ALIAS_GLOBAL:
- snprintf(buf, sizeof buf, "#%u", (unsigned)a->v.global);
- dump_write(w, buf);
+ strbuf_putc(&sb, '#');
+ strbuf_put_u64(&sb, (u64)(unsigned)a->v.global);
+ dump_sb(w, &sb);
break;
case ALIAS_PARAM:
- snprintf(buf, sizeof buf, "#%u", (unsigned)a->v.param_idx);
- dump_write(w, buf);
+ strbuf_putc(&sb, '#');
+ strbuf_put_u64(&sb, (u64)(unsigned)a->v.param_idx);
+ dump_sb(w, &sb);
break;
case ALIAS_STRING:
- snprintf(buf, sizeof buf, "#%u", (unsigned)a->v.string_id);
- dump_write(w, buf);
+ strbuf_putc(&sb, '#');
+ strbuf_put_u64(&sb, (u64)(unsigned)a->v.string_id);
+ dump_sb(w, &sb);
break;
default:
break;
@@ -150,32 +171,41 @@ static void dump_alias(Writer* w, const AliasRoot* a) {
static void dump_operand(Writer* w, const Operand* op) {
char buf[96];
+ StrBuf sb;
if (!op) {
dump_write(w, "-");
return;
}
+ strbuf_init(&sb, buf, sizeof buf);
switch ((OpKind)op->kind) {
case OPK_IMM:
- snprintf(buf, sizeof buf, "imm:%lld", (long long)op->v.imm);
- dump_write(w, buf);
+ strbuf_puts(&sb, "imm:");
+ strbuf_put_i64(&sb, (i64)op->v.imm);
+ dump_sb(w, &sb);
break;
case OPK_REG:
- snprintf(buf, sizeof buf, "v%u", (unsigned)op->v.reg);
- dump_write(w, buf);
+ strbuf_putc(&sb, 'v');
+ strbuf_put_u64(&sb, (u64)(unsigned)op->v.reg);
+ dump_sb(w, &sb);
break;
case OPK_LOCAL:
- snprintf(buf, sizeof buf, "local#%u", (unsigned)op->v.frame_slot);
- dump_write(w, buf);
+ strbuf_puts(&sb, "local#");
+ strbuf_put_u64(&sb, (u64)(unsigned)op->v.frame_slot);
+ dump_sb(w, &sb);
break;
case OPK_GLOBAL:
- snprintf(buf, sizeof buf, "global#%u%+lld", (unsigned)op->v.global.sym,
- (long long)op->v.global.addend);
- dump_write(w, buf);
+ strbuf_puts(&sb, "global#");
+ strbuf_put_u64(&sb, (u64)(unsigned)op->v.global.sym);
+ strbuf_put_i64_plus(&sb, (i64)op->v.global.addend);
+ dump_sb(w, &sb);
break;
case OPK_INDIRECT:
- snprintf(buf, sizeof buf, "[v%u%+d]", (unsigned)op->v.ind.base,
- (int)op->v.ind.ofs);
- dump_write(w, buf);
+ strbuf_putc(&sb, '[');
+ strbuf_putc(&sb, 'v');
+ strbuf_put_u64(&sb, (u64)(unsigned)op->v.ind.base);
+ strbuf_put_i64_plus(&sb, (i64)(int)op->v.ind.ofs);
+ strbuf_putc(&sb, ']');
+ dump_sb(w, &sb);
break;
default:
dump_write(w, "op?");
@@ -194,24 +224,37 @@ static void dump_operands(Writer* w, const Inst* in) {
static void dump_mem(Writer* w, const MemAccess* m) {
char buf[128];
- snprintf(buf, sizeof buf,
- " mem=size%u align%u flags=0x%x alias=", (unsigned)m->size,
- (unsigned)m->align, (unsigned)m->flags);
- dump_write(w, buf);
+ StrBuf sb;
+ strbuf_init(&sb, buf, sizeof buf);
+ strbuf_puts(&sb, " mem=size");
+ strbuf_put_u64(&sb, (u64)(unsigned)m->size);
+ strbuf_puts(&sb, " align");
+ strbuf_put_u64(&sb, (u64)(unsigned)m->align);
+ strbuf_puts(&sb, " flags=");
+ strbuf_put_hex_u64(&sb, (u64)(unsigned)m->flags);
+ strbuf_puts(&sb, " alias=");
+ dump_sb(w, &sb);
dump_alias(w, &m->alias);
}
static void dump_phi(Writer* w, const Inst* in) {
char buf[96];
+ StrBuf sb;
IRPhiAux* aux = (IRPhiAux*)in->extra.aux;
- snprintf(buf, sizeof buf, " slot=%u preds=[",
- aux ? (unsigned)aux->slot_id : 0u);
- dump_write(w, buf);
+ strbuf_init(&sb, buf, sizeof buf);
+ strbuf_puts(&sb, " slot=");
+ strbuf_put_u64(&sb, aux ? (u64)(unsigned)aux->slot_id : 0u);
+ strbuf_puts(&sb, " preds=[");
+ dump_sb(w, &sb);
if (aux) {
for (u32 p = 0; p < aux->npreds; ++p) {
- snprintf(buf, sizeof buf, "%sb%u:v%u", p ? "," : "",
- (unsigned)aux->pred_blocks[p], (unsigned)aux->pred_vals[p]);
- dump_write(w, buf);
+ strbuf_reset(&sb);
+ if (p) strbuf_putc(&sb, ',');
+ strbuf_putc(&sb, 'b');
+ strbuf_put_u64(&sb, (u64)(unsigned)aux->pred_blocks[p]);
+ strbuf_puts(&sb, ":v");
+ strbuf_put_u64(&sb, (u64)(unsigned)aux->pred_vals[p]);
+ dump_sb(w, &sb);
}
}
dump_write(w, "]");
@@ -230,39 +273,64 @@ static void dump_ret(Writer* w, const Inst* in) {
void opt_ir_dump(Func* f, Writer* w) {
if (!f || !w) return;
char buf[160];
- snprintf(buf, sizeof buf, "ir blocks=%u vals=%u\n", (unsigned)f->nblocks,
- (unsigned)f->nvals);
- dump_write(w, buf);
+ StrBuf sb;
+ strbuf_init(&sb, buf, sizeof buf);
+ strbuf_puts(&sb, "ir blocks=");
+ strbuf_put_u64(&sb, (u64)(unsigned)f->nblocks);
+ strbuf_puts(&sb, " vals=");
+ strbuf_put_u64(&sb, (u64)(unsigned)f->nvals);
+ strbuf_putc(&sb, '\n');
+ dump_sb(w, &sb);
for (u32 b = 0; b < f->nblocks; ++b) {
Block* bl = &f->blocks[b];
- snprintf(buf, sizeof buf, "block %u preds=[", (unsigned)b);
- dump_write(w, buf);
+ strbuf_reset(&sb);
+ strbuf_puts(&sb, "block ");
+ strbuf_put_u64(&sb, (u64)(unsigned)b);
+ strbuf_puts(&sb, " preds=[");
+ dump_sb(w, &sb);
for (u32 p = 0; p < bl->npreds; ++p) {
- snprintf(buf, sizeof buf, "%sb%u", p ? "," : "", (unsigned)bl->preds[p]);
- dump_write(w, buf);
+ strbuf_reset(&sb);
+ if (p) strbuf_putc(&sb, ',');
+ strbuf_putc(&sb, 'b');
+ strbuf_put_u64(&sb, (u64)(unsigned)bl->preds[p]);
+ dump_sb(w, &sb);
}
dump_write(w, "] succs=[");
for (u32 s = 0; s < bl->nsucc; ++s) {
- snprintf(buf, sizeof buf, "%sb%u", s ? "," : "", (unsigned)bl->succ[s]);
- dump_write(w, buf);
+ strbuf_reset(&sb);
+ if (s) strbuf_putc(&sb, ',');
+ strbuf_putc(&sb, 'b');
+ strbuf_put_u64(&sb, (u64)(unsigned)bl->succ[s]);
+ dump_sb(w, &sb);
}
- snprintf(buf, sizeof buf, "] insts=%u\n", (unsigned)bl->ninsts);
- dump_write(w, buf);
+ strbuf_reset(&sb);
+ strbuf_puts(&sb, "] insts=");
+ strbuf_put_u64(&sb, (u64)(unsigned)bl->ninsts);
+ strbuf_putc(&sb, '\n');
+ dump_sb(w, &sb);
for (u32 i = 0; i < bl->ninsts; ++i) {
Inst* in = &bl->insts[i];
- snprintf(buf, sizeof buf, " %u %s", (unsigned)i, op_name((IROp)in->op));
- dump_write(w, buf);
+ strbuf_reset(&sb);
+ strbuf_puts(&sb, " ");
+ strbuf_put_u64(&sb, (u64)(unsigned)i);
+ strbuf_putc(&sb, ' ');
+ strbuf_puts(&sb, op_name((IROp)in->op));
+ dump_sb(w, &sb);
if (in->def != VAL_NONE) {
- snprintf(buf, sizeof buf, " def=v%u", (unsigned)in->def);
- dump_write(w, buf);
+ strbuf_reset(&sb);
+ strbuf_puts(&sb, " def=v");
+ strbuf_put_u64(&sb, (u64)(unsigned)in->def);
+ dump_sb(w, &sb);
}
if (in->ndefs) {
dump_write(w, " defs=[");
for (u32 d = 0; d < in->ndefs; ++d) {
- snprintf(buf, sizeof buf, "%sv%u", d ? "," : "",
- (unsigned)in->defs[d]);
- dump_write(w, buf);
+ strbuf_reset(&sb);
+ if (d) strbuf_putc(&sb, ',');
+ strbuf_putc(&sb, 'v');
+ strbuf_put_u64(&sb, (u64)(unsigned)in->defs[d]);
+ dump_sb(w, &sb);
}
dump_write(w, "]");
}
@@ -270,8 +338,10 @@ void opt_ir_dump(Func* f, Writer* w) {
if ((IROp)in->op == IR_LOAD || (IROp)in->op == IR_STORE)
dump_mem(w, &in->extra.mem);
if ((IROp)in->op == IR_LOAD_IMM || (IROp)in->op == IR_CONST_I) {
- snprintf(buf, sizeof buf, " imm=%lld", (long long)in->extra.imm);
- dump_write(w, buf);
+ strbuf_reset(&sb);
+ strbuf_puts(&sb, " imm=");
+ strbuf_put_i64(&sb, (i64)in->extra.imm);
+ dump_sb(w, &sb);
}
if ((IROp)in->op == IR_PHI) dump_phi(w, in);
if ((IROp)in->op == IR_RET) dump_ret(w, in);
diff --git a/src/opt/opt.c b/src/opt/opt.c
@@ -20,6 +20,7 @@
#include "core/arena.h"
#include "core/core.h"
#include "core/metrics.h"
+#include "core/slice.h"
#include "opt/ir.h"
#include "opt/opt_internal.h"
@@ -44,8 +45,9 @@ static OptImpl* impl_of(CGTarget* t) { return (OptImpl*)t; }
static _Noreturn void panic_unsupported(OptImpl* o, const char* what) {
SrcLoc loc = {0, 0, 0};
- compiler_panic(o->c, loc, "opt_cgtarget: %s called under unbounded virtuals",
- what);
+ compiler_panic(o->c, loc,
+ "opt_cgtarget: %.*s called under unbounded virtuals",
+ SLICE_ARG(slice_from_cstr(what)));
}
/* ---- recording helpers ---- */
diff --git a/src/opt/pass_analysis.c b/src/opt/pass_analysis.c
@@ -2,6 +2,7 @@
#include "core/arena.h"
#include "core/core.h"
+#include "core/slice.h"
#include "opt/opt_internal.h"
#define OPT_BLK_NONE 0xffffffffu
@@ -15,13 +16,27 @@ static SrcLoc opt_no_loc(void) {
static void opt_fail(Func* f, const char* stage, const char* msg, u32 a,
u32 b) {
- compiler_panic(f->c, opt_no_loc(), "opt verify[%s]: %s (%u, %u)",
- stage ? stage : "?", msg, (unsigned)a, (unsigned)b);
+ compiler_panic(f->c, opt_no_loc(), "opt verify[%.*s]: %.*s (%u, %u)",
+ SLICE_ARG(slice_from_cstr(stage ? stage : "?")),
+ SLICE_ARG(slice_from_cstr(msg)), (unsigned)a, (unsigned)b);
+}
+
+/* Does `hay` contain the bytes of NUL-terminated `needle`? Length-explicit
+ * substring search; no strstr. */
+static int slice_contains_cstr(Slice hay, const char* needle) {
+ Slice n = slice_from_cstr(needle);
+ size_t i;
+ if (n.len == 0) return 1;
+ if (hay.len < n.len) return 0;
+ for (i = 0; i + n.len <= hay.len; ++i)
+ if (memcmp(hay.s + i, n.s, n.len) == 0) return 1;
+ return 0;
}
static int verify_stage_is_ssa(const char* stage) {
- return stage && strstr(stage, "ssa") != NULL &&
- strstr(stage, "pre-ssa") == NULL;
+ Slice s = slice_from_cstr(stage);
+ return stage && slice_contains_cstr(s, "ssa") &&
+ !slice_contains_cstr(s, "pre-ssa");
}
#endif
diff --git a/src/opt/pass_emit.c b/src/opt/pass_emit.c
@@ -4,6 +4,7 @@
#include "core/arena.h"
#include "core/core.h"
#include "core/metrics.h"
+#include "core/slice.h"
#include "opt/ir.h"
#include "opt/opt_internal.h"
@@ -639,9 +640,10 @@ static void replay_inst(ReplayCtx* r, u32 b, Inst* in) {
replay_planned_call(r, aux);
break;
}
- compiler_panic(r->c, in->loc,
- "opt replay: call has no supported call plan%s%s",
- plan_reason ? ": " : "", plan_reason ? plan_reason : "");
+ compiler_panic(
+ r->c, in->loc, "opt replay: call has no supported call plan%.*s%.*s",
+ SLICE_ARG(plan_reason ? SLICE_LIT(": ") : SLICE_NULL),
+ SLICE_ARG(plan_reason ? slice_from_cstr(plan_reason) : SLICE_NULL));
break;
}
case IR_BR: {
diff --git a/src/opt/pass_live.c b/src/opt/pass_live.c
@@ -1,8 +1,9 @@
-#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "core/arena.h"
+#include "core/slice.h"
+#include "core/strbuf.h"
#include "opt/opt.h"
#include "opt/opt_internal.h"
@@ -253,14 +254,21 @@ void opt_live_blocks(Func* f, OptLiveInfo* live) {
}
static void dump_write(Writer* w, const char* s) {
- cfree_writer_write(w, s, strlen(s));
+ cfree_writer_write(w, s, slice_from_cstr(s).len);
+}
+
+static void dump_sb(Writer* w, const StrBuf* sb) {
+ cfree_writer_write(w, strbuf_cstr(sb), strbuf_len(sb));
}
static void dump_bit(PReg r, void* arg) {
Writer* w = (Writer*)arg;
char buf[32];
- snprintf(buf, sizeof buf, " r%u", (unsigned)r);
- dump_write(w, buf);
+ StrBuf sb;
+ strbuf_init(&sb, buf, sizeof buf);
+ strbuf_puts(&sb, " r");
+ strbuf_put_u64(&sb, (u64)(unsigned)r);
+ dump_sb(w, &sb);
}
static void dump_set(Writer* w, const char* name, const OptBitset* bs) {
@@ -276,8 +284,12 @@ void opt_live_dump_blocks(Func* f, const OptLiveInfo* live, Writer* w) {
if (!live || !w) return;
for (u32 b = 0; b < live->f->nblocks; ++b) {
char buf[64];
- snprintf(buf, sizeof buf, "block %u\n", (unsigned)b);
- dump_write(w, buf);
+ StrBuf sb;
+ strbuf_init(&sb, buf, sizeof buf);
+ strbuf_puts(&sb, "block ");
+ strbuf_put_u64(&sb, (u64)(unsigned)b);
+ strbuf_putc(&sb, '\n');
+ dump_sb(w, &sb);
dump_set(w, "use", &live->blocks[b].live_use);
dump_set(w, "def", &live->blocks[b].live_def);
dump_set(w, "in", &live->blocks[b].live_in);
@@ -794,25 +806,41 @@ void opt_live_dump_ranges(Func* f, const OptLiveRangeSet* ranges, Writer* w) {
(void)f;
if (!ranges || !w) return;
char buf[160];
- snprintf(buf, sizeof buf,
- "ranges total=%u points=%u raw_points=%u whole_block=%u\n",
- (unsigned)ranges->nranges, (unsigned)ranges->point_count,
- (unsigned)ranges->raw_point_count,
- (unsigned)ranges->whole_block_spans);
- dump_write(w, buf);
+ StrBuf sb;
+ strbuf_init(&sb, buf, sizeof buf);
+ strbuf_puts(&sb, "ranges total=");
+ strbuf_put_u64(&sb, (u64)(unsigned)ranges->nranges);
+ strbuf_puts(&sb, " points=");
+ strbuf_put_u64(&sb, (u64)(unsigned)ranges->point_count);
+ strbuf_puts(&sb, " raw_points=");
+ strbuf_put_u64(&sb, (u64)(unsigned)ranges->raw_point_count);
+ strbuf_puts(&sb, " whole_block=");
+ strbuf_put_u64(&sb, (u64)(unsigned)ranges->whole_block_spans);
+ strbuf_putc(&sb, '\n');
+ dump_sb(w, &sb);
for (PReg r = 1; r < opt_reg_count(ranges->f); ++r) {
if (ranges->first_range_by_preg[r] == OPT_RANGE_NONE) continue;
- snprintf(buf, sizeof buf, "r%u len=%u spill=%u:", (unsigned)r,
- (unsigned)ranges->live_length_by_preg[r],
- (unsigned)ranges->spill_cost_by_preg[r]);
- dump_write(w, buf);
+ strbuf_reset(&sb);
+ strbuf_putc(&sb, 'r');
+ strbuf_put_u64(&sb, (u64)(unsigned)r);
+ strbuf_puts(&sb, " len=");
+ strbuf_put_u64(&sb, (u64)(unsigned)ranges->live_length_by_preg[r]);
+ strbuf_puts(&sb, " spill=");
+ strbuf_put_u64(&sb, (u64)(unsigned)ranges->spill_cost_by_preg[r]);
+ strbuf_putc(&sb, ':');
+ dump_sb(w, &sb);
for (u32 ri = ranges->first_range_by_preg[r]; ri != OPT_RANGE_NONE;
ri = ranges->ranges[ri].next) {
const OptLiveRange* lr = &ranges->ranges[ri];
- snprintf(buf, sizeof buf, " [%u,%u)b%u%s", (unsigned)lr->start,
- (unsigned)lr->end, (unsigned)lr->block,
- lr->whole_block ? "*" : "");
- dump_write(w, buf);
+ strbuf_reset(&sb);
+ strbuf_puts(&sb, " [");
+ strbuf_put_u64(&sb, (u64)(unsigned)lr->start);
+ strbuf_putc(&sb, ',');
+ strbuf_put_u64(&sb, (u64)(unsigned)lr->end);
+ strbuf_puts(&sb, ")b");
+ strbuf_put_u64(&sb, (u64)(unsigned)lr->block);
+ if (lr->whole_block) strbuf_putc(&sb, '*');
+ dump_sb(w, &sb);
}
dump_write(w, "\n");
}
diff --git a/src/opt/pass_lower.c b/src/opt/pass_lower.c
@@ -1,4 +1,3 @@
-#include <stdio.h>
#include <stdlib.h>
#include <string.h>
@@ -6,6 +5,8 @@
#include "core/core.h"
#include "core/metrics.h"
#include "core/pool.h"
+#include "core/slice.h"
+#include "core/strbuf.h"
#include "opt/opt_internal.h"
enum {
@@ -1480,27 +1481,43 @@ static void rewrite_func(Func* f, const OptLiveInfo* live_info) {
f->opt_rewritten = 1;
}
-static void rewrite_dump_write(Writer* w, const char* s) {
- cfree_writer_write(w, s, strlen(s));
+static void rewrite_dump_sb(Writer* w, const StrBuf* sb) {
+ cfree_writer_write(w, strbuf_cstr(sb), strbuf_len(sb));
}
void opt_rewrite_dump(Func* f, Writer* w) {
if (!f || !w) return;
char buf[96];
- snprintf(buf, sizeof buf, "rewrite blocks=%u pregs=%u rewritten=%u\n",
- (unsigned)f->nblocks, (unsigned)opt_reg_count(f),
- (unsigned)f->opt_rewritten);
- rewrite_dump_write(w, buf);
+ StrBuf sb;
+ strbuf_init(&sb, buf, sizeof buf);
+ strbuf_puts(&sb, "rewrite blocks=");
+ strbuf_put_u64(&sb, (u64)(unsigned)f->nblocks);
+ strbuf_puts(&sb, " pregs=");
+ strbuf_put_u64(&sb, (u64)(unsigned)opt_reg_count(f));
+ strbuf_puts(&sb, " rewritten=");
+ strbuf_put_u64(&sb, (u64)(unsigned)f->opt_rewritten);
+ strbuf_putc(&sb, '\n');
+ rewrite_dump_sb(w, &sb);
for (u32 b = 0; b < f->nblocks; ++b) {
Block* bl = &f->blocks[b];
- snprintf(buf, sizeof buf, "block %u insts=%u\n", (unsigned)b,
- (unsigned)bl->ninsts);
- rewrite_dump_write(w, buf);
+ strbuf_reset(&sb);
+ strbuf_puts(&sb, "block ");
+ strbuf_put_u64(&sb, (u64)(unsigned)b);
+ strbuf_puts(&sb, " insts=");
+ strbuf_put_u64(&sb, (u64)(unsigned)bl->ninsts);
+ strbuf_putc(&sb, '\n');
+ rewrite_dump_sb(w, &sb);
for (u32 i = 0; i < bl->ninsts; ++i) {
Inst* in = &bl->insts[i];
- snprintf(buf, sizeof buf, " %u op=%u operands=%u\n", (unsigned)i,
- (unsigned)in->op, (unsigned)in->nopnds);
- rewrite_dump_write(w, buf);
+ strbuf_reset(&sb);
+ strbuf_puts(&sb, " ");
+ strbuf_put_u64(&sb, (u64)(unsigned)i);
+ strbuf_puts(&sb, " op=");
+ strbuf_put_u64(&sb, (u64)(unsigned)in->op);
+ strbuf_puts(&sb, " operands=");
+ strbuf_put_u64(&sb, (u64)(unsigned)in->nopnds);
+ strbuf_putc(&sb, '\n');
+ rewrite_dump_sb(w, &sb);
}
}
}
diff --git a/src/opt/pass_machinize.c b/src/opt/pass_machinize.c
@@ -3,6 +3,7 @@
#include "core/arena.h"
#include "core/core.h"
#include "core/pool.h"
+#include "core/slice.h"
#include "opt/opt_internal.h"
static const char* asm_constraint_body(const char* s) {
@@ -21,7 +22,9 @@ static int asm_resolve_fixed_constraint(Func* f, CGTarget* target,
const char* end = body + 1;
while (*end && *end != '}') ++end;
if (*end != '}' || end == body + 1) return 0;
- Sym name = pool_intern(f->c->global, body + 1, (size_t)(end - body - 1));
+ Sym name = pool_intern_slice(
+ f->c->global,
+ (Slice){ .s = body + 1, .len = (size_t)(end - body - 1) });
return target->resolve_reg_name(target, name, reg_out, cls_out) == 0;
}
diff --git a/src/opt/pass_ssa.c b/src/opt/pass_ssa.c
@@ -1,10 +1,11 @@
/* pass_ssa.c - mem2reg SSA construction and phi destruction for O2. */
-#include <stdio.h>
#include <string.h>
#include "core/arena.h"
#include "core/core.h"
+#include "core/slice.h"
+#include "core/strbuf.h"
#include "opt/opt_internal.h"
typedef struct SlotStack {
@@ -975,7 +976,11 @@ void opt_undo_ssa(Func* f) {
}
static void ssa_dump_write(Writer* w, const char* s) {
- cfree_writer_write(w, s, strlen(s));
+ cfree_writer_write(w, s, slice_from_cstr(s).len);
+}
+
+static void ssa_dump_sb(Writer* w, const StrBuf* sb) {
+ cfree_writer_write(w, strbuf_cstr(sb), strbuf_len(sb));
}
typedef struct SsaDumpUseCtx {
@@ -990,8 +995,12 @@ static void ssa_dump_use(Func* f, Inst* in, Operand* op, int is_def,
if (is_def || op->kind != OPK_REG) return;
SsaDumpUseCtx* ctx = (SsaDumpUseCtx*)arg;
char buf[32];
- snprintf(buf, sizeof buf, "%sv%u", ctx->any ? "," : "", (unsigned)op->v.reg);
- ssa_dump_write(ctx->w, buf);
+ StrBuf sb;
+ strbuf_init(&sb, buf, sizeof buf);
+ if (ctx->any) strbuf_putc(&sb, ',');
+ strbuf_putc(&sb, 'v');
+ strbuf_put_u64(&sb, (u64)(unsigned)op->v.reg);
+ ssa_dump_sb(ctx->w, &sb);
ctx->any = 1;
}
@@ -999,34 +1008,57 @@ void opt_ssa_dump(Func* f, Writer* w) {
if (!f || !w) return;
opt_rebuild_def_use(f);
char buf[160];
- snprintf(buf, sizeof buf, "ssa blocks=%u vals=%u uses=%u\n",
- (unsigned)f->nblocks, (unsigned)f->nvals, (unsigned)f->opt_nuses);
- ssa_dump_write(w, buf);
+ StrBuf sb;
+ strbuf_init(&sb, buf, sizeof buf);
+ strbuf_puts(&sb, "ssa blocks=");
+ strbuf_put_u64(&sb, (u64)(unsigned)f->nblocks);
+ strbuf_puts(&sb, " vals=");
+ strbuf_put_u64(&sb, (u64)(unsigned)f->nvals);
+ strbuf_puts(&sb, " uses=");
+ strbuf_put_u64(&sb, (u64)(unsigned)f->opt_nuses);
+ strbuf_putc(&sb, '\n');
+ ssa_dump_sb(w, &sb);
for (u32 b = 0; b < f->nblocks; ++b) {
Block* bl = &f->blocks[b];
- snprintf(buf, sizeof buf, "block %u preds=%u succs=%u\n", (unsigned)b,
- (unsigned)bl->npreds, (unsigned)bl->nsucc);
- ssa_dump_write(w, buf);
+ strbuf_reset(&sb);
+ strbuf_puts(&sb, "block ");
+ strbuf_put_u64(&sb, (u64)(unsigned)b);
+ strbuf_puts(&sb, " preds=");
+ strbuf_put_u64(&sb, (u64)(unsigned)bl->npreds);
+ strbuf_puts(&sb, " succs=");
+ strbuf_put_u64(&sb, (u64)(unsigned)bl->nsucc);
+ strbuf_putc(&sb, '\n');
+ ssa_dump_sb(w, &sb);
for (u32 i = 0; i < bl->ninsts; ++i) {
Inst* in = &bl->insts[i];
- snprintf(buf, sizeof buf, " i%u op=%u", (unsigned)in->id,
- (unsigned)in->op);
- ssa_dump_write(w, buf);
+ strbuf_reset(&sb);
+ strbuf_puts(&sb, " i");
+ strbuf_put_u64(&sb, (u64)(unsigned)in->id);
+ strbuf_puts(&sb, " op=");
+ strbuf_put_u64(&sb, (u64)(unsigned)in->op);
+ ssa_dump_sb(w, &sb);
if (in->def != VAL_NONE) {
- snprintf(buf, sizeof buf, " def=v%u", (unsigned)in->def);
- ssa_dump_write(w, buf);
+ strbuf_reset(&sb);
+ strbuf_puts(&sb, " def=v");
+ strbuf_put_u64(&sb, (u64)(unsigned)in->def);
+ ssa_dump_sb(w, &sb);
}
if ((IROp)in->op == IR_PHI) {
IRPhiAux* aux = (IRPhiAux*)in->extra.aux;
- snprintf(buf, sizeof buf,
- " phi slot=%u preds=", aux ? (unsigned)aux->slot_id : 0u);
- ssa_dump_write(w, buf);
+ strbuf_reset(&sb);
+ strbuf_puts(&sb, " phi slot=");
+ strbuf_put_u64(&sb, aux ? (u64)(unsigned)aux->slot_id : 0u);
+ strbuf_puts(&sb, " preds=");
+ ssa_dump_sb(w, &sb);
if (aux) {
for (u32 p = 0; p < aux->npreds; ++p) {
- snprintf(buf, sizeof buf, "%sb%u:v%u", p ? "," : "",
- (unsigned)aux->pred_blocks[p],
- (unsigned)aux->pred_vals[p]);
- ssa_dump_write(w, buf);
+ strbuf_reset(&sb);
+ if (p) strbuf_putc(&sb, ',');
+ strbuf_putc(&sb, 'b');
+ strbuf_put_u64(&sb, (u64)(unsigned)aux->pred_blocks[p]);
+ strbuf_puts(&sb, ":v");
+ strbuf_put_u64(&sb, (u64)(unsigned)aux->pred_vals[p]);
+ ssa_dump_sb(w, &sb);
}
}
} else {
diff --git a/test/api/abi_classify_test.c b/test/api/abi_classify_test.c
@@ -339,10 +339,10 @@ static CfreeCgTypeId make_i8_record(CfreeCompiler* c, const char* tag_name,
if (nfields > 16) exit(2);
memset(fields, 0, sizeof fields);
for (u32 i = 0; i < nfields; ++i) {
- fields[i].name = cfree_sym_intern(c, names[i]);
+ fields[i].name = cfree_sym_intern(c, cfree_slice_cstr(names[i]));
fields[i].type = i8;
}
- return cfree_cg_type_record(c, cfree_sym_intern(c, tag_name), fields,
+ return cfree_cg_type_record(c, cfree_sym_intern(c, cfree_slice_cstr(tag_name)), fields,
nfields);
}
@@ -352,11 +352,11 @@ static CfreeCgTypeId make_two_i64_record(CfreeCompiler* c, const char* tag_n) {
CfreeCgTypeId i64 = bi.id[CFREE_CG_BUILTIN_I64];
CfreeCgField fields[2];
memset(fields, 0, sizeof fields);
- fields[0].name = cfree_sym_intern(c, "a");
+ fields[0].name = cfree_sym_intern(c, CFREE_SLICE_LIT("a"));
fields[0].type = i64;
- fields[1].name = cfree_sym_intern(c, "b");
+ fields[1].name = cfree_sym_intern(c, CFREE_SLICE_LIT("b"));
fields[1].type = i64;
- return cfree_cg_type_record(c, cfree_sym_intern(c, tag_n), fields, 2);
+ return cfree_cg_type_record(c, cfree_sym_intern(c, cfree_slice_cstr(tag_n)), fields, 2);
}
/* Classify a function `ret_ty fn(p0, p1, ..., pN-1)` and return its info. */
diff --git a/test/api/cg_switch_test.c b/test/api/cg_switch_test.c
@@ -135,7 +135,7 @@ static void build_switch_fn(CfreeCompiler* c, CfreeCgTypeId i32_ty,
snprintf(fn_name, sizeof fn_name, "switch_%s_o%d", sh->name, opt_level);
memset(&decl, 0, sizeof decl);
decl.kind = CFREE_CG_DECL_FUNC;
- decl.linkage_name = cfree_sym_intern(c, fn_name);
+ decl.linkage_name = cfree_sym_intern(c, cfree_slice_cstr(fn_name));
decl.display_name = decl.linkage_name;
decl.type = cfree_cg_type_func(c, sig);
decl.sym.bind = CFREE_SB_GLOBAL;
@@ -146,7 +146,7 @@ static void build_switch_fn(CfreeCompiler* c, CfreeCgTypeId i32_ty,
cfree_cg_func_begin(cg, sym);
memset(&attrs, 0, sizeof attrs);
- attrs.name = cfree_sym_intern(c, "x");
+ attrs.name = cfree_sym_intern(c, CFREE_SLICE_LIT("x"));
param = cfree_cg_param(cg, 0, sh->selector_type, attrs);
EXPECT(param != CFREE_CG_LOCAL_NONE, "[%s/O%d] param failed", sh->name,
opt_level);
diff --git a/test/api/cg_type_test.c b/test/api/cg_type_test.c
@@ -118,7 +118,7 @@ static void exercise_cg_handles(CfreeCompiler* c, CfreeCgTypeId i32_ty,
snprintf(name_buf, sizeof(name_buf), "cg_handles_o%d", opt_level);
memset(&decl, 0, sizeof(decl));
decl.kind = CFREE_CG_DECL_FUNC;
- decl.linkage_name = cfree_sym_intern(c, name_buf);
+ decl.linkage_name = cfree_sym_intern(c, cfree_slice_cstr(name_buf));
decl.display_name = decl.linkage_name;
decl.type = cfree_cg_type_func(c, sig);
decl.sym.bind = CFREE_SB_GLOBAL;
@@ -128,9 +128,9 @@ static void exercise_cg_handles(CfreeCompiler* c, CfreeCgTypeId i32_ty,
cfree_cg_func_begin(cg, sym);
memset(&attrs, 0, sizeof(attrs));
- attrs.name = cfree_sym_intern(c, "p");
+ attrs.name = cfree_sym_intern(c, CFREE_SLICE_LIT("p"));
param = cfree_cg_param(cg, 0, i32_ty, attrs);
- attrs.name = cfree_sym_intern(c, "x");
+ attrs.name = cfree_sym_intern(c, CFREE_SLICE_LIT("x"));
local = cfree_cg_local(cg, i32_ty, attrs);
EXPECT(local != CFREE_CG_LOCAL_NONE, "local handle is none");
EXPECT(param != CFREE_CG_LOCAL_NONE, "param handle is none");
@@ -192,7 +192,7 @@ static void exercise_cg_scalar_local(CfreeCompiler* c, CfreeCgTypeId i32_ty,
snprintf(name_buf, sizeof name_buf, "cg_scalar_local_o%d", opt_level);
memset(&decl, 0, sizeof decl);
decl.kind = CFREE_CG_DECL_FUNC;
- decl.linkage_name = cfree_sym_intern(c, name_buf);
+ decl.linkage_name = cfree_sym_intern(c, cfree_slice_cstr(name_buf));
decl.display_name = decl.linkage_name;
decl.type = cfree_cg_type_func(c, sig);
decl.sym.bind = CFREE_SB_GLOBAL;
@@ -202,7 +202,7 @@ static void exercise_cg_scalar_local(CfreeCompiler* c, CfreeCgTypeId i32_ty,
cfree_cg_func_begin(cg, sym);
memset(&attrs, 0, sizeof attrs);
- attrs.name = cfree_sym_intern(c, "x");
+ attrs.name = cfree_sym_intern(c, CFREE_SLICE_LIT("x"));
local = cfree_cg_local(cg, i32_ty, attrs);
EXPECT(local != CFREE_CG_LOCAL_NONE, "scalar local handle is none");
@@ -258,7 +258,7 @@ static void exercise_cg_late_local_addr(CfreeCompiler* c, CfreeCgTypeId i32_ty,
snprintf(name_buf, sizeof name_buf, "cg_late_local_addr_o%d", opt_level);
memset(&decl, 0, sizeof decl);
decl.kind = CFREE_CG_DECL_FUNC;
- decl.linkage_name = cfree_sym_intern(c, name_buf);
+ decl.linkage_name = cfree_sym_intern(c, cfree_slice_cstr(name_buf));
decl.display_name = decl.linkage_name;
decl.type = cfree_cg_type_func(c, sig);
decl.sym.bind = CFREE_SB_GLOBAL;
@@ -268,7 +268,7 @@ static void exercise_cg_late_local_addr(CfreeCompiler* c, CfreeCgTypeId i32_ty,
cfree_cg_func_begin(cg, sym);
memset(&attrs, 0, sizeof attrs);
- attrs.name = cfree_sym_intern(c, "x");
+ attrs.name = cfree_sym_intern(c, CFREE_SLICE_LIT("x"));
local = cfree_cg_local(cg, i32_ty, attrs);
EXPECT(local != CFREE_CG_LOCAL_NONE, "late addr local handle is none");
@@ -330,7 +330,7 @@ static void exercise_cg_data_entsize(CfreeCompiler* c, CfreeCgTypeId i8_ty) {
memset(&decl, 0, sizeof decl);
decl.kind = CFREE_CG_DECL_OBJECT;
- decl.linkage_name = cfree_sym_intern(c, "cg_entsize_string");
+ decl.linkage_name = cfree_sym_intern(c, CFREE_SLICE_LIT("cg_entsize_string"));
decl.display_name = decl.linkage_name;
decl.type = array_ty;
decl.sym.bind = CFREE_SB_GLOBAL;
@@ -341,7 +341,7 @@ static void exercise_cg_data_entsize(CfreeCompiler* c, CfreeCgTypeId i8_ty) {
EXPECT(sym != CFREE_CG_SYM_NONE, "entsize object decl failed");
memset(&data_attrs, 0, sizeof data_attrs);
- data_attrs.section = cfree_sym_intern(c, ".rodata.cfree.merge");
+ data_attrs.section = cfree_sym_intern(c, CFREE_SLICE_LIT(".rodata.cfree.merge"));
data_attrs.align = 1;
data_attrs.entsize = 1;
data_attrs.flags = CFREE_CG_DATADEF_READONLY | CFREE_CG_DATADEF_MERGE |
@@ -375,7 +375,7 @@ static CfreeCgSym begin_i32_func(CfreeCompiler* c, CfreeCg* cg,
memset(&decl, 0, sizeof decl);
decl.kind = CFREE_CG_DECL_FUNC;
- decl.linkage_name = cfree_sym_intern(c, name);
+ decl.linkage_name = cfree_sym_intern(c, cfree_slice_cstr(name));
decl.display_name = decl.linkage_name;
decl.type = cfree_cg_type_func(c, sig);
decl.sym.bind = CFREE_SB_GLOBAL;
@@ -489,7 +489,7 @@ static uint32_t cg_emit_delayed_chain(CfreeCompiler* c, CfreeCgTypeId i32_ty,
memset(&decl, 0, sizeof decl);
decl.kind = CFREE_CG_DECL_FUNC;
- decl.linkage_name = cfree_sym_intern(c, name);
+ decl.linkage_name = cfree_sym_intern(c, cfree_slice_cstr(name));
decl.display_name = decl.linkage_name;
decl.type = cfree_cg_type_func(c, sig);
decl.sym.bind = CFREE_SB_GLOBAL;
@@ -499,7 +499,7 @@ static uint32_t cg_emit_delayed_chain(CfreeCompiler* c, CfreeCgTypeId i32_ty,
cfree_cg_func_begin(cg, sym);
memset(&attrs, 0, sizeof attrs);
- attrs.name = cfree_sym_intern(c, "p");
+ attrs.name = cfree_sym_intern(c, CFREE_SLICE_LIT("p"));
param = cfree_cg_param(cg, 0, i32_ty, attrs);
EXPECT(param != CFREE_CG_LOCAL_NONE, "delayed chain param failed");
memset(&mem, 0, sizeof mem);
@@ -558,7 +558,7 @@ static uint32_t cg_emit_unary_chain(CfreeCompiler* c, CfreeCgTypeId i32_ty,
memset(&decl, 0, sizeof decl);
decl.kind = CFREE_CG_DECL_FUNC;
- decl.linkage_name = cfree_sym_intern(c, name);
+ decl.linkage_name = cfree_sym_intern(c, cfree_slice_cstr(name));
decl.display_name = decl.linkage_name;
decl.type = cfree_cg_type_func(c, sig);
decl.sym.bind = CFREE_SB_GLOBAL;
@@ -568,7 +568,7 @@ static uint32_t cg_emit_unary_chain(CfreeCompiler* c, CfreeCgTypeId i32_ty,
cfree_cg_func_begin(cg, sym);
memset(&attrs, 0, sizeof attrs);
- attrs.name = cfree_sym_intern(c, "p");
+ attrs.name = cfree_sym_intern(c, CFREE_SLICE_LIT("p"));
param = cfree_cg_param(cg, 0, i32_ty, attrs);
EXPECT(param != CFREE_CG_LOCAL_NONE, "unary chain param failed");
memset(&mem, 0, sizeof mem);
@@ -620,7 +620,7 @@ static uint32_t cg_emit_local_shadow(CfreeCompiler* c, CfreeCgTypeId i32_ty,
memset(&decl, 0, sizeof decl);
decl.kind = CFREE_CG_DECL_FUNC;
- decl.linkage_name = cfree_sym_intern(c, name);
+ decl.linkage_name = cfree_sym_intern(c, cfree_slice_cstr(name));
decl.display_name = decl.linkage_name;
decl.type = cfree_cg_type_func(c, sig);
decl.sym.bind = CFREE_SB_GLOBAL;
@@ -630,7 +630,7 @@ static uint32_t cg_emit_local_shadow(CfreeCompiler* c, CfreeCgTypeId i32_ty,
cfree_cg_func_begin(cg, sym);
memset(&attrs, 0, sizeof attrs);
- attrs.name = cfree_sym_intern(c, "x");
+ attrs.name = cfree_sym_intern(c, CFREE_SLICE_LIT("x"));
local = cfree_cg_local(cg, i32_ty, attrs);
EXPECT(local != CFREE_CG_LOCAL_NONE, "local shadow local failed");
memset(&mem, 0, sizeof mem);
@@ -690,7 +690,7 @@ static uint32_t cg_emit_delayed_cmp(CfreeCompiler* c, CfreeCgTypeId i32_ty,
memset(&decl, 0, sizeof decl);
decl.kind = CFREE_CG_DECL_FUNC;
- decl.linkage_name = cfree_sym_intern(c, name);
+ decl.linkage_name = cfree_sym_intern(c, cfree_slice_cstr(name));
decl.display_name = decl.linkage_name;
decl.type = cfree_cg_type_func(c, sig);
decl.sym.bind = CFREE_SB_GLOBAL;
@@ -700,7 +700,7 @@ static uint32_t cg_emit_delayed_cmp(CfreeCompiler* c, CfreeCgTypeId i32_ty,
cfree_cg_func_begin(cg, sym);
memset(&attrs, 0, sizeof attrs);
- attrs.name = cfree_sym_intern(c, "p");
+ attrs.name = cfree_sym_intern(c, CFREE_SLICE_LIT("p"));
param = cfree_cg_param(cg, 0, i32_ty, attrs);
EXPECT(param != CFREE_CG_LOCAL_NONE, "delayed cmp param failed");
memset(&mem, 0, sizeof mem);
@@ -762,7 +762,7 @@ static uint32_t cg_emit_delayed_store(CfreeCompiler* c, CfreeCgTypeId i32_ty,
memset(&decl, 0, sizeof decl);
decl.kind = CFREE_CG_DECL_FUNC;
- decl.linkage_name = cfree_sym_intern(c, name);
+ decl.linkage_name = cfree_sym_intern(c, cfree_slice_cstr(name));
decl.display_name = decl.linkage_name;
decl.type = cfree_cg_type_func(c, sig);
decl.sym.bind = CFREE_SB_GLOBAL;
@@ -772,9 +772,9 @@ static uint32_t cg_emit_delayed_store(CfreeCompiler* c, CfreeCgTypeId i32_ty,
cfree_cg_func_begin(cg, sym);
memset(&attrs, 0, sizeof attrs);
- attrs.name = cfree_sym_intern(c, "p");
+ attrs.name = cfree_sym_intern(c, CFREE_SLICE_LIT("p"));
param = cfree_cg_param(cg, 0, i32_ty, attrs);
- attrs.name = cfree_sym_intern(c, "x");
+ attrs.name = cfree_sym_intern(c, CFREE_SLICE_LIT("x"));
local = cfree_cg_local(cg, i32_ty, attrs);
EXPECT(param != CFREE_CG_LOCAL_NONE, "delayed store param failed");
EXPECT(local != CFREE_CG_LOCAL_NONE, "delayed store local failed");
@@ -839,7 +839,7 @@ static uint32_t cg_emit_delayed_pressure(CfreeCompiler* c, CfreeCgTypeId i32_ty,
memset(&decl, 0, sizeof decl);
decl.kind = CFREE_CG_DECL_FUNC;
- decl.linkage_name = cfree_sym_intern(c, name);
+ decl.linkage_name = cfree_sym_intern(c, cfree_slice_cstr(name));
decl.display_name = decl.linkage_name;
decl.type = cfree_cg_type_func(c, sig);
decl.sym.bind = CFREE_SB_GLOBAL;
@@ -855,7 +855,7 @@ static uint32_t cg_emit_delayed_pressure(CfreeCompiler* c, CfreeCgTypeId i32_ty,
for (uint32_t i = 0; i < NPARAMS; ++i) {
char pname[8];
snprintf(pname, sizeof pname, "p%u", (unsigned)i);
- attrs.name = cfree_sym_intern(c, pname);
+ attrs.name = cfree_sym_intern(c, cfree_slice_cstr(pname));
params[i] = cfree_cg_param(cg, i, i32_ty, attrs);
EXPECT(params[i] != CFREE_CG_LOCAL_NONE, "delayed pressure param failed");
}
@@ -923,7 +923,7 @@ static uint32_t cg_emit_local_shadow_boundary(CfreeCompiler* c,
memset(&decl, 0, sizeof decl);
decl.kind = CFREE_CG_DECL_FUNC;
- decl.linkage_name = cfree_sym_intern(c, name);
+ decl.linkage_name = cfree_sym_intern(c, cfree_slice_cstr(name));
decl.display_name = decl.linkage_name;
decl.type = cfree_cg_type_func(c, sig);
decl.sym.bind = CFREE_SB_GLOBAL;
@@ -933,7 +933,7 @@ static uint32_t cg_emit_local_shadow_boundary(CfreeCompiler* c,
cfree_cg_func_begin(cg, sym);
memset(&attrs, 0, sizeof attrs);
- attrs.name = cfree_sym_intern(c, "x");
+ attrs.name = cfree_sym_intern(c, CFREE_SLICE_LIT("x"));
local = cfree_cg_local(cg, i32_ty, attrs);
EXPECT(local != CFREE_CG_LOCAL_NONE, "local shadow boundary local failed");
memset(&mem, 0, sizeof mem);
@@ -1025,7 +1025,7 @@ static uint32_t cg_emit_local_shadow_partial_store(CfreeCompiler* c,
memset(&decl, 0, sizeof decl);
decl.kind = CFREE_CG_DECL_FUNC;
- decl.linkage_name = cfree_sym_intern(c, name);
+ decl.linkage_name = cfree_sym_intern(c, cfree_slice_cstr(name));
decl.display_name = decl.linkage_name;
decl.type = cfree_cg_type_func(c, sig);
decl.sym.bind = CFREE_SB_GLOBAL;
@@ -1035,7 +1035,7 @@ static uint32_t cg_emit_local_shadow_partial_store(CfreeCompiler* c,
cfree_cg_func_begin(cg, sym);
memset(&attrs, 0, sizeof attrs);
- attrs.name = cfree_sym_intern(c, "x");
+ attrs.name = cfree_sym_intern(c, CFREE_SLICE_LIT("x"));
local = cfree_cg_local(cg, i32_ty, attrs);
EXPECT(local != CFREE_CG_LOCAL_NONE, "partial shadow local failed");
memset(&mem_i32, 0, sizeof mem_i32);
@@ -1158,7 +1158,7 @@ static CfreeCg* cg_begin_bad_store_func(CfreeCompiler* c, const char* name) {
sig.call_conv = CFREE_CG_CC_TARGET_C;
memset(&decl, 0, sizeof decl);
decl.kind = CFREE_CG_DECL_FUNC;
- decl.linkage_name = cfree_sym_intern(c, name);
+ decl.linkage_name = cfree_sym_intern(c, cfree_slice_cstr(name));
decl.display_name = decl.linkage_name;
decl.type = cfree_cg_type_func(c, sig);
decl.sym.bind = CFREE_SB_LOCAL;
@@ -1238,7 +1238,7 @@ static void exercise_compile_session_two_deltas(CfreeCompiler* c) {
sopts.lang = CFREE_LANG_ASM;
sopts.compile.language_options = &aopts;
memset(&in, 0, sizeof(in));
- in.bytes.name = "<api-session-asm>";
+ in.name = CFREE_SLICE_LIT("<api-session-asm>");
in.bytes.data = empty;
in.bytes.len = 0;
in.lang = CFREE_LANG_ASM;
@@ -1358,7 +1358,7 @@ int main(void) {
"array elem mismatch");
EXPECT(cfree_cg_type_array_count(c, array_i32) == 4, "array count mismatch");
- alias = cfree_cg_type_alias(c, cfree_sym_intern(c, "I"), i32_ty);
+ alias = cfree_cg_type_alias(c, cfree_sym_intern(c, CFREE_SLICE_LIT("I")), i32_ty);
EXPECT(alias != CFREE_CG_TYPE_NONE && alias != i32_ty,
"alias id should be fresh");
EXPECT(cfree_cg_type_kind(c, alias) == CFREE_CG_TYPE_ALIAS,
@@ -1367,15 +1367,15 @@ int main(void) {
"alias size mismatch");
memset(fields, 0, sizeof fields);
- fields[0].name = cfree_sym_intern(c, "a");
+ fields[0].name = cfree_sym_intern(c, CFREE_SLICE_LIT("a"));
fields[0].type = i32_ty;
fields[0].align_override = 0;
- fields[1].name = cfree_sym_intern(c, "b");
+ fields[1].name = cfree_sym_intern(c, CFREE_SLICE_LIT("b"));
fields[1].type = ptr_i32;
fields[1].align_override = 1;
- rec = cfree_cg_type_record(c, cfree_sym_intern(c, "R"), fields, 2);
+ rec = cfree_cg_type_record(c, cfree_sym_intern(c, CFREE_SLICE_LIT("R")), fields, 2);
EXPECT(rec != CFREE_CG_TYPE_NONE, "record type failed");
- EXPECT(cfree_cg_type_record(c, cfree_sym_intern(c, "Bad"), fields, 0) !=
+ EXPECT(cfree_cg_type_record(c, cfree_sym_intern(c, CFREE_SLICE_LIT("Bad")), fields, 0) !=
CFREE_CG_TYPE_NONE,
"empty record type failed");
EXPECT(cfree_cg_type_kind(c, rec) == CFREE_CG_TYPE_RECORD,
@@ -1389,15 +1389,15 @@ int main(void) {
EXPECT(field_off == 4, "record field offset mismatch");
memset(fields, 0, sizeof fields);
- fields[0].name = cfree_sym_intern(c, "lo");
+ fields[0].name = cfree_sym_intern(c, CFREE_SLICE_LIT("lo"));
fields[0].type = i32_ty;
fields[0].flags = CFREE_CG_FIELD_BITFIELD;
fields[0].bit_width = 5;
- fields[1].name = cfree_sym_intern(c, "hi");
+ fields[1].name = cfree_sym_intern(c, CFREE_SLICE_LIT("hi"));
fields[1].type = i32_ty;
fields[1].flags = CFREE_CG_FIELD_BITFIELD;
fields[1].bit_width = 3;
- rec_ex = cfree_cg_type_record(c, cfree_sym_intern(c, "BF"), fields, 2);
+ rec_ex = cfree_cg_type_record(c, cfree_sym_intern(c, CFREE_SLICE_LIT("BF")), fields, 2);
EXPECT(rec_ex != CFREE_CG_TYPE_NONE, "bit-field record type failed");
EXPECT(cfree_cg_type_size(c, rec_ex) == 4, "bit-field record size mismatch");
EXPECT(cfree_cg_type_record_field(c, rec_ex, 1, &field_out, &field_off) == 0,
@@ -1407,13 +1407,13 @@ int main(void) {
"bit-field metadata mismatch");
memset(fields, 0, sizeof fields);
- fields[0].name = cfree_sym_intern(c, "a");
+ fields[0].name = cfree_sym_intern(c, CFREE_SLICE_LIT("a"));
fields[0].type = i32_ty;
- fields[1].name = cfree_sym_intern(c, "b");
+ fields[1].name = cfree_sym_intern(c, CFREE_SLICE_LIT("b"));
fields[1].type = ptr_i32;
fields[1].align_override = 1;
memset(&rdesc, 0, sizeof rdesc);
- rdesc.tag = cfree_sym_intern(c, "U");
+ rdesc.tag = cfree_sym_intern(c, CFREE_SLICE_LIT("U"));
rdesc.fields = fields;
rdesc.nfields = 2;
rdesc.is_union = 1;
@@ -1426,11 +1426,11 @@ int main(void) {
"record desc field query failed");
EXPECT(field_off == 0, "union field offset mismatch");
- vals[0].name = cfree_sym_intern(c, "A");
+ vals[0].name = cfree_sym_intern(c, CFREE_SLICE_LIT("A"));
vals[0].value = 1;
- vals[1].name = cfree_sym_intern(c, "B");
+ vals[1].name = cfree_sym_intern(c, CFREE_SLICE_LIT("B"));
vals[1].value = 2;
- enm = cfree_cg_type_enum(c, cfree_sym_intern(c, "E"), CFREE_CG_TYPE_NONE,
+ enm = cfree_cg_type_enum(c, cfree_sym_intern(c, CFREE_SLICE_LIT("E")), CFREE_CG_TYPE_NONE,
vals, 2);
EXPECT(enm != CFREE_CG_TYPE_NONE, "enum type failed");
diff --git a/test/ar_test.c b/test/ar_test.c
@@ -132,19 +132,19 @@ static uint64_t ar_date_field(const uint8_t* hdr) {
/* ===== tests ===== */
static int test_basic_roundtrip(void) {
- CfreeBytes ms[2];
+ CfreeArInput ms[2];
BufW bw;
- CfreeBytes in;
+ CfreeSlice in;
CfreeArIter* it = NULL;
CfreeArMember m;
int rc;
- ms[0].name = "a.o";
- ms[0].data = (const uint8_t*)"AAAA";
- ms[0].len = 4;
- ms[1].name = "b.o";
- ms[1].data = (const uint8_t*)"BBBBB";
- ms[1].len = 5;
+ ms[0].name = CFREE_SLICE_LIT("a.o");
+ ms[0].bytes.data = (const uint8_t*)"AAAA";
+ ms[0].bytes.len = 4;
+ ms[1].name = CFREE_SLICE_LIT("b.o");
+ ms[1].bytes.data = (const uint8_t*)"BBBBB";
+ ms[1].bytes.len = 5;
bufw_init(&bw);
rc = cfree_ar_write(&bw.base, ms, 2, NULL);
@@ -153,17 +153,16 @@ static int test_basic_roundtrip(void) {
EXPECT(bw.len >= 8, "archive too short");
EXPECT(memcmp(bw.data, "!<arch>\n", 8) == 0, "magic");
- in.name = "test";
in.data = bw.data;
in.len = bw.len;
EXPECT(cfree_ar_iter_new(&g_ctx, &in, &it) == CFREE_OK, "iter_init");
EXPECT(cfree_ar_iter_next(it, &m), "first member");
- EXPECT(strcmp(m.name, "a.o") == 0, "name 0 = %s", m.name);
+ EXPECT(cfree_slice_eq_cstr(m.name, "a.o"), "name 0 = %.*s", CFREE_SLICE_ARG(m.name));
EXPECT(m.size == 4 && memcmp(m.data, "AAAA", 4) == 0, "data 0");
EXPECT(cfree_ar_iter_next(it, &m), "second member");
- EXPECT(strcmp(m.name, "b.o") == 0, "name 1 = %s", m.name);
+ EXPECT(cfree_slice_eq_cstr(m.name, "b.o"), "name 1 = %.*s", CFREE_SLICE_ARG(m.name));
EXPECT(m.size == 5 && memcmp(m.data, "BBBBB", 5) == 0, "data 1");
EXPECT(!cfree_ar_iter_next(it, &m), "iter end");
@@ -175,35 +174,34 @@ static int test_basic_roundtrip(void) {
static int test_long_name_table(void) {
/* >15 chars triggers the // long-name table. */
- CfreeBytes ms[2];
+ CfreeArInput ms[2];
BufW bw;
- CfreeBytes in;
+ CfreeSlice in;
CfreeArIter* it = NULL;
CfreeArMember m;
CfreeArWriteOptions opts = {0};
int rc;
opts.long_names = 1;
- ms[0].name = "short.o";
- ms[0].data = (const uint8_t*)"x";
- ms[0].len = 1;
- ms[1].name = "this_name_is_long_enough.o";
- ms[1].data = (const uint8_t*)"yy";
- ms[1].len = 2;
+ ms[0].name = CFREE_SLICE_LIT("short.o");
+ ms[0].bytes.data = (const uint8_t*)"x";
+ ms[0].bytes.len = 1;
+ ms[1].name = CFREE_SLICE_LIT("this_name_is_long_enough.o");
+ ms[1].bytes.data = (const uint8_t*)"yy";
+ ms[1].bytes.len = 2;
bufw_init(&bw);
rc = cfree_ar_write(&bw.base, ms, 2, &opts);
EXPECT(rc == 0, "write rc=%d", rc);
- in.name = "test";
in.data = bw.data;
in.len = bw.len;
EXPECT(cfree_ar_iter_new(&g_ctx, &in, &it) == CFREE_OK, "iter_init");
EXPECT(cfree_ar_iter_next(it, &m), "first member");
- EXPECT(strcmp(m.name, "short.o") == 0, "name 0 = %s", m.name);
+ EXPECT(cfree_slice_eq_cstr(m.name, "short.o"), "name 0 = %.*s", CFREE_SLICE_ARG(m.name));
EXPECT(cfree_ar_iter_next(it, &m), "second member");
- EXPECT(strcmp(m.name, "this_name_is_long_enough.o") == 0, "long name = %s",
- m.name);
+ EXPECT(cfree_slice_eq_cstr(m.name, "this_name_is_long_enough.o"), "long name = %.*s",
+ CFREE_SLICE_ARG(m.name));
EXPECT(!cfree_ar_iter_next(it, &m), "iter end");
cfree_ar_iter_free(it);
@@ -212,9 +210,9 @@ static int test_long_name_table(void) {
}
static int test_symbol_index_empty(void) {
- CfreeBytes ms[1];
+ CfreeArInput ms[1];
BufW bw;
- CfreeBytes in;
+ CfreeSlice in;
CfreeArIter* it = NULL;
CfreeArMember m;
CfreeArWriteOptions opts = {0};
@@ -222,9 +220,9 @@ static int test_symbol_index_empty(void) {
uint32_t nsyms;
opts.symbol_index = 1;
- ms[0].name = "lonely.o";
- ms[0].data = (const uint8_t*)"P";
- ms[0].len = 1;
+ ms[0].name = CFREE_SLICE_LIT("lonely.o");
+ ms[0].bytes.data = (const uint8_t*)"P";
+ ms[0].bytes.len = 1;
bufw_init(&bw);
rc = cfree_ar_write(&bw.base, ms, 1, &opts);
@@ -238,12 +236,11 @@ static int test_symbol_index_empty(void) {
EXPECT(nsyms == 0, "nsyms = %u", nsyms);
/* Iterator should skip the `/` and yield only the user member. */
- in.name = "test";
in.data = bw.data;
in.len = bw.len;
EXPECT(cfree_ar_iter_new(&g_ctx, &in, &it) == CFREE_OK, "iter_init");
EXPECT(cfree_ar_iter_next(it, &m), "first user member");
- EXPECT(strcmp(m.name, "lonely.o") == 0, "name = %s", m.name);
+ EXPECT(cfree_slice_eq_cstr(m.name, "lonely.o"), "name = %.*s", CFREE_SLICE_ARG(m.name));
EXPECT(!cfree_ar_iter_next(it, &m), "iter end");
cfree_ar_iter_free(it);
@@ -253,10 +250,10 @@ static int test_symbol_index_empty(void) {
static int test_symbol_index_basic(void) {
/* 2 members with symbol lists; verify count, offsets, and names. */
- const char* a_syms[] = {"foo", "bar"};
- const char* b_syms[] = {"baz"};
+ CfreeSlice a_syms[] = {CFREE_SLICE_LIT("foo"), CFREE_SLICE_LIT("bar")};
+ CfreeSlice b_syms[] = {CFREE_SLICE_LIT("baz")};
CfreeArMemberSymbols msyms[2];
- CfreeBytes ms[2];
+ CfreeArInput ms[2];
BufW bw;
CfreeArWriteOptions opts = {0};
int rc;
@@ -270,18 +267,18 @@ static int test_symbol_index_basic(void) {
opts.symbol_index = 1;
opts.long_names = 1;
- msyms[0].names = (const char* const*)a_syms;
+ msyms[0].names = a_syms;
msyms[0].count = 2;
- msyms[1].names = (const char* const*)b_syms;
+ msyms[1].names = b_syms;
msyms[1].count = 1;
opts.member_symbols = msyms;
- ms[0].name = "a.o";
- ms[0].data = (const uint8_t*)"AAAA";
- ms[0].len = 4;
- ms[1].name = "b.o";
- ms[1].data = (const uint8_t*)"BBBBB";
- ms[1].len = 5;
+ ms[0].name = CFREE_SLICE_LIT("a.o");
+ ms[0].bytes.data = (const uint8_t*)"AAAA";
+ ms[0].bytes.len = 4;
+ ms[1].name = CFREE_SLICE_LIT("b.o");
+ ms[1].bytes.data = (const uint8_t*)"BBBBB";
+ ms[1].bytes.len = 5;
bufw_init(&bw);
rc = cfree_ar_write(&bw.base, ms, 2, &opts);
@@ -338,12 +335,12 @@ static int test_symbol_index_basic(void) {
static int test_symbol_index_with_long_names(void) {
/* `/` member must come BEFORE `//` long-name table, and offsets must
* still point at correct member-header positions. */
- const char* syms0[] = {"alpha"};
- const char* syms1[] = {"beta"};
+ CfreeSlice syms0[] = {CFREE_SLICE_LIT("alpha")};
+ CfreeSlice syms1[] = {CFREE_SLICE_LIT("beta")};
CfreeArMemberSymbols msyms[2];
- CfreeBytes ms[2];
+ CfreeArInput ms[2];
BufW bw;
- CfreeBytes in;
+ CfreeSlice in;
CfreeArIter* it = NULL;
CfreeArMember m;
CfreeArWriteOptions opts = {0};
@@ -356,18 +353,18 @@ static int test_symbol_index_with_long_names(void) {
opts.symbol_index = 1;
opts.long_names = 1;
- msyms[0].names = (const char* const*)syms0;
+ msyms[0].names = syms0;
msyms[0].count = 1;
- msyms[1].names = (const char* const*)syms1;
+ msyms[1].names = syms1;
msyms[1].count = 1;
opts.member_symbols = msyms;
- ms[0].name = "this_name_is_long_enough.o"; /* 26 chars → // */
- ms[0].data = (const uint8_t*)"X";
- ms[0].len = 1;
- ms[1].name = "short.o";
- ms[1].data = (const uint8_t*)"YY";
- ms[1].len = 2;
+ ms[0].name = CFREE_SLICE_LIT("this_name_is_long_enough.o"); /* 26 chars → // */
+ ms[0].bytes.data = (const uint8_t*)"X";
+ ms[0].bytes.len = 1;
+ ms[1].name = CFREE_SLICE_LIT("short.o");
+ ms[1].bytes.data = (const uint8_t*)"YY";
+ ms[1].bytes.len = 2;
bufw_init(&bw);
rc = cfree_ar_write(&bw.base, ms, 2, &opts);
@@ -407,15 +404,14 @@ static int test_symbol_index_with_long_names(void) {
EXPECT(memcmp(bw.data + m1_hdr, "short.o/", 8) == 0, "m1 hdr");
/* Iterator should walk past both /, // and yield 2 members. */
- in.name = "test";
in.data = bw.data;
in.len = bw.len;
EXPECT(cfree_ar_iter_new(&g_ctx, &in, &it) == CFREE_OK, "iter_init");
EXPECT(cfree_ar_iter_next(it, &m), "m0");
- EXPECT(strcmp(m.name, "this_name_is_long_enough.o") == 0, "m0 name = %s",
- m.name);
+ EXPECT(cfree_slice_eq_cstr(m.name, "this_name_is_long_enough.o"), "m0 name = %.*s",
+ CFREE_SLICE_ARG(m.name));
EXPECT(cfree_ar_iter_next(it, &m), "m1");
- EXPECT(strcmp(m.name, "short.o") == 0, "m1 name = %s", m.name);
+ EXPECT(cfree_slice_eq_cstr(m.name, "short.o"), "m1 name = %.*s", CFREE_SLICE_ARG(m.name));
EXPECT(!cfree_ar_iter_next(it, &m), "iter end");
/* Optional host cross-check. */
@@ -439,10 +435,10 @@ static int test_symbol_index_with_long_names(void) {
static int test_iter_skips_index(void) {
/* Make sure the iterator never surfaces the `/` member as a user member. */
- const char* s[] = {"only_sym"};
+ CfreeSlice s[] = {CFREE_SLICE_LIT("only_sym")};
CfreeArMemberSymbols msyms[1];
- CfreeBytes ms[1];
- CfreeBytes in;
+ CfreeArInput ms[1];
+ CfreeSlice in;
CfreeArIter* it = NULL;
CfreeArMember m;
BufW bw;
@@ -450,22 +446,21 @@ static int test_iter_skips_index(void) {
int seen = 0;
opts.symbol_index = 1;
- msyms[0].names = (const char* const*)s;
+ msyms[0].names = s;
msyms[0].count = 1;
opts.member_symbols = msyms;
- ms[0].name = "only.o";
- ms[0].data = (const uint8_t*)"Z";
- ms[0].len = 1;
+ ms[0].name = CFREE_SLICE_LIT("only.o");
+ ms[0].bytes.data = (const uint8_t*)"Z";
+ ms[0].bytes.len = 1;
bufw_init(&bw);
EXPECT(cfree_ar_write(&bw.base, ms, 1, &opts) == 0, "write");
- in.name = "test";
in.data = bw.data;
in.len = bw.len;
EXPECT(cfree_ar_iter_new(&g_ctx, &in, &it) == CFREE_OK, "iter_init");
while (cfree_ar_iter_next(it, &m)) {
- EXPECT(m.name[0] != '/' || m.name[1] != '\0',
+ EXPECT(!cfree_slice_eq_cstr(m.name, "/"),
"iter surfaced raw `/` member");
seen++;
}
@@ -479,7 +474,7 @@ static int test_iter_skips_index(void) {
static int test_empty_archive(void) {
/* nmembers == 0 with NULL members should produce a magic-only archive. */
BufW bw;
- CfreeBytes in;
+ CfreeSlice in;
CfreeArIter* it = NULL;
CfreeArMember m;
int rc;
@@ -490,7 +485,6 @@ static int test_empty_archive(void) {
EXPECT(bw.len == 8, "size = %zu", bw.len);
EXPECT(memcmp(bw.data, "!<arch>\n", 8) == 0, "magic only");
- in.name = "test";
in.data = bw.data;
in.len = bw.len;
EXPECT(cfree_ar_iter_new(&g_ctx, &in, &it) == CFREE_OK, "iter_init");
@@ -503,14 +497,14 @@ static int test_empty_archive(void) {
static int test_epoch_field(void) {
/* opts.epoch is written into ar_date for every member. */
- CfreeBytes ms[1];
+ CfreeArInput ms[1];
BufW bw;
CfreeArWriteOptions opts = {0};
int rc;
- ms[0].name = "x.o";
- ms[0].data = (const uint8_t*)"q";
- ms[0].len = 1;
+ ms[0].name = CFREE_SLICE_LIT("x.o");
+ ms[0].bytes.data = (const uint8_t*)"q";
+ ms[0].bytes.len = 1;
opts.epoch = 1234567890u;
bufw_init(&bw);
@@ -534,25 +528,24 @@ static int test_epoch_field(void) {
static int test_path_basename(void) {
/* Member name with path components is stored as basename only. */
- CfreeBytes ms[1];
+ CfreeArInput ms[1];
BufW bw;
- CfreeBytes in;
+ CfreeSlice in;
CfreeArIter* it = NULL;
CfreeArMember m;
- ms[0].name = "src/sub/foo.o";
- ms[0].data = (const uint8_t*)"D";
- ms[0].len = 1;
+ ms[0].name = CFREE_SLICE_LIT("src/sub/foo.o");
+ ms[0].bytes.data = (const uint8_t*)"D";
+ ms[0].bytes.len = 1;
bufw_init(&bw);
EXPECT(cfree_ar_write(&bw.base, ms, 1, NULL) == 0, "write");
- in.name = "test";
in.data = bw.data;
in.len = bw.len;
EXPECT(cfree_ar_iter_new(&g_ctx, &in, &it) == CFREE_OK, "iter_init");
EXPECT(cfree_ar_iter_next(it, &m), "first");
- EXPECT(strcmp(m.name, "foo.o") == 0, "basename = %s", m.name);
+ EXPECT(cfree_slice_eq_cstr(m.name, "foo.o"), "basename = %.*s", CFREE_SLICE_ARG(m.name));
cfree_ar_iter_free(it);
bufw_fini(&bw);
@@ -561,25 +554,24 @@ static int test_path_basename(void) {
static int test_truncate_when_long_names_off(void) {
/* >15 chars without long_names: name is truncated to 15. */
- CfreeBytes ms[1];
+ CfreeArInput ms[1];
BufW bw;
- CfreeBytes in;
+ CfreeSlice in;
CfreeArIter* it = NULL;
CfreeArMember m;
- ms[0].name = "abcdefghijklmnopqrst.o"; /* 22 chars */
- ms[0].data = (const uint8_t*)"D";
- ms[0].len = 1;
+ ms[0].name = CFREE_SLICE_LIT("abcdefghijklmnopqrst.o"); /* 22 chars */
+ ms[0].bytes.data = (const uint8_t*)"D";
+ ms[0].bytes.len = 1;
bufw_init(&bw);
EXPECT(cfree_ar_write(&bw.base, ms, 1, NULL) == 0, "write");
- in.name = "test";
in.data = bw.data;
in.len = bw.len;
EXPECT(cfree_ar_iter_new(&g_ctx, &in, &it) == CFREE_OK, "iter_init");
EXPECT(cfree_ar_iter_next(it, &m), "first");
- EXPECT(strcmp(m.name, "abcdefghijklmno") == 0, "truncated = %s", m.name);
+ EXPECT(cfree_slice_eq_cstr(m.name, "abcdefghijklmno"), "truncated = %.*s", CFREE_SLICE_ARG(m.name));
cfree_ar_iter_free(it);
bufw_fini(&bw);
@@ -588,17 +580,17 @@ static int test_truncate_when_long_names_off(void) {
static int test_name_15_char_boundary(void) {
/* Exactly 15 chars: fits in-header even with long_names enabled. */
- CfreeBytes ms[1];
+ CfreeArInput ms[1];
BufW bw;
- CfreeBytes in;
+ CfreeSlice in;
CfreeArIter* it = NULL;
CfreeArMember m;
CfreeArWriteOptions opts = {0};
opts.long_names = 1;
- ms[0].name = "abcdefghijklmno"; /* 15 chars */
- ms[0].data = (const uint8_t*)"X";
- ms[0].len = 1;
+ ms[0].name = CFREE_SLICE_LIT("abcdefghijklmno"); /* 15 chars */
+ ms[0].bytes.data = (const uint8_t*)"X";
+ ms[0].bytes.len = 1;
bufw_init(&bw);
EXPECT(cfree_ar_write(&bw.base, ms, 1, &opts) == 0, "write");
@@ -607,12 +599,11 @@ static int test_name_15_char_boundary(void) {
EXPECT(memcmp(bw.data + 8, "abcdefghijklmno/", 16) == 0, "name field = %.16s",
(const char*)(bw.data + 8));
- in.name = "test";
in.data = bw.data;
in.len = bw.len;
EXPECT(cfree_ar_iter_new(&g_ctx, &in, &it) == CFREE_OK, "iter_init");
EXPECT(cfree_ar_iter_next(it, &m), "first");
- EXPECT(strcmp(m.name, "abcdefghijklmno") == 0, "name = %s", m.name);
+ EXPECT(cfree_slice_eq_cstr(m.name, "abcdefghijklmno"), "name = %.*s", CFREE_SLICE_ARG(m.name));
cfree_ar_iter_free(it);
bufw_fini(&bw);
@@ -621,28 +612,27 @@ static int test_name_15_char_boundary(void) {
static int test_name_16_char_boundary(void) {
/* Exactly 16 chars: triggers // long-name table. */
- CfreeBytes ms[1];
+ CfreeArInput ms[1];
BufW bw;
- CfreeBytes in;
+ CfreeSlice in;
CfreeArIter* it = NULL;
CfreeArMember m;
CfreeArWriteOptions opts = {0};
opts.long_names = 1;
- ms[0].name = "abcdefghijklmnop"; /* 16 chars */
- ms[0].data = (const uint8_t*)"Y";
- ms[0].len = 1;
+ ms[0].name = CFREE_SLICE_LIT("abcdefghijklmnop"); /* 16 chars */
+ ms[0].bytes.data = (const uint8_t*)"Y";
+ ms[0].bytes.len = 1;
bufw_init(&bw);
EXPECT(cfree_ar_write(&bw.base, ms, 1, &opts) == 0, "write");
EXPECT(bw.data[8] == '/' && bw.data[9] == '/', "// header");
- in.name = "test";
in.data = bw.data;
in.len = bw.len;
EXPECT(cfree_ar_iter_new(&g_ctx, &in, &it) == CFREE_OK, "iter_init");
EXPECT(cfree_ar_iter_next(it, &m), "first");
- EXPECT(strcmp(m.name, "abcdefghijklmnop") == 0, "name = %s", m.name);
+ EXPECT(cfree_slice_eq_cstr(m.name, "abcdefghijklmnop"), "name = %.*s", CFREE_SLICE_ARG(m.name));
cfree_ar_iter_free(it);
bufw_fini(&bw);
@@ -651,33 +641,32 @@ static int test_name_16_char_boundary(void) {
static int test_empty_member_payload(void) {
/* len=0 (data=NULL): header only, no pad; followed by the next member. */
- CfreeBytes ms[2];
+ CfreeArInput ms[2];
BufW bw;
- CfreeBytes in;
+ CfreeSlice in;
CfreeArIter* it = NULL;
CfreeArMember m;
- ms[0].name = "empty.o";
- ms[0].data = NULL;
- ms[0].len = 0;
- ms[1].name = "next.o";
- ms[1].data = (const uint8_t*)"N";
- ms[1].len = 1;
+ ms[0].name = CFREE_SLICE_LIT("empty.o");
+ ms[0].bytes.data = NULL;
+ ms[0].bytes.len = 0;
+ ms[1].name = CFREE_SLICE_LIT("next.o");
+ ms[1].bytes.data = (const uint8_t*)"N";
+ ms[1].bytes.len = 1;
bufw_init(&bw);
EXPECT(cfree_ar_write(&bw.base, ms, 2, NULL) == 0, "write");
/* magic(8) + hdr(60) + 0 + hdr(60) + 1 + pad(1) = 130 */
EXPECT(bw.len == 130, "size = %zu", bw.len);
- in.name = "test";
in.data = bw.data;
in.len = bw.len;
EXPECT(cfree_ar_iter_new(&g_ctx, &in, &it) == CFREE_OK, "iter_init");
EXPECT(cfree_ar_iter_next(it, &m), "first");
- EXPECT(strcmp(m.name, "empty.o") == 0 && m.size == 0, "empty.o size=%zu",
+ EXPECT(cfree_slice_eq_cstr(m.name, "empty.o") && m.size == 0, "empty.o size=%zu",
m.size);
EXPECT(cfree_ar_iter_next(it, &m), "second");
- EXPECT(strcmp(m.name, "next.o") == 0 && m.size == 1 && m.data[0] == 'N',
+ EXPECT(cfree_slice_eq_cstr(m.name, "next.o") && m.size == 1 && m.data[0] == 'N',
"next.o");
EXPECT(!cfree_ar_iter_next(it, &m), "iter end");
@@ -688,18 +677,18 @@ static int test_empty_member_payload(void) {
static int test_odd_payload_pad(void) {
/* Odd-length payloads add a '\n' parity pad; even lengths do not. */
- CfreeBytes ms[3];
+ CfreeArInput ms[3];
BufW bw;
- ms[0].name = "a.o";
- ms[0].data = (const uint8_t*)"x";
- ms[0].len = 1;
- ms[1].name = "b.o";
- ms[1].data = (const uint8_t*)"yy";
- ms[1].len = 2;
- ms[2].name = "c.o";
- ms[2].data = (const uint8_t*)"z";
- ms[2].len = 1;
+ ms[0].name = CFREE_SLICE_LIT("a.o");
+ ms[0].bytes.data = (const uint8_t*)"x";
+ ms[0].bytes.len = 1;
+ ms[1].name = CFREE_SLICE_LIT("b.o");
+ ms[1].bytes.data = (const uint8_t*)"yy";
+ ms[1].bytes.len = 2;
+ ms[2].name = CFREE_SLICE_LIT("c.o");
+ ms[2].bytes.data = (const uint8_t*)"z";
+ ms[2].bytes.len = 1;
bufw_init(&bw);
EXPECT(cfree_ar_write(&bw.base, ms, 3, NULL) == 0, "write");
@@ -716,28 +705,27 @@ static int test_odd_payload_pad(void) {
static int test_ar_list_output(void) {
/* cfree_ar_list emits one user member per line, skipping / and //. */
- CfreeBytes ms[3];
+ CfreeArInput ms[3];
BufW bw, lw;
- CfreeBytes in;
+ CfreeSlice in;
CfreeArWriteOptions opts = {0};
const char* expected = "a.o\nlong_name_member.o\nb.o\n";
opts.symbol_index = 1;
opts.long_names = 1;
- ms[0].name = "a.o";
- ms[0].data = (const uint8_t*)"A";
- ms[0].len = 1;
- ms[1].name = "long_name_member.o";
- ms[1].data = (const uint8_t*)"B";
- ms[1].len = 1;
- ms[2].name = "b.o";
- ms[2].data = (const uint8_t*)"C";
- ms[2].len = 1;
+ ms[0].name = CFREE_SLICE_LIT("a.o");
+ ms[0].bytes.data = (const uint8_t*)"A";
+ ms[0].bytes.len = 1;
+ ms[1].name = CFREE_SLICE_LIT("long_name_member.o");
+ ms[1].bytes.data = (const uint8_t*)"B";
+ ms[1].bytes.len = 1;
+ ms[2].name = CFREE_SLICE_LIT("b.o");
+ ms[2].bytes.data = (const uint8_t*)"C";
+ ms[2].bytes.len = 1;
bufw_init(&bw);
EXPECT(cfree_ar_write(&bw.base, ms, 3, &opts) == 0, "write");
- in.name = "test";
in.data = bw.data;
in.len = bw.len;
bufw_init(&lw);
@@ -755,10 +743,9 @@ static int test_ar_list_output(void) {
static int test_iter_bad_magic(void) {
/* iter_init must reject non-ar inputs. */
static const uint8_t bad[] = "NOT-AN-AR";
- CfreeBytes in;
+ CfreeSlice in;
CfreeArIter* it = NULL;
- in.name = "bad";
in.data = bad;
in.len = sizeof(bad) - 1;
EXPECT(cfree_ar_iter_new(&g_ctx, &in, &it) != CFREE_OK,
@@ -777,10 +764,10 @@ static int test_iter_bad_magic(void) {
static int test_write_invalid_args(void) {
/* Bad argument combinations must return 1 from cfree_ar_write. */
- CfreeBytes ms[1];
+ CfreeArInput ms[1];
BufW bw;
CfreeArWriteOptions opts = {0};
- const char* bad_syms[1];
+ CfreeSlice bad_syms[1];
CfreeArMemberSymbols msyms[1];
bufw_init(&bw);
@@ -789,18 +776,18 @@ static int test_write_invalid_args(void) {
EXPECT(cfree_ar_write(&bw.base, NULL, 1, NULL) != CFREE_OK,
"NULL members with nmembers>0 rejected");
- ms[0].name = NULL;
- ms[0].data = (const uint8_t*)"X";
- ms[0].len = 1;
+ ms[0].name = CFREE_SLICE_NULL;
+ ms[0].bytes.data = (const uint8_t*)"X";
+ ms[0].bytes.len = 1;
EXPECT(cfree_ar_write(&bw.base, ms, 1, NULL) != CFREE_OK, "NULL name rejected");
/* NULL symbol-name with nonzero count. */
- bad_syms[0] = NULL;
- msyms[0].names = (const char* const*)bad_syms;
+ bad_syms[0] = CFREE_SLICE_NULL;
+ msyms[0].names = bad_syms;
msyms[0].count = 1;
opts.symbol_index = 1;
opts.member_symbols = msyms;
- ms[0].name = "ok.o";
+ ms[0].name = CFREE_SLICE_LIT("ok.o");
EXPECT(cfree_ar_write(&bw.base, ms, 1, &opts) != CFREE_OK,
"NULL symbol name rejected");
@@ -813,7 +800,7 @@ static int test_iter_skips_bsd_symdef(void) {
* iterator must not surface it. (cfree_ar_write never emits BSD indexes,
* but the iterator is documented to handle them on read.) */
BufW bw;
- CfreeBytes in;
+ CfreeSlice in;
CfreeArIter* it = NULL;
CfreeArMember m;
char hdr[60];
@@ -859,12 +846,11 @@ static int test_iter_skips_bsd_symdef(void) {
bw.base.write(&bw.base, hdr, 60);
bw.base.write(&bw.base, "U\n", 2);
- in.name = "bsd";
in.data = bw.data;
in.len = bw.len;
EXPECT(cfree_ar_iter_new(&g_ctx, &in, &it) == CFREE_OK, "iter_init");
while (cfree_ar_iter_next(it, &m)) {
- EXPECT(strcmp(m.name, "u.o") == 0, "unexpected name = %s", m.name);
+ EXPECT(cfree_slice_eq_cstr(m.name, "u.o"), "unexpected name = %.*s", CFREE_SLICE_ARG(m.name));
seen++;
}
EXPECT(seen == 1, "saw %d members", seen);
@@ -876,20 +862,19 @@ static int test_iter_skips_bsd_symdef(void) {
static int test_iter_data_aliases_archive(void) {
/* CfreeArMember.data must point into the archive's own bytes. */
- CfreeBytes ms[1];
+ CfreeArInput ms[1];
BufW bw;
- CfreeBytes in;
+ CfreeSlice in;
CfreeArIter* it = NULL;
CfreeArMember m;
- ms[0].name = "a.o";
- ms[0].data = (const uint8_t*)"PAYLOAD";
- ms[0].len = 7;
+ ms[0].name = CFREE_SLICE_LIT("a.o");
+ ms[0].bytes.data = (const uint8_t*)"PAYLOAD";
+ ms[0].bytes.len = 7;
bufw_init(&bw);
EXPECT(cfree_ar_write(&bw.base, ms, 1, NULL) == 0, "write");
- in.name = "test";
in.data = bw.data;
in.len = bw.len;
EXPECT(cfree_ar_iter_new(&g_ctx, &in, &it) == CFREE_OK, "iter_init");
@@ -906,9 +891,9 @@ static int test_iter_data_aliases_archive(void) {
static int test_symbol_index_partial_members(void) {
/* Members with 0 symbols mid-list: cur_offset must still advance for
* every member so later offsets land on the right header. */
- const char* mid_syms[] = {"midsym"};
+ CfreeSlice mid_syms[] = {CFREE_SLICE_LIT("midsym")};
CfreeArMemberSymbols msyms[3];
- CfreeBytes ms[3];
+ CfreeArInput ms[3];
BufW bw;
CfreeArWriteOptions opts = {0};
uint32_t nsyms, off;
@@ -917,21 +902,21 @@ static int test_symbol_index_partial_members(void) {
opts.symbol_index = 1;
msyms[0].names = NULL;
msyms[0].count = 0;
- msyms[1].names = (const char* const*)mid_syms;
+ msyms[1].names = mid_syms;
msyms[1].count = 1;
msyms[2].names = NULL;
msyms[2].count = 0;
opts.member_symbols = msyms;
- ms[0].name = "a.o";
- ms[0].data = (const uint8_t*)"AA";
- ms[0].len = 2;
- ms[1].name = "b.o";
- ms[1].data = (const uint8_t*)"BB";
- ms[1].len = 2;
- ms[2].name = "c.o";
- ms[2].data = (const uint8_t*)"CC";
- ms[2].len = 2;
+ ms[0].name = CFREE_SLICE_LIT("a.o");
+ ms[0].bytes.data = (const uint8_t*)"AA";
+ ms[0].bytes.len = 2;
+ ms[1].name = CFREE_SLICE_LIT("b.o");
+ ms[1].bytes.data = (const uint8_t*)"BB";
+ ms[1].bytes.len = 2;
+ ms[2].name = CFREE_SLICE_LIT("c.o");
+ ms[2].bytes.data = (const uint8_t*)"CC";
+ ms[2].bytes.len = 2;
bufw_init(&bw);
EXPECT(cfree_ar_write(&bw.base, ms, 3, &opts) == 0, "write");
diff --git a/test/arch/aa64_inline_test.c b/test/arch/aa64_inline_test.c
@@ -119,7 +119,7 @@ int main(void) {
ObjBuilder* ob = obj_new(c);
Pool* pool = c->global;
- ObjSecId text_sec = obj_section(ob, pool_intern_cstr(pool, ".text"),
+ ObjSecId text_sec = obj_section(ob, pool_intern_slice(pool, SLICE_LIT(".text")),
SEC_TEXT, SF_EXEC | SF_ALLOC, 4);
MCEmitter* mc = mc_new(c, ob);
mc->set_section(mc, text_sec);
@@ -139,7 +139,7 @@ int main(void) {
in_ops[0].v.reg = 9; /* x9 */
Sym clobs[1];
- clobs[0] = pool_intern_cstr(pool, "x0");
+ clobs[0] = pool_intern_slice(pool, SLICE_LIT("x0"));
u32 start = mc->pos(mc);
target->asm_block(target, "mov w0, %w0; svc #0",
diff --git a/test/arch/aa64_isa_test.c b/test/arch/aa64_isa_test.c
@@ -28,9 +28,9 @@ static void check(u32 word, const char* want_mnem, const char* want_ops_substr)
++fails;
return;
}
- if (strcmp(d->mnemonic, want_mnem) != 0) {
- fprintf(stderr, "FAIL 0x%08x: mnemonic = %s, want %s\n", word, d->mnemonic,
- want_mnem);
+ if (!slice_eq_cstr(d->mnemonic, want_mnem)) {
+ fprintf(stderr, "FAIL 0x%08x: mnemonic = %.*s, want %s\n", word,
+ SLICE_ARG(d->mnemonic), want_mnem);
++fails;
return;
}
@@ -175,10 +175,10 @@ int main(void) {
/* ORR X1, XZR, X2 with shift=0,imm6=0 should resolve to "mov", not "orr". */
u32 w = aa64_mov_reg(1, 1, 2);
const AA64InsnDesc* d = aa64_disasm_find(w);
- if (d == NULL || strcmp(d->mnemonic, "mov") != 0) {
+ if (d == NULL || !slice_eq_cstr(d->mnemonic, "mov")) {
fprintf(stderr,
- "FAIL: alias precedence — ORR-as-MOV resolved to %s (want mov)\n",
- d ? d->mnemonic : "(null)");
+ "FAIL: alias precedence — ORR-as-MOV resolved to %.*s (want mov)\n",
+ SLICE_ARG(d ? d->mnemonic : SLICE_LIT("(null)")));
++fails;
} else if (!(d->flags & AA64_ASMFL_ALIAS)) {
fprintf(stderr, "FAIL: alias precedence — resolved row missing ALIAS\n");
@@ -191,10 +191,10 @@ int main(void) {
{
u32 w = aa64_orr(1, 1, 3, 2);
const AA64InsnDesc* d = aa64_disasm_find(w);
- if (d == NULL || strcmp(d->mnemonic, "orr") != 0) {
+ if (d == NULL || !slice_eq_cstr(d->mnemonic, "orr")) {
fprintf(stderr,
- "FAIL: non-alias ORR resolved to %s (want orr)\n",
- d ? d->mnemonic : "(null)");
+ "FAIL: non-alias ORR resolved to %.*s (want orr)\n",
+ SLICE_ARG(d ? d->mnemonic : SLICE_LIT("(null)")));
++fails;
}
++cases;
diff --git a/test/arch/rv64_inline_test.c b/test/arch/rv64_inline_test.c
@@ -103,7 +103,7 @@ int main(void) {
ObjBuilder* ob = obj_new(c);
Pool* pool = c->global;
- ObjSecId text_sec = obj_section(ob, pool_intern_cstr(pool, ".text"),
+ ObjSecId text_sec = obj_section(ob, pool_intern_slice(pool, SLICE_LIT(".text")),
SEC_TEXT, SF_EXEC | SF_ALLOC, 4);
MCEmitter* mc = mc_new(c, ob);
mc->set_section(mc, text_sec);
@@ -248,7 +248,7 @@ int main(void) {
{
AsmConstraint outs[1] = {{0}};
outs[0].str = "=r";
- outs[0].name = pool_intern_cstr(pool, "sum");
+ outs[0].name = pool_intern_slice(pool, SLICE_LIT("sum"));
outs[0].dir = ASM_OUT;
Operand out_ops[1];
memset(out_ops, 0, sizeof out_ops);
@@ -258,10 +258,10 @@ int main(void) {
AsmConstraint ins[2] = {{0}, {0}};
ins[0].str = "r";
- ins[0].name = pool_intern_cstr(pool, "x");
+ ins[0].name = pool_intern_slice(pool, SLICE_LIT("x"));
ins[0].dir = ASM_IN;
ins[1].str = "r";
- ins[1].name = pool_intern_cstr(pool, "y");
+ ins[1].name = pool_intern_slice(pool, SLICE_LIT("y"));
ins[1].dir = ASM_IN;
Operand in_ops[2];
memset(in_ops, 0, sizeof in_ops);
@@ -324,7 +324,7 @@ int main(void) {
* callee-saved bookkeeping but accepted by the walker. ---- */
{
Sym clobs[1];
- clobs[0] = pool_intern_cstr(pool, "memory");
+ clobs[0] = pool_intern_slice(pool, SLICE_LIT("memory"));
u32 start = mc->pos(mc);
target->asm_block(target, "fence rw, rw",
NULL, 0, NULL, NULL, 0, NULL, clobs, 1);
diff --git a/test/arch/x64_inline_test.c b/test/arch/x64_inline_test.c
@@ -127,7 +127,7 @@ int main(void) {
ObjBuilder* ob = obj_new(c);
Pool* pool = c->global;
- ObjSecId text_sec = obj_section(ob, pool_intern_cstr(pool, ".text"),
+ ObjSecId text_sec = obj_section(ob, pool_intern_slice(pool, SLICE_LIT(".text")),
SEC_TEXT, SF_EXEC | SF_ALLOC, 16);
MCEmitter* mc = mc_new(c, ob);
mc->set_section(mc, text_sec);
@@ -399,7 +399,7 @@ int main(void) {
AsmConstraint outs[1] = {{0}};
outs[0].str = "=r";
outs[0].dir = ASM_OUT;
- outs[0].name = pool_intern_cstr(pool, "dst");
+ outs[0].name = pool_intern_slice(pool, SLICE_LIT("dst"));
Operand out_ops[1];
memset(out_ops, 0, sizeof out_ops);
out_ops[0].kind = OPK_REG;
@@ -410,7 +410,7 @@ int main(void) {
AsmConstraint ins[1] = {{0}};
ins[0].str = "r";
ins[0].dir = ASM_IN;
- ins[0].name = pool_intern_cstr(pool, "src");
+ ins[0].name = pool_intern_slice(pool, SLICE_LIT("src"));
Operand in_ops[1];
memset(in_ops, 0, sizeof in_ops);
in_ops[0].kind = OPK_REG;
diff --git a/test/asm/harness/asm_runner.c b/test/asm/harness/asm_runner.c
@@ -262,7 +262,7 @@ static void target_from_env(CfreeTarget* t) {
static CfreeStatus compile_asm_obj(CfreeCompiler* c,
const CfreeAsmCompileOptions* opts,
- const CfreeBytes* in,
+ CfreeSlice name, const CfreeSlice* in,
CfreeObjBuilder** out) {
CfreeCompileSessionOptions sopts;
CfreeCompileSession* session = NULL;
@@ -274,6 +274,7 @@ static CfreeStatus compile_asm_obj(CfreeCompiler* c,
sopts.compile.diagnostics = opts->diagnostics;
sopts.compile.language_options = opts;
memset(&sin, 0, sizeof(sin));
+ sin.name = name;
sin.bytes = *in;
sin.lang = CFREE_LANG_ASM;
st = cfree_compile_session_new(c, &sopts, &session);
@@ -284,9 +285,10 @@ static CfreeStatus compile_asm_obj(CfreeCompiler* c,
static CfreeStatus compile_asm_emit(CfreeCompiler* c,
const CfreeAsmCompileOptions* opts,
- const CfreeBytes* in, CfreeWriter* w) {
+ CfreeSlice name, const CfreeSlice* in,
+ CfreeWriter* w) {
CfreeObjBuilder* ob = NULL;
- CfreeStatus st = compile_asm_obj(c, opts, in, &ob);
+ CfreeStatus st = compile_asm_obj(c, opts, name, in, &ob);
if (st == CFREE_OK) st = cfree_obj_builder_emit(ob, w);
cfree_obj_builder_free(ob);
return st;
@@ -300,7 +302,7 @@ static CfreeStatus link_one_obj_jit(CfreeCompiler* c, CfreeObjBuilder* ob,
CfreeStatus st;
memset(&opts, 0, sizeof(opts));
opts.output_kind = CFREE_LINK_OUTPUT_JIT;
- opts.entry = entry;
+ opts.entry = cfree_slice_cstr(entry);
opts.jit_host = host;
st = cfree_link_session_new(c, &opts, &link);
if (st == CFREE_OK) st = cfree_link_session_add_obj(link, ob);
@@ -421,13 +423,13 @@ static int mode_encode(const char* src_path, const char* out_path) {
CfreeTarget tgt;
CfreeContext ctx;
CfreeCompiler* c = NULL;
- CfreeBytes in;
+ CfreeSlice in;
CfreeAsmCompileOptions opts;
CfreeWriter* w = NULL;
const uint8_t* obj_bytes;
size_t obj_len = 0;
CfreeObjFile* of = NULL;
- CfreeBytes obj_in;
+ CfreeSlice obj_in;
uint32_t nsec, i;
uint8_t* hex = NULL;
size_t hex_len = 0;
@@ -445,13 +447,13 @@ static int mode_encode(const char* src_path, const char* out_path) {
}
memset(&in, 0, sizeof in);
- in.name = src_path;
in.data = src;
in.len = src_len;
memset(&opts, 0, sizeof opts);
(void)cfree_writer_mem(&g_heap, &w);
- if (compile_asm_emit(c, &opts, &in, w) != CFREE_OK) {
+ if (compile_asm_emit(c, &opts, cfree_slice_cstr(src_path), &in, w) !=
+ CFREE_OK) {
cfree_writer_close(w);
cfree_compiler_free(c);
free(src);
@@ -460,10 +462,11 @@ static int mode_encode(const char* src_path, const char* out_path) {
obj_bytes = cfree_writer_mem_bytes(w, &obj_len);
memset(&obj_in, 0, sizeof obj_in);
- obj_in.name = src_path;
obj_in.data = obj_bytes;
obj_in.len = obj_len;
- if (cfree_obj_open(&ctx, &obj_in, &of) != CFREE_OK || !of) {
+ if (cfree_obj_open(&ctx, cfree_slice_cstr(src_path), &obj_in, &of) !=
+ CFREE_OK ||
+ !of) {
cfree_writer_close(w);
cfree_compiler_free(c);
free(src);
@@ -575,13 +578,13 @@ static int mode_decode(const char* in_path, const char* out_path) {
for (;;) {
CfreeIterResult r = cfree_disasm_iter_next(it, &ins);
if (r != CFREE_ITER_ITEM) break;
- fprintf(out, "%llx:\t%s", (unsigned long long)ins.vaddr,
- ins.mnemonic ? ins.mnemonic : "");
- if (ins.operands && ins.operands[0]) {
- fprintf(out, "\t%s", ins.operands);
+ fprintf(out, "%llx:\t%.*s", (unsigned long long)ins.vaddr,
+ CFREE_SLICE_ARG(ins.mnemonic));
+ if (ins.operands.len) {
+ fprintf(out, "\t%.*s", CFREE_SLICE_ARG(ins.operands));
}
- if (ins.annotation && ins.annotation[0]) {
- fprintf(out, " ; %s", ins.annotation);
+ if (ins.annotation.len) {
+ fprintf(out, " ; %.*s", CFREE_SLICE_ARG(ins.annotation));
}
fputc('\n', out);
}
@@ -603,7 +606,7 @@ static int mode_listing(const char* in_path, const char* out_path) {
CfreeTarget tgt;
CfreeContext ctx;
CfreeCompiler* c = NULL;
- CfreeBytes in;
+ CfreeSlice in;
CfreeWriter* w = NULL;
const uint8_t* data;
size_t len = 0;
@@ -621,7 +624,6 @@ static int mode_listing(const char* in_path, const char* out_path) {
}
memset(&in, 0, sizeof in);
- in.name = in_path;
in.data = bytes;
in.len = nbytes;
@@ -650,7 +652,7 @@ static int mode_emit(const char* src_path, const char* out_path) {
CfreeTarget tgt;
CfreeContext ctx;
CfreeCompiler* c = NULL;
- CfreeBytes in;
+ CfreeSlice in;
CfreeAsmCompileOptions opts;
CfreeWriter* w = NULL;
int rc = 0;
@@ -669,13 +671,13 @@ static int mode_emit(const char* src_path, const char* out_path) {
}
memset(&in, 0, sizeof in);
- in.name = src_path;
in.data = src;
in.len = src_len;
memset(&opts, 0, sizeof opts);
(void)cfree_writer_mem(&g_heap, &w);
- if (compile_asm_emit(c, &opts, &in, w) != CFREE_OK) {
+ if (compile_asm_emit(c, &opts, cfree_slice_cstr(src_path), &in, w) !=
+ CFREE_OK) {
cfree_writer_close(w);
cfree_compiler_free(c);
free(src);
@@ -707,7 +709,7 @@ static int mode_jit(const char* src_path) {
CfreeTarget tgt;
CfreeContext ctx;
CfreeCompiler* c = NULL;
- CfreeBytes in;
+ CfreeSlice in;
CfreeAsmCompileOptions opts;
CfreeObjBuilder* ob = NULL;
CfreeJitHost jhost;
@@ -727,12 +729,13 @@ static int mode_jit(const char* src_path) {
}
memset(&in, 0, sizeof in);
- in.name = src_path;
in.data = src;
in.len = src_len;
memset(&opts, 0, sizeof opts);
- if (compile_asm_obj(c, &opts, &in, &ob) != CFREE_OK || !ob) {
+ if (compile_asm_obj(c, &opts, cfree_slice_cstr(src_path), &in, &ob) !=
+ CFREE_OK ||
+ !ob) {
cfree_compiler_free(c);
free(src);
return 1;
@@ -747,14 +750,14 @@ static int mode_jit(const char* src_path) {
return 1;
}
- fn = (int (*)(void))cfree_jit_lookup(jit, "test_main");
+ fn = (int (*)(void))cfree_jit_lookup(jit, CFREE_SLICE_LIT("test_main"));
#if defined(__aarch64__) || defined(__arm64__)
{
- char* td_start = (char*)cfree_jit_lookup(jit, "__tdata_start");
- char* td_end = (char*)cfree_jit_lookup(jit, "__tdata_end");
+ char* td_start = (char*)cfree_jit_lookup(jit, CFREE_SLICE_LIT("__tdata_start"));
+ char* td_end = (char*)cfree_jit_lookup(jit, CFREE_SLICE_LIT("__tdata_end"));
unsigned long bs_n =
- (unsigned long)(unsigned long long)cfree_jit_lookup(jit, "__tbss_size");
+ (unsigned long)(unsigned long long)cfree_jit_lookup(jit, CFREE_SLICE_LIT("__tbss_size"));
if (td_start && td_end) {
unsigned long td_n = (unsigned long)(td_end - td_start);
unsigned long i;
diff --git a/test/coff/cfree-roundtrip-coff.c b/test/coff/cfree-roundtrip-coff.c
@@ -103,10 +103,9 @@ static void target_aa64_windows(CfreeTarget* t) {
/* ---- shape helpers ------------------------------------------------- */
static int sym_eq_str(Pool* p, Sym s, const char* want) {
- size_t len;
- const char* got = pool_str(p, s, &len);
+ Slice got = pool_slice(p, s);
size_t wlen = strlen(want);
- return got && len == wlen && memcmp(got, want, len) == 0;
+ return got.s && got.len == wlen && memcmp(got.s, want, got.len) == 0;
}
static const Section* find_section_named(const ObjBuilder* ob, Pool* p,
@@ -310,7 +309,7 @@ static void test_header_minimal_x64(void) {
}
ObjBuilder* ob = obj_new(c);
Pool* p = c->global;
- Sym text = pool_intern_cstr(p, ".text");
+ Sym text = pool_intern_slice(p, SLICE_LIT(".text"));
ObjSecId sec = obj_section(ob, text, SEC_TEXT, SF_ALLOC | SF_EXEC, 16);
obj_write(ob, sec, TEXT_X64, sizeof TEXT_X64);
obj_finalize(ob);
@@ -337,7 +336,7 @@ static void test_header_minimal_aa64(void) {
}
ObjBuilder* ob = obj_new(c);
Pool* p = c->global;
- Sym text = pool_intern_cstr(p, ".text");
+ Sym text = pool_intern_slice(p, SLICE_LIT(".text"));
ObjSecId sec = obj_section(ob, text, SEC_TEXT, SF_ALLOC | SF_EXEC, 4);
obj_write(ob, sec, TEXT_AA64, sizeof TEXT_AA64);
obj_finalize(ob);
@@ -380,8 +379,8 @@ static void test_text_only_x64(void) {
}
ObjBuilder* ob = obj_new(c);
Pool* p = c->global;
- Sym tn = pool_intern_cstr(p, ".text");
- Sym mn = pool_intern_cstr(p, "main");
+ Sym tn = pool_intern_slice(p, SLICE_LIT(".text"));
+ Sym mn = pool_intern_slice(p, SLICE_LIT("main"));
ObjSecId sec = obj_section(ob, tn, SEC_TEXT, SF_ALLOC | SF_EXEC, 16);
obj_write(ob, sec, TEXT_X64, sizeof TEXT_X64);
obj_symbol(ob, mn, SB_GLOBAL, SK_FUNC, sec, 0, sizeof TEXT_X64);
@@ -410,8 +409,8 @@ static void test_text_only_aa64(void) {
}
ObjBuilder* ob = obj_new(c);
Pool* p = c->global;
- Sym tn = pool_intern_cstr(p, ".text");
- Sym mn = pool_intern_cstr(p, "main");
+ Sym tn = pool_intern_slice(p, SLICE_LIT(".text"));
+ Sym mn = pool_intern_slice(p, SLICE_LIT("main"));
ObjSecId sec = obj_section(ob, tn, SEC_TEXT, SF_ALLOC | SF_EXEC, 4);
obj_write(ob, sec, TEXT_AA64, sizeof TEXT_AA64);
obj_symbol(ob, mn, SB_GLOBAL, SK_FUNC, sec, 0, sizeof TEXT_AA64);
@@ -455,8 +454,8 @@ static void test_rodata(void) {
}
ObjBuilder* ob = obj_new(c);
Pool* p = c->global;
- Sym rdn = pool_intern_cstr(p, ".rdata");
- Sym kn = pool_intern_cstr(p, "kMsg");
+ Sym rdn = pool_intern_slice(p, SLICE_LIT(".rdata"));
+ Sym kn = pool_intern_slice(p, SLICE_LIT("kMsg"));
ObjSecId sec = obj_section(ob, rdn, SEC_RODATA, SF_ALLOC, 8);
static const uint8_t MSG[12] = "hello world\0";
obj_write(ob, sec, MSG, sizeof MSG);
@@ -497,8 +496,8 @@ static void test_bss(void) {
}
ObjBuilder* ob = obj_new(c);
Pool* p = c->global;
- Sym bn = pool_intern_cstr(p, ".bss");
- Sym vn = pool_intern_cstr(p, "g_buf");
+ Sym bn = pool_intern_slice(p, SLICE_LIT(".bss"));
+ Sym vn = pool_intern_slice(p, SLICE_LIT("g_buf"));
ObjSecId sec = obj_section_ex(ob, bn, SEC_BSS, SSEM_NOBITS,
SF_ALLOC | SF_WRITE, 16, 0, 0, 0);
obj_reserve_bss(ob, sec, 64, 16);
@@ -561,8 +560,8 @@ static void test_data_with_reloc_abs64_x64(void) {
}
ObjBuilder* ob = obj_new(c);
Pool* p = c->global;
- Sym dn = pool_intern_cstr(p, ".data");
- Sym fn = pool_intern_cstr(p, "foo_extern");
+ Sym dn = pool_intern_slice(p, SLICE_LIT(".data"));
+ Sym fn = pool_intern_slice(p, SLICE_LIT("foo_extern"));
ObjSecId sec = obj_section(ob, dn, SEC_DATA, SF_ALLOC | SF_WRITE, 8);
static const uint8_t zero8[8] = {0};
obj_write(ob, sec, zero8, sizeof zero8);
@@ -593,8 +592,8 @@ static void test_data_with_reloc_abs64_aa64(void) {
}
ObjBuilder* ob = obj_new(c);
Pool* p = c->global;
- Sym dn = pool_intern_cstr(p, ".data");
- Sym fn = pool_intern_cstr(p, "foo_extern");
+ Sym dn = pool_intern_slice(p, SLICE_LIT(".data"));
+ Sym fn = pool_intern_slice(p, SLICE_LIT("foo_extern"));
ObjSecId sec = obj_section(ob, dn, SEC_DATA, SF_ALLOC | SF_WRITE, 8);
static const uint8_t zero8[8] = {0};
obj_write(ob, sec, zero8, sizeof zero8);
@@ -646,8 +645,8 @@ static void test_data_with_reloc_rel32_x64(void) {
}
ObjBuilder* ob = obj_new(c);
Pool* p = c->global;
- Sym tn = pool_intern_cstr(p, ".text");
- Sym hn = pool_intern_cstr(p, "helper");
+ Sym tn = pool_intern_slice(p, SLICE_LIT(".text"));
+ Sym hn = pool_intern_slice(p, SLICE_LIT("helper"));
ObjSecId sec = obj_section(ob, tn, SEC_TEXT, SF_ALLOC | SF_EXEC, 16);
/* call helper ; ret — e8 disp32 c3 (disp filled by reloc). */
static const uint8_t bytes[6] = {0xe8, 0, 0, 0, 0, 0xc3};
@@ -703,8 +702,8 @@ static void test_aa64_branch26(void) {
}
ObjBuilder* ob = obj_new(c);
Pool* p = c->global;
- Sym tn = pool_intern_cstr(p, ".text");
- Sym cn = pool_intern_cstr(p, "callee");
+ Sym tn = pool_intern_slice(p, SLICE_LIT(".text"));
+ Sym cn = pool_intern_slice(p, SLICE_LIT("callee"));
ObjSecId sec = obj_section(ob, tn, SEC_TEXT, SF_ALLOC | SF_EXEC, 4);
/* bl callee ; ret — both 4 bytes; disp filled by reloc. */
static const uint8_t bytes[8] = {0, 0, 0, 0x94, 0xc0, 0x03, 0x5f, 0xd6};
@@ -757,9 +756,9 @@ static void test_aa64_pagebase_pageoffset(void) {
}
ObjBuilder* ob = obj_new(c);
Pool* p = c->global;
- Sym tn = pool_intern_cstr(p, ".text");
- Sym rdn = pool_intern_cstr(p, ".rdata");
- Sym kn = pool_intern_cstr(p, "kStr");
+ Sym tn = pool_intern_slice(p, SLICE_LIT(".text"));
+ Sym rdn = pool_intern_slice(p, SLICE_LIT(".rdata"));
+ Sym kn = pool_intern_slice(p, SLICE_LIT("kStr"));
ObjSecId tsec = obj_section(ob, tn, SEC_TEXT, SF_ALLOC | SF_EXEC, 4);
ObjSecId rsec = obj_section(ob, rdn, SEC_RODATA, SF_ALLOC, 8);
/* adrp x0, kStr ; add x0, x0, :lo12:kStr ; ret. */
@@ -807,7 +806,7 @@ static void test_long_section_name(void) {
}
ObjBuilder* ob = obj_new(c);
Pool* p = c->global;
- Sym nm = pool_intern_cstr(p, ".text$long_name_section");
+ Sym nm = pool_intern_slice(p, SLICE_LIT(".text$long_name_section"));
ObjSecId sec = obj_section(ob, nm, SEC_TEXT, SF_ALLOC | SF_EXEC, 16);
obj_write(ob, sec, TEXT_X64, sizeof TEXT_X64);
obj_finalize(ob);
@@ -848,8 +847,8 @@ static void test_long_symbol_name(void) {
}
ObjBuilder* ob = obj_new(c);
Pool* p = c->global;
- Sym tn = pool_intern_cstr(p, ".text");
- Sym sn = pool_intern_cstr(p, "very_long_symbol_name");
+ Sym tn = pool_intern_slice(p, SLICE_LIT(".text"));
+ Sym sn = pool_intern_slice(p, SLICE_LIT("very_long_symbol_name"));
ObjSecId sec = obj_section(ob, tn, SEC_TEXT, SF_ALLOC | SF_EXEC, 16);
obj_write(ob, sec, TEXT_X64, sizeof TEXT_X64);
obj_symbol(ob, sn, SB_GLOBAL, SK_FUNC, sec, 0, sizeof TEXT_X64);
@@ -891,8 +890,8 @@ static void test_weak_global(void) {
}
ObjBuilder* ob = obj_new(c);
Pool* p = c->global;
- Sym tn = pool_intern_cstr(p, ".text");
- Sym wn = pool_intern_cstr(p, "weak_sym");
+ Sym tn = pool_intern_slice(p, SLICE_LIT(".text"));
+ Sym wn = pool_intern_slice(p, SLICE_LIT("weak_sym"));
ObjSecId sec = obj_section(ob, tn, SEC_TEXT, SF_ALLOC | SF_EXEC, 16);
obj_write(ob, sec, TEXT_X64, sizeof TEXT_X64);
obj_symbol(ob, wn, SB_WEAK, SK_FUNC, sec, 0, sizeof TEXT_X64);
@@ -936,7 +935,7 @@ static void test_common_symbol(void) {
}
ObjBuilder* ob = obj_new(c);
Pool* p = c->global;
- Sym cn = pool_intern_cstr(p, "common_var");
+ Sym cn = pool_intern_slice(p, SLICE_LIT("common_var"));
obj_symbol_ex(ob, cn, SB_GLOBAL, SV_DEFAULT, SK_COMMON, OBJ_SEC_NONE, 0, 128,
1);
obj_finalize(ob);
@@ -1003,9 +1002,9 @@ static void test_comdat_group(void) {
* symbol's name is truncated on emit but the reader compares the
* resolved long name. See CORPUS.md §10 / src/obj/coff_read.c
* is_section_sym logic. */
- Sym tn = pool_intern_cstr(p, ".text$x");
- Sym dn = pool_intern_cstr(p, ".data$x");
- Sym sign = pool_intern_cstr(p, "inline_fn");
+ Sym tn = pool_intern_slice(p, SLICE_LIT(".text$x"));
+ Sym dn = pool_intern_slice(p, SLICE_LIT(".data$x"));
+ Sym sign = pool_intern_slice(p, SLICE_LIT("inline_fn"));
ObjSecId tsec = obj_section(ob, tn, SEC_TEXT,
SF_ALLOC | SF_EXEC | SF_GROUP, 16);
@@ -1060,8 +1059,8 @@ static void test_static_local_symbol(void) {
}
ObjBuilder* ob = obj_new(c);
Pool* p = c->global;
- Sym tn = pool_intern_cstr(p, ".text");
- Sym ln = pool_intern_cstr(p, "local_fn");
+ Sym tn = pool_intern_slice(p, SLICE_LIT(".text"));
+ Sym ln = pool_intern_slice(p, SLICE_LIT("local_fn"));
ObjSecId sec = obj_section(ob, tn, SEC_TEXT, SF_ALLOC | SF_EXEC, 16);
obj_write(ob, sec, TEXT_X64, sizeof TEXT_X64);
obj_symbol(ob, ln, SB_LOCAL, SK_FUNC, sec, 0, sizeof TEXT_X64);
@@ -1113,17 +1112,17 @@ static void test_section_symbol_synthesis(void) {
ObjBuilder* ob = obj_new(c);
Pool* p = c->global;
- ObjSecId text = obj_section(ob, pool_intern_cstr(p, ".text"), SEC_TEXT,
+ ObjSecId text = obj_section(ob, pool_intern_slice(p, SLICE_LIT(".text")), SEC_TEXT,
SF_ALLOC | SF_EXEC, 16);
obj_write(ob, text, TEXT_X64, sizeof TEXT_X64);
- ObjSecId data = obj_section(ob, pool_intern_cstr(p, ".data"), SEC_DATA,
+ ObjSecId data = obj_section(ob, pool_intern_slice(p, SLICE_LIT(".data")), SEC_DATA,
SF_ALLOC | SF_WRITE, 8);
static const uint8_t z8[8] = {0};
obj_write(ob, data, z8, sizeof z8);
- ObjSecId rdata = obj_section(ob, pool_intern_cstr(p, ".rdata"), SEC_RODATA,
+ ObjSecId rdata = obj_section(ob, pool_intern_slice(p, SLICE_LIT(".rdata")), SEC_RODATA,
SF_ALLOC, 8);
obj_write(ob, rdata, "hi\0", 3);
- ObjSecId bss = obj_section_ex(ob, pool_intern_cstr(p, ".bss"), SEC_BSS,
+ ObjSecId bss = obj_section_ex(ob, pool_intern_slice(p, SLICE_LIT(".bss")), SEC_BSS,
SSEM_NOBITS, SF_ALLOC | SF_WRITE, 8, 0, 0, 0);
obj_reserve_bss(ob, bss, 16, 8);
@@ -1164,8 +1163,8 @@ static void test_tls_section(void) {
}
ObjBuilder* ob = obj_new(c);
Pool* p = c->global;
- Sym nm = pool_intern_cstr(p, ".tls$");
- Sym vn = pool_intern_cstr(p, "tls_var");
+ Sym nm = pool_intern_slice(p, SLICE_LIT(".tls$"));
+ Sym vn = pool_intern_slice(p, SLICE_LIT("tls_var"));
ObjSecId sec = obj_section(ob, nm, SEC_DATA, SF_ALLOC | SF_WRITE | SF_TLS, 8);
static const uint8_t z8[8] = {0};
obj_write(ob, sec, z8, sizeof z8);
@@ -1206,7 +1205,7 @@ static void test_align_nibble(void) {
}
ObjBuilder* ob = obj_new(c);
Pool* p = c->global;
- Sym nm = pool_intern_cstr(p, ".rdata");
+ Sym nm = pool_intern_slice(p, SLICE_LIT(".rdata"));
ObjSecId sec = obj_section(ob, nm, SEC_RODATA, SF_ALLOC, 4096);
static const uint8_t z[16] = {0};
obj_write(ob, sec, z, sizeof z);
diff --git a/test/coff/pe-dso-forwarder.c b/test/coff/pe-dso-forwarder.c
@@ -236,7 +236,7 @@ static void build_dso(uint8_t* buf) {
/* ---- main --------------------------------------------------------- */
static int has_sym(const ObjBuilder* ob, Pool* p, const char* name) {
- Sym needle = pool_intern_cstr(p, name);
+ Sym needle = pool_intern_slice(p, slice_from_cstr(name));
ObjSymIter* it = obj_symiter_new(ob);
ObjSymEntry e;
int found = 0;
@@ -279,7 +279,7 @@ int main(void) {
EXPECT(ob != NULL, "read_coff_dso returned NULL");
/* soname propagated from the Export Directory's Name field. */
- Sym expected_soname = pool_intern_cstr(c->global, kDllName);
+ Sym expected_soname = pool_intern_slice(c->global, slice_from_cstr(kDllName));
EXPECT(soname == expected_soname,
"soname mismatch (expected interned \"%s\")", kDllName);
diff --git a/test/coff/pe-import-mingw.c b/test/coff/pe-import-mingw.c
@@ -118,9 +118,9 @@ static Compiler* make_compiler(const CfreeTarget* t) {
static ObjBuilder* build_program(Compiler* c) {
ObjBuilder* ob = obj_new(c);
Pool* p = c->global;
- Sym text_name = pool_intern_cstr(p, ".text");
- Sym main_name = pool_intern_cstr(p, "mainCRTStartup");
- Sym exit_name = pool_intern_cstr(p, MINGW_IMPORT_FN);
+ Sym text_name = pool_intern_slice(p, SLICE_LIT(".text"));
+ Sym main_name = pool_intern_slice(p, SLICE_LIT("mainCRTStartup"));
+ Sym exit_name = pool_intern_slice(p, SLICE_LIT(MINGW_IMPORT_FN));
ObjSecId text = obj_section(ob, text_name, SEC_TEXT,
SF_ALLOC | SF_EXEC, 16);
obj_write(ob, text, PROG_TEXT_X64, sizeof PROG_TEXT_X64);
@@ -282,7 +282,7 @@ int main(void) {
/* Sanity: ExitProcess should be present and marked imported. */
{
- Sym exit_name = pool_intern_cstr(c->global, MINGW_IMPORT_FN);
+ Sym exit_name = pool_intern_slice(c->global, SLICE_LIT(MINGW_IMPORT_FN));
const LinkSymbol* found = NULL;
for (LinkSymId i = 1;; ++i) {
const LinkSymbol* s = link_symbol(img, i);
diff --git a/test/coff/pe-import-smoke.c b/test/coff/pe-import-smoke.c
@@ -160,9 +160,9 @@ static void build_short_import_amd64(uint8_t buf[SHIM_TOTAL_LEN]) {
static ObjBuilder* build_program(Compiler* c) {
ObjBuilder* ob = obj_new(c);
Pool* p = c->global;
- Sym text_name = pool_intern_cstr(p, ".text");
- Sym main_name = pool_intern_cstr(p, "mainCRTStartup");
- Sym exit_name = pool_intern_cstr(p, SHIM_SYM_CSTR);
+ Sym text_name = pool_intern_slice(p, SLICE_LIT(".text"));
+ Sym main_name = pool_intern_slice(p, SLICE_LIT("mainCRTStartup"));
+ Sym exit_name = pool_intern_slice(p, SLICE_LIT(SHIM_SYM_CSTR));
ObjSecId text = obj_section(ob, text_name, SEC_TEXT,
SF_ALLOC | SF_EXEC, 16);
obj_write(ob, text, PROG_TEXT_X64, sizeof PROG_TEXT_X64);
@@ -274,7 +274,7 @@ int main(void) {
* holds defined symbols, so link_symbol_lookup can't find an imported
* undef by name — iterate the dense LinkSyms array instead. */
{
- Sym exit_name = pool_intern_cstr(c->global, SHIM_SYM_CSTR);
+ Sym exit_name = pool_intern_slice(c->global, SLICE_LIT(SHIM_SYM_CSTR));
const LinkSymbol* found = NULL;
/* link_symbol returns NULL once we walk off the end. */
for (LinkSymId i = 1;; ++i) {
diff --git a/test/coff/pe-mixed-archive.c b/test/coff/pe-mixed-archive.c
@@ -151,8 +151,8 @@ static void build_short_import_amd64(uint8_t buf[SHIM_TOTAL_LEN]) {
static uint8_t* build_helper_object(Compiler* c, size_t* len_out) {
ObjBuilder* ob = obj_new(c);
Pool* p = c->global;
- Sym data_name = pool_intern_cstr(p, ".data");
- Sym helper_name = pool_intern_cstr(p, HELPER_SYM_CSTR);
+ Sym data_name = pool_intern_slice(p, SLICE_LIT(".data"));
+ Sym helper_name = pool_intern_slice(p, SLICE_LIT(HELPER_SYM_CSTR));
ObjSecId data = obj_section(ob, data_name, SEC_DATA,
SF_ALLOC | SF_WRITE, 4);
static const uint8_t kHelperBytes[4] = {0x2A, 0x00, 0x00, 0x00};
@@ -178,10 +178,10 @@ static uint8_t* build_helper_object(Compiler* c, size_t* len_out) {
static ObjBuilder* build_program(Compiler* c) {
ObjBuilder* ob = obj_new(c);
Pool* p = c->global;
- Sym text_name = pool_intern_cstr(p, ".text");
- Sym main_name = pool_intern_cstr(p, "mainCRTStartup");
- Sym import_name = pool_intern_cstr(p, SHIM_SYM_CSTR);
- Sym helper_name = pool_intern_cstr(p, HELPER_SYM_CSTR);
+ Sym text_name = pool_intern_slice(p, SLICE_LIT(".text"));
+ Sym main_name = pool_intern_slice(p, SLICE_LIT("mainCRTStartup"));
+ Sym import_name = pool_intern_slice(p, SLICE_LIT(SHIM_SYM_CSTR));
+ Sym helper_name = pool_intern_slice(p, SLICE_LIT(HELPER_SYM_CSTR));
ObjSecId text = obj_section(ob, text_name, SEC_TEXT,
SF_ALLOC | SF_EXEC, 16);
obj_write(ob, text, PROG_TEXT_X64, sizeof PROG_TEXT_X64);
@@ -234,13 +234,13 @@ int main(void) {
* every member regardless of the symbol index, so symbol_index=0 is
* sufficient — the linker rediscovers each member's exports during
* scan_presence_before. */
- CfreeBytes members[2];
- members[0].name = "importfn.o";
- members[0].data = shim;
- members[0].len = SHIM_TOTAL_LEN;
- members[1].name = "helper.o";
- members[1].data = helper_bytes;
- members[1].len = helper_len;
+ CfreeArInput members[2];
+ members[0].name = CFREE_SLICE_LIT("importfn.o");
+ members[0].bytes.data = shim;
+ members[0].bytes.len = SHIM_TOTAL_LEN;
+ members[1].name = CFREE_SLICE_LIT("helper.o");
+ members[1].bytes.data = helper_bytes;
+ members[1].bytes.len = helper_len;
CfreeWriter* aw = NULL;
if (cfree_writer_mem(&g_heap, &aw) != CFREE_OK || !aw) {
@@ -289,8 +289,8 @@ int main(void) {
LinkImage* img = link_resolve(l);
EXPECT(img != NULL, "link_resolve returned NULL");
if (img) {
- Sym import_name = pool_intern_cstr(c->global, SHIM_SYM_CSTR);
- Sym helper_name = pool_intern_cstr(c->global, HELPER_SYM_CSTR);
+ Sym import_name = pool_intern_slice(c->global, SLICE_LIT(SHIM_SYM_CSTR));
+ Sym helper_name = pool_intern_slice(c->global, SLICE_LIT(HELPER_SYM_CSTR));
const LinkSymbol* importf = NULL;
const LinkSymbol* helper = NULL;
for (LinkSymId i = 1;; ++i) {
diff --git a/test/debug/cfi_unit.c b/test/debug/cfi_unit.c
@@ -71,9 +71,9 @@ static const Section* sec_by_name(const ObjBuilder* ob, Pool* pool,
u32 i, n = obj_section_count(ob);
for (i = 1; i < n; ++i) {
const Section* s = obj_section_get(ob, i);
- size_t len = 0;
- const char* sn = pool_str(pool, s->name, &len);
- if (sn && strlen(name) == len && memcmp(sn, name, len) == 0) return s;
+ Slice sn = pool_slice(pool, s->name);
+ if (sn.s && strlen(name) == sn.len && memcmp(sn.s, name, sn.len) == 0)
+ return s;
}
return NULL;
}
@@ -154,9 +154,9 @@ static void check_arch(const CfiExpect* ex) {
ob = obj_new(c);
pool = c->global;
- text_sec = obj_section(ob, pool_intern_cstr(pool, ".text"), SEC_TEXT,
+ text_sec = obj_section(ob, pool_intern_slice(pool, SLICE_LIT(".text")), SEC_TEXT,
SF_EXEC | SF_ALLOC, 4);
- fsym = obj_symbol(ob, pool_intern_cstr(pool, "f"), SB_GLOBAL, SK_FUNC,
+ fsym = obj_symbol(ob, pool_intern_slice(pool, SLICE_LIT("f")), SB_GLOBAL, SK_FUNC,
text_sec, 0, 16);
mc = mc_new(c, ob);
diff --git a/test/debug/roundtrip_unit.c b/test/debug/roundtrip_unit.c
@@ -79,9 +79,9 @@ static const Section* sec_by_name(const ObjBuilder* ob, Pool* pool,
u32 i, n = obj_section_count(ob);
for (i = 1; i < n; ++i) {
const Section* s = obj_section_get(ob, i);
- size_t len = 0;
- const char* sn = pool_str(pool, s->name, &len);
- if (sn && strlen(name) == len && memcmp(sn, name, len) == 0) return s;
+ Slice sn = pool_slice(pool, s->name);
+ if (sn.s && strlen(name) == sn.len && memcmp(sn.s, name, sn.len) == 0)
+ return s;
}
return NULL;
}
@@ -140,14 +140,14 @@ static int run_one(CfreeArchKind arch, uint32_t nop_word, const char* tag) {
pool = c->global;
/* .text section + symbol "f". */
- text_sec = obj_section(ob, pool_intern_cstr(pool, ".text"), SEC_TEXT,
+ text_sec = obj_section(ob, pool_intern_slice(pool, SLICE_LIT(".text")), SEC_TEXT,
SF_EXEC | SF_ALLOC, 4);
/* one 4-byte arch nop */
{
u32 nop = nop_word;
obj_write(ob, text_sec, &nop, 4);
}
- fsym = obj_symbol(ob, pool_intern_cstr(pool, "f"), SB_GLOBAL, SK_FUNC,
+ fsym = obj_symbol(ob, pool_intern_slice(pool, SLICE_LIT("f")), SB_GLOBAL, SK_FUNC,
text_sec, 0, 4);
/* Drive Debug. */
@@ -164,7 +164,7 @@ static int run_one(CfreeArchKind arch, uint32_t nop_word, const char* tag) {
SrcLoc decl = {fid, 1, 0};
SrcLoc l10 = {fid, 10, 0};
DebugTypeId int_tid =
- debug_type_base(d, pool_intern_cstr(pool, "int"), DEBUG_BE_SIGNED, 4);
+ debug_type_base(d, pool_intern_slice(pool, SLICE_LIT("int")), DEBUG_BE_SIGNED, 4);
DebugTypeId fn_tid = debug_type_func(d, int_tid, NULL, 0, 0);
/* Pre-register the file as DWARF index 0 = primary. */
(void)debug_file(d, fid);
@@ -290,12 +290,13 @@ static int run_one(CfreeArchKind arch, uint32_t nop_word, const char* tag) {
* f8=fs0=40) and aa64 still resolves x0..x30/sp by their DWARF indices. */
static void check_reg(CfreeArchKind arch, const char* tag, uint32_t expect_idx,
const char* expect_name) {
- const char* nm = cfree_arch_register_name(arch, expect_idx);
+ CfreeSlice nm = cfree_arch_register_name(arch, expect_idx);
uint32_t got_idx = 0u;
- CfreeStatus st = cfree_arch_register_index(arch, expect_name, &got_idx);
- EXPECT(nm != NULL && strcmp(nm, expect_name) == 0,
- "[%s] register_name(%u) expected %s, got %s", tag, expect_idx,
- expect_name, nm ? nm : "(null)");
+ CfreeStatus st =
+ cfree_arch_register_index(arch, cfree_slice_cstr(expect_name), &got_idx);
+ EXPECT(nm.s != NULL && cfree_slice_eq_cstr(nm, expect_name),
+ "[%s] register_name(%u) expected %s, got %.*s", tag, expect_idx,
+ expect_name, CFREE_SLICE_ARG(nm));
EXPECT(st == CFREE_OK && got_idx == expect_idx,
"[%s] register_index(%s) expected %u, got %u (status %d)", tag,
expect_name, expect_idx, got_idx, (int)st);
@@ -321,7 +322,8 @@ static void run_arch_register_checks(void) {
/* "fp" alias for s0/x8 on rv64. */
{
uint32_t idx = 0;
- CfreeStatus st = cfree_arch_register_index(CFREE_ARCH_RV64, "fp", &idx);
+ CfreeStatus st = cfree_arch_register_index(
+ CFREE_ARCH_RV64, CFREE_SLICE_LIT("fp"), &idx);
EXPECT(st == CFREE_OK && idx == 8,
"[rv64] register_index(fp) expected 8, got %u (status %d)",
idx, (int)st);
@@ -351,13 +353,13 @@ static int run_x64_debug_line_check(void) {
xob = obj_new(xc);
xpool = xc->global;
- xtext_sec = obj_section(xob, pool_intern_cstr(xpool, ".text"), SEC_TEXT,
+ xtext_sec = obj_section(xob, pool_intern_slice(xpool, SLICE_LIT(".text")), SEC_TEXT,
SF_EXEC | SF_ALLOC, 1);
{
u8 code[2] = {0x90, 0xc3}; /* nop; ret */
obj_write(xob, xtext_sec, code, sizeof(code));
}
- xfsym = obj_symbol(xob, pool_intern_cstr(xpool, "xf"), SB_GLOBAL, SK_FUNC,
+ xfsym = obj_symbol(xob, pool_intern_slice(xpool, SLICE_LIT("xf")), SB_GLOBAL, SK_FUNC,
xtext_sec, 0, 2);
xd = debug_new(xc, xob);
@@ -369,7 +371,7 @@ static int run_x64_debug_line_check(void) {
SrcLoc l10 = {fid, 10, 0};
SrcLoc l11 = {fid, 11, 0};
DebugTypeId int_tid = debug_type_base(
- xd, pool_intern_cstr(xpool, "int"), DEBUG_BE_SIGNED, 4);
+ xd, pool_intern_slice(xpool, SLICE_LIT("int")), DEBUG_BE_SIGNED, 4);
DebugTypeId fn_tid = debug_type_func(xd, int_tid, NULL, 0, 0);
(void)debug_file(xd, fid);
diff --git a/test/dwarf/dwarf_test.c b/test/dwarf/dwarf_test.c
@@ -711,27 +711,28 @@ static void build_debug_sections(ByteBuf* abbrev, ByteBuf* info, ByteBuf* line,
static void run_tests(CfreeDebugInfo* di) {
/* 1. addr_to_line at func_low. */
- const char* file = NULL;
+ CfreeSlice file = CFREE_SLICE_NULL;
uint32_t line = 0, col = 0;
if (cfree_dwarf_addr_to_line(di, 0x1000, &file, &line, &col) == 0) {
- EXPECT(line == 10, "expected line 10 at 0x1000, got %u (file=%s)", line,
- file ? file : "(null)");
- EXPECT(file && strstr(file, "test.c") != NULL,
- "file should contain test.c, got %s", file ? file : "(null)");
+ EXPECT(line == 10, "expected line 10 at 0x1000, got %u (file=%.*s)", line,
+ CFREE_SLICE_ARG(file));
+ EXPECT(file.s && strstr(file.s, "test.c") != NULL,
+ "file should contain test.c, got %.*s", CFREE_SLICE_ARG(file));
} else {
g_fail++;
fprintf(stderr, "FAIL: addr_to_line(0x1000) returned no entry\n");
}
/* 2. line_to_addr round trip. */
uint64_t pc = 0;
- if (cfree_dwarf_line_to_addr(di, "/proj/test.c", 10, &pc) == 0) {
+ if (cfree_dwarf_line_to_addr(di, CFREE_SLICE_LIT("/proj/test.c"), 10, &pc) ==
+ 0) {
EXPECT(pc == 0x1000, "expected pc 0x1000 for /proj/test.c:10, got 0x%llx",
(unsigned long long)pc);
} else {
fprintf(stderr,
"NOTE: line_to_addr looked up by absolute path failed; "
"trying relative\n");
- if (cfree_dwarf_line_to_addr(di, "test.c", 10, &pc) == 0) {
+ if (cfree_dwarf_line_to_addr(di, CFREE_SLICE_LIT("test.c"), 10, &pc) == 0) {
EXPECT(pc == 0x1000, "expected pc 0x1000 for test.c:10, got 0x%llx",
(unsigned long long)pc);
} else {
@@ -743,15 +744,15 @@ static void run_tests(CfreeDebugInfo* di) {
CfreeDwarfSubprogram sp;
EXPECT(cfree_dwarf_subprogram_at(di, 0x1000, &sp) == 0,
"subprogram_at(0x1000) should succeed");
- if (sp.name) {
- EXPECT(strcmp(sp.name, "test_main") == 0,
- "subprogram name '%s' != test_main", sp.name);
+ if (sp.name.s) {
+ EXPECT(cfree_slice_eq_cstr(sp.name, "test_main"),
+ "subprogram name '%.*s' != test_main", CFREE_SLICE_ARG(sp.name));
}
EXPECT(sp.high_pc > sp.low_pc, "subprogram pc range empty");
/* 4. var_at "x" should be FRAME_OFS. */
CfreeDwarfVarLoc loc;
- EXPECT(cfree_dwarf_var_at(di, 0x1000, "x", &loc) == 0,
+ EXPECT(cfree_dwarf_var_at(di, 0x1000, CFREE_SLICE_LIT("x"), &loc) == 0,
"var_at(0x1000, x) failed");
if (g_fail == 0) {
EXPECT(loc.kind == CFREE_DLOC_FRAME_OFS,
@@ -764,7 +765,7 @@ static void run_tests(CfreeDebugInfo* di) {
}
/* 5. var_at "arg" (param) should be REG. */
- EXPECT(cfree_dwarf_var_at(di, 0x1000, "arg", &loc) == 0,
+ EXPECT(cfree_dwarf_var_at(di, 0x1000, CFREE_SLICE_LIT("arg"), &loc) == 0,
"var_at(0x1000, arg) failed");
EXPECT(loc.kind == CFREE_DLOC_REG, "expected arg.kind=REG, got %d",
(int)loc.kind);
@@ -778,7 +779,8 @@ static void run_tests(CfreeDebugInfo* di) {
EXPECT(ti.kind == CFREE_DT_SINT, "expected SINT, got kind=%d",
(int)ti.kind);
EXPECT(ti.byte_size == 4, "expected byte_size=4, got %u", ti.byte_size);
- EXPECT(strcmp(ti.name, "int") == 0, "expected name=int, got %s", ti.name);
+ EXPECT(cfree_slice_eq_cstr(ti.name, "int"), "expected name=int, got %.*s",
+ CFREE_SLICE_ARG(ti.name));
}
/* 7. param_iter — should yield arg. */
@@ -792,7 +794,8 @@ static void run_tests(CfreeDebugInfo* di) {
CfreeIterResult r = cfree_dwarf_param_iter_next(pi, &v);
if (r != CFREE_ITER_ITEM) break;
n++;
- EXPECT(strcmp(v.name, "arg") == 0, "param name %s != arg", v.name);
+ EXPECT(cfree_slice_eq_cstr(v.name, "arg"), "param name %.*s != arg",
+ CFREE_SLICE_ARG(v.name));
}
EXPECT(n == 1, "expected 1 param, got %d", n);
cfree_dwarf_param_iter_free(pi);
@@ -800,7 +803,7 @@ static void run_tests(CfreeDebugInfo* di) {
/* 8. addr_to_line at second row (0x1004) → line 11. */
{
- const char* f2 = NULL;
+ CfreeSlice f2 = CFREE_SLICE_NULL;
uint32_t l2 = 0, c2 = 0;
if (cfree_dwarf_addr_to_line(di, 0x1004, &f2, &l2, &c2) == 0) {
EXPECT(l2 == 11, "expected line 11 at 0x1004, got %u", l2);
@@ -825,11 +828,11 @@ static void run_tests(CfreeDebugInfo* di) {
if (r != CFREE_ITER_ITEM) break;
if (v.role == CFREE_DVR_LOCAL) {
n_local++;
- if (strcmp(v.name, "x") == 0) saw_x = 1;
- if (strcmp(v.name, "y") == 0) saw_y = 1;
+ if (cfree_slice_eq_cstr(v.name, "x")) saw_x = 1;
+ if (cfree_slice_eq_cstr(v.name, "y")) saw_y = 1;
} else if (v.role == CFREE_DVR_ARG) {
n_arg++;
- if (strcmp(v.name, "arg") == 0) saw_arg = 1;
+ if (cfree_slice_eq_cstr(v.name, "arg")) saw_arg = 1;
}
}
/* The fixture has 6 locals total (x, y, my_int, Point, x_field,
@@ -844,7 +847,7 @@ static void run_tests(CfreeDebugInfo* di) {
/* 10. loc_read REG fast path: pull arg via a fake unwind frame. */
{
CfreeDwarfVarLoc varg;
- if (cfree_dwarf_var_at(di, 0x1000, "arg", &varg) == CFREE_OK) {
+ if (cfree_dwarf_var_at(di, 0x1000, CFREE_SLICE_LIT("arg"), &varg) == CFREE_OK) {
CfreeUnwindFrame fr;
uint32_t v32 = 0;
size_t got = 0;
@@ -863,7 +866,7 @@ static void run_tests(CfreeDebugInfo* di) {
/* 11. type_info: pointer (var "my_int" carries pointer_type → int). */
{
CfreeDwarfVarLoc lp;
- if (cfree_dwarf_var_at(di, 0x1000, "my_int", &lp) == 0) {
+ if (cfree_dwarf_var_at(di, 0x1000, CFREE_SLICE_LIT("my_int"), &lp) == 0) {
CfreeDwarfTypeInfo ti = cfree_dwarf_type_info(lp.type);
EXPECT(ti.kind == CFREE_DT_PTR, "expected PTR, got kind=%d",
(int)ti.kind);
@@ -883,12 +886,12 @@ static void run_tests(CfreeDebugInfo* di) {
/* 12. type_info: typedef (var "Point" carries typedef → int). */
{
CfreeDwarfVarLoc lp;
- if (cfree_dwarf_var_at(di, 0x1000, "Point", &lp) == 0) {
+ if (cfree_dwarf_var_at(di, 0x1000, CFREE_SLICE_LIT("Point"), &lp) == 0) {
CfreeDwarfTypeInfo ti = cfree_dwarf_type_info(lp.type);
EXPECT(ti.kind == CFREE_DT_TYPEDEF, "expected TYPEDEF, got kind=%d",
(int)ti.kind);
- EXPECT(strcmp(ti.name, "my_int") == 0, "typedef name=%s != my_int",
- ti.name);
+ EXPECT(cfree_slice_eq_cstr(ti.name, "my_int"),
+ "typedef name=%.*s != my_int", CFREE_SLICE_ARG(ti.name));
EXPECT(ti.inner != NULL, "typedef inner missing");
}
}
@@ -896,7 +899,7 @@ static void run_tests(CfreeDebugInfo* di) {
/* 13. type_info: array of int [4]. */
{
CfreeDwarfVarLoc lp;
- if (cfree_dwarf_var_at(di, 0x1000, "x_field", &lp) == 0) {
+ if (cfree_dwarf_var_at(di, 0x1000, CFREE_SLICE_LIT("x_field"), &lp) == 0) {
CfreeDwarfTypeInfo ti = cfree_dwarf_type_info(lp.type);
EXPECT(ti.kind == CFREE_DT_ARRAY, "expected ARRAY, got kind=%d",
(int)ti.kind);
@@ -907,12 +910,13 @@ static void run_tests(CfreeDebugInfo* di) {
/* 14. type_info: struct Point with two int fields. */
{
CfreeDwarfVarLoc lp;
- if (cfree_dwarf_var_at(di, 0x1000, "y_field", &lp) == 0) {
+ if (cfree_dwarf_var_at(di, 0x1000, CFREE_SLICE_LIT("y_field"), &lp) == 0) {
CfreeDwarfTypeInfo ti = cfree_dwarf_type_info(lp.type);
EXPECT(ti.kind == CFREE_DT_STRUCT, "expected STRUCT, got kind=%d",
(int)ti.kind);
EXPECT(ti.byte_size == 8, "struct byte_size=%u", ti.byte_size);
- EXPECT(strcmp(ti.name, "Point") == 0, "struct name=%s", ti.name);
+ EXPECT(cfree_slice_eq_cstr(ti.name, "Point"), "struct name=%.*s",
+ CFREE_SLICE_ARG(ti.name));
CfreeDwarfFieldIter* fi = NULL;
EXPECT(cfree_dwarf_field_iter_new(di, lp.type, &fi) == CFREE_OK &&
fi != NULL,
@@ -925,8 +929,10 @@ static void run_tests(CfreeDebugInfo* di) {
CfreeIterResult r = cfree_dwarf_field_iter_next(fi, &f);
if (r != CFREE_ITER_ITEM) break;
count++;
- if (strcmp(f.name, "x_field") == 0 && f.byte_offset == 0) saw_x = 1;
- if (strcmp(f.name, "y_field") == 0 && f.byte_offset == 4) saw_y = 1;
+ if (cfree_slice_eq_cstr(f.name, "x_field") && f.byte_offset == 0)
+ saw_x = 1;
+ if (cfree_slice_eq_cstr(f.name, "y_field") && f.byte_offset == 4)
+ saw_y = 1;
}
EXPECT(count == 2, "expected 2 fields, got %d", count);
EXPECT(saw_x && saw_y, "missing x_field or y_field");
@@ -974,8 +980,8 @@ int main(void) {
/* Build an ObjBuilder via internal API. */
ObjBuilder* ob = obj_new(cc);
- Sym text_name = pool_intern_cstr(cc->global, ".text");
- Sym func_name = pool_intern_cstr(cc->global, "test_main");
+ Sym text_name = pool_intern_slice(cc->global, SLICE_LIT(".text"));
+ Sym func_name = pool_intern_slice(cc->global, SLICE_LIT("test_main"));
ObjSecId text_sec =
obj_section(ob, text_name, SEC_TEXT, SF_EXEC | SF_ALLOC, 4);
/* 8 bytes of nop-like text. */
@@ -983,11 +989,11 @@ int main(void) {
obj_write(ob, text_sec, text_bytes, 8);
obj_symbol(ob, func_name, SB_GLOBAL, SK_FUNC, text_sec, 0, 8);
- Sym n_abbrev = pool_intern_cstr(cc->global, ".debug_abbrev");
- Sym n_info = pool_intern_cstr(cc->global, ".debug_info");
- Sym n_line = pool_intern_cstr(cc->global, ".debug_line");
- Sym n_str = pool_intern_cstr(cc->global, ".debug_str");
- Sym n_line_str = pool_intern_cstr(cc->global, ".debug_line_str");
+ Sym n_abbrev = pool_intern_slice(cc->global, SLICE_LIT(".debug_abbrev"));
+ Sym n_info = pool_intern_slice(cc->global, SLICE_LIT(".debug_info"));
+ Sym n_line = pool_intern_slice(cc->global, SLICE_LIT(".debug_line"));
+ Sym n_str = pool_intern_slice(cc->global, SLICE_LIT(".debug_str"));
+ Sym n_line_str = pool_intern_slice(cc->global, SLICE_LIT(".debug_line_str"));
ObjSecId s_abbrev = obj_section(ob, n_abbrev, SEC_DEBUG, 0, 1);
ObjSecId s_info = obj_section(ob, n_info, SEC_DEBUG, 0, 1);
ObjSecId s_line = obj_section(ob, n_line, SEC_DEBUG, 0, 1);
@@ -1009,13 +1015,12 @@ int main(void) {
fprintf(stderr, "built obj: %zu bytes\n", obj_len);
/* Re-open via the public API. */
- CfreeBytes in;
+ CfreeSlice in;
memset(&in, 0, sizeof in);
- in.name = "test.o";
in.data = obj_bytes;
in.len = obj_len;
CfreeObjFile* obj = NULL;
- EXPECT(cfree_obj_open(&ctx, &in, &obj) == CFREE_OK && obj != NULL,
+ EXPECT(cfree_obj_open(&ctx, CFREE_SLICE_LIT("test.o"), &in, &obj) == CFREE_OK && obj != NULL,
"cfree_obj_open failed");
if (obj) {
CfreeDebugInfo* di = NULL;
diff --git a/test/elf/unit/align_4k.c b/test/elf/unit/align_4k.c
@@ -88,11 +88,11 @@ int main(void) {
}
ObjBuilder* in = obj_new(c);
- Sym text_nm = pool_intern_cstr(c->global, ".text");
+ Sym text_nm = pool_intern_slice(c->global, SLICE_LIT(".text"));
ObjSecId sec =
obj_section(in, text_nm, SEC_TEXT, SF_ALLOC | SF_EXEC, WANT_ALIGN);
obj_write(in, sec, TEXT_BYTES, sizeof TEXT_BYTES);
- obj_symbol(in, pool_intern_cstr(c->global, "f"), SB_GLOBAL, SK_FUNC, sec, 0,
+ obj_symbol(in, pool_intern_slice(c->global, SLICE_LIT("f")), SB_GLOBAL, SK_FUNC, sec, 0,
sizeof TEXT_BYTES);
obj_finalize(in);
@@ -114,9 +114,8 @@ int main(void) {
u32 n = obj_section_count(back);
for (u32 i = 1; i < n; ++i) {
const Section* s = obj_section_get(back, i);
- size_t l;
- const char* nm = pool_str(c->global, s->name, &l);
- if (l == 5 && memcmp(nm, ".text", 5) == 0) {
+ Slice nm = pool_slice(c->global, s->name);
+ if (nm.len == 5 && memcmp(nm.s, ".text", 5) == 0) {
found = 1;
CHECK(s->align == WANT_ALIGN, ".text align=%u after roundtrip, want %u",
s->align, WANT_ALIGN);
diff --git a/test/elf/unit/groupiter.c b/test/elf/unit/groupiter.c
@@ -66,8 +66,8 @@ static const uint8_t TEXT_BYTES[8] = {
0x20, 0x00, 0x80, 0x52, 0xc0, 0x03, 0x5f, 0xd6,
};
-static int name_eq(const char* s, const char* want) {
- return s && strcmp(s, want) == 0;
+static int name_eq(CfreeSlice s, const char* want) {
+ return s.s && cfree_slice_eq_cstr(s, want);
}
int main(void) {
@@ -99,9 +99,9 @@ int main(void) {
ObjBuilder* in = obj_new(c);
Pool* p = c->global;
- Sym sig_nm = pool_intern_cstr(p, "comdat_sig");
- Sym text_nm = pool_intern_cstr(p, ".text.comdat_fn");
- Sym data_nm = pool_intern_cstr(p, ".data.comdat_fn");
+ Sym sig_nm = pool_intern_slice(p, SLICE_LIT("comdat_sig"));
+ Sym text_nm = pool_intern_slice(p, SLICE_LIT(".text.comdat_fn"));
+ Sym data_nm = pool_intern_slice(p, SLICE_LIT(".data.comdat_fn"));
ObjSecId sec_text = obj_section(in, text_nm, SEC_TEXT,
SF_ALLOC | SF_EXEC | SF_GROUP, 4);
@@ -155,19 +155,19 @@ int main(void) {
memcpy(roundtrip, out_data, out_len);
cfree_writer_close(w);
- CfreeBytes input = {.name = "groupiter", .data = roundtrip, .len = out_len};
+ CfreeSlice input = {.data = roundtrip, .len = out_len};
CfreeObjFile* f = NULL;
- CHECK(cfree_obj_open(&ctx, &input, &f) == CFREE_OK && f,
+ CHECK(cfree_obj_open(&ctx, CFREE_SLICE_LIT("groupiter"), &input, &f) == CFREE_OK && f,
"cfree_obj_open failed");
if (f) {
/* Resolve section IDs by name so the test isn't coupled to ordering. */
CfreeObjSection text_pub = CFREE_SECTION_NONE;
CfreeObjSection data_pub = CFREE_SECTION_NONE;
- CHECK(cfree_obj_section_by_name(f, ".text.comdat_fn", &text_pub) ==
+ CHECK(cfree_obj_section_by_name(f, CFREE_SLICE_LIT(".text.comdat_fn"), &text_pub) ==
CFREE_OK,
"section_by_name .text.comdat_fn");
- CHECK(cfree_obj_section_by_name(f, ".data.comdat_fn", &data_pub) ==
+ CHECK(cfree_obj_section_by_name(f, CFREE_SLICE_LIT(".data.comdat_fn"), &data_pub) ==
CFREE_OK,
"section_by_name .data.comdat_fn");
@@ -178,8 +178,8 @@ int main(void) {
CfreeObjGroupInfo gi;
while (cfree_obj_groupiter_next(git, &gi) == CFREE_ITER_ITEM) {
++seen;
- CHECK(name_eq(gi.name, "comdat_sig"), "public iter: name=%s",
- gi.name ? gi.name : "(null)");
+ CHECK(name_eq(gi.name, "comdat_sig"), "public iter: name=%.*s",
+ CFREE_SLICE_ARG(gi.name));
CHECK((gi.flags & CFREE_OBJ_GROUP_COMDAT) != 0,
"public iter: missing COMDAT flag (flags=0x%x)", gi.flags);
CHECK(gi.nsections == 2, "public iter: nsections=%u, want 2",
diff --git a/test/elf/unit/mutate.c b/test/elf/unit/mutate.c
@@ -97,13 +97,13 @@ int main(void) {
ObjBuilder* ob = obj_new(c);
Pool* p = c->global;
- Sym text_nm = pool_intern_cstr(p, ".text");
- Sym data_nm = pool_intern_cstr(p, ".data");
- Sym entry_nm = pool_intern_cstr(p, "entry");
- Sym entry_new_nm = pool_intern_cstr(p, "renamed_entry");
- Sym keep_nm = pool_intern_cstr(p, "keep_global");
- Sym foo_nm = pool_intern_cstr(p, "foo_ref");
- Sym spurious_nm = pool_intern_cstr(p, "spurious_extern");
+ Sym text_nm = pool_intern_slice(p, SLICE_LIT(".text"));
+ Sym data_nm = pool_intern_slice(p, SLICE_LIT(".data"));
+ Sym entry_nm = pool_intern_slice(p, SLICE_LIT("entry"));
+ Sym entry_new_nm = pool_intern_slice(p, SLICE_LIT("renamed_entry"));
+ Sym keep_nm = pool_intern_slice(p, SLICE_LIT("keep_global"));
+ Sym foo_nm = pool_intern_slice(p, SLICE_LIT("foo_ref"));
+ Sym spurious_nm = pool_intern_slice(p, SLICE_LIT("spurious_extern"));
ObjSecId sec_text =
obj_section(ob, text_nm, SEC_TEXT, SF_ALLOC | SF_EXEC, 4);
@@ -163,37 +163,37 @@ int main(void) {
memcpy(roundtrip, out_data, out_len);
cfree_writer_close(w);
- CfreeBytes input = {.name = "mutate", .data = roundtrip, .len = out_len};
+ CfreeSlice input = {.data = roundtrip, .len = out_len};
CfreeObjFile* f = NULL;
- CHECK(cfree_obj_open(&ctx, &input, &f) == CFREE_OK && f, "reopen");
+ CHECK(cfree_obj_open(&ctx, CFREE_SLICE_LIT("mutate"), &input, &f) == CFREE_OK && f, "reopen");
if (f) {
/* .data should be gone. */
CfreeObjSection s_data = CFREE_SECTION_NONE;
CfreeStatus st_data =
- cfree_obj_section_by_name(f, ".data", &s_data);
+ cfree_obj_section_by_name(f, CFREE_SLICE_LIT(".data"), &s_data);
CHECK(st_data == CFREE_NOT_FOUND, ".data still present after removal");
/* .text should remain. */
CfreeObjSection s_text = CFREE_SECTION_NONE;
- CHECK(cfree_obj_section_by_name(f, ".text", &s_text) == CFREE_OK,
+ CHECK(cfree_obj_section_by_name(f, CFREE_SLICE_LIT(".text"), &s_text) == CFREE_OK,
".text missing after roundtrip");
/* Renamed entry symbol is present; old name is gone. */
CfreeObjSymInfo si;
- CHECK(cfree_obj_symbol_by_name(f, "renamed_entry", &si) == CFREE_OK,
+ CHECK(cfree_obj_symbol_by_name(f, CFREE_SLICE_LIT("renamed_entry"), &si) == CFREE_OK,
"renamed_entry not found");
- CHECK(cfree_obj_symbol_by_name(f, "entry", &si) == CFREE_NOT_FOUND,
+ CHECK(cfree_obj_symbol_by_name(f, CFREE_SLICE_LIT("entry"), &si) == CFREE_NOT_FOUND,
"old 'entry' symbol survived rename");
/* keep_global was localized; reads back as SB_LOCAL. */
- CHECK(cfree_obj_symbol_by_name(f, "keep_global", &si) == CFREE_OK,
+ CHECK(cfree_obj_symbol_by_name(f, CFREE_SLICE_LIT("keep_global"), &si) == CFREE_OK,
"keep_global lost");
CHECK(si.bind == CFREE_SB_LOCAL, "keep_global bind=%d, want LOCAL=%d",
(int)si.bind, (int)CFREE_SB_LOCAL);
/* Spurious extern was pruned by the sweep. */
- CHECK(cfree_obj_symbol_by_name(f, "spurious_extern", &si) ==
+ CHECK(cfree_obj_symbol_by_name(f, CFREE_SLICE_LIT("spurious_extern"), &si) ==
CFREE_NOT_FOUND,
"spurious_extern survived sweep");
@@ -203,7 +203,7 @@ int main(void) {
* via obj_reloc_ex at build time, BUT the reloc is then dropped at
* sweep. The symbol's `referenced` flag was set at obj_reloc time and
* does not get cleared, so foo_ref survives as a plain UNDEF. */
- CHECK(cfree_obj_symbol_by_name(f, "foo_ref", &si) == CFREE_OK,
+ CHECK(cfree_obj_symbol_by_name(f, CFREE_SLICE_LIT("foo_ref"), &si) == CFREE_OK,
"foo_ref UNDEF should survive");
/* No relocs should remain — all were in the removed .data. */
diff --git a/test/elf/unit/smoke.c b/test/elf/unit/smoke.c
@@ -80,10 +80,10 @@ static ObjBuilder* build_input(Compiler* c) {
ObjBuilder* ob = obj_new(c);
Pool* p = c->global;
- Sym text = pool_intern_cstr(p, ".text");
- Sym data = pool_intern_cstr(p, ".data");
- Sym main = pool_intern_cstr(p, "main");
- Sym foo = pool_intern_cstr(p, "foo");
+ Sym text = pool_intern_slice(p, SLICE_LIT(".text"));
+ Sym data = pool_intern_slice(p, SLICE_LIT(".data"));
+ Sym main = pool_intern_slice(p, SLICE_LIT("main"));
+ Sym foo = pool_intern_slice(p, SLICE_LIT("foo"));
ObjSecId sec_text = obj_section(ob, text, SEC_TEXT, SF_ALLOC | SF_EXEC, 4);
ObjSecId sec_data = obj_section(ob, data, SEC_DATA, SF_ALLOC | SF_WRITE, 8);
@@ -108,11 +108,10 @@ static ObjBuilder* build_input(Compiler* c) {
/* Pool strings are NOT NUL-terminated (pool_intern stores raw bytes), so
* compare by length + memcmp rather than strcmp. */
static int sym_eq_str(Pool* p, Sym s, const char* want) {
- size_t len;
- const char* got = pool_str(p, s, &len);
+ Slice got = pool_slice(p, s);
size_t wlen = 0;
while (want[wlen]) ++wlen;
- return got && len == wlen && memcmp(got, want, len) == 0;
+ return got.s && got.len == wlen && memcmp(got.s, want, got.len) == 0;
}
static const Section* find_section_named(const ObjBuilder* ob, Pool* p,
@@ -219,10 +218,9 @@ static void verify_shape(const ObjBuilder* ob, Pool* p) {
(long long)found->addend);
const ObjSym* tsym = obj_symbol_get(ob, found->sym);
if (tsym) {
- size_t l;
- const char* nm = pool_str(p, tsym->name, &l);
+ Slice nm = pool_slice(p, tsym->name);
CHECK(sym_eq_str(p, tsym->name, "foo"), "reloc target name = %.*s",
- (int)l, nm ? nm : "(null)");
+ (int)nm.len, nm.s ? nm.s : "(null)");
}
}
}
diff --git a/test/elf/unit/x64_disasm_annotations.c b/test/elf/unit/x64_disasm_annotations.c
@@ -72,12 +72,12 @@ static CfreeTarget x64_elf_target(void) {
static ObjBuilder* build_input(Compiler* c) {
ObjBuilder* ob = obj_new(c);
Pool* p = c->global;
- Sym text = pool_intern_cstr(p, ".text");
- Sym start = pool_intern_cstr(p, "_start");
- Sym load_data = pool_intern_cstr(p, "load_data");
- Sym foo = pool_intern_cstr(p, "foo");
- Sym bar = pool_intern_cstr(p, "bar");
- Sym global_data = pool_intern_cstr(p, "global_data");
+ Sym text = pool_intern_slice(p, SLICE_LIT(".text"));
+ Sym start = pool_intern_slice(p, SLICE_LIT("_start"));
+ Sym load_data = pool_intern_slice(p, SLICE_LIT("load_data"));
+ Sym foo = pool_intern_slice(p, SLICE_LIT("foo"));
+ Sym bar = pool_intern_slice(p, SLICE_LIT("bar"));
+ Sym global_data = pool_intern_slice(p, SLICE_LIT("global_data"));
ObjSecId sec_text = obj_section(ob, text, SEC_TEXT, SF_ALLOC | SF_EXEC, 16);
static const uint8_t text_bytes[] = {
@@ -105,14 +105,14 @@ static ObjBuilder* build_input(Compiler* c) {
return ob;
}
-static void check_reloc_names(const CfreeBytes* bytes, const CfreeContext* ctx) {
+static void check_reloc_names(const CfreeSlice* bytes, const CfreeContext* ctx) {
CfreeObjFile* f = NULL;
CfreeObjRelocIter* it = NULL;
CfreeObjReloc r;
int saw_plt32 = 0;
int saw_pc32 = 0;
- CHECK(cfree_obj_open(ctx, bytes, &f) == CFREE_OK && f, "cfree_obj_open");
+ CHECK(cfree_obj_open(ctx, CFREE_SLICE_LIT("x64_disasm_annotations.o"), bytes, &f) == CFREE_OK && f, "cfree_obj_open");
if (!f) return;
CHECK(cfree_obj_reliter_new(f, &it) == CFREE_OK && it, "reliter_new");
if (!it) {
@@ -121,14 +121,14 @@ static void check_reloc_names(const CfreeBytes* bytes, const CfreeContext* ctx)
}
while (cfree_obj_reliter_next(it, &r) == CFREE_ITER_ITEM) {
if (r.offset == 1 || r.offset == 13) {
- CHECK(r.kind_name && strcmp(r.kind_name, "R_X86_64_PLT32") == 0,
- "PLT32 kind name at offset %llu is %s",
- (unsigned long long)r.offset, r.kind_name ? r.kind_name : "(null)");
+ CHECK(cfree_slice_eq_cstr(r.kind_name, "R_X86_64_PLT32"),
+ "PLT32 kind name at offset %llu is %.*s",
+ (unsigned long long)r.offset, CFREE_SLICE_ARG(r.kind_name));
saw_plt32++;
}
if (r.offset == 8) {
- CHECK(r.kind_name && strcmp(r.kind_name, "R_X86_64_PC32") == 0,
- "PC32 kind name is %s", r.kind_name ? r.kind_name : "(null)");
+ CHECK(cfree_slice_eq_cstr(r.kind_name, "R_X86_64_PC32"),
+ "PC32 kind name is %.*s", CFREE_SLICE_ARG(r.kind_name));
saw_pc32 = 1;
}
}
@@ -138,7 +138,7 @@ static void check_reloc_names(const CfreeBytes* bytes, const CfreeContext* ctx)
cfree_obj_free(f);
}
-static void check_disasm_annotations(const CfreeBytes* bytes,
+static void check_disasm_annotations(const CfreeSlice* bytes,
const CfreeContext* ctx) {
CfreeWriter* w = NULL;
const uint8_t* out;
@@ -178,7 +178,7 @@ int main(void) {
CfreeWriter* w = NULL;
const uint8_t* obj_data;
size_t obj_len = 0;
- CfreeBytes bytes;
+ CfreeSlice bytes;
memset(&ctx, 0, sizeof ctx);
ctx.heap = &g_heap;
@@ -201,7 +201,6 @@ int main(void) {
CHECK(cfree_writer_mem(&g_heap, &w) == CFREE_OK && w, "writer_mem object");
emit_elf(c, ob, w);
obj_data = cfree_writer_mem_bytes(w, &obj_len);
- bytes.name = "x64_disasm_annotations.o";
bytes.data = obj_data;
bytes.len = obj_len;
diff --git a/test/libc/cases/11_strings.c b/test/libc/cases/11_strings.c
@@ -1,21 +1,23 @@
-/* string.h surface: strlen / strcmp / strchr / strstr / memcpy / memset. */
+/* string.h surface: memcpy / memset / memcmp / memchr.
+ *
+ * cfree's freestanding runtime intentionally does not ship the NUL-terminated
+ * str* family (strlen/strcmp/strchr/strstr/...); the project carries lengths
+ * explicitly. Only the length-based mem* primitives are provided. */
#include <stdio.h>
#include <string.h>
int main(void) {
const char *s = "hello, world";
- if (strlen(s) != 12) return 1;
- if (strcmp(s, "hello, world") != 0) return 2;
- if (strcmp(s, "hello") <= 0) return 3;
- if (strchr(s, ',') != s + 5) return 4;
- if (strstr(s, "world") != s + 7) return 5;
+ if (memcmp(s, "hello, world", 13) != 0) return 1; /* incl. NUL */
+ if (memchr(s, ',', 12) != s + 5) return 2;
+ if (memchr(s, 'z', 12) != NULL) return 3;
char buf[16];
memset(buf, '#', sizeof(buf));
memcpy(buf, "hi", 2);
buf[2] = 0;
- if (strcmp(buf, "hi") != 0) return 6;
+ if (memcmp(buf, "hi", 3) != 0) return 4; /* 'h','i','\0' */
printf("strings ok\n");
return 0;
diff --git a/test/libc/cases/13_malloc.c b/test/libc/cases/13_malloc.c
@@ -9,7 +9,7 @@ int main(void) {
if (!buf) return 1;
int n = snprintf(buf, 64, "alloc %d bytes", 64);
if (n != 14) return 2;
- if (strcmp(buf, "alloc 64 bytes") != 0) return 3;
+ if (memcmp(buf, "alloc 64 bytes", 15) != 0) return 3; /* incl. NUL */
free(buf);
printf("malloc ok\n");
return 0;
diff --git a/test/link/harness/jit_runner.c b/test/link/harness/jit_runner.c
@@ -289,7 +289,7 @@ static void* low_extern_default_value(void) {
return &g_extern_default_value;
#endif
}
-static void* extern_resolver(void* user, const char* name) {
+static void* extern_resolver(void* user, CfreeSlice name) {
(void)user;
(void)name;
return low_extern_default_value();
@@ -416,7 +416,8 @@ int main(int argc, char** argv) {
const char* check_present = NULL;
const char* script_path = NULL;
- CfreeBytes objs[64];
+ CfreeSlice objs[64];
+ const char* obj_names[64];
CfreeLinkArchiveInput archives[16];
uint32_t nobj = 0, narc = 0;
uint8_t* bufs[80];
@@ -449,16 +450,16 @@ int main(int argc, char** argv) {
if (next_archive) {
CfreeLinkArchiveInput* a = &archives[narc++];
memset(a, 0, sizeof(*a));
- a->bytes.name = argv[i];
+ a->name = cfree_slice_cstr(argv[i]);
a->bytes.data = data;
a->bytes.len = len;
a->whole_archive = (uint8_t)next_whole;
next_archive = 0;
next_whole = 0;
} else {
- CfreeBytes* o = &objs[nobj++];
+ obj_names[nobj] = argv[i];
+ CfreeSlice* o = &objs[nobj++];
memset(o, 0, sizeof(*o));
- o->name = argv[i];
o->data = data;
o->len = len;
}
@@ -493,7 +494,7 @@ int main(int argc, char** argv) {
CfreeLinkScript* script = NULL;
memset(&opts, 0, sizeof(opts));
opts.output_kind = CFREE_LINK_OUTPUT_JIT;
- opts.entry = "test_main";
+ opts.entry = CFREE_SLICE_LIT("test_main");
opts.gc_sections = gc_sections;
opts.jit_host = &jhost;
if (use_resolver) {
@@ -509,8 +510,8 @@ int main(int argc, char** argv) {
cfree_compiler_free(c);
return 2;
}
- CfreeStatus prc =
- cfree_link_script_parse(&ctx, (const char*)sbytes, slen, &script);
+ CfreeSlice script_text = {.s = (const char*)sbytes, .len = slen};
+ CfreeStatus prc = cfree_link_script_parse(&ctx, script_text, &script);
free(sbytes);
if (prc != CFREE_OK) {
fprintf(stderr, "jit-runner: linker script parse failed: %s\n",
@@ -524,7 +525,8 @@ int main(int argc, char** argv) {
CfreeJit* jit = NULL;
CfreeStatus rc = cfree_link_session_new(c, &opts, &link);
for (uint32_t i = 0; rc == CFREE_OK && i < nobj; ++i)
- rc = cfree_link_session_add_obj_bytes(link, &objs[i]);
+ rc = cfree_link_session_add_obj_bytes(link, cfree_slice_cstr(obj_names[i]),
+ &objs[i]);
for (uint32_t i = 0; rc == CFREE_OK && i < narc; ++i)
rc = cfree_link_session_add_archive_bytes(link, &archives[i]);
if (rc == CFREE_OK) rc = cfree_link_session_jit(link, &jit);
@@ -540,7 +542,7 @@ int main(int argc, char** argv) {
for (int i = 0; i < nbufs; i++) free(bufs[i]);
/* Sanity: a never-defined sentinel must not be found (covers case 29). */
- if (cfree_jit_lookup(jit, "__cfree_test_sentinel__")) {
+ if (cfree_jit_lookup(jit, CFREE_SLICE_LIT("__cfree_test_sentinel__"))) {
fprintf(stderr, "jit-runner: sentinel lookup unexpectedly non-NULL\n");
cfree_jit_run_dtors(jit);
cfree_jit_free(jit);
@@ -550,7 +552,7 @@ int main(int argc, char** argv) {
/* --check-absent SYM: verify symbol was removed (e.g. by --gc-sections). */
if (check_absent) {
- int absent_ok = cfree_jit_lookup(jit, check_absent) == NULL;
+ int absent_ok = cfree_jit_lookup(jit, cfree_slice_cstr(check_absent)) == NULL;
if (!absent_ok)
fprintf(stderr, "jit-runner: symbol '%s' present but expected absent\n",
check_absent);
@@ -562,7 +564,8 @@ int main(int argc, char** argv) {
/* --check-present SYM: verify symbol survives the link / GC. */
if (check_present) {
- int present_ok = cfree_jit_lookup(jit, check_present) != NULL;
+ int present_ok =
+ cfree_jit_lookup(jit, cfree_slice_cstr(check_present)) != NULL;
if (!present_ok)
fprintf(stderr, "jit-runner: symbol '%s' missing but expected present\n",
check_present);
@@ -572,8 +575,8 @@ int main(int argc, char** argv) {
return present_ok ? 0 : 1;
}
- void* wasm_init = cfree_jit_lookup(jit, "__cfree_wasm_init");
- void* entry = cfree_jit_lookup(jit, "test_main");
+ void* wasm_init = cfree_jit_lookup(jit, CFREE_SLICE_LIT("__cfree_wasm_init"));
+ void* entry = cfree_jit_lookup(jit, CFREE_SLICE_LIT("test_main"));
int (*fn)(void) = entry;
/* TLS local-exec setup. Build the static TLS block and install the
@@ -586,10 +589,11 @@ int main(int argc, char** argv) {
int restore_fs = 0;
#endif
{
- char* td_start = (char*)cfree_jit_lookup(jit, "__tdata_start");
- char* td_end = (char*)cfree_jit_lookup(jit, "__tdata_end");
- unsigned long bs_n =
- (unsigned long)(unsigned long long)cfree_jit_lookup(jit, "__tbss_size");
+ char* td_start =
+ (char*)cfree_jit_lookup(jit, CFREE_SLICE_LIT("__tdata_start"));
+ char* td_end = (char*)cfree_jit_lookup(jit, CFREE_SLICE_LIT("__tdata_end"));
+ unsigned long bs_n = (unsigned long)(unsigned long long)cfree_jit_lookup(
+ jit, CFREE_SLICE_LIT("__tbss_size"));
if (td_start && td_end) {
unsigned long td_n = (unsigned long)(td_end - td_start);
unsigned long i;
@@ -662,7 +666,7 @@ int main(int argc, char** argv) {
#endif
if (result == 0) {
- int (*post)(void) = cfree_jit_lookup(jit, "test_post_fini");
+ int (*post)(void) = cfree_jit_lookup(jit, CFREE_SLICE_LIT("test_post_fini"));
if (post) result = post();
}
diff --git a/test/link/harness/link_exe_runner.c b/test/link/harness/link_exe_runner.c
@@ -112,9 +112,11 @@ int main(int argc, char** argv) {
int next_archive = 0;
int next_whole = 0;
- CfreeBytes objs[64];
+ CfreeSlice objs[64];
+ const char* obj_names[64];
CfreeLinkArchiveInput archives[16];
- CfreeBytes dsos[16];
+ CfreeSlice dsos[16];
+ const char* dso_names[16];
uint32_t nobj = 0, narc = 0, ndso = 0;
uint8_t* bufs[96];
int nbufs = 0;
@@ -145,25 +147,25 @@ int main(int argc, char** argv) {
}
bufs[nbufs++] = data;
if (next_dso) {
- CfreeBytes* d = &dsos[ndso++];
+ dso_names[ndso] = argv[i];
+ CfreeSlice* d = &dsos[ndso++];
memset(d, 0, sizeof(*d));
- d->name = argv[i];
d->data = data;
d->len = len;
next_dso = 0;
} else if (next_archive) {
CfreeLinkArchiveInput* a = &archives[narc++];
memset(a, 0, sizeof(*a));
- a->bytes.name = argv[i];
+ a->name = cfree_slice_cstr(argv[i]);
a->bytes.data = data;
a->bytes.len = len;
a->whole_archive = (uint8_t)next_whole;
next_archive = 0;
next_whole = 0;
} else {
- CfreeBytes* o = &objs[nobj++];
+ obj_names[nobj] = argv[i];
+ CfreeSlice* o = &objs[nobj++];
memset(o, 0, sizeof(*o));
- o->name = argv[i];
o->data = data;
o->len = len;
}
@@ -197,7 +199,7 @@ int main(int argc, char** argv) {
CfreeLinkScript* script = NULL;
memset(&opts, 0, sizeof(opts));
opts.output_kind = CFREE_LINK_OUTPUT_EXE;
- opts.entry = entry_name;
+ opts.entry = cfree_slice_cstr(entry_name);
opts.gc_sections = gc_sections;
if (script_path) {
@@ -208,8 +210,8 @@ int main(int argc, char** argv) {
cfree_compiler_free(c);
return 2;
}
- CfreeStatus prc =
- cfree_link_script_parse(&ctx, (const char*)sbytes, slen, &script);
+ CfreeSlice script_text = {.s = (const char*)sbytes, .len = slen};
+ CfreeStatus prc = cfree_link_script_parse(&ctx, script_text, &script);
free(sbytes);
if (prc != CFREE_OK) {
fprintf(stderr, "link-exe-runner: linker script parse failed: %s\n",
@@ -228,11 +230,13 @@ int main(int argc, char** argv) {
CfreeStatus rc = cfree_link_session_new(c, &opts, &link);
for (uint32_t i = 0; rc == CFREE_OK && i < nobj; ++i)
- rc = cfree_link_session_add_obj_bytes(link, &objs[i]);
+ rc = cfree_link_session_add_obj_bytes(link, cfree_slice_cstr(obj_names[i]),
+ &objs[i]);
for (uint32_t i = 0; rc == CFREE_OK && i < narc; ++i)
rc = cfree_link_session_add_archive_bytes(link, &archives[i]);
for (uint32_t i = 0; rc == CFREE_OK && i < ndso; ++i)
- rc = cfree_link_session_add_dso_bytes(link, &dsos[i]);
+ rc = cfree_link_session_add_dso_bytes(link, cfree_slice_cstr(dso_names[i]),
+ &dsos[i]);
if (rc == CFREE_OK) rc = cfree_link_session_emit(link, w);
if (rc != CFREE_OK) {
diff --git a/test/link/rv64_jit_test.c b/test/link/rv64_jit_test.c
@@ -245,7 +245,7 @@ int main(void) {
CfreeObjSectionDesc sec_desc;
memset(&sec_desc, 0, sizeof(sec_desc));
- sec_desc.name = cfree_sym_intern(c, ".text");
+ sec_desc.name = cfree_sym_intern(c, CFREE_SLICE_LIT(".text"));
sec_desc.kind = CFREE_SEC_TEXT;
sec_desc.flags = CFREE_SF_EXEC | CFREE_SF_ALLOC;
sec_desc.align = 4;
@@ -263,7 +263,7 @@ int main(void) {
CfreeObjSymbolDesc sym_desc;
memset(&sym_desc, 0, sizeof(sym_desc));
- sym_desc.name = cfree_sym_intern(c, "rv64_jit_answer");
+ sym_desc.name = cfree_sym_intern(c, CFREE_SLICE_LIT("rv64_jit_answer"));
sym_desc.bind = CFREE_SB_GLOBAL;
sym_desc.kind = CFREE_SK_FUNC;
sym_desc.section = text;
@@ -290,7 +290,7 @@ int main(void) {
CfreeLinkSessionOptions opts;
memset(&opts, 0, sizeof(opts));
opts.output_kind = CFREE_LINK_OUTPUT_JIT;
- opts.entry = "rv64_jit_answer";
+ opts.entry = CFREE_SLICE_LIT("rv64_jit_answer");
opts.jit_host = &jhost;
CfreeLinkSession* sess = NULL;
@@ -312,7 +312,7 @@ int main(void) {
}
cfree_link_session_free(sess);
- void* fn = cfree_jit_lookup(jit, "rv64_jit_answer");
+ void* fn = cfree_jit_lookup(jit, CFREE_SLICE_LIT("rv64_jit_answer"));
if (!fn) {
fprintf(stderr, "rv64_jit_test: lookup failed\n");
cfree_jit_free(jit);
diff --git a/test/opt/opt_test.c b/test/opt/opt_test.c
@@ -874,8 +874,9 @@ static void mock_plan_hard_regs(CGTarget* t, RegClass cls, const Reg* regs,
static int mock_resolve_reg_name(CGTarget* t, Sym name, Reg* out,
RegClass* cls_out) {
- size_t len = 0;
- const char* s = pool_str(t->c->global, name, &len);
+ Slice sl = pool_slice(t->c->global, name);
+ const char* s = sl.s;
+ size_t len = sl.len;
if (!s || len < 2) return 1;
if ((s[0] != 'r' && s[0] != 'x' && s[0] != 'v') || s[1] < '0' || s[1] > '9')
return 1;
@@ -1153,9 +1154,9 @@ static CfreeCgTypeId record_of_i64s(TestCtx* tc, const char* name, u64 count) {
CfreeCgTypeId arr = cfree_cg_type_array(tc->c, tc->i64, count);
CfreeCgField field;
memset(&field, 0, sizeof field);
- field.name = cfree_sym_intern(tc->c, "a");
+ field.name = cfree_sym_intern(tc->c, CFREE_SLICE_LIT("a"));
field.type = arr;
- return cfree_cg_type_record(tc->c, cfree_sym_intern(tc->c, name), &field, 1);
+ return cfree_cg_type_record(tc->c, cfree_sym_intern(tc->c, cfree_slice_cstr(name)), &field, 1);
}
static CfreeCgTypeId make_func_type(TestCtx* tc, CfreeCgTypeId ret,
@@ -4853,7 +4854,7 @@ static void opt_inline_asm_constraints_and_clobbers(void) {
aux->ins[0].type = tc.i32;
aux->out_ops[0] = op_reg_(out, tc.i32);
aux->in_ops[0] = op_reg_(fixed, tc.i32);
- aux->clobbers[0] = pool_intern_cstr(tc.c->global, "x20");
+ aux->clobbers[0] = pool_intern_slice(tc.c->global, SLICE_LIT("x20"));
in->extra.aux = aux;
in->ndefs = 1;
in->defs = arena_array(f->arena, Val, 1);
diff --git a/test/parse/harness/parse_runner.c b/test/parse/harness/parse_runner.c
@@ -342,7 +342,7 @@ static int add_runtime_archive(CfreeLinkArchiveInput* rt_archive,
path = "build/rt/x86_64-linux/libcfree_rt.a";
if (read_file(path, &data, &len) != 0) return 0;
memset(rt_archive, 0, sizeof *rt_archive);
- rt_archive->bytes.name = path;
+ rt_archive->name = cfree_slice_cstr(path);
rt_archive->bytes.data = data;
rt_archive->bytes.len = len;
*rt_data_out = data;
@@ -351,7 +351,8 @@ static int add_runtime_archive(CfreeLinkArchiveInput* rt_archive,
static CfreeStatus compile_c_obj(CfreeCompiler* c,
const CfreeCCompileOptions* opts,
- const CfreeBytes* in, CfreeObjBuilder** out) {
+ CfreeSlice name, const CfreeSlice* in,
+ CfreeObjBuilder** out) {
CfreeCompileSessionOptions sopts;
CfreeCompileSession* session = NULL;
CfreeSourceInput sin;
@@ -362,6 +363,7 @@ static CfreeStatus compile_c_obj(CfreeCompiler* c,
sopts.compile.diagnostics = opts->diagnostics;
sopts.compile.language_options = opts;
memset(&sin, 0, sizeof(sin));
+ sin.name = name;
sin.bytes = *in;
sin.lang = CFREE_LANG_C;
st = cfree_compile_session_new(c, &sopts, &session);
@@ -372,9 +374,10 @@ static CfreeStatus compile_c_obj(CfreeCompiler* c,
static CfreeStatus compile_c_emit(CfreeCompiler* c,
const CfreeCCompileOptions* opts,
- const CfreeBytes* in, CfreeWriter* w) {
+ CfreeSlice name, const CfreeSlice* in,
+ CfreeWriter* w) {
CfreeObjBuilder* ob = NULL;
- CfreeStatus st = compile_c_obj(c, opts, in, &ob);
+ CfreeStatus st = compile_c_obj(c, opts, name, in, &ob);
if (st == CFREE_OK && !opts->code.emit_c_source)
st = cfree_obj_builder_emit(ob, w);
cfree_obj_builder_free(ob);
@@ -390,7 +393,7 @@ static int mode_emit_impl(const char* src_path, const char* out_path,
CfreeTarget tgt;
CfreeContext ctx;
CfreeCompiler* c = NULL;
- CfreeBytes in;
+ CfreeSlice in;
CfreeCCompileOptions opts;
CfreeWriter* w = NULL;
int rc = 0;
@@ -409,7 +412,6 @@ static int mode_emit_impl(const char* src_path, const char* out_path,
return 2;
}
memset(&in, 0, sizeof in);
- in.name = src_path;
in.data = src;
in.len = src_len;
@@ -424,7 +426,7 @@ static int mode_emit_impl(const char* src_path, const char* out_path,
opts.code.emit_c_source = true;
opts.code.c_source_writer = w;
}
- if (compile_c_emit(c, &opts, &in, w) != CFREE_OK) {
+ if (compile_c_emit(c, &opts, cfree_slice_cstr(src_path), &in, w) != CFREE_OK) {
cfree_writer_close(w);
cfree_compiler_free(c);
free(src);
@@ -470,7 +472,7 @@ static int mode_jit(const char* src_path) {
CfreeTarget tgt;
CfreeContext ctx;
CfreeCompiler* c = NULL;
- CfreeBytes in;
+ CfreeSlice in;
CfreeCCompileOptions opts;
CfreeObjBuilder* ob = NULL;
CfreeLinkArchiveInput rt_archive;
@@ -493,14 +495,14 @@ static int mode_jit(const char* src_path) {
return 2;
}
memset(&in, 0, sizeof in);
- in.name = src_path;
in.data = src;
in.len = src_len;
memset(&opts, 0, sizeof opts);
opts.code.opt_level = opt_level_from_env();
add_test_system_includes(&opts);
- if (compile_c_obj(c, &opts, &in, &ob) != CFREE_OK || !ob) {
+ if (compile_c_obj(c, &opts, cfree_slice_cstr(src_path), &in, &ob) != CFREE_OK ||
+ !ob) {
cfree_compiler_free(c);
free(src);
return 1;
@@ -508,7 +510,7 @@ static int mode_jit(const char* src_path) {
memset(&lopts, 0, sizeof lopts);
lopts.output_kind = CFREE_LINK_OUTPUT_JIT;
- lopts.entry = "test_main";
+ lopts.entry = CFREE_SLICE_LIT("test_main");
memset(&jhost, 0, sizeof jhost);
jhost.execmem = &g_execmem;
@@ -531,14 +533,14 @@ static int mode_jit(const char* src_path) {
}
cfree_link_session_free(link);
- fn = (int (*)(void))cfree_jit_lookup(jit, "test_main");
+ fn = (int (*)(void))cfree_jit_lookup(jit, CFREE_SLICE_LIT("test_main"));
#if defined(__aarch64__) || defined(__arm64__)
{
- char* td_start = (char*)cfree_jit_lookup(jit, "__tdata_start");
- char* td_end = (char*)cfree_jit_lookup(jit, "__tdata_end");
+ char* td_start = (char*)cfree_jit_lookup(jit, CFREE_SLICE_LIT("__tdata_start"));
+ char* td_end = (char*)cfree_jit_lookup(jit, CFREE_SLICE_LIT("__tdata_end"));
unsigned long bs_n =
- (unsigned long)(unsigned long long)cfree_jit_lookup(jit, "__tbss_size");
+ (unsigned long)(unsigned long long)cfree_jit_lookup(jit, CFREE_SLICE_LIT("__tbss_size"));
if (td_start && td_end) {
unsigned long td_n = (unsigned long)(td_end - td_start);
unsigned long i;
diff --git a/test/wasm/harness/wasm_tool.c b/test/wasm/harness/wasm_tool.c
@@ -120,9 +120,8 @@ int main(int argc, char** argv) {
free(src);
return 2;
}
- CfreeBytes in;
+ CfreeSlice in;
memset(&in, 0, sizeof in);
- in.name = argv[2];
in.data = src;
in.len = src_len;
int rc = cfree_wasm_wat_to_wasm(c, &in, w);