arocc icon indicating copy to clipboard operation
arocc copied to clipboard

Simplify library usage

Open mateuszradomski opened this issue 3 years ago • 4 comments

#define D ((sizeof(int) * 8 - 1) / (sizeof(int) * 8))
int a[D];
thread 40444 panic: access of inactive union field
/home/radomski/programs/rrc_values/arocc/src/Type.zig:549:102: 0x2b3e86 in .arocc.Type.elemType (rrc)
        .pointer, .unspecified_variable_len_array, .decayed_unspecified_variable_len_array => ty.data.sub_type.*,
                                                                                                     ^
/home/radomski/programs/rrc_values/arocc/src/Type.zig:2001:40: 0x2b4a94 in .arocc.Type.printPrologue (rrc)
            const elem_ty = ty.elemType();
                                       ^
/home/radomski/programs/rrc_values/arocc/src/Type.zig:1968:29: 0x2b4713 in .arocc.Type.print (rrc)
    _ = try ty.printPrologue(mapper, w);
                            ^
/home/radomski/programs/rrc_values/arocc/src/Type.zig:1987:32: 0x2b4983 in .arocc.Type.printPrologue (rrc)
        try non_atomic_ty.print(mapper, w);
                               ^
/home/radomski/programs/rrc_values/arocc/src/Type.zig:1968:29: 0x2b4713 in .arocc.Type.print (rrc)
    _ = try ty.printPrologue(mapper, w);
                            ^
/home/radomski/programs/rrc_values/arocc/src/Parser.zig:363:16: 0x2b2705 in .arocc.Parser.typePairStrExtra (rrc)
    try a.print(mapper, p.strings.writer());
               ^
/home/radomski/programs/rrc_values/arocc/src/Parser.zig:354:30: 0x34b980 in .arocc.Parser.typePairStr (rrc)
    return p.typePairStrExtra(a, " and ", b);
                             ^
/home/radomski/programs/rrc_values/arocc/src/Parser.zig:4579:64: 0x3498b0 in .arocc.Parser.Result.invalidBinTy (rrc)
        try p.errStr(.invalid_bin_types, tok, try p.typePairStr(a.ty, b.ty));
                                                               ^
/home/radomski/programs/rrc_values/arocc/src/Parser.zig:4220:55: 0x31ced5 in .arocc.Parser.Result.adjustTypes (rrc)
        if (kind == .arithmetic) return a.invalidBinTy(tok, b, p);
                                                      ^
/home/radomski/programs/rrc_values/arocc/src/Parser.zig:5348:32: 0x3acb20 in .arocc.Parser.mulExpr (rrc)
        if (try lhs.adjustTypes(percent.?, &rhs, p, if (tag == .mod_expr) .integer else .arithmetic)) {
                               ^
/home/radomski/programs/rrc_values/arocc/src/Parser.zig:5304:28: 0x3aac06 in .arocc.Parser.addExpr (rrc)
    var lhs = try p.mulExpr();

Related I think, because doing just:

int a[sizeof(int)];
thread 41922 panic: access of inactive union field
/home/radomski/programs/rrc_values/arocc/src/Type.zig:1917:108: 0x2eb9c2 in .arocc.Type.Builder.fromType (rrc)
            .decayed_unspecified_variable_len_array => .{ .decayed_unspecified_variable_len_array = ty.data.sub_type },
                                                                                                           ^
/home/radomski/programs/rrc_values/arocc/src/Parser.zig:344:30: 0x2c29c0 in .arocc.Parser.typeStr (rrc)
    if (Type.Builder.fromType(ty).str()) |str| return str;
                             ^
/home/radomski/programs/rrc_values/arocc/src/Parser.zig:2505:70: 0x2f751a in .arocc.Parser.directDeclarator (rrc)
            try p.errStr(.array_size_non_int, size_tok, try p.typeStr(size.ty));
                                                                     ^
/home/radomski/programs/rrc_values/arocc/src/Parser.zig:2403:38: 0x2c201f in .arocc.Parser.declarator (rrc)
        d.ty = try p.directDeclarator(d.ty, &d, kind);
                                     ^
/home/radomski/programs/rrc_values/arocc/src/Parser.zig:1399:31: 0x2bfd32 in .arocc.Parser.initDeclarator (rrc)
        .d = (try p.declarator(decl_spec.ty, .normal)) orelse return null,
                              ^
/home/radomski/programs/rrc_values/arocc/src/Parser.zig:746:39: 0x2bb0a1 in .arocc.Parser.decl (rrc)
    var init_d = (try p.initDeclarator(&decl_spec, attr_buf_top)) orelse {
                                      ^
/home/radomski/programs/rrc_values/arocc/src/Parser.zig:634:16: 0x28e9c4 in .arocc.Parser.parseOrNextDecl (rrc)
    return func(p) catch |er| switch (er) {
               ^
/home/radomski/programs/rrc_values/arocc/src/Parser.zig:571:34: 0x274785 in .arocc.Parser.parse (rrc)
        if (try p.parseOrNextDecl(decl)) continue;
                                 ^
/home/radomski/programs/rrc_values/src/main.zig:41:38: 0x26e4dc in main (rrc)
    var tree = try arocc.Parser.parse(&pp);
                                     ^
/home/radomski/programs/rrc_values/zig/lib/std/start.zig:576:37: 0x24d343 in std.start.posixCallMainAndExit (rrc)
            const result = root.main() catch |err| {
                                    ^
/home/radomski/programs/rrc_values/zig/lib/std/start.zig:338:5: 0x24d0d2 in std.start._start (rrc)
    @call(.{ .modifier = .never_inline }, posixCallMainAndExit, .{});
    ^

mateuszradomski avatar Aug 02 '22 16:08 mateuszradomski

Are you using the latest master branch? And what command-line flags & platform for arocc are you using? Neither of those examples crashes for me, tested on MacOS and Linux.

ehaas avatar Aug 02 '22 17:08 ehaas

Sory for the late response. I'm using arocc as a library and extract the AST from a given file. From what I can see is that invoking just the compiler on the provided examples does not reproduce the error, but using the compiler as a library reproduces the error every time.

I tried to create the smallest example that reproduces the issue.

const std = @import("std");
const arocc = @import("arocc");

pub fn main() !void {
    var arena_instance = std.heap.ArenaAllocator.init(std.heap.page_allocator);
    defer arena_instance.deinit();
    const arena = arena_instance.allocator();

    var comp = arocc.Compilation.init(arena);
    defer comp.deinit();
    try comp.addDefaultPragmaHandlers();
    try comp.include_dirs.append("/usr/include");
    var file = try comp.addSourceFromBuffer("test.c", "int a[sizeof(int)];");

    var pp = arocc.Preprocessor.init(&comp);
    defer pp.deinit();
    try pp.addBuiltinMacros();
    const eof = pp.preprocess(file) catch |err| {
        if (!std.unicode.utf8ValidateSlice(file.buf)) {
            if (comp.diag.list.items.len > 0 and comp.diag.list.items[comp.diag.list.items.len - 1].tag == .invalid_utf8) {
                return;
            }
        }
        return err;
    };
    try pp.tokens.append(arena, eof);

    var tree = try arocc.Parser.parse(&pp);
    defer tree.deinit();
}

Commands issued

ateusz@DESKTOP-M8RDHEV e2v $ ./zig/zig build-exe repro.zig --pkg-begin arocc arocc/src/lib.zig --pkg-begin zig arocc/deps/zig/lib.zig --pkg-end --pkg-end
mateusz@DESKTOP-M8RDHEV e2v $ ./repro
thread 2510 panic: access of inactive union field
/home/mateusz/e2v/arocc/src/Type.zig:1917:108: 0x2cb8a2 in .arocc.Type.Builder.fromType (repro)
            .decayed_unspecified_variable_len_array => .{ .decayed_unspecified_variable_len_array = ty.data.sub_type },
                                                                                                           ^
/home/mateusz/e2v/arocc/src/Parser.zig:344:30: 0x2acc50 in .arocc.Parser.typeStr (repro)
    if (Type.Builder.fromType(ty).str()) |str| return str;
                             ^
/home/mateusz/e2v/arocc/src/Parser.zig:2505:70: 0x2d756a in .arocc.Parser.directDeclarator (repro)
            try p.errStr(.array_size_non_int, size_tok, try p.typeStr(size.ty));
                                                                     ^
/home/mateusz/e2v/arocc/src/Parser.zig:2403:38: 0x2ac2af in .arocc.Parser.declarator (repro)
        d.ty = try p.directDeclarator(d.ty, &d, kind);
                                     ^
/home/mateusz/e2v/arocc/src/Parser.zig:1399:31: 0x2a9fc2 in .arocc.Parser.initDeclarator (repro)
        .d = (try p.declarator(decl_spec.ty, .normal)) orelse return null,
                              ^
/home/mateusz/e2v/arocc/src/Parser.zig:746:39: 0x2a5331 in .arocc.Parser.decl (repro)
    var init_d = (try p.initDeclarator(&decl_spec, attr_buf_top)) orelse {
                                      ^
/home/mateusz/e2v/arocc/src/Parser.zig:634:16: 0x2853d4 in .arocc.Parser.parseOrNextDecl (repro)
    return func(p) catch |er| switch (er) {
               ^
/home/mateusz/e2v/arocc/src/Parser.zig:571:34: 0x26c665 in .arocc.Parser.parse (repro)
        if (try p.parseOrNextDecl(decl)) continue;
                                 ^
/home/mateusz/e2v/repro.zig:28:38: 0x2671f6 in main (repro)
    var tree = try arocc.Parser.parse(&pp);
                                     ^
/home/mateusz/e2v/zig/lib/std/start.zig:576:37: 0x246023 in std.start.posixCallMainAndExit (repro)
            const result = root.main() catch |err| {
                                    ^
/home/mateusz/e2v/zig/lib/std/start.zig:338:5: 0x245db2 in std.start._start (repro)
    @call(.{ .modifier = .never_inline }, posixCallMainAndExit, .{});
    ^
Aborted
mateusz@DESKTOP-M8RDHEV e2v $ ./zig/zig version
0.10.0-dev.3394+1a1b7a3af
mateusz@DESKTOP-M8RDHEV e2v $ 

mateuszradomski avatar Aug 08 '22 17:08 mateuszradomski

The problem is that the compilation's built-in size type (size_t) was never generated, because you need to generate it via comp.generateBuiltinMacros. I can see how it's confusing since Compilation and Preprocessor have something that sounds like "built-in macros"; maybe that's an API sharp edge we can refine a little bit. Try this:

const std = @import("std");
const arocc = @import("arocc");

pub fn main() !void {
    var arena_instance = std.heap.ArenaAllocator.init(std.heap.page_allocator);
    defer arena_instance.deinit();
    const arena = arena_instance.allocator();

    var comp = arocc.Compilation.init(arena);
    defer comp.deinit();
    try comp.addDefaultPragmaHandlers();
    const builtin = try comp.generateBuiltinMacros();  // added this
    try comp.include_dirs.append("/usr/include");
    var file = try comp.addSourceFromBuffer("test.c", "int a[sizeof(int)];");

    var pp = arocc.Preprocessor.init(&comp);
    defer pp.deinit();

    try pp.addBuiltinMacros();
    _ = try pp.preprocess(builtin);  // and this

    const eof = pp.preprocess(file) catch |err| {
        if (!std.unicode.utf8ValidateSlice(file.buf)) {
            if (comp.diag.list.items.len > 0 and comp.diag.list.items[comp.diag.list.items.len - 1].tag == .invalid_utf8) {
                return;
            }
        }
        return err;
    };
    try pp.tokens.append(arena, eof);

    var tree = try arocc.Parser.parse(&pp);
    defer tree.deinit();
}

ehaas avatar Aug 08 '22 18:08 ehaas

Yeah, that's much better. Thank you for your help :+)

mateuszradomski avatar Aug 08 '22 18:08 mateuszradomski