Skip to documentation
SLOP

tiny.chant.driver

Reference tiny.chant driver

Defined in tiny.chant.

API (8)

Actions

Public operations.

Types and contracts

Public types and contracts.

No direct callersNo direct callstiny.chantdriver
Static calls · unresolved targets: unknown · external targets: unknown.

Source

Called byCallstest sourcelib.chant.src.drivertest: compileFile accepts c23 embed i...test sourcelib.chant.src.drivertest: compileFile accepts c23 embed o...test sourcelib.chant.src.drivertest: compileFile accepts c23 math he...test sourcelib.chant.src.drivertest: compileFile accepts c23 standar...test sourcelib.chant.src.drivertest: compileFile accepts c23 stdlib ...test sourcelib.chant.src.drivertest: compileFile accepts c23 string ...drivercompileSourcedriverpreprocessdrivercompileFile
Static calls · unresolved targets: 0 · external targets: 0.
Called byCallsNo direct callsdrivercompileFiletest sourcelib.chant.src.drivertest: compileSource accepts c23 aggre...test sourcelib.chant.src.drivertest: compileSource accepts c23 bit p...test sourcelib.chant.src.drivertest: compileSource accepts c23 bool ...test sourcelib.chant.src.drivertest: compileSource accepts c23 decim...+5 moredrivercompileSource
Static calls · unresolved targets: 0 · external targets: 15.
Called byCallstest sourcelib.chant.src.drivertest: compileFile accepts c23 math he...test sourcelib.chant.src.drivertest: compileFile accepts c23 standar...test sourcelib.chant.src.drivertest: compileFile accepts c23 stdlib ...test sourcelib.chant.src.drivertest: compileFile accepts c23 string ...test sourcelib.chant.src.drivertest: preprocess accepts c23 preproce...test sourcelib.chant.src.drivertest: preprocess accepts c23 standard...private sourcelib.chant.src.driverdirectoryExistsdriverincludeDir
Static calls · unresolved targets: 0 · external targets: 0.
Called byCallsNo direct callsdrivercompileFiletest sourcelib.chant.src.drivertest: preprocess accepts c23 preproce...test sourcelib.chant.src.drivertest: preprocess accepts c23 standard...test sourcelib.chant.src.drivertest: preprocess delegates to the sys...driverpreprocess
Static calls · unresolved targets: 1 · external targets: 0.

Source: lib/chant/src/driver.zig

zig
const std = @import("std");const choir = @import("choir");const sys = @import("sys");const lexer = @import("lexer/root.zig");const parse = @import("parse/root.zig");const preprocess_mod = @import("preprocess/root.zig");const lower = @import("lower/root.zig");pub const Error = preprocess_mod.Error || lexer.Error || lexer.CapacityError ||    lexer.Exhaustion || lexer.Storage.InitError || parse.Error ||    parse.CapacityError || parse.Exhaustion || parse.Storage.InitError || lower.Error;pub const Diagnostic = preprocess_mod.Diagnostic;pub const Options = preprocess_mod.Options;pub fn preprocess(    arena: std.mem.Allocator,    environ: std.process.Environ,    source_path: []const u8,    options: Options,    diagnostic: ?*Diagnostic,) Error![]const u8 {    return preprocess_mod.run(arena, environ, source_path, options, diagnostic);}pub const Compiled = struct {    unit: lower.Unit,    diagnostic: parse.Diagnostic = .{},};pub fn compileSource(    gpa: std.mem.Allocator,    arena: std.mem.Allocator,    ctx: *choir.Context,    source: []const u8,    file: []const u8,    diagnostic: ?*parse.Diagnostic,) Error!Compiled {    const token_survey = try lexer.survey(source, file);    const token_capacity = try lexer.Capacity.derive(token_survey.limits);    const token_bytes = try arena.alignedAlloc(        u8,        .fromByteUnits(lexer.Storage.storage_alignment),        token_capacity.storage_bytes,    );    var token_storage = try lexer.Storage.init(token_bytes, token_survey.limits);    token_storage.activate();    defer _ = token_storage.deinit();    const tokens = try token_storage.fill(token_survey, source, file);    const node_survey = parse.survey(tokens);    const node_capacity = try parse.Capacity.derive(node_survey.limits);    const node_bytes = try arena.alignedAlloc(        u8,        .fromByteUnits(parse.Storage.storage_alignment),        node_capacity.storage_bytes,    );    var node_storage = try parse.Storage.init(node_bytes, node_survey.limits);    node_storage.activate();    defer _ = node_storage.deinit();    var parser = try parse.init(arena, &node_storage, node_survey, tokens);    const tree = parse.parseTranslationUnit(&parser) catch |err| {        if (diagnostic) |out| out.* = parser.diagnostic;        return err;    };    const unit = try lower.lowerUnit(gpa, arena, ctx, tree);    return .{ .unit = unit };}pub fn compileFile(    gpa: std.mem.Allocator,    arena: std.mem.Allocator,    ctx: *choir.Context,    environ: std.process.Environ,    source_path: []const u8,    options: Options,    diagnostic: ?*Diagnostic,) Error!Compiled {    const source = try preprocess(arena, environ, source_path, options, diagnostic);    return compileSource(gpa, arena, ctx, source, source_path, diagnostic);}test "compileSource drives the full pipeline" {    var arena_state = std.heap.ArenaAllocator.init(std.testing.allocator);    defer arena_state.deinit();    const arena = arena_state.allocator();    var ctx = try choir.Context.init(arena, choir.Context.Limits.testing);    defer ctx.deinit(arena);    try choir.dialects.registerAllDialects(&ctx);    const compiled = try compileSource(std.testing.allocator, arena, &ctx,        \\void scale(int n, double a, double *x) {        \\  int i;        \\  for (i = 0; i < n; i++)        \\    x[i] = x[i] * a;        \\}    , "scale.c", null);    try std.testing.expectEqual(@as(usize, 1), compiled.unit.lowered.items.len);    try std.testing.expectEqualStrings("scale", compiled.unit.lowered.items[0]);}test "compileSource accepts c23 bool and separated constants" {    var arena_state = std.heap.ArenaAllocator.init(std.testing.allocator);    defer arena_state.deinit();    const arena = arena_state.allocator();    var ctx = try choir.Context.init(arena, choir.Context.Limits.testing);    defer ctx.deinit(arena);    try choir.dialects.registerAllDialects(&ctx);    const compiled = try compileSource(std.testing.allocator, arena, &ctx,        \\void c23(int n, double *x) {        \\  bool enabled = true;        \\  int stride = 0b10'00;        \\  double scale = 1.5'0;        \\  for (int i = 0; i < n; i++)        \\    if (enabled)        \\      x[i] = x[i] + scale * stride;        \\}    , "c23.c", null);    try std.testing.expectEqual(@as(usize, 1), compiled.unit.lowered.items.len);    try std.testing.expectEqualStrings("c23", compiled.unit.lowered.items[0]);}test "compileSource accepts c23 parser syntax" {    var arena_state = std.heap.ArenaAllocator.init(std.testing.allocator);    defer arena_state.deinit();    const arena = arena_state.allocator();    var ctx = try choir.Context.init(arena, choir.Context.Limits.testing);    defer ctx.deinit(arena);    try choir.dialects.registerAllDialects(&ctx);    const compiled = try compileSource(std.testing.allocator, arena, &ctx,        \\static_assert(alignof(double) == 8, "lp64");        \\[[maybe_unused]] thread_local alignas(16) int global [[maybe_unused]] = {};        \\void c23_syntax(int n, double *x) {        \\start:        \\  int i = {};        \\  for (i = 0; i < n; i++) {        \\  body:        \\    x[i] = x[i] + 1.0;        \\  end:        \\  }        \\}    , "c23-syntax.c", null);    try std.testing.expectEqual(@as(usize, 1), compiled.unit.lowered.items.len);    try std.testing.expectEqualStrings("c23_syntax", compiled.unit.lowered.items[0]);}test "compileSource accepts c23 inferred scalar syntax" {    var arena_state = std.heap.ArenaAllocator.init(std.testing.allocator);    defer arena_state.deinit();    const arena = arena_state.allocator();    var ctx = try choir.Context.init(arena, choir.Context.Limits.testing);    defer ctx.deinit(arena);    try choir.dialects.registerAllDialects(&ctx);    const compiled = try compileSource(std.testing.allocator, arena, &ctx,        \\typedef typeof(nullptr) nullptr_t;        \\static_assert(!nullptr);        \\static_assert(sizeof(typeof(int *)) == 8);        \\constexpr int lanes = 4;        \\static_assert(lanes == 4);        \\alignas(lanes) int aligned_lanes = 0;        \\void c23_types(int n, double *x) {        \\  constexpr auto stride = 2;        \\  static_assert(stride == 2);        \\  unsigned _BitInt(stride + 1) mask = 3uwb;        \\  typeof_unqual(*x) scale = 1.0;        \\  for (typeof(n) i = 0; i < n; i++)        \\    x[i] = x[i] + scale * stride + mask;        \\}    , "c23-types.c", null);    try std.testing.expectEqual(@as(usize, 1), compiled.unit.lowered.items.len);    try std.testing.expectEqualStrings("c23_types", compiled.unit.lowered.items[0]);}test "compileSource accepts c23 bit precise integers" {    var arena_state = std.heap.ArenaAllocator.init(std.testing.allocator);    defer arena_state.deinit();    const arena = arena_state.allocator();    var ctx = try choir.Context.init(arena, choir.Context.Limits.testing);    defer ctx.deinit(arena);    try choir.dialects.registerAllDialects(&ctx);    const compiled = try compileSource(std.testing.allocator, arena, &ctx,        \\void c23_bitint(int n, double *x) {        \\  _BitInt(17) offset = 3wb;        \\  unsigned _BitInt(6) mask = 0b101010uwb;        \\  for (int i = 0; i < n; i++)        \\    x[i] = x[i] + offset + (_BitInt(17))mask;        \\}    , "c23-bitint.c", null);    try std.testing.expectEqual(@as(usize, 1), compiled.unit.lowered.items.len);    try std.testing.expectEqualStrings("c23_bitint", compiled.unit.lowered.items[0]);}test "compileSource accepts c23 decimal floating syntax" {    var arena_state = std.heap.ArenaAllocator.init(std.testing.allocator);    defer arena_state.deinit();    const arena = arena_state.allocator();    var ctx = try choir.Context.init(arena, choir.Context.Limits.testing);    defer ctx.deinit(arena);    try choir.dialects.registerAllDialects(&ctx);    const compiled = try compileSource(std.testing.allocator, arena, &ctx,        \\void c23_decimal(int n, double *x) {        \\  _Decimal32 step = 1.25df;        \\  _Decimal64 scale = 2.5DD;        \\  for (int i = 0; i < n; i++)        \\    x[i] = x[i] + step + scale;        \\}    , "c23-decimal.c", null);    try std.testing.expectEqual(@as(usize, 1), compiled.unit.lowered.items.len);    try std.testing.expectEqualStrings("c23_decimal", compiled.unit.lowered.items[0]);}test "compileSource accepts c23 fixed underlying enums" {    var arena_state = std.heap.ArenaAllocator.init(std.testing.allocator);    defer arena_state.deinit();    const arena = arena_state.allocator();    var ctx = try choir.Context.init(arena, choir.Context.Limits.testing);    defer ctx.deinit(arena);    try choir.dialects.registerAllDialects(&ctx);    const compiled = try compileSource(std.testing.allocator, arena, &ctx,        \\enum Color : unsigned int { RED = 1, GREEN, BLUE = RED + 4 };        \\enum Forward : unsigned short;        \\enum Forward : unsigned short { SMALL = 3, SMALL_NEXT };        \\enum Wide { WIDE = 2147483648L, WIDE_NEXT };        \\static_assert(BLUE == 5);        \\static_assert(SMALL_NEXT == 4);        \\static_assert(WIDE_NEXT == 2147483649L);        \\void c23_enum(int n, double *x) {        \\  enum Color c = BLUE;        \\  enum Forward small = SMALL_NEXT;        \\  typeof(WIDE) w = WIDE_NEXT;        \\  for (int i = 0; i < n; i++)        \\    x[i] = x[i] + c + GREEN + small + w;        \\}    , "c23-enum.c", null);    try std.testing.expectEqual(@as(usize, 1), compiled.unit.lowered.items.len);    try std.testing.expectEqualStrings("c23_enum", compiled.unit.lowered.items[0]);}test "compileSource accepts c23 aggregate initializers" {    var arena_state = std.heap.ArenaAllocator.init(std.testing.allocator);    defer arena_state.deinit();    const arena = arena_state.allocator();    var ctx = try choir.Context.init(arena, choir.Context.Limits.testing);    defer ctx.deinit(arena);    try choir.dialects.registerAllDialects(&ctx);    const compiled = try compileSource(std.testing.allocator, arena, &ctx,        \\void c23_init(int n, double *x) {        \\  int empty[3] = {};        \\  int values[3] = {1, 2, 3,};        \\  for (int i = 0; i < n; i++)        \\    x[i] = x[i] + empty[0] + values[2];        \\}    , "c23-init.c", null);    try std.testing.expectEqual(@as(usize, 1), compiled.unit.lowered.items.len);    try std.testing.expectEqualStrings("c23_init", compiled.unit.lowered.items[0]);}test "compileSource accepts c23 deeper array initializers" {    var arena_state = std.heap.ArenaAllocator.init(std.testing.allocator);    defer arena_state.deinit();    const arena = arena_state.allocator();    var ctx = try choir.Context.init(arena, choir.Context.Limits.testing);    defer ctx.deinit(arena);    try choir.dialects.registerAllDialects(&ctx);    const compiled = try compileSource(std.testing.allocator, arena, &ctx,        \\void c23_init_deep(int n, double *x) {        \\  char word[] = "az";        \\  int inferred[] = {1, 2, [4] = 5};        \\  int nested[2][3] = {{1, 2}, [1][2] = 6};        \\  int flat[][2] = {1, 2, 3, 4};        \\  for (int i = 0; i < n; i++)        \\    x[i] = x[i] + word[1] + inferred[4] + nested[1][2] + flat[1][1];        \\}    , "c23-init-deep.c", null);    try std.testing.expectEqual(@as(usize, 1), compiled.unit.lowered.items.len);    try std.testing.expectEqualStrings("c23_init_deep", compiled.unit.lowered.items[0]);}test "compileFile accepts c23 standard header surface" {    var arena_state = std.heap.ArenaAllocator.init(std.testing.allocator);    defer arena_state.deinit();    const arena = arena_state.allocator();    var ctx = try choir.Context.init(arena, choir.Context.Limits.testing);    defer ctx.deinit(arena);    try choir.dialects.registerAllDialects(&ctx);    var tmp = std.testing.tmpDir(.{});    defer tmp.cleanup();    const tmp_path = try tmp.parent_dir.realPathFileAlloc(sys.fs.debugIo(), tmp.sub_path[0..], arena);    const source_path = try std.fs.path.join(arena, &.{ tmp_path, "header-compile.c" });    try sys.fs.writeFile(source_path,        \\#include <stdbit.h>        \\#include <stdckdint.h>        \\#include <uchar.h>        \\void c23_headers(int n, double *x) {        \\  unsigned int stride = stdc_count_ones(15u);        \\  unsigned int width = stdc_bit_width(stride);        \\  unsigned int floor = stdc_bit_floor(stride);        \\  unsigned int zeros = stdc_count_zeros(stride);        \\  unsigned int single = stdc_has_single_bit(width);        \\  unsigned int leading = stdc_leading_zeros(width);        \\  unsigned int trailing = stdc_trailing_zeros(floor);        \\  unsigned int first = stdc_first_trailing_one(floor);        \\  unsigned int ceil = stdc_bit_ceil(stride);        \\  unsigned int checked = 0;        \\  unsigned int overflow = ckd_add(&checked, stride, width);        \\  overflow += ckd_sub(&checked, checked, floor);        \\  overflow += ckd_mul(&checked, checked, 2u);        \\  char8_t marker = u8'a';        \\  for (int i = 0; i < n; i++)        \\    x[i] = x[i] + stride + width + floor + zeros + single + leading + trailing + first + ceil + checked + overflow + marker;        \\}        \\    );    const include_dir = try includeDir(arena);    const environ = sys.env.current();    const compiled = compileFile(std.testing.allocator, arena, &ctx, environ, source_path, .{        .include_dirs = &.{include_dir},    }, null) catch |err| switch (err) {        error.PreprocessorUnavailable => return error.SkipZigTest,        else => return err,    };    try std.testing.expectEqual(@as(usize, 1), compiled.unit.lowered.items.len);    try std.testing.expectEqualStrings("c23_headers", compiled.unit.lowered.items[0]);}test "compileFile accepts c23 string and time header surface" {    var arena_state = std.heap.ArenaAllocator.init(std.testing.allocator);    defer arena_state.deinit();    const arena = arena_state.allocator();    var ctx = try choir.Context.init(arena, choir.Context.Limits.testing);    defer ctx.deinit(arena);    try choir.dialects.registerAllDialects(&ctx);    var tmp = std.testing.tmpDir(.{});    defer tmp.cleanup();    const tmp_path = try tmp.parent_dir.realPathFileAlloc(sys.fs.debugIo(), tmp.sub_path[0..], arena);    const source_path = try std.fs.path.join(arena, &.{ tmp_path, "lib-header-compile.c" });    try sys.fs.writeFile(source_path,        \\#include <string.h>        \\#include <time.h>        \\static_assert(__STDC_VERSION_STRING_H__ == 202311L);        \\static_assert(__STDC_VERSION_TIME_H__ == 202311L);        \\void c23_lib_headers(int n, char *dst, char *src, time_t *timer, double *x) {        \\  size_t len = strlen(src);        \\  int same = strcmp(dst, src);        \\  int prefix = strncmp(dst, src, len);        \\  int bytes = memcmp(dst, src, len);        \\  time_t now = time(timer);        \\  double diff = difftime(now, 0);        \\  clock_t ticks = clock();        \\  for (int i = 0; i < n; i++)        \\    x[i] = x[i] + len + same + prefix + bytes + now + diff + ticks;        \\}        \\    );    const include_dir = try includeDir(arena);    const environ = sys.env.current();    const compiled = compileFile(std.testing.allocator, arena, &ctx, environ, source_path, .{        .include_dirs = &.{include_dir},    }, null) catch |err| switch (err) {        error.PreprocessorUnavailable => return error.SkipZigTest,        else => return err,    };    try std.testing.expectEqual(@as(usize, 1), compiled.unit.lowered.items.len);    try std.testing.expectEqualStrings("c23_lib_headers", compiled.unit.lowered.items[0]);}test "compileFile accepts c23 stdlib header surface" {    var arena_state = std.heap.ArenaAllocator.init(std.testing.allocator);    defer arena_state.deinit();    const arena = arena_state.allocator();    var ctx = try choir.Context.init(arena, choir.Context.Limits.testing);    defer ctx.deinit(arena);    try choir.dialects.registerAllDialects(&ctx);    var tmp = std.testing.tmpDir(.{});    defer tmp.cleanup();    const tmp_path = try tmp.parent_dir.realPathFileAlloc(sys.fs.debugIo(), tmp.sub_path[0..], arena);    const source_path = try std.fs.path.join(arena, &.{ tmp_path, "stdlib-header-compile.c" });    try sys.fs.writeFile(source_path,        \\#include <stdlib.h>        \\static_assert(__STDC_VERSION_STDLIB_H__ == 202311L);        \\void c23_stdlib(int n, char *text, char *buffer, double *x) {        \\  int as_int = atoi(text);        \\  double as_double = atof(text);        \\  long as_long = atol(text);        \\  long as_wide = atoll(text);        \\  int magnitude = abs(as_int);        \\  long wide = labs(as_long) + llabs(as_wide);        \\  size_t alignment = memalignment(buffer);        \\  free_sized(buffer, alignment);        \\  free_aligned_sized(buffer, alignment, alignment);        \\  for (int i = 0; i < n; i++)        \\    x[i] = x[i] + as_int + as_double + magnitude + wide + alignment + EXIT_SUCCESS + EXIT_FAILURE;        \\}        \\    );    const include_dir = try includeDir(arena);    const environ = sys.env.current();    const compiled = compileFile(std.testing.allocator, arena, &ctx, environ, source_path, .{        .include_dirs = &.{include_dir},    }, null) catch |err| switch (err) {        error.PreprocessorUnavailable => return error.SkipZigTest,        else => return err,    };    try std.testing.expectEqual(@as(usize, 1), compiled.unit.lowered.items.len);    try std.testing.expectEqualStrings("c23_stdlib", compiled.unit.lowered.items[0]);}test "compileFile accepts c23 math header surface" {    var arena_state = std.heap.ArenaAllocator.init(std.testing.allocator);    defer arena_state.deinit();    const arena = arena_state.allocator();    var ctx = try choir.Context.init(arena, choir.Context.Limits.testing);    defer ctx.deinit(arena);    try choir.dialects.registerAllDialects(&ctx);    var tmp = std.testing.tmpDir(.{});    defer tmp.cleanup();    const tmp_path = try tmp.parent_dir.realPathFileAlloc(sys.fs.debugIo(), tmp.sub_path[0..], arena);    const source_path = try std.fs.path.join(arena, &.{ tmp_path, "math-header-compile.c" });    try sys.fs.writeFile(source_path,        \\#include <math.h>        \\static_assert(__STDC_VERSION_MATH_H__ == 202311L);        \\void c23_math(int n, double *x) {        \\  for (int i = 0; i < n; i++) {        \\    double expo = exp10(x[i]) + exp10m1(x[i]) + exp2m1(x[i]);        \\    double logs = logp1(x[i]) + log2p1(x[i]) + log10p1(x[i]);        \\    double trig = acospi(0.25) + asinpi(0.25) + atanpi(x[i]) + atan2pi(x[i], 1.0);        \\    trig += sinpi(x[i]) + cospi(x[i]) + tanpi(x[i]);        \\    double powers = compoundn(x[i], 2) + pown(x[i], 2) + powr(2.0, x[i]) + rootn(x[i], 2) + rsqrt(x[i]);        \\    double rounded = roundeven(x[i]) + fromfp(x[i], FP_INT_TONEAREST, 32) + ufromfp(x[i], FP_INT_TOWARDZERO, 32);        \\    rounded += fromfpx(x[i], FP_INT_UPWARD, 32) + ufromfpx(x[i], FP_INT_DOWNWARD, 32);        \\    double adjacent = nextup(x[i]) + nextdown(x[i]);        \\    double extrema = fmaximum(x[i], 1.0) + fminimum(x[i], 1.0) + fmaximum_mag(x[i], -1.0) + fminimum_mag(x[i], -1.0);        \\    extrema += fmaximum_num(x[i], 1.0) + fminimum_num(x[i], 1.0) + fmaximum_mag_num(x[i], -1.0) + fminimum_mag_num(x[i], -1.0);        \\    long exponent = llogb(x[i]);        \\    x[i] = x[i] + expo + logs + trig + powers + rounded + adjacent + extrema + exponent;        \\  }        \\}        \\    );    const include_dir = try includeDir(arena);    const environ = sys.env.current();    const compiled = compileFile(std.testing.allocator, arena, &ctx, environ, source_path, .{        .include_dirs = &.{include_dir},    }, null) catch |err| switch (err) {        error.PreprocessorUnavailable => return error.SkipZigTest,        else => return err,    };    try std.testing.expectEqual(@as(usize, 1), compiled.unit.lowered.items.len);    try std.testing.expectEqualStrings("c23_math", compiled.unit.lowered.items[0]);}test "preprocess delegates to the system compiler when present" {    var arena_state = std.heap.ArenaAllocator.init(std.testing.allocator);    defer arena_state.deinit();    const arena = arena_state.allocator();    var tmp = std.testing.tmpDir(.{});    defer tmp.cleanup();    const tmp_path = try tmp.parent_dir.realPathFileAlloc(sys.fs.debugIo(), tmp.sub_path[0..], arena);    const source_path = try std.fs.path.join(arena, &.{ tmp_path, "driver.c" });    try sys.fs.writeFile(source_path, "#define N 4\nint values[N];\n");    const environ = sys.env.current();    const output = preprocess(arena, environ, source_path, .{}, null) catch |err| switch (err) {        error.PreprocessorUnavailable => return error.SkipZigTest,        else => return err,    };    try std.testing.expect(std.mem.indexOf(u8, output, "int values[4];") != null);}test "preprocess accepts c23 standard headers" {    var arena_state = std.heap.ArenaAllocator.init(std.testing.allocator);    defer arena_state.deinit();    const arena = arena_state.allocator();    var tmp = std.testing.tmpDir(.{});    defer tmp.cleanup();    const tmp_path = try tmp.parent_dir.realPathFileAlloc(sys.fs.debugIo(), tmp.sub_path[0..], arena);    const source_path = try std.fs.path.join(arena, &.{ tmp_path, "header-preprocess.c" });    try sys.fs.writeFile(source_path,        \\#include <limits.h>        \\#include <math.h>        \\#include <stdbool.h>        \\#include <stdbit.h>        \\#include <stdckdint.h>        \\#include <stdlib.h>        \\#include <string.h>        \\#include <time.h>        \\#include <uchar.h>        \\#if __STDC_VERSION_LIMITS_H__ != 202311L        \\#error bad limits version        \\#endif        \\#if BITINT_MAXWIDTH != ULLONG_WIDTH        \\#error bad bitint max width        \\#endif        \\#if __STDC_VERSION_MATH_H__ != 202311L        \\#error bad math version        \\#endif        \\#if __STDC_VERSION_STDBIT_H__ != 202311L        \\#error bad stdbit version        \\#endif        \\#if __STDC_VERSION_STDCKDINT_H__ != 202311L        \\#error bad stdckdint version        \\#endif        \\#if __STDC_VERSION_STDLIB_H__ != 202311L        \\#error bad stdlib version        \\#endif        \\#if __STDC_VERSION_STRING_H__ != 202311L        \\#error bad string version        \\#endif        \\#if __STDC_VERSION_TIME_H__ != 202311L        \\#error bad time version        \\#endif        \\#if __STDC_VERSION_UCHAR_H__ != 202311L        \\#error bad uchar version        \\#endif        \\#if __STDC_ENDIAN_NATIVE__ != __STDC_ENDIAN_LITTLE__ && __STDC_ENDIAN_NATIVE__ != __STDC_ENDIAN_BIG__        \\#error bad endian value        \\#endif        \\int checked(int a, int b) {        \\  int out;        \\  bool overflow = ckd_add(&out, a, b);        \\  char8_t byte = u8'a';        \\  return overflow || stdc_count_ones((unsigned int)byte) == 0;        \\}        \\double math_probe(double x) {        \\  return roundeven(x) + nextup(x) + logp1(x);        \\}        \\    );    const include_dir = try includeDir(arena);    const environ = sys.env.current();    const output = preprocess(arena, environ, source_path, .{        .include_dirs = &.{include_dir},    }, null) catch |err| switch (err) {        error.PreprocessorUnavailable => return error.SkipZigTest,        else => return err,    };    try std.testing.expect(std.mem.indexOf(u8, output, "__builtin_add_overflow") != null);    try std.testing.expect(std.mem.indexOf(u8, output, "char8_t byte") != null);    try std.testing.expect(std.mem.indexOf(u8, output, "stdc_count_ones_ull") != null);    try std.testing.expect(std.mem.indexOf(u8, output, "[[unsequenced]]") != null);    try std.testing.expect(std.mem.indexOf(u8, output, "free_sized") != null);    try std.testing.expect(std.mem.indexOf(u8, output, "memalignment") != null);    try std.testing.expect(std.mem.indexOf(u8, output, "memset_explicit") != null);    try std.testing.expect(std.mem.indexOf(u8, output, "timespec_getres") != null);    try std.testing.expect(std.mem.indexOf(u8, output, "roundeven") != null);}test "preprocess accepts c23 preprocessor additions" {    var arena_state = std.heap.ArenaAllocator.init(std.testing.allocator);    defer arena_state.deinit();    const arena = arena_state.allocator();    var tmp = std.testing.tmpDir(.{});    defer tmp.cleanup();    const tmp_path = try tmp.parent_dir.realPathFileAlloc(sys.fs.debugIo(), tmp.sub_path[0..], arena);    const source_path = try std.fs.path.join(arena, &.{ tmp_path, "preprocessor.c" });    const data_path = try std.fs.path.join(arena, &.{ tmp_path, "resource.bin" });    const empty_path = try std.fs.path.join(arena, &.{ tmp_path, "empty.bin" });    try sys.fs.writeFile(data_path, &.{ 11, 12, 13 });    try sys.fs.writeFile(empty_path, "");    try sys.fs.writeFile(source_path,        \\#include <stddef.h>        \\#warning chant c23 warning smoke        \\#if !__has_include(<stddef.h>)        \\#error missing has_include        \\#endif        \\#if !__has_c_attribute(maybe_unused)        \\#error missing has_c_attribute        \\#endif        \\#if __has_embed("resource.bin") != __STDC_EMBED_FOUND__        \\#error missing has_embed        \\#endif        \\#if __has_embed("empty.bin") != __STDC_EMBED_EMPTY__        \\#error missing empty has_embed        \\#endif        \\#if 0        \\#error bad elifdef branch        \\#elifdef __has_embed        \\int elifdef_has_embed = 1;        \\#else        \\#error missing elifdef        \\#endif        \\#if 0        \\#error bad elifndef branch        \\#elifndef __has_embed        \\#error has_embed should be defined        \\#else        \\int elifndef_has_embed = 1;        \\#endif        \\#define C23_VA(base, ...) base __VA_OPT__(+) __VA_ARGS__        \\int va_empty = C23_VA(5);        \\int va_full = C23_VA(5, 7);        \\unsigned char bytes[] = {        \\#embed "resource.bin" limit(2) prefix(1,) suffix(, 2)        \\};        \\int empty_value =        \\#embed "empty.bin" if_empty(9)        \\;        \\    );    const include_dir = try includeDir(arena);    const output = preprocess(arena, sys.env.current(), source_path, .{        .include_dirs = &.{include_dir},    }, null) catch |err| switch (err) {        error.PreprocessorUnavailable => return error.SkipZigTest,        else => return err,    };    try std.testing.expect(std.mem.indexOf(u8, output, "int elifdef_has_embed = 1;") != null);    try std.testing.expect(std.mem.indexOf(u8, output, "int elifndef_has_embed = 1;") != null);    try std.testing.expect(std.mem.indexOf(u8, output, "int va_empty = 5 ;") != null);    try std.testing.expect(std.mem.indexOf(u8, output, "int va_full = 5 + 7;") != null);    try std.testing.expect(std.mem.indexOf(u8, output, "1,11,12, 2") != null);    try std.testing.expect(std.mem.indexOf(u8, output, "int empty_value =\n9") != null);}test "compileFile accepts c23 embed output" {    var arena_state = std.heap.ArenaAllocator.init(std.testing.allocator);    defer arena_state.deinit();    const arena = arena_state.allocator();    var ctx = try choir.Context.init(arena, choir.Context.Limits.testing);    defer ctx.deinit(arena);    try choir.dialects.registerAllDialects(&ctx);    var tmp = std.testing.tmpDir(.{});    defer tmp.cleanup();    const tmp_path = try tmp.parent_dir.realPathFileAlloc(sys.fs.debugIo(), tmp.sub_path[0..], arena);    const source_path = try std.fs.path.join(arena, &.{ tmp_path, "embed-compile.c" });    const data_path = try std.fs.path.join(arena, &.{ tmp_path, "resource.bin" });    try sys.fs.writeFile(data_path, &.{5});    try sys.fs.writeFile(source_path,        \\#if __has_embed("resource.bin") != __STDC_EMBED_FOUND__        \\#error missing embed resource        \\#endif        \\void c23_embed(int n, double *x) {        \\  int add =        \\#embed "resource.bin"        \\  ;        \\  for (int i = 0; i < n; i++)        \\    x[i] = x[i] + add;        \\}        \\    );    const compiled = compileFile(std.testing.allocator, arena, &ctx, sys.env.current(), source_path, .{}, null) catch |err| switch (err) {        error.PreprocessorUnavailable => return error.SkipZigTest,        else => return err,    };    try std.testing.expectEqual(@as(usize, 1), compiled.unit.lowered.items.len);    try std.testing.expectEqualStrings("c23_embed", compiled.unit.lowered.items[0]);}test "compileFile accepts c23 embed inside included headers" {    var arena_state = std.heap.ArenaAllocator.init(std.testing.allocator);    defer arena_state.deinit();    const arena = arena_state.allocator();    var ctx = try choir.Context.init(arena, choir.Context.Limits.testing);    defer ctx.deinit(arena);    try choir.dialects.registerAllDialects(&ctx);    var tmp = std.testing.tmpDir(.{});    defer tmp.cleanup();    const tmp_path = try tmp.parent_dir.realPathFileAlloc(sys.fs.debugIo(), tmp.sub_path[0..], arena);    const include_dir = try std.fs.path.join(arena, &.{ tmp_path, "include" });    try sys.fs.createDirPath(include_dir);    const source_path = try std.fs.path.join(arena, &.{ tmp_path, "header-embed-main.c" });    const header_path = try std.fs.path.join(arena, &.{ include_dir, "header_embed.h" });    const data_path = try std.fs.path.join(arena, &.{ include_dir, "payload.bin" });    try sys.fs.writeFile(data_path, &.{ 17, 18 });    try sys.fs.writeFile(header_path,        \\#define HEADER_RESOURCE "payload.bin"        \\#define HEADER_LIMIT limit(1)        \\void c23_header_embed(int n, double *x) {        \\  int add =        \\#embed HEADER_RESOURCE HEADER_LIMIT        \\  ;        \\  for (int i = 0; i < n; i++)        \\    x[i] = x[i] + add;        \\}        \\    );    try sys.fs.writeFile(source_path,        \\#include <header_embed.h>        \\    );    const compiled = compileFile(std.testing.allocator, arena, &ctx, sys.env.current(), source_path, .{        .include_dirs = &.{include_dir},    }, null) catch |err| switch (err) {        error.PreprocessorUnavailable => return error.SkipZigTest,        else => return err,    };    try std.testing.expectEqual(@as(usize, 1), compiled.unit.lowered.items.len);    try std.testing.expectEqualStrings("c23_header_embed", compiled.unit.lowered.items[0]);}pub fn includeDir(arena: std.mem.Allocator) ![]const u8 {    if (directoryExists("include")) return std.fs.path.resolve(arena, &.{"include"});    return std.fs.path.resolve(arena, &.{ "lib", "chant", "include" });}fn directoryExists(path: []const u8) bool {    sys.fs.cwd().access(sys.fs.debugIo(), path, .{}) catch return false;    return true;}

Source: lib/chant/src/root.zig:65

zig
pub const driver = @import("driver.zig");

Complete caller list for driver.compileSource

10 direct callers.

Audit

Definitions7
Public names7
Members2
Version26.7.0
Revisiondaab053ee433