mirror of
https://github.com/ziglang/zig.git
synced 2024-11-26 15:12:31 +00:00
Sync Aro sources (#19199)
ref: 02353ad9f17f659e173f68975a442fcec3dd2c94
This commit is contained in:
parent
1e67f50211
commit
90ab8ea9e6
2
.gitattributes
vendored
2
.gitattributes
vendored
@ -12,4 +12,4 @@ lib/libcxx/** linguist-vendored
|
||||
lib/libcxxabi/** linguist-vendored
|
||||
lib/libunwind/** linguist-vendored
|
||||
lib/tsan/** linguist-vendored
|
||||
deps/** linguist-vendored
|
||||
lib/compiler/aro/** linguist-vendored
|
||||
|
3
lib/compiler/aro/README.md
vendored
3
lib/compiler/aro/README.md
vendored
@ -20,8 +20,7 @@ int main(void) {
|
||||
printf("Hello, world!\n");
|
||||
return 0;
|
||||
}
|
||||
$ zig build run -- hello.c -o hello
|
||||
$ zig build && ./zig-out/bin/arocc hello.c -o hello
|
||||
$ ./hello
|
||||
Hello, world!
|
||||
$
|
||||
```
|
||||
|
22
lib/compiler/aro/aro/Attribute/names.zig
vendored
22
lib/compiler/aro/aro/Attribute/names.zig
vendored
@ -1,4 +1,4 @@
|
||||
//! Autogenerated by GenerateDef from deps/aro/aro/Attribute/names.def, do not edit
|
||||
//! Autogenerated by GenerateDef from src/aro/Attribute/names.def, do not edit
|
||||
// zig fmt: off
|
||||
|
||||
const std = @import("std");
|
||||
@ -142,15 +142,7 @@ pub fn nameFromUniqueIndex(index: u16, buf: []u8) []u8 {
|
||||
return fbs.getWritten();
|
||||
}
|
||||
|
||||
/// We're 1 bit shy of being able to fit this in a u32:
|
||||
/// - char only contains 0-9, a-z, A-Z, and _, so it could use a enum(u6) with a way to convert <-> u8
|
||||
/// (note: this would have a performance cost that may make the u32 not worth it)
|
||||
/// - number has a max value of > 2047 and < 4095 (the first _ node has the largest number),
|
||||
/// so it could fit into a u12
|
||||
/// - child_index currently has a max of > 4095 and < 8191, so it could fit into a u13
|
||||
///
|
||||
/// with the end_of_word/end_of_list 2 bools, that makes 33 bits total
|
||||
const Node = packed struct(u64) {
|
||||
const Node = packed struct(u32) {
|
||||
char: u8,
|
||||
/// Nodes are numbered with "an integer which gives the number of words that
|
||||
/// would be accepted by the automaton starting from that state." This numbering
|
||||
@ -158,18 +150,16 @@ const Node = packed struct(u64) {
|
||||
/// (L is the number of words accepted by the automaton) and the words themselves."
|
||||
///
|
||||
/// Essentially, this allows us to have a minimal perfect hashing scheme such that
|
||||
/// it's possible to store & lookup the properties of each builtin using a separate array.
|
||||
number: u16,
|
||||
/// If true, this node is the end of a valid builtin.
|
||||
/// it's possible to store & lookup the properties of each name using a separate array.
|
||||
number: u8,
|
||||
/// If true, this node is the end of a valid name.
|
||||
/// Note: This does not necessarily mean that this node does not have child nodes.
|
||||
end_of_word: bool,
|
||||
/// If true, this node is the end of a sibling list.
|
||||
/// If false, then (index + 1) will contain the next sibling.
|
||||
end_of_list: bool,
|
||||
/// Padding bits to get to u64, unsure if there's some way to use these to improve something.
|
||||
_extra: u22 = 0,
|
||||
/// Index of the first child of this node.
|
||||
child_index: u16,
|
||||
child_index: u14,
|
||||
};
|
||||
|
||||
const dafsa = [_]Node{
|
||||
|
5
lib/compiler/aro/aro/Builtins.zig
vendored
5
lib/compiler/aro/aro/Builtins.zig
vendored
@ -99,10 +99,7 @@ fn createType(desc: TypeDescription, it: *TypeDescription.TypeIterator, comp: *c
|
||||
}
|
||||
},
|
||||
.h => builder.combine(undefined, .fp16, 0) catch unreachable,
|
||||
.x => {
|
||||
// Todo: _Float16
|
||||
return .{ .specifier = .invalid };
|
||||
},
|
||||
.x => builder.combine(undefined, .float16, 0) catch unreachable,
|
||||
.y => {
|
||||
// Todo: __bf16
|
||||
return .{ .specifier = .invalid };
|
||||
|
2
lib/compiler/aro/aro/Builtins/Builtin.zig
vendored
2
lib/compiler/aro/aro/Builtins/Builtin.zig
vendored
@ -1,4 +1,4 @@
|
||||
//! Autogenerated by GenerateDef from deps/aro/aro/Builtins/Builtin.def, do not edit
|
||||
//! Autogenerated by GenerateDef from src/aro/Builtins/Builtin.def, do not edit
|
||||
// zig fmt: off
|
||||
|
||||
const std = @import("std");
|
||||
|
59
lib/compiler/aro/aro/Compilation.zig
vendored
59
lib/compiler/aro/aro/Compilation.zig
vendored
@ -241,6 +241,12 @@ pub const SystemDefinesMode = enum {
|
||||
fn generateSystemDefines(comp: *Compilation, w: anytype) !void {
|
||||
const ptr_width = comp.target.ptrBitWidth();
|
||||
|
||||
if (comp.langopts.gnuc_version > 0) {
|
||||
try w.print("#define __GNUC__ {d}\n", .{comp.langopts.gnuc_version / 10_000});
|
||||
try w.print("#define __GNUC_MINOR__ {d}\n", .{comp.langopts.gnuc_version / 100 % 100});
|
||||
try w.print("#define __GNUC_PATCHLEVEL__ {d}\n", .{comp.langopts.gnuc_version % 100});
|
||||
}
|
||||
|
||||
// os macros
|
||||
switch (comp.target.os.tag) {
|
||||
.linux => try w.writeAll(
|
||||
@ -419,6 +425,25 @@ fn generateSystemDefines(comp: *Compilation, w: anytype) !void {
|
||||
\\
|
||||
);
|
||||
|
||||
// TODO: Set these to target-specific constants depending on backend capabilities
|
||||
// For now they are just set to the "may be lock-free" value
|
||||
try w.writeAll(
|
||||
\\#define __ATOMIC_BOOL_LOCK_FREE 1
|
||||
\\#define __ATOMIC_CHAR_LOCK_FREE 1
|
||||
\\#define __ATOMIC_CHAR16_T_LOCK_FREE 1
|
||||
\\#define __ATOMIC_CHAR32_T_LOCK_FREE 1
|
||||
\\#define __ATOMIC_WCHAR_T_LOCK_FREE 1
|
||||
\\#define __ATOMIC_SHORT_LOCK_FREE 1
|
||||
\\#define __ATOMIC_INT_LOCK_FREE 1
|
||||
\\#define __ATOMIC_LONG_LOCK_FREE 1
|
||||
\\#define __ATOMIC_LLONG_LOCK_FREE 1
|
||||
\\#define __ATOMIC_POINTER_LOCK_FREE 1
|
||||
\\
|
||||
);
|
||||
if (comp.langopts.hasChar8_T()) {
|
||||
try w.writeAll("#define __ATOMIC_CHAR8_T_LOCK_FREE 1\n");
|
||||
}
|
||||
|
||||
// types
|
||||
if (comp.getCharSignedness() == .unsigned) try w.writeAll("#define __CHAR_UNSIGNED__ 1\n");
|
||||
try w.writeAll("#define __CHAR_BIT__ 8\n");
|
||||
@ -438,6 +463,7 @@ fn generateSystemDefines(comp: *Compilation, w: anytype) !void {
|
||||
try comp.generateIntMaxAndWidth(w, "PTRDIFF", comp.types.ptrdiff);
|
||||
try comp.generateIntMaxAndWidth(w, "INTPTR", comp.types.intptr);
|
||||
try comp.generateIntMaxAndWidth(w, "UINTPTR", comp.types.intptr.makeIntegerUnsigned());
|
||||
try comp.generateIntMaxAndWidth(w, "SIG_ATOMIC", target_util.sigAtomicType(comp.target));
|
||||
|
||||
// int widths
|
||||
try w.print("#define __BITINT_MAXWIDTH__ {d}\n", .{bit_int_max_bits});
|
||||
@ -474,6 +500,8 @@ fn generateSystemDefines(comp: *Compilation, w: anytype) !void {
|
||||
try generateTypeMacro(w, mapper, "__PTRDIFF_TYPE__", comp.types.ptrdiff, comp.langopts);
|
||||
try generateTypeMacro(w, mapper, "__SIZE_TYPE__", comp.types.size, comp.langopts);
|
||||
try generateTypeMacro(w, mapper, "__WCHAR_TYPE__", comp.types.wchar, comp.langopts);
|
||||
try generateTypeMacro(w, mapper, "__CHAR16_TYPE__", comp.types.uint_least16_t, comp.langopts);
|
||||
try generateTypeMacro(w, mapper, "__CHAR32_TYPE__", comp.types.uint_least32_t, comp.langopts);
|
||||
|
||||
try comp.generateExactWidthTypes(w, mapper);
|
||||
try comp.generateFastAndLeastWidthTypes(w, mapper);
|
||||
@ -518,7 +546,6 @@ pub fn generateBuiltinMacros(comp: *Compilation, system_defines_mode: SystemDefi
|
||||
|
||||
// standard macros
|
||||
try buf.appendSlice(
|
||||
\\#define __STDC_NO_ATOMICS__ 1
|
||||
\\#define __STDC_NO_COMPLEX__ 1
|
||||
\\#define __STDC_NO_THREADS__ 1
|
||||
\\#define __STDC_NO_VLA__ 1
|
||||
@ -1030,9 +1057,8 @@ pub fn getCharSignedness(comp: *const Compilation) std.builtin.Signedness {
|
||||
return comp.langopts.char_signedness_override orelse comp.target.charSignedness();
|
||||
}
|
||||
|
||||
pub fn defineSystemIncludes(comp: *Compilation, aro_dir: []const u8) !void {
|
||||
var stack_fallback = std.heap.stackFallback(path_buf_stack_limit, comp.gpa);
|
||||
const allocator = stack_fallback.get();
|
||||
/// Add built-in aro headers directory to system include paths
|
||||
pub fn addBuiltinIncludeDir(comp: *Compilation, aro_dir: []const u8) !void {
|
||||
var search_path = aro_dir;
|
||||
while (std.fs.path.dirname(search_path)) |dirname| : (search_path = dirname) {
|
||||
var base_dir = std.fs.cwd().openDir(dirname, .{}) catch continue;
|
||||
@ -1044,23 +1070,12 @@ pub fn defineSystemIncludes(comp: *Compilation, aro_dir: []const u8) !void {
|
||||
try comp.system_include_dirs.append(comp.gpa, path);
|
||||
break;
|
||||
} else return error.AroIncludeNotFound;
|
||||
}
|
||||
|
||||
if (comp.target.os.tag == .linux) {
|
||||
const triple_str = try comp.target.linuxTriple(allocator);
|
||||
defer allocator.free(triple_str);
|
||||
|
||||
const multiarch_path = try std.fs.path.join(allocator, &.{ "/usr/include", triple_str });
|
||||
defer allocator.free(multiarch_path);
|
||||
|
||||
if (!std.meta.isError(std.fs.accessAbsolute(multiarch_path, .{}))) {
|
||||
const duped = try comp.gpa.dupe(u8, multiarch_path);
|
||||
errdefer comp.gpa.free(duped);
|
||||
try comp.system_include_dirs.append(comp.gpa, duped);
|
||||
}
|
||||
}
|
||||
const usr_include = try comp.gpa.dupe(u8, "/usr/include");
|
||||
errdefer comp.gpa.free(usr_include);
|
||||
try comp.system_include_dirs.append(comp.gpa, usr_include);
|
||||
pub fn addSystemIncludeDir(comp: *Compilation, path: []const u8) !void {
|
||||
const duped = try comp.gpa.dupe(u8, path);
|
||||
errdefer comp.gpa.free(duped);
|
||||
try comp.system_include_dirs.append(comp.gpa, duped);
|
||||
}
|
||||
|
||||
pub fn getSource(comp: *const Compilation, id: Source.Id) Source {
|
||||
@ -1331,6 +1346,10 @@ pub fn hasInclude(
|
||||
/// __has_include vs __has_include_next
|
||||
which: WhichInclude,
|
||||
) !bool {
|
||||
if (mem.indexOfScalar(u8, filename, 0) != null) {
|
||||
return false;
|
||||
}
|
||||
|
||||
const cwd = std.fs.cwd();
|
||||
if (std.fs.path.isAbsolute(filename)) {
|
||||
if (which == .next) return false;
|
||||
|
4
lib/compiler/aro/aro/Diagnostics.zig
vendored
4
lib/compiler/aro/aro/Diagnostics.zig
vendored
@ -208,6 +208,8 @@ pub const Options = struct {
|
||||
@"unsupported-embed-param": Kind = .default,
|
||||
@"unused-result": Kind = .default,
|
||||
normalized: Kind = .default,
|
||||
@"shift-count-negative": Kind = .default,
|
||||
@"shift-count-overflow": Kind = .default,
|
||||
};
|
||||
|
||||
const Diagnostics = @This();
|
||||
@ -291,7 +293,7 @@ pub fn addExtra(
|
||||
.kind = .note,
|
||||
.extra = .{ .unsigned = expansion_locs.len - d.macro_backtrace_limit },
|
||||
});
|
||||
i = half - 1;
|
||||
i = half -| 1;
|
||||
while (i > 0) {
|
||||
i -= 1;
|
||||
d.list.appendAssumeCapacity(.{
|
||||
|
12
lib/compiler/aro/aro/Diagnostics/messages.zig
vendored
12
lib/compiler/aro/aro/Diagnostics/messages.zig
vendored
@ -1,4 +1,4 @@
|
||||
//! Autogenerated by GenerateDef from deps/aro/aro/Diagnostics/messages.def, do not edit
|
||||
//! Autogenerated by GenerateDef from src/aro/Diagnostics/messages.def, do not edit
|
||||
// zig fmt: off
|
||||
|
||||
const std = @import("std");
|
||||
@ -504,6 +504,11 @@ pub const Tag = enum {
|
||||
c23_auto_single_declarator,
|
||||
c32_auto_requires_initializer,
|
||||
c23_auto_scalar_init,
|
||||
negative_shift_count,
|
||||
too_big_shift_count,
|
||||
complex_conj,
|
||||
overflow_builtin_requires_int,
|
||||
overflow_result_requires_ptr,
|
||||
|
||||
pub fn property(tag: Tag) Properties {
|
||||
return named_data[@intFromEnum(tag)];
|
||||
@ -1005,6 +1010,11 @@ pub const Tag = enum {
|
||||
.{ .msg = "'auto' can only be used with a single declarator", .kind = .@"error" },
|
||||
.{ .msg = "'auto' requires an initializer", .kind = .@"error" },
|
||||
.{ .msg = "'auto' requires a scalar initializer", .kind = .@"error" },
|
||||
.{ .msg = "shift count is negative", .opt = W("shift-count-negative"), .kind = .warning, .all = true },
|
||||
.{ .msg = "shift count >= width of type", .opt = W("shift-count-overflow"), .kind = .warning, .all = true },
|
||||
.{ .msg = "ISO C does not support '~' for complex conjugation of '{s}'", .opt = W("pedantic"), .extra = .str, .kind = .off },
|
||||
.{ .msg = "operand argument to overflow builtin must be an integer ('{s}' invalid)", .extra = .str, .kind = .@"error" },
|
||||
.{ .msg = "result argument to overflow builtin must be a pointer to a non-const integer ('{s}' invalid)", .extra = .str, .kind = .@"error" },
|
||||
};
|
||||
};
|
||||
};
|
||||
|
30
lib/compiler/aro/aro/Driver.zig
vendored
30
lib/compiler/aro/aro/Driver.zig
vendored
@ -12,6 +12,7 @@ const Preprocessor = @import("Preprocessor.zig");
|
||||
const Source = @import("Source.zig");
|
||||
const Toolchain = @import("Toolchain.zig");
|
||||
const target_util = @import("target.zig");
|
||||
const GCCVersion = @import("Driver/GCCVersion.zig");
|
||||
|
||||
pub const Linker = enum {
|
||||
ld,
|
||||
@ -43,6 +44,9 @@ verbose_pp: bool = false,
|
||||
verbose_ir: bool = false,
|
||||
verbose_linker_args: bool = false,
|
||||
color: ?bool = null,
|
||||
nobuiltininc: bool = false,
|
||||
nostdinc: bool = false,
|
||||
nostdlibinc: bool = false,
|
||||
|
||||
/// Full path to the aro executable
|
||||
aro_name: []const u8 = "",
|
||||
@ -95,6 +99,7 @@ pub const usage =
|
||||
\\ -fcolor-diagnostics Enable colors in diagnostics
|
||||
\\ -fno-color-diagnostics Disable colors in diagnostics
|
||||
\\ -fdeclspec Enable support for __declspec attributes
|
||||
\\ -fgnuc-version=<value> Controls value of __GNUC__ and related macros. Set to 0 or empty to disable them.
|
||||
\\ -fno-declspec Disable support for __declspec attributes
|
||||
\\ -ffp-eval-method=[source|double|extended]
|
||||
\\ Evaluation method to use for floating-point arithmetic
|
||||
@ -127,6 +132,10 @@ pub const usage =
|
||||
\\ -isystem Add directory to SYSTEM include search path
|
||||
\\ --emulate=[clang|gcc|msvc]
|
||||
\\ Select which C compiler to emulate (default clang)
|
||||
\\ -nobuiltininc Do not search the compiler's builtin directory for include files
|
||||
\\ -nostdinc, --no-standard-includes
|
||||
\\ Do not search the standard system directories or compiler builtin directories for include files.
|
||||
\\ -nostdlibinc Do not search the standard system directories for include files, but do search compiler builtin include directories
|
||||
\\ -o <file> Write output to <file>
|
||||
\\ -P, --no-line-commands Disable linemarker output in -E mode
|
||||
\\ -pedantic Warn on language extensions
|
||||
@ -180,6 +189,7 @@ pub fn parseArgs(
|
||||
var i: usize = 1;
|
||||
var comment_arg: []const u8 = "";
|
||||
var hosted: ?bool = null;
|
||||
var gnuc_version: []const u8 = "4.2.1"; // default value set by clang
|
||||
while (i < args.len) : (i += 1) {
|
||||
const arg = args[i];
|
||||
if (mem.startsWith(u8, arg, "-") and arg.len > 1) {
|
||||
@ -303,6 +313,10 @@ pub fn parseArgs(
|
||||
d.only_syntax = true;
|
||||
} else if (mem.startsWith(u8, arg, "-fno-syntax-only")) {
|
||||
d.only_syntax = false;
|
||||
} else if (mem.eql(u8, arg, "-fgnuc-version=")) {
|
||||
gnuc_version = "0";
|
||||
} else if (option(arg, "-fgnuc-version=")) |version| {
|
||||
gnuc_version = version;
|
||||
} else if (mem.startsWith(u8, arg, "-isystem")) {
|
||||
var path = arg["-isystem".len..];
|
||||
if (path.len == 0) {
|
||||
@ -421,6 +435,12 @@ pub fn parseArgs(
|
||||
d.nodefaultlibs = true;
|
||||
} else if (mem.eql(u8, arg, "-nolibc")) {
|
||||
d.nolibc = true;
|
||||
} else if (mem.eql(u8, arg, "-nobuiltininc")) {
|
||||
d.nobuiltininc = true;
|
||||
} else if (mem.eql(u8, arg, "-nostdinc") or mem.eql(u8, arg, "--no-standard-includes")) {
|
||||
d.nostdinc = true;
|
||||
} else if (mem.eql(u8, arg, "-nostdlibinc")) {
|
||||
d.nostdlibinc = true;
|
||||
} else if (mem.eql(u8, arg, "-nostdlib")) {
|
||||
d.nostdlib = true;
|
||||
} else if (mem.eql(u8, arg, "-nostartfiles")) {
|
||||
@ -459,6 +479,11 @@ pub fn parseArgs(
|
||||
d.comp.target.os.tag = .freestanding;
|
||||
}
|
||||
}
|
||||
const version = GCCVersion.parse(gnuc_version);
|
||||
if (version.major == -1) {
|
||||
return d.fatal("invalid value '{0s}' in '-fgnuc-version={0s}'", .{gnuc_version});
|
||||
}
|
||||
d.comp.langopts.gnuc_version = version.toUnsigned();
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -558,7 +583,8 @@ pub fn main(d: *Driver, tc: *Toolchain, args: []const []const u8, comptime fast_
|
||||
try d.comp.addDiagnostic(.{ .tag = .cli_unused_link_object, .extra = .{ .str = obj } }, &.{});
|
||||
};
|
||||
|
||||
d.comp.defineSystemIncludes(d.aro_name) catch |er| switch (er) {
|
||||
try tc.discover();
|
||||
tc.defineSystemIncludes() catch |er| switch (er) {
|
||||
error.OutOfMemory => return error.OutOfMemory,
|
||||
error.AroIncludeNotFound => return d.fatal("unable to find Aro builtin headers", .{}),
|
||||
};
|
||||
@ -763,8 +789,6 @@ fn dumpLinkerArgs(items: []const []const u8) !void {
|
||||
/// The entry point of the Aro compiler.
|
||||
/// **MAY call `exit` if `fast_exit` is set.**
|
||||
pub fn invokeLinker(d: *Driver, tc: *Toolchain, comptime fast_exit: bool) !void {
|
||||
try tc.discover();
|
||||
|
||||
var argv = std.ArrayList([]const u8).init(d.comp.gpa);
|
||||
defer argv.deinit();
|
||||
|
||||
|
10
lib/compiler/aro/aro/Driver/GCCVersion.zig
vendored
10
lib/compiler/aro/aro/Driver/GCCVersion.zig
vendored
@ -98,6 +98,16 @@ pub fn order(a: GCCVersion, b: GCCVersion) Order {
|
||||
return .eq;
|
||||
}
|
||||
|
||||
/// Used for determining __GNUC__ macro values
|
||||
/// This matches clang's logic for overflowing values
|
||||
pub fn toUnsigned(self: GCCVersion) u32 {
|
||||
var result: u32 = 0;
|
||||
if (self.major > 0) result = @as(u32, @intCast(self.major)) *% 10_000;
|
||||
if (self.minor > 0) result +%= @as(u32, @intCast(self.minor)) *% 100;
|
||||
if (self.patch > 0) result +%= @as(u32, @intCast(self.patch));
|
||||
return result;
|
||||
}
|
||||
|
||||
test parse {
|
||||
const versions = [10]GCCVersion{
|
||||
parse("5"),
|
||||
|
191
lib/compiler/aro/aro/Hideset.zig
vendored
Normal file
191
lib/compiler/aro/aro/Hideset.zig
vendored
Normal file
@ -0,0 +1,191 @@
|
||||
//! A hideset is a linked list (implemented as an array so that elements are identified by 4-byte indices)
|
||||
//! of the set of identifiers from which a token was expanded.
|
||||
//! During macro expansion, if a token would otherwise be expanded, but its hideset contains
|
||||
//! the token itself, then it is not expanded
|
||||
//! Most tokens have an empty hideset, and the hideset is not needed once expansion is complete,
|
||||
//! so we use a hash map to store them instead of directly storing them with the token.
|
||||
//! The C standard underspecifies the algorithm for updating a token's hideset;
|
||||
//! we use the one here: https://www.spinellis.gr/blog/20060626/cpp.algo.pdf
|
||||
|
||||
const std = @import("std");
|
||||
const mem = std.mem;
|
||||
const Allocator = mem.Allocator;
|
||||
const Source = @import("Source.zig");
|
||||
const Compilation = @import("Compilation.zig");
|
||||
const Tokenizer = @import("Tokenizer.zig");
|
||||
|
||||
pub const Hideset = @This();
|
||||
|
||||
const Identifier = struct {
|
||||
id: Source.Id = .unused,
|
||||
byte_offset: u32 = 0,
|
||||
|
||||
fn slice(self: Identifier, comp: *const Compilation) []const u8 {
|
||||
var tmp_tokenizer = Tokenizer{
|
||||
.buf = comp.getSource(self.id).buf,
|
||||
.langopts = comp.langopts,
|
||||
.index = self.byte_offset,
|
||||
.source = .generated,
|
||||
};
|
||||
const res = tmp_tokenizer.next();
|
||||
return tmp_tokenizer.buf[res.start..res.end];
|
||||
}
|
||||
|
||||
fn fromLocation(loc: Source.Location) Identifier {
|
||||
return .{
|
||||
.id = loc.id,
|
||||
.byte_offset = loc.byte_offset,
|
||||
};
|
||||
}
|
||||
};
|
||||
|
||||
const Item = struct {
|
||||
identifier: Identifier = .{},
|
||||
next: Index = .none,
|
||||
|
||||
const List = std.MultiArrayList(Item);
|
||||
};
|
||||
|
||||
const Index = enum(u32) {
|
||||
none = std.math.maxInt(u32),
|
||||
_,
|
||||
};
|
||||
|
||||
map: std.AutoHashMapUnmanaged(Identifier, Index) = .{},
|
||||
/// Used for computing intersection of two lists; stored here so that allocations can be retained
|
||||
/// until hideset is deinit'ed
|
||||
intersection_map: std.AutoHashMapUnmanaged(Identifier, void) = .{},
|
||||
linked_list: Item.List = .{},
|
||||
comp: *const Compilation,
|
||||
|
||||
/// Invalidated if the underlying MultiArrayList slice is reallocated due to resize
|
||||
const Iterator = struct {
|
||||
slice: Item.List.Slice,
|
||||
i: Index,
|
||||
|
||||
fn next(self: *Iterator) ?Identifier {
|
||||
if (self.i == .none) return null;
|
||||
defer self.i = self.slice.items(.next)[@intFromEnum(self.i)];
|
||||
return self.slice.items(.identifier)[@intFromEnum(self.i)];
|
||||
}
|
||||
};
|
||||
|
||||
pub fn deinit(self: *Hideset) void {
|
||||
self.map.deinit(self.comp.gpa);
|
||||
self.intersection_map.deinit(self.comp.gpa);
|
||||
self.linked_list.deinit(self.comp.gpa);
|
||||
}
|
||||
|
||||
pub fn clearRetainingCapacity(self: *Hideset) void {
|
||||
self.linked_list.shrinkRetainingCapacity(0);
|
||||
self.map.clearRetainingCapacity();
|
||||
}
|
||||
|
||||
pub fn clearAndFree(self: *Hideset) void {
|
||||
self.map.clearAndFree(self.comp.gpa);
|
||||
self.intersection_map.clearAndFree(self.comp.gpa);
|
||||
self.linked_list.shrinkAndFree(self.comp.gpa, 0);
|
||||
}
|
||||
|
||||
/// Iterator is invalidated if the underlying MultiArrayList slice is reallocated due to resize
|
||||
fn iterator(self: *const Hideset, idx: Index) Iterator {
|
||||
return Iterator{
|
||||
.slice = self.linked_list.slice(),
|
||||
.i = idx,
|
||||
};
|
||||
}
|
||||
|
||||
pub fn get(self: *const Hideset, loc: Source.Location) Index {
|
||||
return self.map.get(Identifier.fromLocation(loc)) orelse .none;
|
||||
}
|
||||
|
||||
pub fn put(self: *Hideset, loc: Source.Location, value: Index) !void {
|
||||
try self.map.put(self.comp.gpa, Identifier.fromLocation(loc), value);
|
||||
}
|
||||
|
||||
fn ensureUnusedCapacity(self: *Hideset, new_size: usize) !void {
|
||||
try self.linked_list.ensureUnusedCapacity(self.comp.gpa, new_size);
|
||||
}
|
||||
|
||||
/// Creates a one-item list with contents `identifier`
|
||||
fn createNodeAssumeCapacity(self: *Hideset, identifier: Identifier) Index {
|
||||
const next_idx = self.linked_list.len;
|
||||
self.linked_list.appendAssumeCapacity(.{ .identifier = identifier });
|
||||
return @enumFromInt(next_idx);
|
||||
}
|
||||
|
||||
/// Create a new list with `identifier` at the front followed by `tail`
|
||||
pub fn prepend(self: *Hideset, loc: Source.Location, tail: Index) !Index {
|
||||
const new_idx = self.linked_list.len;
|
||||
try self.linked_list.append(self.comp.gpa, .{ .identifier = Identifier.fromLocation(loc), .next = tail });
|
||||
return @enumFromInt(new_idx);
|
||||
}
|
||||
|
||||
/// Copy a, then attach b at the end
|
||||
pub fn @"union"(self: *Hideset, a: Index, b: Index) !Index {
|
||||
var cur: Index = .none;
|
||||
var head: Index = b;
|
||||
try self.ensureUnusedCapacity(self.len(a));
|
||||
var it = self.iterator(a);
|
||||
while (it.next()) |identifier| {
|
||||
const new_idx = self.createNodeAssumeCapacity(identifier);
|
||||
if (head == b) {
|
||||
head = new_idx;
|
||||
}
|
||||
if (cur != .none) {
|
||||
self.linked_list.items(.next)[@intFromEnum(cur)] = new_idx;
|
||||
}
|
||||
cur = new_idx;
|
||||
}
|
||||
if (cur != .none) {
|
||||
self.linked_list.items(.next)[@intFromEnum(cur)] = b;
|
||||
}
|
||||
return head;
|
||||
}
|
||||
|
||||
pub fn contains(self: *const Hideset, list: Index, str: []const u8) bool {
|
||||
var it = self.iterator(list);
|
||||
while (it.next()) |identifier| {
|
||||
if (mem.eql(u8, str, identifier.slice(self.comp))) return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
fn len(self: *const Hideset, list: Index) usize {
|
||||
const nexts = self.linked_list.items(.next);
|
||||
var cur = list;
|
||||
var count: usize = 0;
|
||||
while (cur != .none) : (count += 1) {
|
||||
cur = nexts[@intFromEnum(cur)];
|
||||
}
|
||||
return count;
|
||||
}
|
||||
|
||||
pub fn intersection(self: *Hideset, a: Index, b: Index) !Index {
|
||||
if (a == .none or b == .none) return .none;
|
||||
self.intersection_map.clearRetainingCapacity();
|
||||
|
||||
var cur: Index = .none;
|
||||
var head: Index = .none;
|
||||
var it = self.iterator(a);
|
||||
var a_len: usize = 0;
|
||||
while (it.next()) |identifier| : (a_len += 1) {
|
||||
try self.intersection_map.put(self.comp.gpa, identifier, {});
|
||||
}
|
||||
try self.ensureUnusedCapacity(@min(a_len, self.len(b)));
|
||||
|
||||
it = self.iterator(b);
|
||||
while (it.next()) |identifier| {
|
||||
if (self.intersection_map.contains(identifier)) {
|
||||
const new_idx = self.createNodeAssumeCapacity(identifier);
|
||||
if (head == .none) {
|
||||
head = new_idx;
|
||||
}
|
||||
if (cur != .none) {
|
||||
self.linked_list.items(.next)[@intFromEnum(cur)] = new_idx;
|
||||
}
|
||||
cur = new_idx;
|
||||
}
|
||||
}
|
||||
return head;
|
||||
}
|
5
lib/compiler/aro/aro/LangOpts.zig
vendored
5
lib/compiler/aro/aro/LangOpts.zig
vendored
@ -135,6 +135,11 @@ preserve_comments: bool = false,
|
||||
/// Preserve comments in macros when preprocessing
|
||||
preserve_comments_in_macros: bool = false,
|
||||
|
||||
/// Used ONLY for generating __GNUC__ and related macros. Does not control the presence/absence of any features
|
||||
/// Encoded as major * 10,000 + minor * 100 + patch
|
||||
/// e.g. 4.2.1 == 40201
|
||||
gnuc_version: u32 = 0,
|
||||
|
||||
pub fn setStandard(self: *LangOpts, name: []const u8) error{InvalidStandard}!void {
|
||||
self.standard = Standard.NameMap.get(name) orelse return error.InvalidStandard;
|
||||
}
|
||||
|
199
lib/compiler/aro/aro/Parser.zig
vendored
199
lib/compiler/aro/aro/Parser.zig
vendored
@ -403,7 +403,7 @@ pub fn errExtra(p: *Parser, tag: Diagnostics.Tag, tok_i: TokenIndex, extra: Diag
|
||||
.tag = tag,
|
||||
.loc = loc,
|
||||
.extra = extra,
|
||||
}, tok.expansionSlice());
|
||||
}, p.pp.expansionSlice(tok_i));
|
||||
}
|
||||
|
||||
pub fn errTok(p: *Parser, tag: Diagnostics.Tag, tok_i: TokenIndex) Compilation.Error!void {
|
||||
@ -432,6 +432,11 @@ pub fn removeNull(p: *Parser, str: Value) !Value {
|
||||
}
|
||||
|
||||
pub fn typeStr(p: *Parser, ty: Type) ![]const u8 {
|
||||
if (@import("builtin").mode != .Debug) {
|
||||
if (ty.is(.invalid)) {
|
||||
return "Tried to render invalid type - this is an aro bug.";
|
||||
}
|
||||
}
|
||||
if (Type.Builder.fromType(ty).str(p.comp.langopts)) |str| return str;
|
||||
const strings_top = p.strings.items.len;
|
||||
defer p.strings.items.len = strings_top;
|
||||
@ -446,6 +451,11 @@ pub fn typePairStr(p: *Parser, a: Type, b: Type) ![]const u8 {
|
||||
}
|
||||
|
||||
pub fn typePairStrExtra(p: *Parser, a: Type, msg: []const u8, b: Type) ![]const u8 {
|
||||
if (@import("builtin").mode != .Debug) {
|
||||
if (a.is(.invalid) or b.is(.invalid)) {
|
||||
return "Tried to render invalid type - this is an aro bug.";
|
||||
}
|
||||
}
|
||||
const strings_top = p.strings.items.len;
|
||||
defer p.strings.items.len = strings_top;
|
||||
|
||||
@ -635,7 +645,6 @@ fn diagnoseIncompleteDefinitions(p: *Parser) !void {
|
||||
const tys = node_slices.items(.ty);
|
||||
const data = node_slices.items(.data);
|
||||
|
||||
const err_start = p.comp.diagnostics.list.items.len;
|
||||
for (p.decl_buf.items) |decl_node| {
|
||||
const idx = @intFromEnum(decl_node);
|
||||
switch (tags[idx]) {
|
||||
@ -656,8 +665,6 @@ fn diagnoseIncompleteDefinitions(p: *Parser) !void {
|
||||
try p.errStr(.tentative_definition_incomplete, tentative_def_tok, type_str);
|
||||
try p.errStr(.forward_declaration_here, data[idx].decl_ref, type_str);
|
||||
}
|
||||
const errors_added = p.comp.diagnostics.list.items.len - err_start;
|
||||
assert(errors_added == 2 * p.tentative_defs.count()); // Each tentative def should add an error + note
|
||||
}
|
||||
|
||||
/// root : (decl | assembly ';' | staticAssert)*
|
||||
@ -2201,7 +2208,15 @@ fn recordSpec(p: *Parser) Error!Type {
|
||||
} else {
|
||||
record_ty.fields = try p.arena.dupe(Type.Record.Field, p.record_buf.items[record_buf_top..]);
|
||||
}
|
||||
if (old_field_attr_start < p.field_attr_buf.items.len) {
|
||||
const attr_count = p.field_attr_buf.items.len - old_field_attr_start;
|
||||
const record_decls = p.decl_buf.items[decl_buf_top..];
|
||||
if (attr_count > 0) {
|
||||
if (attr_count != record_decls.len) {
|
||||
// A mismatch here means that non-field decls were parsed. This can happen if there were
|
||||
// parse errors during attribute parsing. Bail here because if there are any field attributes,
|
||||
// there must be exactly one per field.
|
||||
return error.ParsingFailed;
|
||||
}
|
||||
const field_attr_slice = p.field_attr_buf.items[old_field_attr_start..];
|
||||
const duped = try p.arena.dupe([]const Attribute, field_attr_slice);
|
||||
record_ty.field_attributes = duped.ptr;
|
||||
@ -2242,7 +2257,6 @@ fn recordSpec(p: *Parser) Error!Type {
|
||||
.ty = ty,
|
||||
.data = .{ .bin = .{ .lhs = .none, .rhs = .none } },
|
||||
};
|
||||
const record_decls = p.decl_buf.items[decl_buf_top..];
|
||||
switch (record_decls.len) {
|
||||
0 => {},
|
||||
1 => node.data = .{ .bin = .{ .lhs = record_decls[0], .rhs = .none } },
|
||||
@ -2560,6 +2574,7 @@ fn enumSpec(p: *Parser) Error!Type {
|
||||
if (field.ty.eql(Type.int, p.comp, false)) continue;
|
||||
|
||||
const sym = p.syms.get(field.name, .vars) orelse continue;
|
||||
if (sym.kind != .enumeration) continue; // already an error
|
||||
|
||||
var res = Result{ .node = field.node, .ty = field.ty, .val = sym.val };
|
||||
const dest_ty = if (p.comp.fixedEnumTagSpecifier()) |some|
|
||||
@ -4603,24 +4618,31 @@ fn nodeIsNoreturn(p: *Parser, node: NodeIndex) NoreturnKind {
|
||||
},
|
||||
.compound_stmt_two => {
|
||||
const data = p.nodes.items(.data)[@intFromEnum(node)];
|
||||
if (data.bin.rhs != .none) return p.nodeIsNoreturn(data.bin.rhs);
|
||||
if (data.bin.lhs != .none) return p.nodeIsNoreturn(data.bin.lhs);
|
||||
const lhs_type = if (data.bin.lhs != .none) p.nodeIsNoreturn(data.bin.lhs) else .no;
|
||||
const rhs_type = if (data.bin.rhs != .none) p.nodeIsNoreturn(data.bin.rhs) else .no;
|
||||
if (lhs_type == .complex or rhs_type == .complex) return .complex;
|
||||
if (lhs_type == .yes or rhs_type == .yes) return .yes;
|
||||
return .no;
|
||||
},
|
||||
.compound_stmt => {
|
||||
const data = p.nodes.items(.data)[@intFromEnum(node)];
|
||||
return p.nodeIsNoreturn(p.data.items[data.range.end - 1]);
|
||||
var it = data.range.start;
|
||||
while (it != data.range.end) : (it += 1) {
|
||||
const kind = p.nodeIsNoreturn(p.data.items[it]);
|
||||
if (kind != .no) return kind;
|
||||
}
|
||||
return .no;
|
||||
},
|
||||
.labeled_stmt => {
|
||||
const data = p.nodes.items(.data)[@intFromEnum(node)];
|
||||
return p.nodeIsNoreturn(data.decl.node);
|
||||
},
|
||||
.switch_stmt => {
|
||||
.default_stmt => {
|
||||
const data = p.nodes.items(.data)[@intFromEnum(node)];
|
||||
if (data.bin.rhs == .none) return .complex;
|
||||
if (p.nodeIsNoreturn(data.bin.rhs) == .yes) return .yes;
|
||||
return .complex;
|
||||
if (data.un == .none) return .no;
|
||||
return p.nodeIsNoreturn(data.un);
|
||||
},
|
||||
.while_stmt, .do_while_stmt, .for_decl_stmt, .forever_stmt, .for_stmt, .switch_stmt => return .complex,
|
||||
else => return .no,
|
||||
}
|
||||
}
|
||||
@ -4787,7 +4809,11 @@ const CallExpr = union(enum) {
|
||||
Builtin.tagFromName("__va_start").?,
|
||||
Builtin.tagFromName("va_start").?,
|
||||
=> arg_idx != 1,
|
||||
Builtin.tagFromName("__builtin_complex").? => false,
|
||||
Builtin.tagFromName("__builtin_complex").?,
|
||||
Builtin.tagFromName("__builtin_add_overflow").?,
|
||||
Builtin.tagFromName("__builtin_sub_overflow").?,
|
||||
Builtin.tagFromName("__builtin_mul_overflow").?,
|
||||
=> false,
|
||||
else => true,
|
||||
},
|
||||
};
|
||||
@ -4800,6 +4826,7 @@ const CallExpr = union(enum) {
|
||||
}
|
||||
|
||||
fn checkVarArg(self: CallExpr, p: *Parser, first_after: TokenIndex, param_tok: TokenIndex, arg: *Result, arg_idx: u32) !void {
|
||||
@setEvalBranchQuota(10_000);
|
||||
if (self == .standard) return;
|
||||
|
||||
const builtin_tok = p.nodes.items(.data)[@intFromEnum(self.builtin.node)].decl.name;
|
||||
@ -4809,6 +4836,11 @@ const CallExpr = union(enum) {
|
||||
Builtin.tagFromName("va_start").?,
|
||||
=> return p.checkVaStartArg(builtin_tok, first_after, param_tok, arg, arg_idx),
|
||||
Builtin.tagFromName("__builtin_complex").? => return p.checkComplexArg(builtin_tok, first_after, param_tok, arg, arg_idx),
|
||||
Builtin.tagFromName("__builtin_add_overflow").?,
|
||||
Builtin.tagFromName("__builtin_sub_overflow").?,
|
||||
Builtin.tagFromName("__builtin_mul_overflow").?,
|
||||
=> return p.checkArithOverflowArg(builtin_tok, first_after, param_tok, arg, arg_idx),
|
||||
|
||||
else => {},
|
||||
}
|
||||
}
|
||||
@ -4823,16 +4855,44 @@ const CallExpr = union(enum) {
|
||||
return switch (self) {
|
||||
.standard => null,
|
||||
.builtin => |builtin| switch (builtin.tag) {
|
||||
Builtin.tagFromName("__builtin_complex").? => 2,
|
||||
Builtin.tagFromName("__c11_atomic_thread_fence").?,
|
||||
Builtin.tagFromName("__c11_atomic_signal_fence").?,
|
||||
Builtin.tagFromName("__c11_atomic_is_lock_free").?,
|
||||
=> 1,
|
||||
|
||||
Builtin.tagFromName("__builtin_complex").?,
|
||||
Builtin.tagFromName("__c11_atomic_load").?,
|
||||
Builtin.tagFromName("__c11_atomic_init").?,
|
||||
=> 2,
|
||||
|
||||
Builtin.tagFromName("__c11_atomic_store").?,
|
||||
Builtin.tagFromName("__c11_atomic_exchange").?,
|
||||
Builtin.tagFromName("__c11_atomic_fetch_add").?,
|
||||
Builtin.tagFromName("__c11_atomic_fetch_sub").?,
|
||||
Builtin.tagFromName("__c11_atomic_fetch_or").?,
|
||||
Builtin.tagFromName("__c11_atomic_fetch_xor").?,
|
||||
Builtin.tagFromName("__c11_atomic_fetch_and").?,
|
||||
Builtin.tagFromName("__atomic_fetch_add").?,
|
||||
Builtin.tagFromName("__atomic_fetch_sub").?,
|
||||
Builtin.tagFromName("__atomic_fetch_and").?,
|
||||
Builtin.tagFromName("__atomic_fetch_xor").?,
|
||||
Builtin.tagFromName("__atomic_fetch_or").?,
|
||||
Builtin.tagFromName("__atomic_fetch_nand").?,
|
||||
Builtin.tagFromName("__atomic_add_fetch").?,
|
||||
Builtin.tagFromName("__atomic_sub_fetch").?,
|
||||
Builtin.tagFromName("__atomic_and_fetch").?,
|
||||
Builtin.tagFromName("__atomic_xor_fetch").?,
|
||||
Builtin.tagFromName("__atomic_or_fetch").?,
|
||||
Builtin.tagFromName("__atomic_nand_fetch").?,
|
||||
Builtin.tagFromName("__builtin_add_overflow").?,
|
||||
Builtin.tagFromName("__builtin_sub_overflow").?,
|
||||
Builtin.tagFromName("__builtin_mul_overflow").?,
|
||||
=> 3,
|
||||
|
||||
Builtin.tagFromName("__c11_atomic_compare_exchange_strong").?,
|
||||
Builtin.tagFromName("__c11_atomic_compare_exchange_weak").?,
|
||||
=> 5,
|
||||
|
||||
Builtin.tagFromName("__atomic_compare_exchange").?,
|
||||
Builtin.tagFromName("__atomic_compare_exchange_n").?,
|
||||
=> 6,
|
||||
@ -4845,15 +4905,45 @@ const CallExpr = union(enum) {
|
||||
return switch (self) {
|
||||
.standard => callable_ty.returnType(),
|
||||
.builtin => |builtin| switch (builtin.tag) {
|
||||
Builtin.tagFromName("__c11_atomic_exchange").? => {
|
||||
if (p.list_buf.items.len != 4) return Type.invalid; // wrong number of arguments; already an error
|
||||
const second_param = p.list_buf.items[2];
|
||||
return p.nodes.items(.ty)[@intFromEnum(second_param)];
|
||||
},
|
||||
Builtin.tagFromName("__c11_atomic_load").? => {
|
||||
if (p.list_buf.items.len != 3) return Type.invalid; // wrong number of arguments; already an error
|
||||
const first_param = p.list_buf.items[1];
|
||||
const ty = p.nodes.items(.ty)[@intFromEnum(first_param)];
|
||||
if (!ty.isPtr()) return Type.invalid;
|
||||
return ty.elemType();
|
||||
},
|
||||
|
||||
Builtin.tagFromName("__atomic_fetch_add").?,
|
||||
Builtin.tagFromName("__atomic_add_fetch").?,
|
||||
Builtin.tagFromName("__c11_atomic_fetch_add").?,
|
||||
|
||||
Builtin.tagFromName("__atomic_fetch_sub").?,
|
||||
Builtin.tagFromName("__atomic_sub_fetch").?,
|
||||
Builtin.tagFromName("__c11_atomic_fetch_sub").?,
|
||||
|
||||
Builtin.tagFromName("__atomic_fetch_and").?,
|
||||
Builtin.tagFromName("__atomic_and_fetch").?,
|
||||
Builtin.tagFromName("__c11_atomic_fetch_and").?,
|
||||
|
||||
Builtin.tagFromName("__atomic_fetch_xor").?,
|
||||
Builtin.tagFromName("__atomic_xor_fetch").?,
|
||||
Builtin.tagFromName("__c11_atomic_fetch_xor").?,
|
||||
|
||||
Builtin.tagFromName("__atomic_fetch_or").?,
|
||||
Builtin.tagFromName("__atomic_or_fetch").?,
|
||||
Builtin.tagFromName("__c11_atomic_fetch_or").?,
|
||||
|
||||
Builtin.tagFromName("__atomic_fetch_nand").?,
|
||||
Builtin.tagFromName("__atomic_nand_fetch").?,
|
||||
Builtin.tagFromName("__c11_atomic_fetch_nand").?,
|
||||
=> {
|
||||
if (p.list_buf.items.len < 2) return Type.invalid; // not enough arguments; already an error
|
||||
const second_param = p.list_buf.items[p.list_buf.items.len - 2];
|
||||
if (p.list_buf.items.len != 3) return Type.invalid; // wrong number of arguments; already an error
|
||||
const second_param = p.list_buf.items[2];
|
||||
return p.nodes.items(.ty)[@intFromEnum(second_param)];
|
||||
},
|
||||
Builtin.tagFromName("__builtin_complex").? => {
|
||||
@ -4863,8 +4953,17 @@ const CallExpr = union(enum) {
|
||||
},
|
||||
Builtin.tagFromName("__atomic_compare_exchange").?,
|
||||
Builtin.tagFromName("__atomic_compare_exchange_n").?,
|
||||
Builtin.tagFromName("__c11_atomic_is_lock_free").?,
|
||||
=> .{ .specifier = .bool },
|
||||
else => callable_ty.returnType(),
|
||||
|
||||
Builtin.tagFromName("__c11_atomic_compare_exchange_strong").?,
|
||||
Builtin.tagFromName("__c11_atomic_compare_exchange_weak").?,
|
||||
=> {
|
||||
if (p.list_buf.items.len != 6) return Type.invalid; // wrong number of arguments
|
||||
const third_param = p.list_buf.items[3];
|
||||
return p.nodes.items(.ty)[@intFromEnum(third_param)];
|
||||
},
|
||||
},
|
||||
};
|
||||
}
|
||||
@ -4975,15 +5074,19 @@ pub const Result = struct {
|
||||
.call_expr_one => {
|
||||
const fn_ptr = p.nodes.items(.data)[@intFromEnum(cur_node)].bin.lhs;
|
||||
const fn_ty = p.nodes.items(.ty)[@intFromEnum(fn_ptr)].elemType();
|
||||
if (fn_ty.hasAttribute(.nodiscard)) try p.errStr(.nodiscard_unused, expr_start, "TODO get name");
|
||||
if (fn_ty.hasAttribute(.warn_unused_result)) try p.errStr(.warn_unused_result, expr_start, "TODO get name");
|
||||
const cast_info = p.nodes.items(.data)[@intFromEnum(fn_ptr)].cast.operand;
|
||||
const decl_ref = p.nodes.items(.data)[@intFromEnum(cast_info)].decl_ref;
|
||||
if (fn_ty.hasAttribute(.nodiscard)) try p.errStr(.nodiscard_unused, expr_start, p.tokSlice(decl_ref));
|
||||
if (fn_ty.hasAttribute(.warn_unused_result)) try p.errStr(.warn_unused_result, expr_start, p.tokSlice(decl_ref));
|
||||
return;
|
||||
},
|
||||
.call_expr => {
|
||||
const fn_ptr = p.data.items[p.nodes.items(.data)[@intFromEnum(cur_node)].range.start];
|
||||
const fn_ty = p.nodes.items(.ty)[@intFromEnum(fn_ptr)].elemType();
|
||||
if (fn_ty.hasAttribute(.nodiscard)) try p.errStr(.nodiscard_unused, expr_start, "TODO get name");
|
||||
if (fn_ty.hasAttribute(.warn_unused_result)) try p.errStr(.warn_unused_result, expr_start, "TODO get name");
|
||||
const cast_info = p.nodes.items(.data)[@intFromEnum(fn_ptr)].cast.operand;
|
||||
const decl_ref = p.nodes.items(.data)[@intFromEnum(cast_info)].decl_ref;
|
||||
if (fn_ty.hasAttribute(.nodiscard)) try p.errStr(.nodiscard_unused, expr_start, p.tokSlice(decl_ref));
|
||||
if (fn_ty.hasAttribute(.warn_unused_result)) try p.errStr(.warn_unused_result, expr_start, p.tokSlice(decl_ref));
|
||||
return;
|
||||
},
|
||||
.stmt_expr => {
|
||||
@ -6356,8 +6459,15 @@ fn shiftExpr(p: *Parser) Error!Result {
|
||||
try rhs.expect(p);
|
||||
|
||||
if (try lhs.adjustTypes(shr.?, &rhs, p, .integer)) {
|
||||
if (rhs.val.compare(.lt, Value.zero, p.comp)) {
|
||||
try p.errStr(.negative_shift_count, shl orelse shr.?, try rhs.str(p));
|
||||
}
|
||||
if (rhs.val.compare(.gte, try Value.int(lhs.ty.bitSizeof(p.comp).?, p.comp), p.comp)) {
|
||||
try p.errStr(.too_big_shift_count, shl orelse shr.?, try rhs.str(p));
|
||||
}
|
||||
if (shl != null) {
|
||||
if (try lhs.val.shl(lhs.val, rhs.val, lhs.ty, p.comp)) try p.errOverflow(shl.?, lhs);
|
||||
if (try lhs.val.shl(lhs.val, rhs.val, lhs.ty, p.comp) and
|
||||
lhs.ty.signedness(p.comp) != .unsigned) try p.errOverflow(shl.?, lhs);
|
||||
} else {
|
||||
lhs.val = try lhs.val.shr(rhs.val, lhs.ty, p.comp);
|
||||
}
|
||||
@ -6381,9 +6491,11 @@ fn addExpr(p: *Parser) Error!Result {
|
||||
const lhs_ty = lhs.ty;
|
||||
if (try lhs.adjustTypes(minus.?, &rhs, p, if (plus != null) .add else .sub)) {
|
||||
if (plus != null) {
|
||||
if (try lhs.val.add(lhs.val, rhs.val, lhs.ty, p.comp)) try p.errOverflow(plus.?, lhs);
|
||||
if (try lhs.val.add(lhs.val, rhs.val, lhs.ty, p.comp) and
|
||||
lhs.ty.signedness(p.comp) != .unsigned) try p.errOverflow(plus.?, lhs);
|
||||
} else {
|
||||
if (try lhs.val.sub(lhs.val, rhs.val, lhs.ty, p.comp)) try p.errOverflow(minus.?, lhs);
|
||||
if (try lhs.val.sub(lhs.val, rhs.val, lhs.ty, p.comp) and
|
||||
lhs.ty.signedness(p.comp) != .unsigned) try p.errOverflow(minus.?, lhs);
|
||||
}
|
||||
}
|
||||
if (lhs.ty.specifier != .invalid and lhs_ty.isPtr() and !lhs_ty.isVoidStar() and lhs_ty.elemType().hasIncompleteSize()) {
|
||||
@ -6420,9 +6532,11 @@ fn mulExpr(p: *Parser) Error!Result {
|
||||
|
||||
if (try lhs.adjustTypes(percent.?, &rhs, p, if (tag == .mod_expr) .integer else .arithmetic)) {
|
||||
if (mul != null) {
|
||||
if (try lhs.val.mul(lhs.val, rhs.val, lhs.ty, p.comp)) try p.errOverflow(mul.?, lhs);
|
||||
if (try lhs.val.mul(lhs.val, rhs.val, lhs.ty, p.comp) and
|
||||
lhs.ty.signedness(p.comp) != .unsigned) try p.errOverflow(mul.?, lhs);
|
||||
} else if (div != null) {
|
||||
if (try lhs.val.div(lhs.val, rhs.val, lhs.ty, p.comp)) try p.errOverflow(mul.?, lhs);
|
||||
if (try lhs.val.div(lhs.val, rhs.val, lhs.ty, p.comp) and
|
||||
lhs.ty.signedness(p.comp) != .unsigned) try p.errOverflow(mul.?, lhs);
|
||||
} else {
|
||||
var res = try Value.rem(lhs.val, rhs.val, lhs.ty, p.comp);
|
||||
if (res.opt_ref == .none) {
|
||||
@ -6827,7 +6941,7 @@ fn unExpr(p: *Parser) Error!Result {
|
||||
try p.errStr(.invalid_argument_un, tok, try p.typeStr(operand.ty));
|
||||
|
||||
try operand.usualUnaryConversion(p, tok);
|
||||
if (operand.val.is(.int, p.comp)) {
|
||||
if (operand.val.is(.int, p.comp) or operand.val.is(.float, p.comp)) {
|
||||
_ = try operand.val.sub(Value.zero, operand.val, operand.ty, p.comp);
|
||||
} else {
|
||||
operand.val = .{};
|
||||
@ -6898,6 +7012,8 @@ fn unExpr(p: *Parser) Error!Result {
|
||||
if (operand.val.is(.int, p.comp)) {
|
||||
operand.val = try operand.val.bitNot(operand.ty, p.comp);
|
||||
}
|
||||
} else if (operand.ty.isComplex()) {
|
||||
try p.errStr(.complex_conj, tok, try p.typeStr(operand.ty));
|
||||
} else {
|
||||
try p.errStr(.invalid_argument_un, tok, try p.typeStr(operand.ty));
|
||||
operand.val = .{};
|
||||
@ -7334,6 +7450,20 @@ fn checkVaStartArg(p: *Parser, builtin_tok: TokenIndex, first_after: TokenIndex,
|
||||
}
|
||||
}
|
||||
|
||||
fn checkArithOverflowArg(p: *Parser, builtin_tok: TokenIndex, first_after: TokenIndex, param_tok: TokenIndex, arg: *Result, idx: u32) !void {
|
||||
_ = builtin_tok;
|
||||
_ = first_after;
|
||||
if (idx <= 1) {
|
||||
if (!arg.ty.isInt()) {
|
||||
return p.errStr(.overflow_builtin_requires_int, param_tok, try p.typeStr(arg.ty));
|
||||
}
|
||||
} else if (idx == 2) {
|
||||
if (!arg.ty.isPtr()) return p.errStr(.overflow_result_requires_ptr, param_tok, try p.typeStr(arg.ty));
|
||||
const child = arg.ty.elemType();
|
||||
if (!child.isInt() or child.is(.bool) or child.is(.@"enum") or child.qual.@"const") return p.errStr(.overflow_result_requires_ptr, param_tok, try p.typeStr(arg.ty));
|
||||
}
|
||||
}
|
||||
|
||||
fn checkComplexArg(p: *Parser, builtin_tok: TokenIndex, first_after: TokenIndex, param_tok: TokenIndex, arg: *Result, idx: u32) !void {
|
||||
_ = builtin_tok;
|
||||
_ = first_after;
|
||||
@ -7880,6 +8010,7 @@ fn charLiteral(p: *Parser) Error!Result {
|
||||
|
||||
const slice = char_kind.contentSlice(p.tokSlice(p.tok_i));
|
||||
|
||||
var is_multichar = false;
|
||||
if (slice.len == 1 and std.ascii.isASCII(slice[0])) {
|
||||
// fast path: single unescaped ASCII char
|
||||
val = slice[0];
|
||||
@ -7913,7 +8044,7 @@ fn charLiteral(p: *Parser) Error!Result {
|
||||
},
|
||||
};
|
||||
|
||||
const is_multichar = chars.items.len > 1;
|
||||
is_multichar = chars.items.len > 1;
|
||||
if (is_multichar) {
|
||||
if (char_kind == .char and chars.items.len == 4) {
|
||||
char_literal_parser.warn(.four_char_char_literal, .{ .none = {} });
|
||||
@ -7956,9 +8087,19 @@ fn charLiteral(p: *Parser) Error!Result {
|
||||
else
|
||||
p.comp.types.intmax;
|
||||
|
||||
var value = try Value.int(val, p.comp);
|
||||
// C99 6.4.4.4.10
|
||||
// > If an integer character constant contains a single character or escape sequence,
|
||||
// > its value is the one that results when an object with type char whose value is
|
||||
// > that of the single character or escape sequence is converted to type int.
|
||||
// This conversion only matters if `char` is signed and has a high-order bit of `1`
|
||||
if (char_kind == .char and !is_multichar and val > 0x7F and p.comp.getCharSignedness() == .signed) {
|
||||
try value.intCast(.{ .specifier = .char }, p.comp);
|
||||
}
|
||||
|
||||
const res = Result{
|
||||
.ty = if (p.in_macro) macro_ty else ty,
|
||||
.val = try Value.int(val, p.comp),
|
||||
.val = value,
|
||||
.node = try p.addNode(.{ .tag = .char_literal, .ty = ty, .data = undefined }),
|
||||
};
|
||||
if (!p.in_macro) try p.value_map.put(res.node, res.val);
|
||||
|
433
lib/compiler/aro/aro/Preprocessor.zig
vendored
433
lib/compiler/aro/aro/Preprocessor.zig
vendored
File diff suppressed because it is too large
Load Diff
19
lib/compiler/aro/aro/Toolchain.zig
vendored
19
lib/compiler/aro/aro/Toolchain.zig
vendored
@ -487,3 +487,22 @@ pub fn addRuntimeLibs(tc: *const Toolchain, argv: *std.ArrayList([]const u8)) !v
|
||||
try argv.append("-ldl");
|
||||
}
|
||||
}
|
||||
|
||||
pub fn defineSystemIncludes(tc: *Toolchain) !void {
|
||||
return switch (tc.inner) {
|
||||
.uninitialized => unreachable,
|
||||
.linux => |*linux| linux.defineSystemIncludes(tc),
|
||||
.unknown => {
|
||||
if (tc.driver.nostdinc) return;
|
||||
|
||||
const comp = tc.driver.comp;
|
||||
if (!tc.driver.nobuiltininc) {
|
||||
try comp.addBuiltinIncludeDir(tc.driver.aro_name);
|
||||
}
|
||||
|
||||
if (!tc.driver.nostdlibinc) {
|
||||
try comp.addSystemIncludeDir("/usr/include");
|
||||
}
|
||||
},
|
||||
};
|
||||
}
|
||||
|
25
lib/compiler/aro/aro/Tree.zig
vendored
25
lib/compiler/aro/aro/Tree.zig
vendored
@ -12,6 +12,16 @@ const StringInterner = @import("StringInterner.zig");
|
||||
|
||||
pub const Token = struct {
|
||||
id: Id,
|
||||
loc: Source.Location,
|
||||
|
||||
pub const List = std.MultiArrayList(Token);
|
||||
pub const Id = Tokenizer.Token.Id;
|
||||
pub const NumberPrefix = number_affixes.Prefix;
|
||||
pub const NumberSuffix = number_affixes.Suffix;
|
||||
};
|
||||
|
||||
pub const TokenWithExpansionLocs = struct {
|
||||
id: Token.Id,
|
||||
flags: packed struct {
|
||||
expansion_disabled: bool = false,
|
||||
is_macro_arg: bool = false,
|
||||
@ -22,15 +32,15 @@ pub const Token = struct {
|
||||
loc: Source.Location,
|
||||
expansion_locs: ?[*]Source.Location = null,
|
||||
|
||||
pub fn expansionSlice(tok: Token) []const Source.Location {
|
||||
pub fn expansionSlice(tok: TokenWithExpansionLocs) []const Source.Location {
|
||||
const locs = tok.expansion_locs orelse return &[0]Source.Location{};
|
||||
var i: usize = 0;
|
||||
while (locs[i].id != .unused) : (i += 1) {}
|
||||
return locs[0..i];
|
||||
}
|
||||
|
||||
pub fn addExpansionLocation(tok: *Token, gpa: std.mem.Allocator, new: []const Source.Location) !void {
|
||||
if (new.len == 0 or tok.id == .whitespace) return;
|
||||
pub fn addExpansionLocation(tok: *TokenWithExpansionLocs, gpa: std.mem.Allocator, new: []const Source.Location) !void {
|
||||
if (new.len == 0 or tok.id == .whitespace or tok.id == .macro_ws or tok.id == .placemarker) return;
|
||||
var list = std.ArrayList(Source.Location).init(gpa);
|
||||
defer {
|
||||
@memset(list.items.ptr[list.items.len..list.capacity], .{});
|
||||
@ -70,14 +80,14 @@ pub const Token = struct {
|
||||
gpa.free(locs[0 .. i + 1]);
|
||||
}
|
||||
|
||||
pub fn dupe(tok: Token, gpa: std.mem.Allocator) !Token {
|
||||
pub fn dupe(tok: TokenWithExpansionLocs, gpa: std.mem.Allocator) !TokenWithExpansionLocs {
|
||||
var copy = tok;
|
||||
copy.expansion_locs = null;
|
||||
try copy.addExpansionLocation(gpa, tok.expansionSlice());
|
||||
return copy;
|
||||
}
|
||||
|
||||
pub fn checkMsEof(tok: Token, source: Source, comp: *Compilation) !void {
|
||||
pub fn checkMsEof(tok: TokenWithExpansionLocs, source: Source, comp: *Compilation) !void {
|
||||
std.debug.assert(tok.id == .eof);
|
||||
if (source.buf.len > tok.loc.byte_offset and source.buf[tok.loc.byte_offset] == 0x1A) {
|
||||
try comp.addDiagnostic(.{
|
||||
@ -90,11 +100,6 @@ pub const Token = struct {
|
||||
}, &.{});
|
||||
}
|
||||
}
|
||||
|
||||
pub const List = std.MultiArrayList(Token);
|
||||
pub const Id = Tokenizer.Token.Id;
|
||||
pub const NumberPrefix = number_affixes.Prefix;
|
||||
pub const NumberSuffix = number_affixes.Suffix;
|
||||
};
|
||||
|
||||
pub const TokenIndex = u32;
|
||||
|
7
lib/compiler/aro/aro/Type.zig
vendored
7
lib/compiler/aro/aro/Type.zig
vendored
@ -105,6 +105,7 @@ pub const Func = struct {
|
||||
fn eql(a: *const Func, b: *const Func, a_spec: Specifier, b_spec: Specifier, comp: *const Compilation) bool {
|
||||
// return type cannot have qualifiers
|
||||
if (!a.return_type.eql(b.return_type, comp, false)) return false;
|
||||
if (a.params.len == 0 and b.params.len == 0) return true;
|
||||
|
||||
if (a.params.len != b.params.len) {
|
||||
if (a_spec == .old_style_func or b_spec == .old_style_func) {
|
||||
@ -114,6 +115,7 @@ pub const Func = struct {
|
||||
}
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
if ((a_spec == .func) != (b_spec == .func)) return false;
|
||||
// TODO validate this
|
||||
@ -887,7 +889,8 @@ pub fn hasIncompleteSize(ty: Type) bool {
|
||||
.@"struct", .@"union" => ty.data.record.isIncomplete(),
|
||||
.array, .static_array => ty.data.array.elem.hasIncompleteSize(),
|
||||
.typeof_type => ty.data.sub_type.hasIncompleteSize(),
|
||||
.typeof_expr => ty.data.expr.ty.hasIncompleteSize(),
|
||||
.typeof_expr, .variable_len_array => ty.data.expr.ty.hasIncompleteSize(),
|
||||
.unspecified_variable_len_array => ty.data.sub_type.hasIncompleteSize(),
|
||||
.attributed => ty.data.attributed.base.hasIncompleteSize(),
|
||||
else => false,
|
||||
};
|
||||
@ -1053,7 +1056,7 @@ pub fn bitSizeof(ty: Type, comp: *const Compilation) ?u64 {
|
||||
}
|
||||
|
||||
pub fn alignable(ty: Type) bool {
|
||||
return ty.isArray() or !ty.hasIncompleteSize() or ty.is(.void);
|
||||
return (ty.isArray() or !ty.hasIncompleteSize() or ty.is(.void)) and !ty.is(.invalid);
|
||||
}
|
||||
|
||||
/// Get the alignment of a type
|
||||
|
8
lib/compiler/aro/aro/Value.zig
vendored
8
lib/compiler/aro/aro/Value.zig
vendored
@ -60,7 +60,8 @@ test "minUnsignedBits" {
|
||||
|
||||
var comp = Compilation.init(std.testing.allocator);
|
||||
defer comp.deinit();
|
||||
comp.target = (try std.zig.CrossTarget.parse(.{ .arch_os_abi = "x86_64-linux-gnu" })).toTarget();
|
||||
const target_query = try std.Target.Query.parse(.{ .arch_os_abi = "x86_64-linux-gnu" });
|
||||
comp.target = try std.zig.system.resolveTargetQuery(target_query);
|
||||
|
||||
try Test.checkIntBits(&comp, 0, 0);
|
||||
try Test.checkIntBits(&comp, 1, 1);
|
||||
@ -94,7 +95,8 @@ test "minSignedBits" {
|
||||
|
||||
var comp = Compilation.init(std.testing.allocator);
|
||||
defer comp.deinit();
|
||||
comp.target = (try std.zig.CrossTarget.parse(.{ .arch_os_abi = "x86_64-linux-gnu" })).toTarget();
|
||||
const target_query = try std.Target.Query.parse(.{ .arch_os_abi = "x86_64-linux-gnu" });
|
||||
comp.target = try std.zig.system.resolveTargetQuery(target_query);
|
||||
|
||||
try Test.checkIntBits(&comp, -1, 1);
|
||||
try Test.checkIntBits(&comp, -2, 2);
|
||||
@ -224,7 +226,7 @@ pub fn intCast(v: *Value, dest_ty: Type, comp: *Compilation) !void {
|
||||
v.* = try intern(comp, .{ .int = .{ .big_int = result_bigint.toConst() } });
|
||||
}
|
||||
|
||||
/// Converts the stored value from an integer to a float.
|
||||
/// Converts the stored value to a float of the specified type
|
||||
/// `.none` value remains unchanged.
|
||||
pub fn floatCast(v: *Value, dest_ty: Type, comp: *Compilation) !void {
|
||||
if (v.opt_ref == .none) return;
|
||||
|
18
lib/compiler/aro/aro/pragmas/gcc.zig
vendored
18
lib/compiler/aro/aro/pragmas/gcc.zig
vendored
@ -80,7 +80,7 @@ fn diagnosticHandler(self: *GCC, pp: *Preprocessor, start_idx: TokenIndex) Pragm
|
||||
.tag = .pragma_requires_string_literal,
|
||||
.loc = diagnostic_tok.loc,
|
||||
.extra = .{ .str = "GCC diagnostic" },
|
||||
}, diagnostic_tok.expansionSlice());
|
||||
}, pp.expansionSlice(start_idx));
|
||||
},
|
||||
else => |e| return e,
|
||||
};
|
||||
@ -90,7 +90,7 @@ fn diagnosticHandler(self: *GCC, pp: *Preprocessor, start_idx: TokenIndex) Pragm
|
||||
.tag = .malformed_warning_check,
|
||||
.loc = next.loc,
|
||||
.extra = .{ .str = "GCC diagnostic" },
|
||||
}, next.expansionSlice());
|
||||
}, pp.expansionSlice(start_idx + 1));
|
||||
}
|
||||
const new_kind: Diagnostics.Kind = switch (diagnostic) {
|
||||
.ignored => .off,
|
||||
@ -116,7 +116,7 @@ fn preprocessorHandler(pragma: *Pragma, pp: *Preprocessor, start_idx: TokenIndex
|
||||
return pp.comp.addDiagnostic(.{
|
||||
.tag = .unknown_gcc_pragma,
|
||||
.loc = directive_tok.loc,
|
||||
}, directive_tok.expansionSlice());
|
||||
}, pp.expansionSlice(start_idx + 1));
|
||||
|
||||
switch (gcc_pragma) {
|
||||
.warning, .@"error" => {
|
||||
@ -126,7 +126,7 @@ fn preprocessorHandler(pragma: *Pragma, pp: *Preprocessor, start_idx: TokenIndex
|
||||
.tag = .pragma_requires_string_literal,
|
||||
.loc = directive_tok.loc,
|
||||
.extra = .{ .str = @tagName(gcc_pragma) },
|
||||
}, directive_tok.expansionSlice());
|
||||
}, pp.expansionSlice(start_idx + 1));
|
||||
},
|
||||
else => |e| return e,
|
||||
};
|
||||
@ -134,7 +134,7 @@ fn preprocessorHandler(pragma: *Pragma, pp: *Preprocessor, start_idx: TokenIndex
|
||||
const diagnostic_tag: Diagnostics.Tag = if (gcc_pragma == .warning) .pragma_warning_message else .pragma_error_message;
|
||||
return pp.comp.addDiagnostic(
|
||||
.{ .tag = diagnostic_tag, .loc = directive_tok.loc, .extra = extra },
|
||||
directive_tok.expansionSlice(),
|
||||
pp.expansionSlice(start_idx + 1),
|
||||
);
|
||||
},
|
||||
.diagnostic => return self.diagnosticHandler(pp, start_idx + 2) catch |err| switch (err) {
|
||||
@ -143,12 +143,12 @@ fn preprocessorHandler(pragma: *Pragma, pp: *Preprocessor, start_idx: TokenIndex
|
||||
return pp.comp.addDiagnostic(.{
|
||||
.tag = .unknown_gcc_pragma_directive,
|
||||
.loc = tok.loc,
|
||||
}, tok.expansionSlice());
|
||||
}, pp.expansionSlice(start_idx + 2));
|
||||
},
|
||||
else => |e| return e,
|
||||
},
|
||||
.poison => {
|
||||
var i: usize = 2;
|
||||
var i: u32 = 2;
|
||||
while (true) : (i += 1) {
|
||||
const tok = pp.tokens.get(start_idx + i);
|
||||
if (tok.id == .nl) break;
|
||||
@ -157,14 +157,14 @@ fn preprocessorHandler(pragma: *Pragma, pp: *Preprocessor, start_idx: TokenIndex
|
||||
return pp.comp.addDiagnostic(.{
|
||||
.tag = .pragma_poison_identifier,
|
||||
.loc = tok.loc,
|
||||
}, tok.expansionSlice());
|
||||
}, pp.expansionSlice(start_idx + i));
|
||||
}
|
||||
const str = pp.expandedSlice(tok);
|
||||
if (pp.defines.get(str) != null) {
|
||||
try pp.comp.addDiagnostic(.{
|
||||
.tag = .pragma_poison_macro,
|
||||
.loc = tok.loc,
|
||||
}, tok.expansionSlice());
|
||||
}, pp.expansionSlice(start_idx + i));
|
||||
}
|
||||
try pp.poisoned_identifiers.put(str, {});
|
||||
}
|
||||
|
2
lib/compiler/aro/aro/pragmas/message.zig
vendored
2
lib/compiler/aro/aro/pragmas/message.zig
vendored
@ -28,7 +28,7 @@ fn deinit(pragma: *Pragma, comp: *Compilation) void {
|
||||
|
||||
fn preprocessorHandler(_: *Pragma, pp: *Preprocessor, start_idx: TokenIndex) Pragma.Error!void {
|
||||
const message_tok = pp.tokens.get(start_idx);
|
||||
const message_expansion_locs = message_tok.expansionSlice();
|
||||
const message_expansion_locs = pp.expansionSlice(start_idx);
|
||||
|
||||
const str = Pragma.pasteTokens(pp, start_idx + 1) catch |err| switch (err) {
|
||||
error.ExpectedStringLiteral => {
|
||||
|
2
lib/compiler/aro/aro/pragmas/once.zig
vendored
2
lib/compiler/aro/aro/pragmas/once.zig
vendored
@ -45,7 +45,7 @@ fn preprocessorHandler(pragma: *Pragma, pp: *Preprocessor, start_idx: TokenIndex
|
||||
try pp.comp.addDiagnostic(.{
|
||||
.tag = .extra_tokens_directive_end,
|
||||
.loc = name_tok.loc,
|
||||
}, next.expansionSlice());
|
||||
}, pp.expansionSlice(start_idx + 1));
|
||||
}
|
||||
const seen = self.preprocess_count == pp.preprocess_count;
|
||||
const prev = try self.pragma_once.fetchPut(name_tok.loc.id, {});
|
||||
|
2
lib/compiler/aro/aro/pragmas/pack.zig
vendored
2
lib/compiler/aro/aro/pragmas/pack.zig
vendored
@ -37,7 +37,7 @@ fn parserHandler(pragma: *Pragma, p: *Parser, start_idx: TokenIndex) Compilation
|
||||
return p.comp.addDiagnostic(.{
|
||||
.tag = .pragma_pack_lparen,
|
||||
.loc = l_paren.loc,
|
||||
}, l_paren.expansionSlice());
|
||||
}, p.pp.expansionSlice(idx));
|
||||
}
|
||||
idx += 1;
|
||||
|
||||
|
10
lib/compiler/aro/aro/target.zig
vendored
10
lib/compiler/aro/aro/target.zig
vendored
@ -102,6 +102,16 @@ pub fn int16Type(target: std.Target) Type {
|
||||
};
|
||||
}
|
||||
|
||||
/// sig_atomic_t for this target
|
||||
pub fn sigAtomicType(target: std.Target) Type {
|
||||
if (target.cpu.arch.isWasm()) return .{ .specifier = .long };
|
||||
return switch (target.cpu.arch) {
|
||||
.avr => .{ .specifier = .schar },
|
||||
.msp430 => .{ .specifier = .long },
|
||||
else => .{ .specifier = .int },
|
||||
};
|
||||
}
|
||||
|
||||
/// int64_t for this target
|
||||
pub fn int64Type(target: std.Target) Type {
|
||||
switch (target.cpu.arch) {
|
||||
|
48
lib/compiler/aro/aro/toolchains/Linux.zig
vendored
48
lib/compiler/aro/aro/toolchains/Linux.zig
vendored
@ -373,6 +373,50 @@ fn getOSLibDir(target: std.Target) []const u8 {
|
||||
return "lib64";
|
||||
}
|
||||
|
||||
pub fn defineSystemIncludes(self: *const Linux, tc: *const Toolchain) !void {
|
||||
if (tc.driver.nostdinc) return;
|
||||
|
||||
const comp = tc.driver.comp;
|
||||
const target = tc.getTarget();
|
||||
|
||||
// musl prefers /usr/include before builtin includes, so musl targets will add builtins
|
||||
// at the end of this function (unless disabled with nostdlibinc)
|
||||
if (!tc.driver.nobuiltininc and (!target.isMusl() or tc.driver.nostdlibinc)) {
|
||||
try comp.addBuiltinIncludeDir(tc.driver.aro_name);
|
||||
}
|
||||
|
||||
if (tc.driver.nostdlibinc) return;
|
||||
|
||||
const sysroot = tc.getSysroot();
|
||||
const local_include = try std.fmt.allocPrint(comp.gpa, "{s}{s}", .{ sysroot, "/usr/local/include" });
|
||||
defer comp.gpa.free(local_include);
|
||||
try comp.addSystemIncludeDir(local_include);
|
||||
|
||||
if (self.gcc_detector.is_valid) {
|
||||
const gcc_include_path = try std.fs.path.join(comp.gpa, &.{ self.gcc_detector.parent_lib_path, "..", self.gcc_detector.gcc_triple, "include" });
|
||||
defer comp.gpa.free(gcc_include_path);
|
||||
try comp.addSystemIncludeDir(gcc_include_path);
|
||||
}
|
||||
|
||||
if (getMultiarchTriple(target)) |triple| {
|
||||
const joined = try std.fs.path.join(comp.gpa, &.{ sysroot, "usr", "include", triple });
|
||||
defer comp.gpa.free(joined);
|
||||
if (tc.filesystem.exists(joined)) {
|
||||
try comp.addSystemIncludeDir(joined);
|
||||
}
|
||||
}
|
||||
|
||||
if (target.os.tag == .rtems) return;
|
||||
|
||||
try comp.addSystemIncludeDir("/include");
|
||||
try comp.addSystemIncludeDir("/usr/include");
|
||||
|
||||
std.debug.assert(!tc.driver.nostdlibinc);
|
||||
if (!tc.driver.nobuiltininc and target.isMusl()) {
|
||||
try comp.addBuiltinIncludeDir(tc.driver.aro_name);
|
||||
}
|
||||
}
|
||||
|
||||
test Linux {
|
||||
if (@import("builtin").os.tag == .windows) return error.SkipZigTest;
|
||||
|
||||
@ -388,8 +432,8 @@ test Linux {
|
||||
defer comp.environment = .{};
|
||||
|
||||
const raw_triple = "x86_64-linux-gnu";
|
||||
const cross = std.zig.CrossTarget.parse(.{ .arch_os_abi = raw_triple }) catch unreachable;
|
||||
comp.target = cross.toTarget(); // TODO deprecated
|
||||
const target_query = try std.Target.Query.parse(.{ .arch_os_abi = raw_triple });
|
||||
comp.target = try std.zig.system.resolveTargetQuery(target_query);
|
||||
comp.langopts.setEmulatedCompiler(.gcc);
|
||||
|
||||
var driver: Driver = .{ .comp = &comp };
|
||||
|
4
lib/compiler/aro/backend/Interner.zig
vendored
4
lib/compiler/aro/backend/Interner.zig
vendored
@ -485,11 +485,11 @@ pub fn put(i: *Interner, gpa: Allocator, key: Key) !Ref {
|
||||
.data = try i.addExtra(gpa, Tag.F64.pack(data)),
|
||||
}),
|
||||
.f80 => |data| i.items.appendAssumeCapacity(.{
|
||||
.tag = .f64,
|
||||
.tag = .f80,
|
||||
.data = try i.addExtra(gpa, Tag.F80.pack(data)),
|
||||
}),
|
||||
.f128 => |data| i.items.appendAssumeCapacity(.{
|
||||
.tag = .f64,
|
||||
.tag = .f128,
|
||||
.data = try i.addExtra(gpa, Tag.F128.pack(data)),
|
||||
}),
|
||||
},
|
||||
|
2
lib/compiler/aro/backend/Ir.zig
vendored
2
lib/compiler/aro/backend/Ir.zig
vendored
@ -649,7 +649,7 @@ fn writeValue(ir: Ir, val: Interner.Ref, config: std.io.tty.Config, w: anytype)
|
||||
.float => |repr| switch (repr) {
|
||||
inline else => |x| return w.print("{d}", .{@as(f64, @floatCast(x))}),
|
||||
},
|
||||
.bytes => |b| return std.zig.fmt.stringEscape(b, "", .{}, w),
|
||||
.bytes => |b| return std.zig.stringEscape(b, "", .{}, w),
|
||||
else => unreachable, // not a value
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user