kit

kit
git clone https://git.ryansepassi.com/git/kit.git
Log | Files | Refs | README

commit 923c2ef63261ed6e24eee8c65c9ff7f5153345e5
parent ce021f13c697ea50f184ce1aeef44bef4b6e9a0e
Author: Ryan Sepassi <rsepassi@gmail.com>
Date:   Mon, 11 May 2026 17:18:07 -0700

Preprocess .S inputs in assembler driver

Diffstat:
Mdriver/as.c | 63+++++++++++++++++++++++++++++++++++++++++++++++++++++++--------
1 file changed, 55 insertions(+), 8 deletions(-)

diff --git a/driver/as.c b/driver/as.c @@ -1,11 +1,12 @@ #include <stdint.h> +#include "cflags.h" #include "driver.h" /* `cfree as` — standalone assembler. Reads a single text source, writes a * relocatable object via cfree_compile_obj_emit with the input tagged - * CFREE_LANG_ASM. The accepted input is a GAS subset (AT&T syntax on x86); - * see <cfree.h>. */ + * CFREE_LANG_ASM. `.S` inputs are preprocessed first; `.s` inputs are not. + * The accepted input is a GAS subset (AT&T syntax on x86); see <cfree.h>. */ #define AS_TOOL "as" @@ -18,7 +19,7 @@ typedef struct AsOptions { static void as_usage(void) { driver_errf(AS_TOOL, "%s", - "usage: cfree as [-g] [-target TRIPLE] -o out.o input.s\n" + "usage: cfree as [-g] [-target TRIPLE] -o out.o input.{s,S}\n" " cfree as --help for full option reference"); } @@ -29,16 +30,22 @@ void driver_help_as(void) { "\n" "USAGE\n" " cfree as [options] -o OUT.o INPUT.s\n" + " cfree as [options] -o OUT.o INPUT.S\n" "\n" "DESCRIPTION\n" " Reads a single text source written in a GAS subset (AT&T syntax on\n" " x86, standard mnemonics on aarch64/riscv64) and writes a relocatable\n" - " object via the same back-end the C compiler emits to. Exactly one\n" - " positional input is required; -o is required.\n" + " object via the same back-end the C compiler emits to. INPUT.S is run\n" + " through the C preprocessor first; INPUT.s is assembled directly.\n" + " Exactly one positional input is required; -o is required.\n" "\n" "OPTIONS\n" " -o PATH Output object path (required)\n" " -g Emit DWARF debug info from .file/.loc directives\n" + " -I DIR, -IDIR Add a user include directory for INPUT.S\n" + " -isystem DIR Add a system include directory for INPUT.S\n" + " -D NAME[=VALUE] Define a preprocessor macro for INPUT.S\n" + " -U NAME Undefine a preprocessor macro for INPUT.S\n" " -target TRIPLE Cross-assemble target. See `cfree cc --help` for " "the\n" " full list of recognized arches and OSes. Default:\n" @@ -50,13 +57,19 @@ void driver_help_as(void) { } /* Returns 0 on success; non-zero on bad args (already reported). */ -static int as_parse(int argc, char** argv, AsOptions* o) { +static int as_parse(int argc, char** argv, AsOptions* o, DriverEnv* env, + DriverCflags* cf) { int i; o->target = driver_host_target(); for (i = 1; i < argc; ++i) { const char* a = argv[i]; + int r; + + r = driver_cflags_try_consume(cf, env, AS_TOOL, argc, argv, &i); + if (r < 0) return 1; + if (r > 0) continue; if (driver_streq(a, "-g")) { o->debug_info = 1; @@ -111,13 +124,19 @@ static int as_parse(int argc, char** argv, AsOptions* o) { int driver_as(int argc, char** argv) { DriverEnv env; AsOptions o = {0}; + DriverCflags cf = {0}; CfreeEnv cenv; + CfreePpOptions pp; CfreeCompiler* compiler = NULL; CfreeWriter* writer = NULL; + CfreeWriter* pp_writer = NULL; CfreeFileData src = {0}; CfreeBytesInput input; + CfreeBytesInput asm_input; CfreeCompileOptions copts; CfreeCompileOptions zero = {0}; + const uint8_t* pp_data; + size_t pp_len; int rc = 1; int loaded = 0; @@ -128,10 +147,18 @@ int driver_as(int argc, char** argv) { driver_env_init(&env); - if (as_parse(argc, argv, &o) != 0) { + if (driver_cflags_init(&cf, &env, argc) != 0) { + driver_errf(AS_TOOL, "out of memory"); + driver_env_fini(&env); + return 2; + } + + if (as_parse(argc, argv, &o, &env, &cf) != 0) { + driver_cflags_fini(&cf, &env); driver_env_fini(&env); return 2; } + driver_cflags_fill_pp(&cf, &pp); cenv = driver_env_to_cfree(&env); @@ -160,13 +187,33 @@ int driver_as(int argc, char** argv) { input.data = src.data; input.len = src.size; input.lang = CFREE_LANG_ASM; + asm_input = input; + + if (driver_has_suffix(o.source, ".S")) { + pp_writer = cfree_writer_mem(cenv.heap); + if (!pp_writer) { + driver_errf(AS_TOOL, "out of memory"); + goto out; + } + if (cfree_preprocess(compiler, &pp, &input, pp_writer) != 0) goto out; + if (cfree_writer_error(pp_writer)) { + driver_errf(AS_TOOL, "failed to preprocess: %s", o.source); + goto out; + } + pp_data = cfree_writer_mem_bytes(pp_writer, &pp_len); + asm_input.data = pp_data; + asm_input.len = pp_len; + asm_input.lang = CFREE_LANG_ASM; + } - rc = cfree_compile_obj_emit(compiler, &copts, &input, writer); + rc = cfree_compile_obj_emit(compiler, &copts, &asm_input, writer); out: if (compiler) driver_compiler_free(compiler); + if (pp_writer) cfree_writer_close(pp_writer); if (writer) cfree_writer_close(writer); if (loaded) cenv.file_io->release(cenv.file_io->user, &src); + driver_cflags_fini(&cf, &env); driver_env_fini(&env); return rc; }