mirror of
https://github.com/ziglang/zig.git
synced 2025-12-06 06:13:07 +00:00
Merge pull request #25780 from Vexu/translate-c
Update Aro and translate-c to latest
This commit is contained in:
commit
db622f14c4
6
lib/compiler/aro/aro.zig
vendored
6
lib/compiler/aro/aro.zig
vendored
@ -6,7 +6,7 @@ pub const Parser = @import("aro/Parser.zig");
|
|||||||
pub const Preprocessor = @import("aro/Preprocessor.zig");
|
pub const Preprocessor = @import("aro/Preprocessor.zig");
|
||||||
pub const Source = @import("aro/Source.zig");
|
pub const Source = @import("aro/Source.zig");
|
||||||
pub const StringInterner = @import("aro/StringInterner.zig");
|
pub const StringInterner = @import("aro/StringInterner.zig");
|
||||||
pub const target_util = @import("aro/target.zig");
|
pub const Target = @import("aro/Target.zig");
|
||||||
pub const Tokenizer = @import("aro/Tokenizer.zig");
|
pub const Tokenizer = @import("aro/Tokenizer.zig");
|
||||||
pub const Toolchain = @import("aro/Toolchain.zig");
|
pub const Toolchain = @import("aro/Toolchain.zig");
|
||||||
pub const Tree = @import("aro/Tree.zig");
|
pub const Tree = @import("aro/Tree.zig");
|
||||||
@ -31,11 +31,11 @@ test {
|
|||||||
_ = @import("aro/char_info.zig");
|
_ = @import("aro/char_info.zig");
|
||||||
_ = @import("aro/Compilation.zig");
|
_ = @import("aro/Compilation.zig");
|
||||||
_ = @import("aro/Driver/Distro.zig");
|
_ = @import("aro/Driver/Distro.zig");
|
||||||
_ = @import("aro/Driver/Filesystem.zig");
|
|
||||||
_ = @import("aro/Driver/GCCVersion.zig");
|
_ = @import("aro/Driver/GCCVersion.zig");
|
||||||
_ = @import("aro/InitList.zig");
|
_ = @import("aro/InitList.zig");
|
||||||
|
_ = @import("aro/LangOpts.zig");
|
||||||
_ = @import("aro/Preprocessor.zig");
|
_ = @import("aro/Preprocessor.zig");
|
||||||
_ = @import("aro/target.zig");
|
_ = @import("aro/Target.zig");
|
||||||
_ = @import("aro/Tokenizer.zig");
|
_ = @import("aro/Tokenizer.zig");
|
||||||
_ = @import("aro/Value.zig");
|
_ = @import("aro/Value.zig");
|
||||||
}
|
}
|
||||||
|
|||||||
65
lib/compiler/aro/aro/Attribute.zig
vendored
65
lib/compiler/aro/aro/Attribute.zig
vendored
@ -61,25 +61,21 @@ pub const Iterator = struct {
|
|||||||
return .{ self.slice[self.index], self.index };
|
return .{ self.slice[self.index], self.index };
|
||||||
}
|
}
|
||||||
if (self.source) |*source| {
|
if (self.source) |*source| {
|
||||||
var cur = source.qt;
|
if (source.qt.isInvalid()) {
|
||||||
if (cur.isInvalid()) {
|
|
||||||
self.source = null;
|
self.source = null;
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
while (true) switch (cur.type(source.comp)) {
|
loop: switch (source.qt.type(source.comp)) {
|
||||||
.typeof => |typeof| cur = typeof.base,
|
.typeof => |typeof| continue :loop typeof.base.type(source.comp),
|
||||||
.attributed => |attributed| {
|
.attributed => |attributed| {
|
||||||
self.slice = attributed.attributes;
|
self.slice = attributed.attributes;
|
||||||
self.index = 1;
|
self.index = 1;
|
||||||
source.qt = attributed.base;
|
source.qt = attributed.base;
|
||||||
return .{ self.slice[0], 0 };
|
return .{ self.slice[0], 0 };
|
||||||
},
|
},
|
||||||
.typedef => |typedef| cur = typedef.base,
|
.typedef => |typedef| continue :loop typedef.base.type(source.comp),
|
||||||
else => {
|
else => self.source = null,
|
||||||
self.source = null;
|
}
|
||||||
break;
|
|
||||||
},
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
@ -712,6 +708,9 @@ const attributes = struct {
|
|||||||
pub const thiscall = struct {};
|
pub const thiscall = struct {};
|
||||||
pub const sysv_abi = struct {};
|
pub const sysv_abi = struct {};
|
||||||
pub const ms_abi = struct {};
|
pub const ms_abi = struct {};
|
||||||
|
// TODO cannot be combined with weak or selectany
|
||||||
|
pub const internal_linkage = struct {};
|
||||||
|
pub const availability = struct {};
|
||||||
};
|
};
|
||||||
|
|
||||||
pub const Tag = std.meta.DeclEnum(attributes);
|
pub const Tag = std.meta.DeclEnum(attributes);
|
||||||
@ -776,9 +775,9 @@ pub fn fromString(kind: Kind, namespace: ?[]const u8, name: []const u8) ?Tag {
|
|||||||
|
|
||||||
const tag_and_opts = attribute_names.fromName(normalized) orelse return null;
|
const tag_and_opts = attribute_names.fromName(normalized) orelse return null;
|
||||||
switch (actual_kind) {
|
switch (actual_kind) {
|
||||||
inline else => |tag| {
|
inline else => |available_kind| {
|
||||||
if (@field(tag_and_opts.properties, @tagName(tag)))
|
if (@field(tag_and_opts, @tagName(available_kind)))
|
||||||
return tag_and_opts.properties.tag;
|
return tag_and_opts.tag;
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
@ -814,7 +813,7 @@ fn applyVariableOrParameterAttributes(p: *Parser, qt: QualType, attr_buf_start:
|
|||||||
for (attrs, toks) |attr, tok| switch (attr.tag) {
|
for (attrs, toks) |attr, tok| switch (attr.tag) {
|
||||||
// zig fmt: off
|
// zig fmt: off
|
||||||
.alias, .may_alias, .deprecated, .unavailable, .unused, .warn_if_not_aligned, .weak, .used,
|
.alias, .may_alias, .deprecated, .unavailable, .unused, .warn_if_not_aligned, .weak, .used,
|
||||||
.noinit, .retain, .persistent, .section, .mode, .asm_label, .nullability, .unaligned,
|
.noinit, .retain, .persistent, .section, .mode, .asm_label, .nullability, .unaligned, .selectany, .internal_linkage,
|
||||||
=> try p.attr_application_buf.append(gpa, attr),
|
=> try p.attr_application_buf.append(gpa, attr),
|
||||||
// zig fmt: on
|
// zig fmt: on
|
||||||
.common => if (nocommon) {
|
.common => if (nocommon) {
|
||||||
@ -874,18 +873,18 @@ fn applyVariableOrParameterAttributes(p: *Parser, qt: QualType, attr_buf_start:
|
|||||||
|
|
||||||
pub fn applyFieldAttributes(p: *Parser, field_qt: *QualType, attr_buf_start: usize) ![]const Attribute {
|
pub fn applyFieldAttributes(p: *Parser, field_qt: *QualType, attr_buf_start: usize) ![]const Attribute {
|
||||||
const attrs = p.attr_buf.items(.attr)[attr_buf_start..];
|
const attrs = p.attr_buf.items(.attr)[attr_buf_start..];
|
||||||
const toks = p.attr_buf.items(.tok)[attr_buf_start..];
|
const seen = p.attr_buf.items(.seen)[attr_buf_start..];
|
||||||
p.attr_application_buf.items.len = 0;
|
p.attr_application_buf.items.len = 0;
|
||||||
for (attrs, toks) |attr, tok| switch (attr.tag) {
|
for (attrs, 0..) |attr, i| switch (attr.tag) {
|
||||||
// zig fmt: off
|
.@"packed" => {
|
||||||
.@"packed", .may_alias, .deprecated, .unavailable, .unused, .warn_if_not_aligned,
|
try p.attr_application_buf.append(p.comp.gpa, attr);
|
||||||
.mode, .warn_unused_result, .nodiscard, .nullability, .unaligned,
|
seen[i] = true;
|
||||||
=> try p.attr_application_buf.append(p.comp.gpa, attr),
|
},
|
||||||
// zig fmt: on
|
.aligned => {
|
||||||
.vector_size => try attr.applyVectorSize(p, tok, field_qt),
|
try attr.applyAligned(p, field_qt.*, null);
|
||||||
.aligned => try attr.applyAligned(p, field_qt.*, null),
|
seen[i] = true;
|
||||||
.calling_convention => try applyCallingConvention(attr, p, tok, field_qt.*),
|
},
|
||||||
else => try ignoredAttrErr(p, tok, attr.tag, "fields"),
|
else => {},
|
||||||
};
|
};
|
||||||
return p.attr_application_buf.items;
|
return p.attr_application_buf.items;
|
||||||
}
|
}
|
||||||
@ -894,11 +893,16 @@ pub fn applyTypeAttributes(p: *Parser, qt: QualType, attr_buf_start: usize, diag
|
|||||||
const gpa = p.comp.gpa;
|
const gpa = p.comp.gpa;
|
||||||
const attrs = p.attr_buf.items(.attr)[attr_buf_start..];
|
const attrs = p.attr_buf.items(.attr)[attr_buf_start..];
|
||||||
const toks = p.attr_buf.items(.tok)[attr_buf_start..];
|
const toks = p.attr_buf.items(.tok)[attr_buf_start..];
|
||||||
|
const seens = p.attr_buf.items(.seen)[attr_buf_start..];
|
||||||
p.attr_application_buf.items.len = 0;
|
p.attr_application_buf.items.len = 0;
|
||||||
var base_qt = qt;
|
var base_qt = qt;
|
||||||
for (attrs, toks) |attr, tok| switch (attr.tag) {
|
for (attrs, toks, seens) |attr, tok, seen| {
|
||||||
|
if (seen) continue;
|
||||||
|
|
||||||
|
switch (attr.tag) {
|
||||||
// zig fmt: off
|
// zig fmt: off
|
||||||
.@"packed", .may_alias, .deprecated, .unavailable, .unused, .warn_if_not_aligned, .mode, .nullability, .unaligned,
|
.@"packed", .may_alias, .deprecated, .unavailable, .unused, .warn_if_not_aligned, .mode,
|
||||||
|
.nullability, .unaligned, .warn_unused_result,
|
||||||
=> try p.attr_application_buf.append(gpa, attr),
|
=> try p.attr_application_buf.append(gpa, attr),
|
||||||
// zig fmt: on
|
// zig fmt: on
|
||||||
.transparent_union => try attr.applyTransparentUnion(p, tok, base_qt),
|
.transparent_union => try attr.applyTransparentUnion(p, tok, base_qt),
|
||||||
@ -916,7 +920,8 @@ pub fn applyTypeAttributes(p: *Parser, qt: QualType, attr_buf_start: usize, diag
|
|||||||
.nonstring,
|
.nonstring,
|
||||||
=> |t| try p.err(tok, .attribute_todo, .{ @tagName(t), "types" }),
|
=> |t| try p.err(tok, .attribute_todo, .{ @tagName(t), "types" }),
|
||||||
else => try ignoredAttrErr(p, tok, attr.tag, "types"),
|
else => try ignoredAttrErr(p, tok, attr.tag, "types"),
|
||||||
};
|
}
|
||||||
|
}
|
||||||
return applySelected(base_qt, p);
|
return applySelected(base_qt, p);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -935,7 +940,7 @@ pub fn applyFunctionAttributes(p: *Parser, qt: QualType, attr_buf_start: usize)
|
|||||||
.noreturn, .unused, .used, .warning, .deprecated, .unavailable, .weak, .pure, .leaf,
|
.noreturn, .unused, .used, .warning, .deprecated, .unavailable, .weak, .pure, .leaf,
|
||||||
.@"const", .warn_unused_result, .section, .returns_nonnull, .returns_twice, .@"error",
|
.@"const", .warn_unused_result, .section, .returns_nonnull, .returns_twice, .@"error",
|
||||||
.externally_visible, .retain, .flatten, .gnu_inline, .alias, .asm_label, .nodiscard,
|
.externally_visible, .retain, .flatten, .gnu_inline, .alias, .asm_label, .nodiscard,
|
||||||
.reproducible, .unsequenced, .nothrow, .nullability, .unaligned,
|
.reproducible, .unsequenced, .nothrow, .nullability, .unaligned, .internal_linkage,
|
||||||
=> try p.attr_application_buf.append(gpa, attr),
|
=> try p.attr_application_buf.append(gpa, attr),
|
||||||
// zig fmt: on
|
// zig fmt: on
|
||||||
.hot => if (cold) {
|
.hot => if (cold) {
|
||||||
@ -1164,7 +1169,7 @@ pub fn applyStatementAttributes(p: *Parser, expr_start: TokenIndex, attr_buf_sta
|
|||||||
try p.attr_application_buf.append(p.comp.gpa, attr);
|
try p.attr_application_buf.append(p.comp.gpa, attr);
|
||||||
break;
|
break;
|
||||||
},
|
},
|
||||||
.r_brace => {},
|
.r_brace, .semicolon => {},
|
||||||
else => {
|
else => {
|
||||||
try p.err(expr_start, .invalid_fallthrough, .{});
|
try p.err(expr_start, .invalid_fallthrough, .{});
|
||||||
break;
|
break;
|
||||||
|
|||||||
1601
lib/compiler/aro/aro/Attribute/names.zig
vendored
1601
lib/compiler/aro/aro/Attribute/names.zig
vendored
File diff suppressed because it is too large
Load Diff
293
lib/compiler/aro/aro/Builtins.zig
vendored
293
lib/compiler/aro/aro/Builtins.zig
vendored
@ -3,25 +3,75 @@ const std = @import("std");
|
|||||||
const Compilation = @import("Compilation.zig");
|
const Compilation = @import("Compilation.zig");
|
||||||
const LangOpts = @import("LangOpts.zig");
|
const LangOpts = @import("LangOpts.zig");
|
||||||
const Parser = @import("Parser.zig");
|
const Parser = @import("Parser.zig");
|
||||||
const target_util = @import("target.zig");
|
const Target = @import("Target.zig");
|
||||||
const TypeStore = @import("TypeStore.zig");
|
const TypeStore = @import("TypeStore.zig");
|
||||||
const QualType = TypeStore.QualType;
|
const QualType = TypeStore.QualType;
|
||||||
const Builder = TypeStore.Builder;
|
const Builder = TypeStore.Builder;
|
||||||
const TypeDescription = @import("Builtins/TypeDescription.zig");
|
const TypeDescription = @import("Builtins/TypeDescription.zig");
|
||||||
|
const properties = @import("Builtins/properties.zig");
|
||||||
|
|
||||||
const Properties = @import("Builtins/Properties.zig");
|
const BuiltinBase = struct {
|
||||||
pub const Builtin = @import("Builtins/Builtin.zig").with(Properties);
|
param_str: [*:0]const u8,
|
||||||
|
language: properties.Language = .all_languages,
|
||||||
const Expanded = struct {
|
attributes: properties.Attributes = .{},
|
||||||
qt: QualType,
|
header: properties.Header = .none,
|
||||||
builtin: Builtin,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
const NameToTypeMap = std.StringHashMapUnmanaged(QualType);
|
const BuiltinTarget = struct {
|
||||||
|
param_str: [*:0]const u8,
|
||||||
|
language: properties.Language = .all_languages,
|
||||||
|
attributes: properties.Attributes = .{},
|
||||||
|
header: properties.Header = .none,
|
||||||
|
features: ?[*:0]const u8 = null,
|
||||||
|
};
|
||||||
|
|
||||||
|
const aarch64 = @import("Builtins/aarch64.zig").with(BuiltinTarget);
|
||||||
|
const amdgcn = @import("Builtins/amdgcn.zig").with(BuiltinTarget);
|
||||||
|
const arm = @import("Builtins/arm.zig").with(BuiltinTarget);
|
||||||
|
const bpf = @import("Builtins/bpf.zig").with(BuiltinTarget);
|
||||||
|
const common = @import("Builtins/common.zig").with(BuiltinBase);
|
||||||
|
const hexagon = @import("Builtins/hexagon.zig").with(BuiltinTarget);
|
||||||
|
const loongarch = @import("Builtins/loongarch.zig").with(BuiltinTarget);
|
||||||
|
const mips = @import("Builtins/mips.zig").with(BuiltinBase);
|
||||||
|
const nvptx = @import("Builtins/nvptx.zig").with(BuiltinTarget);
|
||||||
|
const powerpc = @import("Builtins/powerpc.zig").with(BuiltinTarget);
|
||||||
|
const riscv = @import("Builtins/riscv.zig").with(BuiltinTarget);
|
||||||
|
const s390x = @import("Builtins/s390x.zig").with(BuiltinTarget);
|
||||||
|
const ve = @import("Builtins/ve.zig").with(BuiltinBase);
|
||||||
|
const x86_64 = @import("Builtins/x86_64.zig").with(BuiltinTarget);
|
||||||
|
const x86 = @import("Builtins/x86.zig").with(BuiltinTarget);
|
||||||
|
const xcore = @import("Builtins/xcore.zig").with(BuiltinBase);
|
||||||
|
|
||||||
|
pub const Tag = union(enum) {
|
||||||
|
aarch64: aarch64.Tag,
|
||||||
|
amdgcn: amdgcn.Tag,
|
||||||
|
arm: arm.Tag,
|
||||||
|
bpf: bpf.Tag,
|
||||||
|
common: common.Tag,
|
||||||
|
hexagon: hexagon.Tag,
|
||||||
|
loongarch: loongarch.Tag,
|
||||||
|
mips: mips.Tag,
|
||||||
|
nvptx: nvptx.Tag,
|
||||||
|
powerpc: powerpc.Tag,
|
||||||
|
riscv: riscv.Tag,
|
||||||
|
s390x: s390x.Tag,
|
||||||
|
ve: ve.Tag,
|
||||||
|
x86_64: x86_64.Tag,
|
||||||
|
x86: x86.Tag,
|
||||||
|
xcore: xcore.Tag,
|
||||||
|
};
|
||||||
|
|
||||||
|
pub const Expanded = struct {
|
||||||
|
tag: Tag,
|
||||||
|
qt: QualType,
|
||||||
|
language: properties.Language = .all_languages,
|
||||||
|
attributes: properties.Attributes = .{},
|
||||||
|
header: properties.Header = .none,
|
||||||
|
};
|
||||||
|
|
||||||
const Builtins = @This();
|
const Builtins = @This();
|
||||||
|
|
||||||
_name_to_type_map: NameToTypeMap = .{},
|
_name_to_type_map: std.StringHashMapUnmanaged(Expanded) = .{},
|
||||||
|
|
||||||
pub fn deinit(b: *Builtins, gpa: std.mem.Allocator) void {
|
pub fn deinit(b: *Builtins, gpa: std.mem.Allocator) void {
|
||||||
b._name_to_type_map.deinit(gpa);
|
b._name_to_type_map.deinit(gpa);
|
||||||
@ -47,6 +97,7 @@ fn createType(desc: TypeDescription, it: *TypeDescription.TypeIterator, comp: *C
|
|||||||
var parser: Parser = undefined;
|
var parser: Parser = undefined;
|
||||||
parser.comp = comp;
|
parser.comp = comp;
|
||||||
var builder: TypeStore.Builder = .{ .parser = &parser, .error_on_invalid = true };
|
var builder: TypeStore.Builder = .{ .parser = &parser, .error_on_invalid = true };
|
||||||
|
var actual_suffix = desc.suffix;
|
||||||
|
|
||||||
var require_native_int32 = false;
|
var require_native_int32 = false;
|
||||||
var require_native_int64 = false;
|
var require_native_int64 = false;
|
||||||
@ -66,7 +117,7 @@ fn createType(desc: TypeDescription, it: *TypeDescription.TypeIterator, comp: *C
|
|||||||
.W => require_native_int64 = true,
|
.W => require_native_int64 = true,
|
||||||
.N => {
|
.N => {
|
||||||
std.debug.assert(desc.spec == .i);
|
std.debug.assert(desc.spec == .i);
|
||||||
if (!target_util.isLP64(comp.target)) {
|
if (!comp.target.isLP64()) {
|
||||||
builder.combine(.long, 0) catch unreachable;
|
builder.combine(.long, 0) catch unreachable;
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@ -102,10 +153,7 @@ fn createType(desc: TypeDescription, it: *TypeDescription.TypeIterator, comp: *C
|
|||||||
},
|
},
|
||||||
.h => builder.combine(.fp16, 0) catch unreachable,
|
.h => builder.combine(.fp16, 0) catch unreachable,
|
||||||
.x => builder.combine(.float16, 0) catch unreachable,
|
.x => builder.combine(.float16, 0) catch unreachable,
|
||||||
.y => {
|
.y => builder.combine(.bf16, 0) catch unreachable,
|
||||||
// Todo: __bf16
|
|
||||||
return .invalid;
|
|
||||||
},
|
|
||||||
.f => builder.combine(.float, 0) catch unreachable,
|
.f => builder.combine(.float, 0) catch unreachable,
|
||||||
.d => {
|
.d => {
|
||||||
if (builder.type == .long_long) {
|
if (builder.type == .long_long) {
|
||||||
@ -126,18 +174,6 @@ fn createType(desc: TypeDescription, it: *TypeDescription.TypeIterator, comp: *C
|
|||||||
std.debug.assert(builder.type == .none);
|
std.debug.assert(builder.type == .none);
|
||||||
builder.type = Builder.fromType(comp, comp.type_store.ns_constant_string);
|
builder.type = Builder.fromType(comp, comp.type_store.ns_constant_string);
|
||||||
},
|
},
|
||||||
.G => {
|
|
||||||
// Todo: id
|
|
||||||
return .invalid;
|
|
||||||
},
|
|
||||||
.H => {
|
|
||||||
// Todo: SEL
|
|
||||||
return .invalid;
|
|
||||||
},
|
|
||||||
.M => {
|
|
||||||
// Todo: struct objc_super
|
|
||||||
return .invalid;
|
|
||||||
},
|
|
||||||
.a => {
|
.a => {
|
||||||
std.debug.assert(builder.type == .none);
|
std.debug.assert(builder.type == .none);
|
||||||
std.debug.assert(desc.suffix.len == 0);
|
std.debug.assert(desc.suffix.len == 0);
|
||||||
@ -152,7 +188,9 @@ fn createType(desc: TypeDescription, it: *TypeDescription.TypeIterator, comp: *C
|
|||||||
},
|
},
|
||||||
.V => |element_count| {
|
.V => |element_count| {
|
||||||
std.debug.assert(desc.suffix.len == 0);
|
std.debug.assert(desc.suffix.len == 0);
|
||||||
const child_desc = it.next().?;
|
var child_desc = it.next().?;
|
||||||
|
actual_suffix = child_desc.suffix;
|
||||||
|
child_desc.suffix = &.{};
|
||||||
const elem_qt = try createType(child_desc, undefined, comp);
|
const elem_qt = try createType(child_desc, undefined, comp);
|
||||||
const vector_qt = try comp.type_store.put(comp.gpa, .{ .vector = .{
|
const vector_qt = try comp.type_store.put(comp.gpa, .{ .vector = .{
|
||||||
.elem = elem_qt,
|
.elem = elem_qt,
|
||||||
@ -160,8 +198,8 @@ fn createType(desc: TypeDescription, it: *TypeDescription.TypeIterator, comp: *C
|
|||||||
} });
|
} });
|
||||||
builder.type = .{ .other = vector_qt };
|
builder.type = .{ .other = vector_qt };
|
||||||
},
|
},
|
||||||
.q => {
|
.Q => {
|
||||||
// Todo: scalable vector
|
// Todo: target builtin type
|
||||||
return .invalid;
|
return .invalid;
|
||||||
},
|
},
|
||||||
.E => {
|
.E => {
|
||||||
@ -219,9 +257,8 @@ fn createType(desc: TypeDescription, it: *TypeDescription.TypeIterator, comp: *C
|
|||||||
std.debug.assert(desc.suffix.len == 0);
|
std.debug.assert(desc.suffix.len == 0);
|
||||||
builder.type = Builder.fromType(comp, comp.type_store.pid_t);
|
builder.type = Builder.fromType(comp, comp.type_store.pid_t);
|
||||||
},
|
},
|
||||||
.@"!" => return .invalid,
|
|
||||||
}
|
}
|
||||||
for (desc.suffix) |suffix| {
|
for (actual_suffix) |suffix| {
|
||||||
switch (suffix) {
|
switch (suffix) {
|
||||||
.@"*" => |address_space| {
|
.@"*" => |address_space| {
|
||||||
_ = address_space; // TODO: handle address space
|
_ = address_space; // TODO: handle address space
|
||||||
@ -243,144 +280,122 @@ fn createType(desc: TypeDescription, it: *TypeDescription.TypeIterator, comp: *C
|
|||||||
return builder.finish() catch unreachable;
|
return builder.finish() catch unreachable;
|
||||||
}
|
}
|
||||||
|
|
||||||
fn createBuiltin(comp: *Compilation, builtin: Builtin) !QualType {
|
fn createBuiltin(comp: *Compilation, param_str: [*:0]const u8) !QualType {
|
||||||
var it = TypeDescription.TypeIterator.init(builtin.properties.param_str);
|
var it = TypeDescription.TypeIterator.init(param_str);
|
||||||
|
|
||||||
const ret_ty_desc = it.next().?;
|
const ret_ty_desc = it.next().?;
|
||||||
if (ret_ty_desc.spec == .@"!") {
|
|
||||||
// Todo: handle target-dependent definition
|
|
||||||
}
|
|
||||||
const ret_ty = try createType(ret_ty_desc, &it, comp);
|
const ret_ty = try createType(ret_ty_desc, &it, comp);
|
||||||
var param_count: usize = 0;
|
var param_count: usize = 0;
|
||||||
var params: [Builtin.max_param_count]TypeStore.Type.Func.Param = undefined;
|
var params: [32]TypeStore.Type.Func.Param = undefined;
|
||||||
while (it.next()) |desc| : (param_count += 1) {
|
while (it.next()) |desc| : (param_count += 1) {
|
||||||
params[param_count] = .{ .name_tok = 0, .qt = try createType(desc, &it, comp), .name = .empty, .node = .null };
|
params[param_count] = .{ .name_tok = 0, .qt = try createType(desc, &it, comp), .name = .empty, .node = .null };
|
||||||
}
|
}
|
||||||
|
|
||||||
return comp.type_store.put(comp.gpa, .{ .func = .{
|
return comp.type_store.put(comp.gpa, .{ .func = .{
|
||||||
.return_type = ret_ty,
|
.return_type = ret_ty,
|
||||||
.kind = if (builtin.properties.isVarArgs()) .variadic else .normal,
|
.kind = if (properties.isVarArgs(param_str)) .variadic else .normal,
|
||||||
.params = params[0..param_count],
|
.params = params[0..param_count],
|
||||||
} });
|
} });
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Asserts that the builtin has already been created
|
/// Asserts that the builtin has already been created
|
||||||
pub fn lookup(b: *const Builtins, name: []const u8) Expanded {
|
pub fn lookup(b: *const Builtins, name: []const u8) Expanded {
|
||||||
const builtin = Builtin.fromName(name).?;
|
return b._name_to_type_map.get(name).?;
|
||||||
const qt = b._name_to_type_map.get(name).?;
|
|
||||||
return .{ .builtin = builtin, .qt = qt };
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn getOrCreate(b: *Builtins, comp: *Compilation, name: []const u8) !?Expanded {
|
pub fn getOrCreate(b: *Builtins, comp: *Compilation, name: []const u8) !?Expanded {
|
||||||
const qt = b._name_to_type_map.get(name) orelse {
|
if (b._name_to_type_map.get(name)) |expanded| return expanded;
|
||||||
const builtin = Builtin.fromName(name) orelse return null;
|
|
||||||
if (!comp.hasBuiltinFunction(builtin)) return null;
|
const builtin = fromName(comp, name) orelse return null;
|
||||||
|
if (builtin.features) |_| {
|
||||||
|
// TODO check features
|
||||||
|
}
|
||||||
|
|
||||||
try b._name_to_type_map.ensureUnusedCapacity(comp.gpa, 1);
|
try b._name_to_type_map.ensureUnusedCapacity(comp.gpa, 1);
|
||||||
const qt = try createBuiltin(comp, builtin);
|
const expanded: Expanded = .{
|
||||||
b._name_to_type_map.putAssumeCapacity(name, qt);
|
.tag = builtin.tag,
|
||||||
|
.qt = try createBuiltin(comp, builtin.param_str),
|
||||||
|
.attributes = builtin.attributes,
|
||||||
|
.header = builtin.header,
|
||||||
|
.language = builtin.language,
|
||||||
|
};
|
||||||
|
b._name_to_type_map.putAssumeCapacity(name, expanded);
|
||||||
|
return expanded;
|
||||||
|
}
|
||||||
|
|
||||||
|
pub const FromName = struct {
|
||||||
|
tag: Tag,
|
||||||
|
param_str: [*:0]const u8,
|
||||||
|
language: properties.Language = .all_languages,
|
||||||
|
attributes: properties.Attributes = .{},
|
||||||
|
header: properties.Header = .none,
|
||||||
|
features: ?[*:0]const u8 = null,
|
||||||
|
};
|
||||||
|
|
||||||
|
pub fn fromName(comp: *Compilation, name: []const u8) ?FromName {
|
||||||
|
if (fromNameExtra(name, .common)) |found| return found;
|
||||||
|
switch (comp.target.cpu.arch) {
|
||||||
|
.aarch64, .aarch64_be => if (fromNameExtra(name, .aarch64)) |found| return found,
|
||||||
|
.amdgcn => if (fromNameExtra(name, .amdgcn)) |found| return found,
|
||||||
|
.arm, .armeb, .thumb, .thumbeb => if (fromNameExtra(name, .arm)) |found| return found,
|
||||||
|
.bpfeb, .bpfel => if (fromNameExtra(name, .bpf)) |found| return found,
|
||||||
|
.hexagon => if (fromNameExtra(name, .hexagon)) |found| return found,
|
||||||
|
.loongarch32, .loongarch64 => if (fromNameExtra(name, .loongarch)) |found| return found,
|
||||||
|
.mips64, .mips64el, .mips, .mipsel => if (fromNameExtra(name, .mips)) |found| return found,
|
||||||
|
.nvptx, .nvptx64 => if (fromNameExtra(name, .nvptx)) |found| return found,
|
||||||
|
.powerpc64, .powerpc64le, .powerpc, .powerpcle => if (fromNameExtra(name, .powerpc)) |found| return found,
|
||||||
|
.riscv32, .riscv32be, .riscv64, .riscv64be => if (fromNameExtra(name, .riscv)) |found| return found,
|
||||||
|
.s390x => if (fromNameExtra(name, .s390x)) |found| return found,
|
||||||
|
.ve => if (fromNameExtra(name, .ve)) |found| return found,
|
||||||
|
.xcore => if (fromNameExtra(name, .xcore)) |found| return found,
|
||||||
|
.x86_64 => {
|
||||||
|
if (fromNameExtra(name, .x86_64)) |found| return found;
|
||||||
|
if (fromNameExtra(name, .x86)) |found| return found;
|
||||||
|
},
|
||||||
|
.x86 => if (fromNameExtra(name, .x86)) |found| return found,
|
||||||
|
else => {},
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
fn fromNameExtra(name: []const u8, comptime arch: std.meta.Tag(Tag)) ?FromName {
|
||||||
|
const list = @field(@This(), @tagName(arch));
|
||||||
|
const tag = list.tagFromName(name) orelse return null;
|
||||||
|
const builtin = list.data[@intFromEnum(tag)];
|
||||||
|
|
||||||
return .{
|
return .{
|
||||||
.builtin = builtin,
|
.tag = @unionInit(Tag, @tagName(arch), tag),
|
||||||
.qt = qt,
|
.param_str = builtin.param_str,
|
||||||
};
|
.header = builtin.header,
|
||||||
};
|
.language = builtin.language,
|
||||||
const builtin = Builtin.fromName(name).?;
|
.attributes = builtin.attributes,
|
||||||
return .{ .builtin = builtin, .qt = qt };
|
.features = if (@hasField(@TypeOf(builtin), "features")) builtin.features else null,
|
||||||
}
|
|
||||||
|
|
||||||
pub const Iterator = struct {
|
|
||||||
index: u16 = 1,
|
|
||||||
name_buf: [Builtin.longest_name]u8 = undefined,
|
|
||||||
|
|
||||||
pub const Entry = struct {
|
|
||||||
/// Memory of this slice is overwritten on every call to `next`
|
|
||||||
name: []const u8,
|
|
||||||
builtin: Builtin,
|
|
||||||
};
|
|
||||||
|
|
||||||
pub fn next(self: *Iterator) ?Entry {
|
|
||||||
if (self.index > Builtin.data.len) return null;
|
|
||||||
const index = self.index;
|
|
||||||
const data_index = index - 1;
|
|
||||||
self.index += 1;
|
|
||||||
return .{
|
|
||||||
.name = Builtin.nameFromUniqueIndex(index, &self.name_buf),
|
|
||||||
.builtin = Builtin.data[data_index],
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
};
|
|
||||||
|
|
||||||
test Iterator {
|
test "all builtins" {
|
||||||
const gpa = std.testing.allocator;
|
const list_names = comptime std.meta.fieldNames(Tag);
|
||||||
var it = Iterator{};
|
inline for (list_names) |list_name| {
|
||||||
|
const list = @field(Builtins, list_name);
|
||||||
var seen: std.StringHashMapUnmanaged(Builtin) = .empty;
|
for (list.data, 0..) |builtin, index| {
|
||||||
defer seen.deinit(gpa);
|
{
|
||||||
|
var it = TypeDescription.TypeIterator.init(builtin.param_str);
|
||||||
var arena_state = std.heap.ArenaAllocator.init(gpa);
|
while (it.next()) |_| {}
|
||||||
defer arena_state.deinit();
|
|
||||||
const arena = arena_state.allocator();
|
|
||||||
|
|
||||||
while (it.next()) |entry| {
|
|
||||||
const index = Builtin.uniqueIndex(entry.name).?;
|
|
||||||
var buf: [Builtin.longest_name]u8 = undefined;
|
|
||||||
const name_from_index = Builtin.nameFromUniqueIndex(index, &buf);
|
|
||||||
try std.testing.expectEqualStrings(entry.name, name_from_index);
|
|
||||||
|
|
||||||
if (seen.contains(entry.name)) {
|
|
||||||
std.debug.print("iterated over {s} twice\n", .{entry.name});
|
|
||||||
std.debug.print("current data: {}\n", .{entry.builtin});
|
|
||||||
std.debug.print("previous data: {}\n", .{seen.get(entry.name).?});
|
|
||||||
return error.TestExpectedUniqueEntries;
|
|
||||||
}
|
}
|
||||||
try seen.put(gpa, try arena.dupe(u8, entry.name), entry.builtin);
|
if (@hasField(@TypeOf(builtin), "features")) {
|
||||||
|
const corrected_name = comptime if (std.mem.eql(u8, list_name, "x86_64")) "x86" else list_name;
|
||||||
|
const features = &@field(std.Target, corrected_name).all_features;
|
||||||
|
|
||||||
|
const feature_string = builtin.features orelse continue;
|
||||||
|
var it = std.mem.tokenizeAny(u8, std.mem.span(feature_string), "()|,");
|
||||||
|
|
||||||
|
outer: while (it.next()) |feature| {
|
||||||
|
for (features) |valid_feature| {
|
||||||
|
if (std.mem.eql(u8, feature, valid_feature.name)) continue :outer;
|
||||||
}
|
}
|
||||||
try std.testing.expectEqual(@as(usize, Builtin.data.len), seen.count());
|
std.debug.panic("unknown feature {s} on {t}\n", .{ feature, @as(list.Tag, @enumFromInt(index)) });
|
||||||
}
|
|
||||||
|
|
||||||
test "All builtins" {
|
|
||||||
var arena_state: std.heap.ArenaAllocator = .init(std.testing.allocator);
|
|
||||||
defer arena_state.deinit();
|
|
||||||
const arena = arena_state.allocator();
|
|
||||||
|
|
||||||
var comp = Compilation.init(std.testing.allocator, arena, undefined, std.fs.cwd());
|
|
||||||
defer comp.deinit();
|
|
||||||
|
|
||||||
try comp.type_store.initNamedTypes(&comp);
|
|
||||||
comp.type_store.va_list = try comp.type_store.va_list.decay(&comp);
|
|
||||||
|
|
||||||
var builtin_it = Iterator{};
|
|
||||||
while (builtin_it.next()) |entry| {
|
|
||||||
const name = try arena.dupe(u8, entry.name);
|
|
||||||
if (try comp.builtins.getOrCreate(&comp, name)) |func_ty| {
|
|
||||||
const get_again = (try comp.builtins.getOrCreate(&comp, name)).?;
|
|
||||||
const found_by_lookup = comp.builtins.lookup(name);
|
|
||||||
try std.testing.expectEqual(func_ty.builtin.tag, get_again.builtin.tag);
|
|
||||||
try std.testing.expectEqual(func_ty.builtin.tag, found_by_lookup.builtin.tag);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
test "Allocation failures" {
|
|
||||||
const Test = struct {
|
|
||||||
fn testOne(allocator: std.mem.Allocator) !void {
|
|
||||||
var arena_state: std.heap.ArenaAllocator = .init(allocator);
|
|
||||||
defer arena_state.deinit();
|
|
||||||
const arena = arena_state.allocator();
|
|
||||||
|
|
||||||
var comp = Compilation.init(allocator, arena, undefined, std.fs.cwd());
|
|
||||||
defer comp.deinit();
|
|
||||||
_ = try comp.generateBuiltinMacros(.include_system_defines);
|
|
||||||
|
|
||||||
const num_builtins = 40;
|
|
||||||
var builtin_it = Iterator{};
|
|
||||||
for (0..num_builtins) |_| {
|
|
||||||
const entry = builtin_it.next().?;
|
|
||||||
_ = try comp.builtins.getOrCreate(&comp, entry.name);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
|
||||||
|
|
||||||
try std.testing.checkAllAllocationFailures(std.testing.allocator, Test.testOne, .{});
|
|
||||||
}
|
|
||||||
|
|||||||
13191
lib/compiler/aro/aro/Builtins/Builtin.zig
vendored
13191
lib/compiler/aro/aro/Builtins/Builtin.zig
vendored
File diff suppressed because it is too large
Load Diff
@ -13,10 +13,10 @@ pub const Component = union(enum) {
|
|||||||
};
|
};
|
||||||
|
|
||||||
pub const ComponentIterator = struct {
|
pub const ComponentIterator = struct {
|
||||||
str: []const u8,
|
str: [*:0]const u8,
|
||||||
idx: usize,
|
idx: usize,
|
||||||
|
|
||||||
pub fn init(str: []const u8) ComponentIterator {
|
pub fn init(str: [*:0]const u8) ComponentIterator {
|
||||||
return .{
|
return .{
|
||||||
.str = str,
|
.str = str,
|
||||||
.idx = 0,
|
.idx = 0,
|
||||||
@ -30,8 +30,8 @@ pub const ComponentIterator = struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn next(self: *ComponentIterator) ?Component {
|
pub fn next(self: *ComponentIterator) ?Component {
|
||||||
if (self.idx == self.str.len) return null;
|
|
||||||
const c = self.str[self.idx];
|
const c = self.str[self.idx];
|
||||||
|
if (c == 0) return null;
|
||||||
self.idx += 1;
|
self.idx += 1;
|
||||||
switch (c) {
|
switch (c) {
|
||||||
'L' => {
|
'L' => {
|
||||||
@ -68,18 +68,14 @@ pub const ComponentIterator = struct {
|
|||||||
'z' => return .{ .spec = .z },
|
'z' => return .{ .spec = .z },
|
||||||
'w' => return .{ .spec = .w },
|
'w' => return .{ .spec = .w },
|
||||||
'F' => return .{ .spec = .F },
|
'F' => return .{ .spec = .F },
|
||||||
'G' => return .{ .spec = .G },
|
|
||||||
'H' => return .{ .spec = .H },
|
|
||||||
'M' => return .{ .spec = .M },
|
|
||||||
'a' => return .{ .spec = .a },
|
'a' => return .{ .spec = .a },
|
||||||
'A' => return .{ .spec = .A },
|
'A' => return .{ .spec = .A },
|
||||||
'V', 'q', 'E' => {
|
'V', 'E' => {
|
||||||
const start = self.idx;
|
const start = self.idx;
|
||||||
while (std.ascii.isDigit(self.str[self.idx])) : (self.idx += 1) {}
|
while (std.ascii.isDigit(self.str[self.idx])) : (self.idx += 1) {}
|
||||||
const count = std.fmt.parseUnsigned(u32, self.str[start..self.idx], 10) catch unreachable;
|
const count = std.fmt.parseUnsigned(u32, self.str[start..self.idx], 10) catch unreachable;
|
||||||
return switch (c) {
|
return switch (c) {
|
||||||
'V' => .{ .spec = .{ .V = count } },
|
'V' => .{ .spec = .{ .V = count } },
|
||||||
'q' => .{ .spec = .{ .q = count } },
|
|
||||||
'E' => .{ .spec = .{ .E = count } },
|
'E' => .{ .spec = .{ .E = count } },
|
||||||
else => unreachable,
|
else => unreachable,
|
||||||
};
|
};
|
||||||
@ -103,16 +99,12 @@ pub const ComponentIterator = struct {
|
|||||||
'p' => return .{ .spec = .p },
|
'p' => return .{ .spec = .p },
|
||||||
'.' => {
|
'.' => {
|
||||||
// can only appear at end of param string; indicates varargs function
|
// can only appear at end of param string; indicates varargs function
|
||||||
std.debug.assert(self.idx == self.str.len);
|
std.debug.assert(self.str[self.idx] == 0);
|
||||||
return null;
|
return null;
|
||||||
},
|
},
|
||||||
'!' => {
|
|
||||||
std.debug.assert(self.str.len == 1);
|
|
||||||
return .{ .spec = .@"!" };
|
|
||||||
},
|
|
||||||
|
|
||||||
'*' => {
|
'*' => {
|
||||||
if (self.idx < self.str.len and std.ascii.isDigit(self.str[self.idx])) {
|
if (std.ascii.isDigit(self.str[self.idx])) {
|
||||||
defer self.idx += 1;
|
defer self.idx += 1;
|
||||||
const addr_space = self.str[self.idx] - '0';
|
const addr_space = self.str[self.idx] - '0';
|
||||||
return .{ .suffix = .{ .@"*" = addr_space } };
|
return .{ .suffix = .{ .@"*" = addr_space } };
|
||||||
@ -123,6 +115,14 @@ pub const ComponentIterator = struct {
|
|||||||
'C' => return .{ .suffix = .C },
|
'C' => return .{ .suffix = .C },
|
||||||
'D' => return .{ .suffix = .D },
|
'D' => return .{ .suffix = .D },
|
||||||
'R' => return .{ .suffix = .R },
|
'R' => return .{ .suffix = .R },
|
||||||
|
'Q' => {
|
||||||
|
defer self.idx += 1;
|
||||||
|
switch (self.str[self.idx]) {
|
||||||
|
'a' => return .{ .spec = .{ .Q = .aarch64_svcount_t } },
|
||||||
|
'b' => return .{ .spec = .{ .Q = .amdgpu_buffer_rsrc_t } },
|
||||||
|
else => unreachable,
|
||||||
|
}
|
||||||
|
},
|
||||||
else => unreachable,
|
else => unreachable,
|
||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
@ -130,13 +130,13 @@ pub const ComponentIterator = struct {
|
|||||||
};
|
};
|
||||||
|
|
||||||
pub const TypeIterator = struct {
|
pub const TypeIterator = struct {
|
||||||
param_str: []const u8,
|
param_str: [*:0]const u8,
|
||||||
prefix: [4]Prefix,
|
prefix: [4]Prefix,
|
||||||
spec: Spec,
|
spec: Spec,
|
||||||
suffix: [4]Suffix,
|
suffix: [4]Suffix,
|
||||||
idx: usize,
|
idx: usize,
|
||||||
|
|
||||||
pub fn init(param_str: []const u8) TypeIterator {
|
pub fn init(param_str: [*:0]const u8) TypeIterator {
|
||||||
return .{
|
return .{
|
||||||
.param_str = param_str,
|
.param_str = param_str,
|
||||||
.prefix = undefined,
|
.prefix = undefined,
|
||||||
@ -176,7 +176,7 @@ pub const TypeIterator = struct {
|
|||||||
_ = it.next();
|
_ = it.next();
|
||||||
}
|
}
|
||||||
if (maybe_spec) |spec| {
|
if (maybe_spec) |spec| {
|
||||||
return TypeDescription{
|
return .{
|
||||||
.prefix = self.prefix[0..prefix_count],
|
.prefix = self.prefix[0..prefix_count],
|
||||||
.spec = spec,
|
.spec = spec,
|
||||||
.suffix = self.suffix[0..suffix_count],
|
.suffix = self.suffix[0..suffix_count],
|
||||||
@ -236,20 +236,17 @@ const Spec = union(enum) {
|
|||||||
w,
|
w,
|
||||||
/// constant CFString
|
/// constant CFString
|
||||||
F,
|
F,
|
||||||
/// id
|
|
||||||
G,
|
|
||||||
/// SEL
|
|
||||||
H,
|
|
||||||
/// struct objc_super
|
|
||||||
M,
|
|
||||||
/// __builtin_va_list
|
/// __builtin_va_list
|
||||||
a,
|
a,
|
||||||
/// "reference" to __builtin_va_list
|
/// "reference" to __builtin_va_list
|
||||||
A,
|
A,
|
||||||
/// Vector, followed by the number of elements and the base type.
|
/// Vector, followed by the number of elements and the base type.
|
||||||
V: u32,
|
V: u32,
|
||||||
/// Scalable vector, followed by the number of elements and the base type.
|
/// target builtin type, followed by a character to distinguish the builtin type
|
||||||
q: u32,
|
Q: enum {
|
||||||
|
aarch64_svcount_t,
|
||||||
|
amdgpu_buffer_rsrc_t,
|
||||||
|
},
|
||||||
/// ext_vector, followed by the number of elements and the base type.
|
/// ext_vector, followed by the number of elements and the base type.
|
||||||
E: u32,
|
E: u32,
|
||||||
/// _Complex, followed by the base type.
|
/// _Complex, followed by the base type.
|
||||||
@ -270,8 +267,6 @@ const Spec = union(enum) {
|
|||||||
K,
|
K,
|
||||||
/// pid_t
|
/// pid_t
|
||||||
p,
|
p,
|
||||||
/// Used to indicate a builtin with target-dependent param types. Must appear by itself
|
|
||||||
@"!",
|
|
||||||
};
|
};
|
||||||
|
|
||||||
const Suffix = union(enum) {
|
const Suffix = union(enum) {
|
||||||
|
|||||||
1150
lib/compiler/aro/aro/Builtins/aarch64.zig
vendored
Normal file
1150
lib/compiler/aro/aro/Builtins/aarch64.zig
vendored
Normal file
File diff suppressed because it is too large
Load Diff
2851
lib/compiler/aro/aro/Builtins/amdgcn.zig
vendored
Normal file
2851
lib/compiler/aro/aro/Builtins/amdgcn.zig
vendored
Normal file
File diff suppressed because it is too large
Load Diff
1076
lib/compiler/aro/aro/Builtins/arm.zig
vendored
Normal file
1076
lib/compiler/aro/aro/Builtins/arm.zig
vendored
Normal file
File diff suppressed because it is too large
Load Diff
231
lib/compiler/aro/aro/Builtins/bpf.zig
vendored
Normal file
231
lib/compiler/aro/aro/Builtins/bpf.zig
vendored
Normal file
@ -0,0 +1,231 @@
|
|||||||
|
//! Autogenerated by GenerateDef from src/aro/Builtins/bpf.def, do not edit
|
||||||
|
// zig fmt: off
|
||||||
|
|
||||||
|
const std = @import("std");
|
||||||
|
|
||||||
|
pub fn with(comptime Properties: type) type {
|
||||||
|
return struct {
|
||||||
|
|
||||||
|
/// Integer starting at 0 derived from the unique index,
|
||||||
|
/// corresponds with the data array index.
|
||||||
|
pub const Tag = enum(u16) { __builtin_btf_type_id,
|
||||||
|
__builtin_preserve_enum_value,
|
||||||
|
__builtin_preserve_field_info,
|
||||||
|
__builtin_preserve_type_info,
|
||||||
|
};
|
||||||
|
|
||||||
|
pub fn fromName(name: []const u8) ?Properties {
|
||||||
|
const data_index = tagFromName(name) orelse return null;
|
||||||
|
return data[@intFromEnum(data_index)];
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn tagFromName(name: []const u8) ?Tag {
|
||||||
|
const unique_index = uniqueIndex(name) orelse return null;
|
||||||
|
return @enumFromInt(unique_index - 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn fromTag(tag: Tag) Properties {
|
||||||
|
return data[@intFromEnum(tag)];
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn nameFromTagIntoBuf(tag: Tag, name_buf: []u8) []u8 {
|
||||||
|
std.debug.assert(name_buf.len >= longest_name);
|
||||||
|
const unique_index = @intFromEnum(tag) + 1;
|
||||||
|
return nameFromUniqueIndex(unique_index, name_buf);
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn nameFromTag(tag: Tag) NameBuf {
|
||||||
|
var name_buf: NameBuf = undefined;
|
||||||
|
const unique_index = @intFromEnum(tag) + 1;
|
||||||
|
const name = nameFromUniqueIndex(unique_index, &name_buf.buf);
|
||||||
|
name_buf.len = @intCast(name.len);
|
||||||
|
return name_buf;
|
||||||
|
}
|
||||||
|
|
||||||
|
pub const NameBuf = struct {
|
||||||
|
buf: [longest_name]u8 = undefined,
|
||||||
|
len: std.math.IntFittingRange(0, longest_name),
|
||||||
|
|
||||||
|
pub fn span(self: *const NameBuf) []const u8 {
|
||||||
|
return self.buf[0..self.len];
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
pub fn exists(name: []const u8) bool {
|
||||||
|
if (name.len < shortest_name or name.len > longest_name) return false;
|
||||||
|
|
||||||
|
var index: u16 = 0;
|
||||||
|
for (name) |c| {
|
||||||
|
index = findInList(dafsa[index].child_index, c) orelse return false;
|
||||||
|
}
|
||||||
|
return dafsa[index].end_of_word;
|
||||||
|
}
|
||||||
|
|
||||||
|
pub const shortest_name = 21;
|
||||||
|
pub const longest_name = 29;
|
||||||
|
|
||||||
|
/// Search siblings of `first_child_index` for the `char`
|
||||||
|
/// If found, returns the index of the node within the `dafsa` array.
|
||||||
|
/// Otherwise, returns `null`.
|
||||||
|
pub fn findInList(first_child_index: u16, char: u8) ?u16 {
|
||||||
|
@setEvalBranchQuota(8);
|
||||||
|
var index = first_child_index;
|
||||||
|
while (true) {
|
||||||
|
if (dafsa[index].char == char) return index;
|
||||||
|
if (dafsa[index].end_of_list) return null;
|
||||||
|
index += 1;
|
||||||
|
}
|
||||||
|
unreachable;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Returns a unique (minimal perfect hash) index (starting at 1) for the `name`,
|
||||||
|
/// or null if the name was not found.
|
||||||
|
pub fn uniqueIndex(name: []const u8) ?u16 {
|
||||||
|
if (name.len < shortest_name or name.len > longest_name) return null;
|
||||||
|
|
||||||
|
var index: u16 = 0;
|
||||||
|
var node_index: u16 = 0;
|
||||||
|
|
||||||
|
for (name) |c| {
|
||||||
|
const child_index = findInList(dafsa[node_index].child_index, c) orelse return null;
|
||||||
|
var sibling_index = dafsa[node_index].child_index;
|
||||||
|
while (true) {
|
||||||
|
const sibling_c = dafsa[sibling_index].char;
|
||||||
|
std.debug.assert(sibling_c != 0);
|
||||||
|
if (sibling_c < c) {
|
||||||
|
index += dafsa[sibling_index].number;
|
||||||
|
}
|
||||||
|
if (dafsa[sibling_index].end_of_list) break;
|
||||||
|
sibling_index += 1;
|
||||||
|
}
|
||||||
|
node_index = child_index;
|
||||||
|
if (dafsa[node_index].end_of_word) index += 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!dafsa[node_index].end_of_word) return null;
|
||||||
|
|
||||||
|
return index;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Returns a slice of `buf` with the name associated with the given `index`.
|
||||||
|
/// This function should only be called with an `index` that
|
||||||
|
/// is already known to exist within the `dafsa`, e.g. an index
|
||||||
|
/// returned from `uniqueIndex`.
|
||||||
|
pub fn nameFromUniqueIndex(index: u16, buf: []u8) []u8 {
|
||||||
|
std.debug.assert(index >= 1 and index <= data.len);
|
||||||
|
|
||||||
|
var node_index: u16 = 0;
|
||||||
|
var count: u16 = index;
|
||||||
|
var w = std.Io.Writer.fixed(buf);
|
||||||
|
|
||||||
|
while (true) {
|
||||||
|
var sibling_index = dafsa[node_index].child_index;
|
||||||
|
while (true) {
|
||||||
|
if (dafsa[sibling_index].number > 0 and dafsa[sibling_index].number < count) {
|
||||||
|
count -= dafsa[sibling_index].number;
|
||||||
|
} else {
|
||||||
|
w.writeByte(dafsa[sibling_index].char) catch unreachable;
|
||||||
|
node_index = sibling_index;
|
||||||
|
if (dafsa[node_index].end_of_word) {
|
||||||
|
count -= 1;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (dafsa[sibling_index].end_of_list) break;
|
||||||
|
sibling_index += 1;
|
||||||
|
}
|
||||||
|
if (count == 0) break;
|
||||||
|
}
|
||||||
|
|
||||||
|
return w.buffered();
|
||||||
|
}
|
||||||
|
|
||||||
|
const Node = packed struct {
|
||||||
|
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
|
||||||
|
/// allows calculating "a one-to-one correspondence between the integers 1 to L
|
||||||
|
/// (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: std.math.IntFittingRange(0, data.len),
|
||||||
|
/// If true, this node is the end of a valid builtin.
|
||||||
|
/// 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,
|
||||||
|
/// Index of the first child of this node.
|
||||||
|
child_index: u16,
|
||||||
|
};
|
||||||
|
|
||||||
|
const dafsa = [_]Node{
|
||||||
|
.{ .char = 0, .end_of_word = false, .end_of_list = true, .number = 0, .child_index = 1 },
|
||||||
|
.{ .char = '_', .end_of_word = false, .end_of_list = true, .number = 4, .child_index = 2 },
|
||||||
|
.{ .char = '_', .end_of_word = false, .end_of_list = true, .number = 4, .child_index = 3 },
|
||||||
|
.{ .char = 'b', .end_of_word = false, .end_of_list = true, .number = 4, .child_index = 4 },
|
||||||
|
.{ .char = 'u', .end_of_word = false, .end_of_list = true, .number = 4, .child_index = 5 },
|
||||||
|
.{ .char = 'i', .end_of_word = false, .end_of_list = true, .number = 4, .child_index = 6 },
|
||||||
|
.{ .char = 'l', .end_of_word = false, .end_of_list = true, .number = 4, .child_index = 7 },
|
||||||
|
.{ .char = 't', .end_of_word = false, .end_of_list = true, .number = 4, .child_index = 8 },
|
||||||
|
.{ .char = 'i', .end_of_word = false, .end_of_list = true, .number = 4, .child_index = 9 },
|
||||||
|
.{ .char = 'n', .end_of_word = false, .end_of_list = true, .number = 4, .child_index = 10 },
|
||||||
|
.{ .char = '_', .end_of_word = false, .end_of_list = true, .number = 4, .child_index = 11 },
|
||||||
|
.{ .char = 'b', .end_of_word = false, .end_of_list = false, .number = 1, .child_index = 13 },
|
||||||
|
.{ .char = 'p', .end_of_word = false, .end_of_list = true, .number = 3, .child_index = 14 },
|
||||||
|
.{ .char = 't', .end_of_word = false, .end_of_list = true, .number = 1, .child_index = 15 },
|
||||||
|
.{ .char = 'r', .end_of_word = false, .end_of_list = true, .number = 3, .child_index = 16 },
|
||||||
|
.{ .char = 'f', .end_of_word = false, .end_of_list = true, .number = 1, .child_index = 17 },
|
||||||
|
.{ .char = 'e', .end_of_word = false, .end_of_list = true, .number = 3, .child_index = 18 },
|
||||||
|
.{ .char = '_', .end_of_word = false, .end_of_list = true, .number = 1, .child_index = 19 },
|
||||||
|
.{ .char = 's', .end_of_word = false, .end_of_list = true, .number = 3, .child_index = 20 },
|
||||||
|
.{ .char = 't', .end_of_word = false, .end_of_list = true, .number = 1, .child_index = 21 },
|
||||||
|
.{ .char = 'e', .end_of_word = false, .end_of_list = true, .number = 3, .child_index = 22 },
|
||||||
|
.{ .char = 'y', .end_of_word = false, .end_of_list = true, .number = 1, .child_index = 23 },
|
||||||
|
.{ .char = 'r', .end_of_word = false, .end_of_list = true, .number = 3, .child_index = 24 },
|
||||||
|
.{ .char = 'p', .end_of_word = false, .end_of_list = true, .number = 1, .child_index = 25 },
|
||||||
|
.{ .char = 'v', .end_of_word = false, .end_of_list = true, .number = 3, .child_index = 26 },
|
||||||
|
.{ .char = 'e', .end_of_word = false, .end_of_list = true, .number = 1, .child_index = 27 },
|
||||||
|
.{ .char = 'e', .end_of_word = false, .end_of_list = true, .number = 3, .child_index = 28 },
|
||||||
|
.{ .char = '_', .end_of_word = false, .end_of_list = true, .number = 1, .child_index = 29 },
|
||||||
|
.{ .char = '_', .end_of_word = false, .end_of_list = true, .number = 3, .child_index = 30 },
|
||||||
|
.{ .char = 'i', .end_of_word = false, .end_of_list = true, .number = 1, .child_index = 33 },
|
||||||
|
.{ .char = 'e', .end_of_word = false, .end_of_list = false, .number = 1, .child_index = 34 },
|
||||||
|
.{ .char = 'f', .end_of_word = false, .end_of_list = false, .number = 1, .child_index = 35 },
|
||||||
|
.{ .char = 't', .end_of_word = false, .end_of_list = true, .number = 1, .child_index = 36 },
|
||||||
|
.{ .char = 'd', .end_of_word = true, .end_of_list = true, .number = 1, .child_index = 0 },
|
||||||
|
.{ .char = 'n', .end_of_word = false, .end_of_list = true, .number = 1, .child_index = 37 },
|
||||||
|
.{ .char = 'i', .end_of_word = false, .end_of_list = true, .number = 1, .child_index = 38 },
|
||||||
|
.{ .char = 'y', .end_of_word = false, .end_of_list = true, .number = 1, .child_index = 39 },
|
||||||
|
.{ .char = 'u', .end_of_word = false, .end_of_list = true, .number = 1, .child_index = 40 },
|
||||||
|
.{ .char = 'e', .end_of_word = false, .end_of_list = true, .number = 1, .child_index = 41 },
|
||||||
|
.{ .char = 'p', .end_of_word = false, .end_of_list = true, .number = 1, .child_index = 42 },
|
||||||
|
.{ .char = 'm', .end_of_word = false, .end_of_list = true, .number = 1, .child_index = 43 },
|
||||||
|
.{ .char = 'l', .end_of_word = false, .end_of_list = true, .number = 1, .child_index = 44 },
|
||||||
|
.{ .char = 'e', .end_of_word = false, .end_of_list = true, .number = 1, .child_index = 45 },
|
||||||
|
.{ .char = '_', .end_of_word = false, .end_of_list = true, .number = 1, .child_index = 46 },
|
||||||
|
.{ .char = 'd', .end_of_word = false, .end_of_list = true, .number = 1, .child_index = 45 },
|
||||||
|
.{ .char = '_', .end_of_word = false, .end_of_list = true, .number = 1, .child_index = 47 },
|
||||||
|
.{ .char = 'v', .end_of_word = false, .end_of_list = true, .number = 1, .child_index = 48 },
|
||||||
|
.{ .char = 'i', .end_of_word = false, .end_of_list = true, .number = 1, .child_index = 49 },
|
||||||
|
.{ .char = 'a', .end_of_word = false, .end_of_list = true, .number = 1, .child_index = 50 },
|
||||||
|
.{ .char = 'n', .end_of_word = false, .end_of_list = true, .number = 1, .child_index = 51 },
|
||||||
|
.{ .char = 'l', .end_of_word = false, .end_of_list = true, .number = 1, .child_index = 52 },
|
||||||
|
.{ .char = 'f', .end_of_word = false, .end_of_list = true, .number = 1, .child_index = 53 },
|
||||||
|
.{ .char = 'u', .end_of_word = false, .end_of_list = true, .number = 1, .child_index = 54 },
|
||||||
|
.{ .char = 'o', .end_of_word = true, .end_of_list = true, .number = 1, .child_index = 0 },
|
||||||
|
.{ .char = 'e', .end_of_word = true, .end_of_list = true, .number = 1, .child_index = 0 },
|
||||||
|
};
|
||||||
|
pub const data = blk: {
|
||||||
|
@setEvalBranchQuota(36);
|
||||||
|
break :blk [_]Properties{
|
||||||
|
.{ .param_str = "LUi.", .attributes = .{ .custom_typecheck = true } },
|
||||||
|
.{ .param_str = "Li.", .attributes = .{ .custom_typecheck = true } },
|
||||||
|
.{ .param_str = "Ui.", .attributes = .{ .custom_typecheck = true } },
|
||||||
|
.{ .param_str = "LUi.", .attributes = .{ .custom_typecheck = true } },
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
}
|
||||||
5527
lib/compiler/aro/aro/Builtins/common.zig
vendored
Normal file
5527
lib/compiler/aro/aro/Builtins/common.zig
vendored
Normal file
File diff suppressed because it is too large
Load Diff
11
lib/compiler/aro/aro/Builtins/eval.zig
vendored
11
lib/compiler/aro/aro/Builtins/eval.zig
vendored
@ -2,7 +2,6 @@ const std = @import("std");
|
|||||||
const backend = @import("../../backend.zig");
|
const backend = @import("../../backend.zig");
|
||||||
const Interner = backend.Interner;
|
const Interner = backend.Interner;
|
||||||
const Builtins = @import("../Builtins.zig");
|
const Builtins = @import("../Builtins.zig");
|
||||||
const Builtin = Builtins.Builtin;
|
|
||||||
const Parser = @import("../Parser.zig");
|
const Parser = @import("../Parser.zig");
|
||||||
const Tree = @import("../Tree.zig");
|
const Tree = @import("../Tree.zig");
|
||||||
const TypeStore = @import("../TypeStore.zig");
|
const TypeStore = @import("../TypeStore.zig");
|
||||||
@ -23,11 +22,11 @@ fn makeNan(comptime T: type, str: []const u8) T {
|
|||||||
return @bitCast(@as(UnsignedSameSize, bits) | @as(UnsignedSameSize, @bitCast(std.math.nan(T))));
|
return @bitCast(@as(UnsignedSameSize, bits) | @as(UnsignedSameSize, @bitCast(std.math.nan(T))));
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn eval(tag: Builtin.Tag, p: *Parser, args: []const Tree.Node.Index) !Value {
|
pub fn eval(expanded: Builtins.Expanded, p: *Parser, args: []const Tree.Node.Index) !Value {
|
||||||
const builtin = Builtin.fromTag(tag);
|
if (!expanded.attributes.const_evaluable) return .{};
|
||||||
if (!builtin.properties.attributes.const_evaluable) return .{};
|
|
||||||
|
|
||||||
switch (tag) {
|
switch (expanded.tag) {
|
||||||
|
.common => |tag| switch (tag) {
|
||||||
.__builtin_inff,
|
.__builtin_inff,
|
||||||
.__builtin_inf,
|
.__builtin_inf,
|
||||||
.__builtin_infl,
|
.__builtin_infl,
|
||||||
@ -82,6 +81,8 @@ pub fn eval(tag: Builtin.Tag, p: *Parser, args: []const Tree.Node.Index) !Value
|
|||||||
return Value.intern(p.comp, .{ .float = f });
|
return Value.intern(p.comp, .{ .float = f });
|
||||||
},
|
},
|
||||||
else => {},
|
else => {},
|
||||||
|
},
|
||||||
|
else => {},
|
||||||
}
|
}
|
||||||
return .{};
|
return .{};
|
||||||
}
|
}
|
||||||
|
|||||||
6500
lib/compiler/aro/aro/Builtins/hexagon.zig
vendored
Normal file
6500
lib/compiler/aro/aro/Builtins/hexagon.zig
vendored
Normal file
File diff suppressed because it is too large
Load Diff
3884
lib/compiler/aro/aro/Builtins/loongarch.zig
vendored
Normal file
3884
lib/compiler/aro/aro/Builtins/loongarch.zig
vendored
Normal file
File diff suppressed because it is too large
Load Diff
2110
lib/compiler/aro/aro/Builtins/mips.zig
vendored
Normal file
2110
lib/compiler/aro/aro/Builtins/mips.zig
vendored
Normal file
File diff suppressed because it is too large
Load Diff
3253
lib/compiler/aro/aro/Builtins/nvptx.zig
vendored
Normal file
3253
lib/compiler/aro/aro/Builtins/nvptx.zig
vendored
Normal file
File diff suppressed because it is too large
Load Diff
2491
lib/compiler/aro/aro/Builtins/powerpc.zig
vendored
Normal file
2491
lib/compiler/aro/aro/Builtins/powerpc.zig
vendored
Normal file
File diff suppressed because it is too large
Load Diff
@ -1,13 +1,5 @@
|
|||||||
const std = @import("std");
|
const std = @import("std");
|
||||||
|
|
||||||
const Properties = @This();
|
|
||||||
|
|
||||||
param_str: []const u8,
|
|
||||||
language: Language = .all_languages,
|
|
||||||
attributes: Attributes = Attributes{},
|
|
||||||
header: Header = .none,
|
|
||||||
target_set: TargetSet = TargetSet.initOne(.basic),
|
|
||||||
|
|
||||||
/// Header which must be included for a builtin to be available
|
/// Header which must be included for a builtin to be available
|
||||||
pub const Header = enum {
|
pub const Header = enum {
|
||||||
none,
|
none,
|
||||||
@ -41,6 +33,18 @@ pub const Header = enum {
|
|||||||
complex,
|
complex,
|
||||||
/// Blocks.h
|
/// Blocks.h
|
||||||
blocks,
|
blocks,
|
||||||
|
/// intrin.h
|
||||||
|
intrin,
|
||||||
|
/// immintrin.h
|
||||||
|
immintrin,
|
||||||
|
/// xmmintrin.h
|
||||||
|
xmmintrin,
|
||||||
|
/// emmintrin.h
|
||||||
|
emmintrin,
|
||||||
|
/// mmintrin.h
|
||||||
|
mmintrin,
|
||||||
|
/// arm_acle.h
|
||||||
|
arm_acle,
|
||||||
};
|
};
|
||||||
|
|
||||||
/// Languages in which a builtin is available
|
/// Languages in which a builtin is available
|
||||||
@ -49,6 +53,7 @@ pub const Language = enum {
|
|||||||
all_ms_languages,
|
all_ms_languages,
|
||||||
all_gnu_languages,
|
all_gnu_languages,
|
||||||
gnu_lang,
|
gnu_lang,
|
||||||
|
c23_lang,
|
||||||
};
|
};
|
||||||
|
|
||||||
pub const Attributes = packed struct {
|
pub const Attributes = packed struct {
|
||||||
@ -106,38 +111,7 @@ pub const Attributes = packed struct {
|
|||||||
const_evaluable: bool = false,
|
const_evaluable: bool = false,
|
||||||
};
|
};
|
||||||
|
|
||||||
pub const Target = enum {
|
pub fn isVarArgs(param_str: [*:0]const u8) bool {
|
||||||
/// Supported on all targets
|
const slice = std.mem.sliceTo(param_str, 0);
|
||||||
basic,
|
return slice[slice.len - 1] == '.';
|
||||||
aarch64,
|
|
||||||
aarch64_neon_sve_bridge,
|
|
||||||
aarch64_neon_sve_bridge_cg,
|
|
||||||
amdgpu,
|
|
||||||
arm,
|
|
||||||
bpf,
|
|
||||||
hexagon,
|
|
||||||
hexagon_dep,
|
|
||||||
hexagon_map_custom_dep,
|
|
||||||
loong_arch,
|
|
||||||
mips,
|
|
||||||
neon,
|
|
||||||
nvptx,
|
|
||||||
ppc,
|
|
||||||
riscv,
|
|
||||||
riscv_vector,
|
|
||||||
sve,
|
|
||||||
systemz,
|
|
||||||
ve,
|
|
||||||
vevl_gen,
|
|
||||||
webassembly,
|
|
||||||
x86,
|
|
||||||
x86_64,
|
|
||||||
xcore,
|
|
||||||
};
|
|
||||||
|
|
||||||
/// Targets for which a builtin is enabled
|
|
||||||
pub const TargetSet = std.enums.EnumSet(Target);
|
|
||||||
|
|
||||||
pub fn isVarArgs(properties: Properties) bool {
|
|
||||||
return properties.param_str[properties.param_str.len - 1] == '.';
|
|
||||||
}
|
}
|
||||||
469
lib/compiler/aro/aro/Builtins/riscv.zig
vendored
Normal file
469
lib/compiler/aro/aro/Builtins/riscv.zig
vendored
Normal file
@ -0,0 +1,469 @@
|
|||||||
|
//! Autogenerated by GenerateDef from src/aro/Builtins/riscv.def, do not edit
|
||||||
|
// zig fmt: off
|
||||||
|
|
||||||
|
const std = @import("std");
|
||||||
|
|
||||||
|
pub fn with(comptime Properties: type) type {
|
||||||
|
return struct {
|
||||||
|
|
||||||
|
/// Integer starting at 0 derived from the unique index,
|
||||||
|
/// corresponds with the data array index.
|
||||||
|
pub const Tag = enum(u16) { __builtin_riscv_aes32dsi,
|
||||||
|
__builtin_riscv_aes32dsmi,
|
||||||
|
__builtin_riscv_aes32esi,
|
||||||
|
__builtin_riscv_aes32esmi,
|
||||||
|
__builtin_riscv_aes64ds,
|
||||||
|
__builtin_riscv_aes64dsm,
|
||||||
|
__builtin_riscv_aes64es,
|
||||||
|
__builtin_riscv_aes64esm,
|
||||||
|
__builtin_riscv_aes64im,
|
||||||
|
__builtin_riscv_aes64ks1i,
|
||||||
|
__builtin_riscv_aes64ks2,
|
||||||
|
__builtin_riscv_brev8_32,
|
||||||
|
__builtin_riscv_brev8_64,
|
||||||
|
__builtin_riscv_clmul_32,
|
||||||
|
__builtin_riscv_clmul_64,
|
||||||
|
__builtin_riscv_clmulh_32,
|
||||||
|
__builtin_riscv_clmulh_64,
|
||||||
|
__builtin_riscv_clmulr_32,
|
||||||
|
__builtin_riscv_clmulr_64,
|
||||||
|
__builtin_riscv_clz_32,
|
||||||
|
__builtin_riscv_clz_64,
|
||||||
|
__builtin_riscv_ctz_32,
|
||||||
|
__builtin_riscv_ctz_64,
|
||||||
|
__builtin_riscv_cv_alu_addN,
|
||||||
|
__builtin_riscv_cv_alu_addRN,
|
||||||
|
__builtin_riscv_cv_alu_adduN,
|
||||||
|
__builtin_riscv_cv_alu_adduRN,
|
||||||
|
__builtin_riscv_cv_alu_clip,
|
||||||
|
__builtin_riscv_cv_alu_clipu,
|
||||||
|
__builtin_riscv_cv_alu_extbs,
|
||||||
|
__builtin_riscv_cv_alu_extbz,
|
||||||
|
__builtin_riscv_cv_alu_exths,
|
||||||
|
__builtin_riscv_cv_alu_exthz,
|
||||||
|
__builtin_riscv_cv_alu_sle,
|
||||||
|
__builtin_riscv_cv_alu_sleu,
|
||||||
|
__builtin_riscv_cv_alu_subN,
|
||||||
|
__builtin_riscv_cv_alu_subRN,
|
||||||
|
__builtin_riscv_cv_alu_subuN,
|
||||||
|
__builtin_riscv_cv_alu_subuRN,
|
||||||
|
__builtin_riscv_ntl_load,
|
||||||
|
__builtin_riscv_ntl_store,
|
||||||
|
__builtin_riscv_orc_b_32,
|
||||||
|
__builtin_riscv_orc_b_64,
|
||||||
|
__builtin_riscv_pause,
|
||||||
|
__builtin_riscv_sha256sig0,
|
||||||
|
__builtin_riscv_sha256sig1,
|
||||||
|
__builtin_riscv_sha256sum0,
|
||||||
|
__builtin_riscv_sha256sum1,
|
||||||
|
__builtin_riscv_sha512sig0,
|
||||||
|
__builtin_riscv_sha512sig0h,
|
||||||
|
__builtin_riscv_sha512sig0l,
|
||||||
|
__builtin_riscv_sha512sig1,
|
||||||
|
__builtin_riscv_sha512sig1h,
|
||||||
|
__builtin_riscv_sha512sig1l,
|
||||||
|
__builtin_riscv_sha512sum0,
|
||||||
|
__builtin_riscv_sha512sum0r,
|
||||||
|
__builtin_riscv_sha512sum1,
|
||||||
|
__builtin_riscv_sha512sum1r,
|
||||||
|
__builtin_riscv_sm3p0,
|
||||||
|
__builtin_riscv_sm3p1,
|
||||||
|
__builtin_riscv_sm4ed,
|
||||||
|
__builtin_riscv_sm4ks,
|
||||||
|
__builtin_riscv_unzip_32,
|
||||||
|
__builtin_riscv_xperm4_32,
|
||||||
|
__builtin_riscv_xperm4_64,
|
||||||
|
__builtin_riscv_xperm8_32,
|
||||||
|
__builtin_riscv_xperm8_64,
|
||||||
|
__builtin_riscv_zip_32,
|
||||||
|
};
|
||||||
|
|
||||||
|
pub fn fromName(name: []const u8) ?Properties {
|
||||||
|
const data_index = tagFromName(name) orelse return null;
|
||||||
|
return data[@intFromEnum(data_index)];
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn tagFromName(name: []const u8) ?Tag {
|
||||||
|
const unique_index = uniqueIndex(name) orelse return null;
|
||||||
|
return @enumFromInt(unique_index - 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn fromTag(tag: Tag) Properties {
|
||||||
|
return data[@intFromEnum(tag)];
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn nameFromTagIntoBuf(tag: Tag, name_buf: []u8) []u8 {
|
||||||
|
std.debug.assert(name_buf.len >= longest_name);
|
||||||
|
const unique_index = @intFromEnum(tag) + 1;
|
||||||
|
return nameFromUniqueIndex(unique_index, name_buf);
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn nameFromTag(tag: Tag) NameBuf {
|
||||||
|
var name_buf: NameBuf = undefined;
|
||||||
|
const unique_index = @intFromEnum(tag) + 1;
|
||||||
|
const name = nameFromUniqueIndex(unique_index, &name_buf.buf);
|
||||||
|
name_buf.len = @intCast(name.len);
|
||||||
|
return name_buf;
|
||||||
|
}
|
||||||
|
|
||||||
|
pub const NameBuf = struct {
|
||||||
|
buf: [longest_name]u8 = undefined,
|
||||||
|
len: std.math.IntFittingRange(0, longest_name),
|
||||||
|
|
||||||
|
pub fn span(self: *const NameBuf) []const u8 {
|
||||||
|
return self.buf[0..self.len];
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
pub fn exists(name: []const u8) bool {
|
||||||
|
if (name.len < shortest_name or name.len > longest_name) return false;
|
||||||
|
|
||||||
|
var index: u16 = 0;
|
||||||
|
for (name) |c| {
|
||||||
|
index = findInList(dafsa[index].child_index, c) orelse return false;
|
||||||
|
}
|
||||||
|
return dafsa[index].end_of_word;
|
||||||
|
}
|
||||||
|
|
||||||
|
pub const shortest_name = 21;
|
||||||
|
pub const longest_name = 29;
|
||||||
|
|
||||||
|
/// Search siblings of `first_child_index` for the `char`
|
||||||
|
/// If found, returns the index of the node within the `dafsa` array.
|
||||||
|
/// Otherwise, returns `null`.
|
||||||
|
pub fn findInList(first_child_index: u16, char: u8) ?u16 {
|
||||||
|
@setEvalBranchQuota(136);
|
||||||
|
var index = first_child_index;
|
||||||
|
while (true) {
|
||||||
|
if (dafsa[index].char == char) return index;
|
||||||
|
if (dafsa[index].end_of_list) return null;
|
||||||
|
index += 1;
|
||||||
|
}
|
||||||
|
unreachable;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Returns a unique (minimal perfect hash) index (starting at 1) for the `name`,
|
||||||
|
/// or null if the name was not found.
|
||||||
|
pub fn uniqueIndex(name: []const u8) ?u16 {
|
||||||
|
if (name.len < shortest_name or name.len > longest_name) return null;
|
||||||
|
|
||||||
|
var index: u16 = 0;
|
||||||
|
var node_index: u16 = 0;
|
||||||
|
|
||||||
|
for (name) |c| {
|
||||||
|
const child_index = findInList(dafsa[node_index].child_index, c) orelse return null;
|
||||||
|
var sibling_index = dafsa[node_index].child_index;
|
||||||
|
while (true) {
|
||||||
|
const sibling_c = dafsa[sibling_index].char;
|
||||||
|
std.debug.assert(sibling_c != 0);
|
||||||
|
if (sibling_c < c) {
|
||||||
|
index += dafsa[sibling_index].number;
|
||||||
|
}
|
||||||
|
if (dafsa[sibling_index].end_of_list) break;
|
||||||
|
sibling_index += 1;
|
||||||
|
}
|
||||||
|
node_index = child_index;
|
||||||
|
if (dafsa[node_index].end_of_word) index += 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!dafsa[node_index].end_of_word) return null;
|
||||||
|
|
||||||
|
return index;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Returns a slice of `buf` with the name associated with the given `index`.
|
||||||
|
/// This function should only be called with an `index` that
|
||||||
|
/// is already known to exist within the `dafsa`, e.g. an index
|
||||||
|
/// returned from `uniqueIndex`.
|
||||||
|
pub fn nameFromUniqueIndex(index: u16, buf: []u8) []u8 {
|
||||||
|
std.debug.assert(index >= 1 and index <= data.len);
|
||||||
|
|
||||||
|
var node_index: u16 = 0;
|
||||||
|
var count: u16 = index;
|
||||||
|
var w = std.Io.Writer.fixed(buf);
|
||||||
|
|
||||||
|
while (true) {
|
||||||
|
var sibling_index = dafsa[node_index].child_index;
|
||||||
|
while (true) {
|
||||||
|
if (dafsa[sibling_index].number > 0 and dafsa[sibling_index].number < count) {
|
||||||
|
count -= dafsa[sibling_index].number;
|
||||||
|
} else {
|
||||||
|
w.writeByte(dafsa[sibling_index].char) catch unreachable;
|
||||||
|
node_index = sibling_index;
|
||||||
|
if (dafsa[node_index].end_of_word) {
|
||||||
|
count -= 1;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (dafsa[sibling_index].end_of_list) break;
|
||||||
|
sibling_index += 1;
|
||||||
|
}
|
||||||
|
if (count == 0) break;
|
||||||
|
}
|
||||||
|
|
||||||
|
return w.buffered();
|
||||||
|
}
|
||||||
|
|
||||||
|
const Node = packed struct {
|
||||||
|
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
|
||||||
|
/// allows calculating "a one-to-one correspondence between the integers 1 to L
|
||||||
|
/// (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: std.math.IntFittingRange(0, data.len),
|
||||||
|
/// If true, this node is the end of a valid builtin.
|
||||||
|
/// 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,
|
||||||
|
/// Index of the first child of this node.
|
||||||
|
child_index: u16,
|
||||||
|
};
|
||||||
|
|
||||||
|
const dafsa = [_]Node{
|
||||||
|
.{ .char = 0, .end_of_word = false, .end_of_list = true, .number = 0, .child_index = 1 },
|
||||||
|
.{ .char = '_', .end_of_word = false, .end_of_list = true, .number = 68, .child_index = 2 },
|
||||||
|
.{ .char = '_', .end_of_word = false, .end_of_list = true, .number = 68, .child_index = 3 },
|
||||||
|
.{ .char = 'b', .end_of_word = false, .end_of_list = true, .number = 68, .child_index = 4 },
|
||||||
|
.{ .char = 'u', .end_of_word = false, .end_of_list = true, .number = 68, .child_index = 5 },
|
||||||
|
.{ .char = 'i', .end_of_word = false, .end_of_list = true, .number = 68, .child_index = 6 },
|
||||||
|
.{ .char = 'l', .end_of_word = false, .end_of_list = true, .number = 68, .child_index = 7 },
|
||||||
|
.{ .char = 't', .end_of_word = false, .end_of_list = true, .number = 68, .child_index = 8 },
|
||||||
|
.{ .char = 'i', .end_of_word = false, .end_of_list = true, .number = 68, .child_index = 9 },
|
||||||
|
.{ .char = 'n', .end_of_word = false, .end_of_list = true, .number = 68, .child_index = 10 },
|
||||||
|
.{ .char = '_', .end_of_word = false, .end_of_list = true, .number = 68, .child_index = 11 },
|
||||||
|
.{ .char = 'r', .end_of_word = false, .end_of_list = true, .number = 68, .child_index = 12 },
|
||||||
|
.{ .char = 'i', .end_of_word = false, .end_of_list = true, .number = 68, .child_index = 13 },
|
||||||
|
.{ .char = 's', .end_of_word = false, .end_of_list = true, .number = 68, .child_index = 14 },
|
||||||
|
.{ .char = 'c', .end_of_word = false, .end_of_list = true, .number = 68, .child_index = 15 },
|
||||||
|
.{ .char = 'v', .end_of_word = false, .end_of_list = true, .number = 68, .child_index = 16 },
|
||||||
|
.{ .char = '_', .end_of_word = false, .end_of_list = true, .number = 68, .child_index = 17 },
|
||||||
|
.{ .char = 'a', .end_of_word = false, .end_of_list = false, .number = 11, .child_index = 27 },
|
||||||
|
.{ .char = 'b', .end_of_word = false, .end_of_list = false, .number = 2, .child_index = 28 },
|
||||||
|
.{ .char = 'c', .end_of_word = false, .end_of_list = false, .number = 26, .child_index = 29 },
|
||||||
|
.{ .char = 'n', .end_of_word = false, .end_of_list = false, .number = 2, .child_index = 32 },
|
||||||
|
.{ .char = 'o', .end_of_word = false, .end_of_list = false, .number = 2, .child_index = 33 },
|
||||||
|
.{ .char = 'p', .end_of_word = false, .end_of_list = false, .number = 1, .child_index = 34 },
|
||||||
|
.{ .char = 's', .end_of_word = false, .end_of_list = false, .number = 18, .child_index = 35 },
|
||||||
|
.{ .char = 'u', .end_of_word = false, .end_of_list = false, .number = 1, .child_index = 37 },
|
||||||
|
.{ .char = 'x', .end_of_word = false, .end_of_list = false, .number = 4, .child_index = 38 },
|
||||||
|
.{ .char = 'z', .end_of_word = false, .end_of_list = true, .number = 1, .child_index = 39 },
|
||||||
|
.{ .char = 'e', .end_of_word = false, .end_of_list = true, .number = 11, .child_index = 40 },
|
||||||
|
.{ .char = 'r', .end_of_word = false, .end_of_list = true, .number = 2, .child_index = 41 },
|
||||||
|
.{ .char = 'l', .end_of_word = false, .end_of_list = false, .number = 8, .child_index = 42 },
|
||||||
|
.{ .char = 't', .end_of_word = false, .end_of_list = false, .number = 2, .child_index = 44 },
|
||||||
|
.{ .char = 'v', .end_of_word = false, .end_of_list = true, .number = 16, .child_index = 45 },
|
||||||
|
.{ .char = 't', .end_of_word = false, .end_of_list = true, .number = 2, .child_index = 46 },
|
||||||
|
.{ .char = 'r', .end_of_word = false, .end_of_list = true, .number = 2, .child_index = 47 },
|
||||||
|
.{ .char = 'a', .end_of_word = false, .end_of_list = true, .number = 1, .child_index = 48 },
|
||||||
|
.{ .char = 'h', .end_of_word = false, .end_of_list = false, .number = 14, .child_index = 49 },
|
||||||
|
.{ .char = 'm', .end_of_word = false, .end_of_list = true, .number = 4, .child_index = 50 },
|
||||||
|
.{ .char = 'n', .end_of_word = false, .end_of_list = true, .number = 1, .child_index = 52 },
|
||||||
|
.{ .char = 'p', .end_of_word = false, .end_of_list = true, .number = 4, .child_index = 53 },
|
||||||
|
.{ .char = 'i', .end_of_word = false, .end_of_list = true, .number = 1, .child_index = 54 },
|
||||||
|
.{ .char = 's', .end_of_word = false, .end_of_list = true, .number = 11, .child_index = 55 },
|
||||||
|
.{ .char = 'e', .end_of_word = false, .end_of_list = true, .number = 2, .child_index = 57 },
|
||||||
|
.{ .char = 'm', .end_of_word = false, .end_of_list = false, .number = 6, .child_index = 58 },
|
||||||
|
.{ .char = 'z', .end_of_word = false, .end_of_list = true, .number = 2, .child_index = 59 },
|
||||||
|
.{ .char = 'z', .end_of_word = false, .end_of_list = true, .number = 2, .child_index = 59 },
|
||||||
|
.{ .char = '_', .end_of_word = false, .end_of_list = true, .number = 16, .child_index = 60 },
|
||||||
|
.{ .char = 'l', .end_of_word = false, .end_of_list = true, .number = 2, .child_index = 61 },
|
||||||
|
.{ .char = 'c', .end_of_word = false, .end_of_list = true, .number = 2, .child_index = 62 },
|
||||||
|
.{ .char = 'u', .end_of_word = false, .end_of_list = true, .number = 1, .child_index = 63 },
|
||||||
|
.{ .char = 'a', .end_of_word = false, .end_of_list = true, .number = 14, .child_index = 64 },
|
||||||
|
.{ .char = '3', .end_of_word = false, .end_of_list = false, .number = 2, .child_index = 66 },
|
||||||
|
.{ .char = '4', .end_of_word = false, .end_of_list = true, .number = 2, .child_index = 67 },
|
||||||
|
.{ .char = 'z', .end_of_word = false, .end_of_list = true, .number = 1, .child_index = 39 },
|
||||||
|
.{ .char = 'e', .end_of_word = false, .end_of_list = true, .number = 4, .child_index = 69 },
|
||||||
|
.{ .char = 'p', .end_of_word = false, .end_of_list = true, .number = 1, .child_index = 70 },
|
||||||
|
.{ .char = '3', .end_of_word = false, .end_of_list = false, .number = 4, .child_index = 71 },
|
||||||
|
.{ .char = '6', .end_of_word = false, .end_of_list = true, .number = 7, .child_index = 72 },
|
||||||
|
.{ .char = 'v', .end_of_word = false, .end_of_list = true, .number = 2, .child_index = 73 },
|
||||||
|
.{ .char = 'u', .end_of_word = false, .end_of_list = true, .number = 6, .child_index = 74 },
|
||||||
|
.{ .char = '_', .end_of_word = false, .end_of_list = true, .number = 2, .child_index = 75 },
|
||||||
|
.{ .char = 'a', .end_of_word = false, .end_of_list = true, .number = 16, .child_index = 77 },
|
||||||
|
.{ .char = '_', .end_of_word = false, .end_of_list = true, .number = 2, .child_index = 78 },
|
||||||
|
.{ .char = '_', .end_of_word = false, .end_of_list = true, .number = 2, .child_index = 80 },
|
||||||
|
.{ .char = 's', .end_of_word = false, .end_of_list = true, .number = 1, .child_index = 81 },
|
||||||
|
.{ .char = '2', .end_of_word = false, .end_of_list = false, .number = 4, .child_index = 82 },
|
||||||
|
.{ .char = '5', .end_of_word = false, .end_of_list = true, .number = 10, .child_index = 83 },
|
||||||
|
.{ .char = 'p', .end_of_word = false, .end_of_list = true, .number = 2, .child_index = 84 },
|
||||||
|
.{ .char = 'e', .end_of_word = false, .end_of_list = false, .number = 1, .child_index = 86 },
|
||||||
|
.{ .char = 'k', .end_of_word = false, .end_of_list = true, .number = 1, .child_index = 87 },
|
||||||
|
.{ .char = 'r', .end_of_word = false, .end_of_list = true, .number = 4, .child_index = 88 },
|
||||||
|
.{ .char = '_', .end_of_word = false, .end_of_list = true, .number = 1, .child_index = 89 },
|
||||||
|
.{ .char = '2', .end_of_word = false, .end_of_list = true, .number = 4, .child_index = 90 },
|
||||||
|
.{ .char = '4', .end_of_word = false, .end_of_list = true, .number = 7, .child_index = 92 },
|
||||||
|
.{ .char = '8', .end_of_word = false, .end_of_list = true, .number = 2, .child_index = 59 },
|
||||||
|
.{ .char = 'l', .end_of_word = false, .end_of_list = true, .number = 6, .child_index = 96 },
|
||||||
|
.{ .char = '3', .end_of_word = false, .end_of_list = false, .number = 1, .child_index = 99 },
|
||||||
|
.{ .char = '6', .end_of_word = false, .end_of_list = true, .number = 1, .child_index = 100 },
|
||||||
|
.{ .char = 'l', .end_of_word = false, .end_of_list = true, .number = 16, .child_index = 101 },
|
||||||
|
.{ .char = 'l', .end_of_word = false, .end_of_list = false, .number = 1, .child_index = 102 },
|
||||||
|
.{ .char = 's', .end_of_word = false, .end_of_list = true, .number = 1, .child_index = 103 },
|
||||||
|
.{ .char = 'b', .end_of_word = false, .end_of_list = true, .number = 2, .child_index = 59 },
|
||||||
|
.{ .char = 'e', .end_of_word = true, .end_of_list = true, .number = 1, .child_index = 0 },
|
||||||
|
.{ .char = '5', .end_of_word = false, .end_of_list = true, .number = 4, .child_index = 104 },
|
||||||
|
.{ .char = '1', .end_of_word = false, .end_of_list = true, .number = 10, .child_index = 105 },
|
||||||
|
.{ .char = '0', .end_of_word = true, .end_of_list = false, .number = 1, .child_index = 0 },
|
||||||
|
.{ .char = '1', .end_of_word = true, .end_of_list = true, .number = 1, .child_index = 0 },
|
||||||
|
.{ .char = 'd', .end_of_word = true, .end_of_list = true, .number = 1, .child_index = 0 },
|
||||||
|
.{ .char = 's', .end_of_word = true, .end_of_list = true, .number = 1, .child_index = 0 },
|
||||||
|
.{ .char = 'm', .end_of_word = false, .end_of_list = true, .number = 4, .child_index = 106 },
|
||||||
|
.{ .char = '3', .end_of_word = false, .end_of_list = true, .number = 1, .child_index = 99 },
|
||||||
|
.{ .char = 'd', .end_of_word = false, .end_of_list = false, .number = 2, .child_index = 108 },
|
||||||
|
.{ .char = 'e', .end_of_word = false, .end_of_list = true, .number = 2, .child_index = 108 },
|
||||||
|
.{ .char = 'd', .end_of_word = false, .end_of_list = false, .number = 2, .child_index = 109 },
|
||||||
|
.{ .char = 'e', .end_of_word = false, .end_of_list = false, .number = 2, .child_index = 109 },
|
||||||
|
.{ .char = 'i', .end_of_word = false, .end_of_list = false, .number = 1, .child_index = 110 },
|
||||||
|
.{ .char = 'k', .end_of_word = false, .end_of_list = true, .number = 2, .child_index = 111 },
|
||||||
|
.{ .char = '_', .end_of_word = false, .end_of_list = false, .number = 2, .child_index = 75 },
|
||||||
|
.{ .char = 'h', .end_of_word = false, .end_of_list = false, .number = 2, .child_index = 59 },
|
||||||
|
.{ .char = 'r', .end_of_word = false, .end_of_list = true, .number = 2, .child_index = 59 },
|
||||||
|
.{ .char = '2', .end_of_word = true, .end_of_list = true, .number = 1, .child_index = 0 },
|
||||||
|
.{ .char = '4', .end_of_word = true, .end_of_list = true, .number = 1, .child_index = 0 },
|
||||||
|
.{ .char = 'u', .end_of_word = false, .end_of_list = true, .number = 16, .child_index = 112 },
|
||||||
|
.{ .char = 'o', .end_of_word = false, .end_of_list = true, .number = 1, .child_index = 113 },
|
||||||
|
.{ .char = 't', .end_of_word = false, .end_of_list = true, .number = 1, .child_index = 114 },
|
||||||
|
.{ .char = '6', .end_of_word = false, .end_of_list = true, .number = 4, .child_index = 115 },
|
||||||
|
.{ .char = '2', .end_of_word = false, .end_of_list = true, .number = 10, .child_index = 116 },
|
||||||
|
.{ .char = '4', .end_of_word = false, .end_of_list = false, .number = 2, .child_index = 59 },
|
||||||
|
.{ .char = '8', .end_of_word = false, .end_of_list = true, .number = 2, .child_index = 59 },
|
||||||
|
.{ .char = 's', .end_of_word = false, .end_of_list = true, .number = 2, .child_index = 117 },
|
||||||
|
.{ .char = 's', .end_of_word = true, .end_of_list = true, .number = 2, .child_index = 119 },
|
||||||
|
.{ .char = 'm', .end_of_word = true, .end_of_list = true, .number = 1, .child_index = 0 },
|
||||||
|
.{ .char = 's', .end_of_word = false, .end_of_list = true, .number = 2, .child_index = 120 },
|
||||||
|
.{ .char = '_', .end_of_word = false, .end_of_list = true, .number = 16, .child_index = 122 },
|
||||||
|
.{ .char = 'a', .end_of_word = false, .end_of_list = true, .number = 1, .child_index = 86 },
|
||||||
|
.{ .char = 'o', .end_of_word = false, .end_of_list = true, .number = 1, .child_index = 126 },
|
||||||
|
.{ .char = 's', .end_of_word = false, .end_of_list = true, .number = 4, .child_index = 127 },
|
||||||
|
.{ .char = 's', .end_of_word = false, .end_of_list = true, .number = 10, .child_index = 129 },
|
||||||
|
.{ .char = 'i', .end_of_word = true, .end_of_list = false, .number = 1, .child_index = 0 },
|
||||||
|
.{ .char = 'm', .end_of_word = false, .end_of_list = true, .number = 1, .child_index = 131 },
|
||||||
|
.{ .char = 'm', .end_of_word = true, .end_of_list = true, .number = 1, .child_index = 0 },
|
||||||
|
.{ .char = '1', .end_of_word = false, .end_of_list = false, .number = 1, .child_index = 131 },
|
||||||
|
.{ .char = '2', .end_of_word = true, .end_of_list = true, .number = 1, .child_index = 0 },
|
||||||
|
.{ .char = 'a', .end_of_word = false, .end_of_list = false, .number = 4, .child_index = 132 },
|
||||||
|
.{ .char = 'c', .end_of_word = false, .end_of_list = false, .number = 2, .child_index = 133 },
|
||||||
|
.{ .char = 'e', .end_of_word = false, .end_of_list = false, .number = 4, .child_index = 134 },
|
||||||
|
.{ .char = 's', .end_of_word = false, .end_of_list = true, .number = 6, .child_index = 135 },
|
||||||
|
.{ .char = 'r', .end_of_word = false, .end_of_list = true, .number = 1, .child_index = 81 },
|
||||||
|
.{ .char = 'i', .end_of_word = false, .end_of_list = false, .number = 2, .child_index = 137 },
|
||||||
|
.{ .char = 'u', .end_of_word = false, .end_of_list = true, .number = 2, .child_index = 138 },
|
||||||
|
.{ .char = 'i', .end_of_word = false, .end_of_list = false, .number = 6, .child_index = 139 },
|
||||||
|
.{ .char = 'u', .end_of_word = false, .end_of_list = true, .number = 4, .child_index = 140 },
|
||||||
|
.{ .char = 'i', .end_of_word = true, .end_of_list = true, .number = 1, .child_index = 0 },
|
||||||
|
.{ .char = 'd', .end_of_word = false, .end_of_list = true, .number = 4, .child_index = 141 },
|
||||||
|
.{ .char = 'l', .end_of_word = false, .end_of_list = true, .number = 2, .child_index = 142 },
|
||||||
|
.{ .char = 'x', .end_of_word = false, .end_of_list = true, .number = 4, .child_index = 143 },
|
||||||
|
.{ .char = 'l', .end_of_word = false, .end_of_list = false, .number = 2, .child_index = 144 },
|
||||||
|
.{ .char = 'u', .end_of_word = false, .end_of_list = true, .number = 4, .child_index = 145 },
|
||||||
|
.{ .char = 'g', .end_of_word = false, .end_of_list = true, .number = 2, .child_index = 84 },
|
||||||
|
.{ .char = 'm', .end_of_word = false, .end_of_list = true, .number = 2, .child_index = 84 },
|
||||||
|
.{ .char = 'g', .end_of_word = false, .end_of_list = true, .number = 6, .child_index = 146 },
|
||||||
|
.{ .char = 'm', .end_of_word = false, .end_of_list = true, .number = 4, .child_index = 148 },
|
||||||
|
.{ .char = 'd', .end_of_word = false, .end_of_list = true, .number = 4, .child_index = 150 },
|
||||||
|
.{ .char = 'i', .end_of_word = false, .end_of_list = true, .number = 2, .child_index = 153 },
|
||||||
|
.{ .char = 't', .end_of_word = false, .end_of_list = true, .number = 4, .child_index = 154 },
|
||||||
|
.{ .char = 'e', .end_of_word = true, .end_of_list = true, .number = 2, .child_index = 156 },
|
||||||
|
.{ .char = 'b', .end_of_word = false, .end_of_list = true, .number = 4, .child_index = 150 },
|
||||||
|
.{ .char = '0', .end_of_word = true, .end_of_list = false, .number = 3, .child_index = 157 },
|
||||||
|
.{ .char = '1', .end_of_word = true, .end_of_list = true, .number = 3, .child_index = 157 },
|
||||||
|
.{ .char = '0', .end_of_word = true, .end_of_list = false, .number = 2, .child_index = 159 },
|
||||||
|
.{ .char = '1', .end_of_word = true, .end_of_list = true, .number = 2, .child_index = 159 },
|
||||||
|
.{ .char = 'N', .end_of_word = true, .end_of_list = false, .number = 1, .child_index = 0 },
|
||||||
|
.{ .char = 'R', .end_of_word = false, .end_of_list = false, .number = 1, .child_index = 160 },
|
||||||
|
.{ .char = 'u', .end_of_word = false, .end_of_list = true, .number = 2, .child_index = 161 },
|
||||||
|
.{ .char = 'p', .end_of_word = true, .end_of_list = true, .number = 2, .child_index = 156 },
|
||||||
|
.{ .char = 'b', .end_of_word = false, .end_of_list = false, .number = 2, .child_index = 163 },
|
||||||
|
.{ .char = 'h', .end_of_word = false, .end_of_list = true, .number = 2, .child_index = 163 },
|
||||||
|
.{ .char = 'u', .end_of_word = true, .end_of_list = true, .number = 1, .child_index = 0 },
|
||||||
|
.{ .char = 'h', .end_of_word = true, .end_of_list = false, .number = 1, .child_index = 0 },
|
||||||
|
.{ .char = 'l', .end_of_word = true, .end_of_list = true, .number = 1, .child_index = 0 },
|
||||||
|
.{ .char = 'r', .end_of_word = true, .end_of_list = true, .number = 1, .child_index = 0 },
|
||||||
|
.{ .char = 'N', .end_of_word = true, .end_of_list = true, .number = 1, .child_index = 0 },
|
||||||
|
.{ .char = 'N', .end_of_word = true, .end_of_list = false, .number = 1, .child_index = 0 },
|
||||||
|
.{ .char = 'R', .end_of_word = false, .end_of_list = true, .number = 1, .child_index = 160 },
|
||||||
|
.{ .char = 's', .end_of_word = true, .end_of_list = false, .number = 1, .child_index = 0 },
|
||||||
|
.{ .char = 'z', .end_of_word = true, .end_of_list = true, .number = 1, .child_index = 0 },
|
||||||
|
};
|
||||||
|
pub const data = blk: {
|
||||||
|
@setEvalBranchQuota(612);
|
||||||
|
break :blk [_]Properties{
|
||||||
|
.{ .param_str = "UiUiUiIUi", .features = "zknd,32bit", .attributes = .{ .@"const" = true } },
|
||||||
|
.{ .param_str = "UiUiUiIUi", .features = "zknd,32bit", .attributes = .{ .@"const" = true } },
|
||||||
|
.{ .param_str = "UiUiUiIUi", .features = "zkne,32bit", .attributes = .{ .@"const" = true } },
|
||||||
|
.{ .param_str = "UiUiUiIUi", .features = "zkne,32bit", .attributes = .{ .@"const" = true } },
|
||||||
|
.{ .param_str = "UWiUWiUWi", .features = "zknd,64bit", .attributes = .{ .@"const" = true } },
|
||||||
|
.{ .param_str = "UWiUWiUWi", .features = "zknd,64bit", .attributes = .{ .@"const" = true } },
|
||||||
|
.{ .param_str = "UWiUWiUWi", .features = "zkne,64bit", .attributes = .{ .@"const" = true } },
|
||||||
|
.{ .param_str = "UWiUWiUWi", .features = "zkne,64bit", .attributes = .{ .@"const" = true } },
|
||||||
|
.{ .param_str = "UWiUWi", .features = "zknd,64bit", .attributes = .{ .@"const" = true } },
|
||||||
|
.{ .param_str = "UWiUWiIUi", .features = "zknd|zkne,64bit", .attributes = .{ .@"const" = true } },
|
||||||
|
.{ .param_str = "UWiUWiUWi", .features = "zknd|zkne,64bit", .attributes = .{ .@"const" = true } },
|
||||||
|
.{ .param_str = "UiUi", .features = "zbkb", .attributes = .{ .@"const" = true } },
|
||||||
|
.{ .param_str = "UWiUWi", .features = "zbkb,64bit", .attributes = .{ .@"const" = true } },
|
||||||
|
.{ .param_str = "UiUiUi", .features = "zbc|zbkc", .attributes = .{ .@"const" = true } },
|
||||||
|
.{ .param_str = "UWiUWiUWi", .features = "zbc|zbkc,64bit", .attributes = .{ .@"const" = true } },
|
||||||
|
.{ .param_str = "UiUiUi", .features = "zbc|zbkc,32bit", .attributes = .{ .@"const" = true } },
|
||||||
|
.{ .param_str = "UWiUWiUWi", .features = "zbc|zbkc,64bit", .attributes = .{ .@"const" = true } },
|
||||||
|
.{ .param_str = "UiUiUi", .features = "zbc,32bit", .attributes = .{ .@"const" = true } },
|
||||||
|
.{ .param_str = "UWiUWiUWi", .features = "zbc,64bit", .attributes = .{ .@"const" = true } },
|
||||||
|
.{ .param_str = "UiUi", .features = "zbb|xtheadbb", .attributes = .{ .@"const" = true } },
|
||||||
|
.{ .param_str = "UiUWi", .features = "zbb|xtheadbb,64bit", .attributes = .{ .@"const" = true } },
|
||||||
|
.{ .param_str = "UiUi", .features = "zbb", .attributes = .{ .@"const" = true } },
|
||||||
|
.{ .param_str = "UiUWi", .features = "zbb,64bit", .attributes = .{ .@"const" = true } },
|
||||||
|
.{ .param_str = "iiiUi", .features = "xcvalu", .attributes = .{ .@"const" = true } },
|
||||||
|
.{ .param_str = "iiiUi", .features = "xcvalu", .attributes = .{ .@"const" = true } },
|
||||||
|
.{ .param_str = "UiUiUiUi", .features = "xcvalu", .attributes = .{ .@"const" = true } },
|
||||||
|
.{ .param_str = "UiUiUiUi", .features = "xcvalu", .attributes = .{ .@"const" = true } },
|
||||||
|
.{ .param_str = "iii", .features = "xcvalu", .attributes = .{ .@"const" = true } },
|
||||||
|
.{ .param_str = "UiUiUi", .features = "xcvalu", .attributes = .{ .@"const" = true } },
|
||||||
|
.{ .param_str = "ii", .features = "xcvalu", .attributes = .{ .@"const" = true } },
|
||||||
|
.{ .param_str = "UiUi", .features = "xcvalu", .attributes = .{ .@"const" = true } },
|
||||||
|
.{ .param_str = "ii", .features = "xcvalu", .attributes = .{ .@"const" = true } },
|
||||||
|
.{ .param_str = "UiUi", .features = "xcvalu", .attributes = .{ .@"const" = true } },
|
||||||
|
.{ .param_str = "iii", .features = "xcvalu", .attributes = .{ .@"const" = true } },
|
||||||
|
.{ .param_str = "iUiUi", .features = "xcvalu", .attributes = .{ .@"const" = true } },
|
||||||
|
.{ .param_str = "iiiUi", .features = "xcvalu", .attributes = .{ .@"const" = true } },
|
||||||
|
.{ .param_str = "iiiUi", .features = "xcvalu", .attributes = .{ .@"const" = true } },
|
||||||
|
.{ .param_str = "UiUiUiUi", .features = "xcvalu", .attributes = .{ .@"const" = true } },
|
||||||
|
.{ .param_str = "UiUiUiUi", .features = "xcvalu", .attributes = .{ .@"const" = true } },
|
||||||
|
.{ .param_str = "v.", .features = "zihintntl", .attributes = .{ .custom_typecheck = true } },
|
||||||
|
.{ .param_str = "v.", .features = "zihintntl", .attributes = .{ .custom_typecheck = true } },
|
||||||
|
.{ .param_str = "UiUi", .features = "zbb", .attributes = .{ .@"const" = true } },
|
||||||
|
.{ .param_str = "UWiUWi", .features = "zbb,64bit", .attributes = .{ .@"const" = true } },
|
||||||
|
.{ .param_str = "v", .features = "zihintpause" },
|
||||||
|
.{ .param_str = "UiUi", .features = "zknh", .attributes = .{ .@"const" = true } },
|
||||||
|
.{ .param_str = "UiUi", .features = "zknh", .attributes = .{ .@"const" = true } },
|
||||||
|
.{ .param_str = "UiUi", .features = "zknh", .attributes = .{ .@"const" = true } },
|
||||||
|
.{ .param_str = "UiUi", .features = "zknh", .attributes = .{ .@"const" = true } },
|
||||||
|
.{ .param_str = "UWiUWi", .features = "zknh,64bit", .attributes = .{ .@"const" = true } },
|
||||||
|
.{ .param_str = "UiUiUi", .features = "zknh,32bit", .attributes = .{ .@"const" = true } },
|
||||||
|
.{ .param_str = "UiUiUi", .features = "zknh,32bit", .attributes = .{ .@"const" = true } },
|
||||||
|
.{ .param_str = "UWiUWi", .features = "zknh,64bit", .attributes = .{ .@"const" = true } },
|
||||||
|
.{ .param_str = "UiUiUi", .features = "zknh,32bit", .attributes = .{ .@"const" = true } },
|
||||||
|
.{ .param_str = "UiUiUi", .features = "zknh,32bit", .attributes = .{ .@"const" = true } },
|
||||||
|
.{ .param_str = "UWiUWi", .features = "zknh,64bit", .attributes = .{ .@"const" = true } },
|
||||||
|
.{ .param_str = "UiUiUi", .features = "zknh,32bit", .attributes = .{ .@"const" = true } },
|
||||||
|
.{ .param_str = "UWiUWi", .features = "zknh,64bit", .attributes = .{ .@"const" = true } },
|
||||||
|
.{ .param_str = "UiUiUi", .features = "zknh,32bit", .attributes = .{ .@"const" = true } },
|
||||||
|
.{ .param_str = "UiUi", .features = "zksh", .attributes = .{ .@"const" = true } },
|
||||||
|
.{ .param_str = "UiUi", .features = "zksh", .attributes = .{ .@"const" = true } },
|
||||||
|
.{ .param_str = "UiUiUiIUi", .features = "zksed", .attributes = .{ .@"const" = true } },
|
||||||
|
.{ .param_str = "UiUiUiIUi", .features = "zksed", .attributes = .{ .@"const" = true } },
|
||||||
|
.{ .param_str = "UiUi", .features = "zbkb,32bit", .attributes = .{ .@"const" = true } },
|
||||||
|
.{ .param_str = "UiUiUi", .features = "zbkx,32bit", .attributes = .{ .@"const" = true } },
|
||||||
|
.{ .param_str = "UWiUWiUWi", .features = "zbkx,64bit", .attributes = .{ .@"const" = true } },
|
||||||
|
.{ .param_str = "UiUiUi", .features = "zbkx,32bit", .attributes = .{ .@"const" = true } },
|
||||||
|
.{ .param_str = "UWiUWiUWi", .features = "zbkx,64bit", .attributes = .{ .@"const" = true } },
|
||||||
|
.{ .param_str = "UiUi", .features = "zbkb,32bit", .attributes = .{ .@"const" = true } },
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
}
|
||||||
1068
lib/compiler/aro/aro/Builtins/s390x.zig
vendored
Normal file
1068
lib/compiler/aro/aro/Builtins/s390x.zig
vendored
Normal file
File diff suppressed because it is too large
Load Diff
3370
lib/compiler/aro/aro/Builtins/ve.zig
vendored
Normal file
3370
lib/compiler/aro/aro/Builtins/ve.zig
vendored
Normal file
File diff suppressed because it is too large
Load Diff
6379
lib/compiler/aro/aro/Builtins/x86.zig
vendored
Normal file
6379
lib/compiler/aro/aro/Builtins/x86.zig
vendored
Normal file
File diff suppressed because it is too large
Load Diff
1122
lib/compiler/aro/aro/Builtins/x86_64.zig
vendored
Normal file
1122
lib/compiler/aro/aro/Builtins/x86_64.zig
vendored
Normal file
File diff suppressed because it is too large
Load Diff
204
lib/compiler/aro/aro/Builtins/xcore.zig
vendored
Normal file
204
lib/compiler/aro/aro/Builtins/xcore.zig
vendored
Normal file
@ -0,0 +1,204 @@
|
|||||||
|
//! Autogenerated by GenerateDef from src/aro/Builtins/xcore.def, do not edit
|
||||||
|
// zig fmt: off
|
||||||
|
|
||||||
|
const std = @import("std");
|
||||||
|
|
||||||
|
pub fn with(comptime Properties: type) type {
|
||||||
|
return struct {
|
||||||
|
|
||||||
|
/// Integer starting at 0 derived from the unique index,
|
||||||
|
/// corresponds with the data array index.
|
||||||
|
pub const Tag = enum(u16) { __builtin_bitrev,
|
||||||
|
__builtin_getid,
|
||||||
|
__builtin_getps,
|
||||||
|
__builtin_setps,
|
||||||
|
};
|
||||||
|
|
||||||
|
pub fn fromName(name: []const u8) ?Properties {
|
||||||
|
const data_index = tagFromName(name) orelse return null;
|
||||||
|
return data[@intFromEnum(data_index)];
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn tagFromName(name: []const u8) ?Tag {
|
||||||
|
const unique_index = uniqueIndex(name) orelse return null;
|
||||||
|
return @enumFromInt(unique_index - 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn fromTag(tag: Tag) Properties {
|
||||||
|
return data[@intFromEnum(tag)];
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn nameFromTagIntoBuf(tag: Tag, name_buf: []u8) []u8 {
|
||||||
|
std.debug.assert(name_buf.len >= longest_name);
|
||||||
|
const unique_index = @intFromEnum(tag) + 1;
|
||||||
|
return nameFromUniqueIndex(unique_index, name_buf);
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn nameFromTag(tag: Tag) NameBuf {
|
||||||
|
var name_buf: NameBuf = undefined;
|
||||||
|
const unique_index = @intFromEnum(tag) + 1;
|
||||||
|
const name = nameFromUniqueIndex(unique_index, &name_buf.buf);
|
||||||
|
name_buf.len = @intCast(name.len);
|
||||||
|
return name_buf;
|
||||||
|
}
|
||||||
|
|
||||||
|
pub const NameBuf = struct {
|
||||||
|
buf: [longest_name]u8 = undefined,
|
||||||
|
len: std.math.IntFittingRange(0, longest_name),
|
||||||
|
|
||||||
|
pub fn span(self: *const NameBuf) []const u8 {
|
||||||
|
return self.buf[0..self.len];
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
pub fn exists(name: []const u8) bool {
|
||||||
|
if (name.len < shortest_name or name.len > longest_name) return false;
|
||||||
|
|
||||||
|
var index: u16 = 0;
|
||||||
|
for (name) |c| {
|
||||||
|
index = findInList(dafsa[index].child_index, c) orelse return false;
|
||||||
|
}
|
||||||
|
return dafsa[index].end_of_word;
|
||||||
|
}
|
||||||
|
|
||||||
|
pub const shortest_name = 15;
|
||||||
|
pub const longest_name = 16;
|
||||||
|
|
||||||
|
/// Search siblings of `first_child_index` for the `char`
|
||||||
|
/// If found, returns the index of the node within the `dafsa` array.
|
||||||
|
/// Otherwise, returns `null`.
|
||||||
|
pub fn findInList(first_child_index: u16, char: u8) ?u16 {
|
||||||
|
@setEvalBranchQuota(8);
|
||||||
|
var index = first_child_index;
|
||||||
|
while (true) {
|
||||||
|
if (dafsa[index].char == char) return index;
|
||||||
|
if (dafsa[index].end_of_list) return null;
|
||||||
|
index += 1;
|
||||||
|
}
|
||||||
|
unreachable;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Returns a unique (minimal perfect hash) index (starting at 1) for the `name`,
|
||||||
|
/// or null if the name was not found.
|
||||||
|
pub fn uniqueIndex(name: []const u8) ?u16 {
|
||||||
|
if (name.len < shortest_name or name.len > longest_name) return null;
|
||||||
|
|
||||||
|
var index: u16 = 0;
|
||||||
|
var node_index: u16 = 0;
|
||||||
|
|
||||||
|
for (name) |c| {
|
||||||
|
const child_index = findInList(dafsa[node_index].child_index, c) orelse return null;
|
||||||
|
var sibling_index = dafsa[node_index].child_index;
|
||||||
|
while (true) {
|
||||||
|
const sibling_c = dafsa[sibling_index].char;
|
||||||
|
std.debug.assert(sibling_c != 0);
|
||||||
|
if (sibling_c < c) {
|
||||||
|
index += dafsa[sibling_index].number;
|
||||||
|
}
|
||||||
|
if (dafsa[sibling_index].end_of_list) break;
|
||||||
|
sibling_index += 1;
|
||||||
|
}
|
||||||
|
node_index = child_index;
|
||||||
|
if (dafsa[node_index].end_of_word) index += 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!dafsa[node_index].end_of_word) return null;
|
||||||
|
|
||||||
|
return index;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Returns a slice of `buf` with the name associated with the given `index`.
|
||||||
|
/// This function should only be called with an `index` that
|
||||||
|
/// is already known to exist within the `dafsa`, e.g. an index
|
||||||
|
/// returned from `uniqueIndex`.
|
||||||
|
pub fn nameFromUniqueIndex(index: u16, buf: []u8) []u8 {
|
||||||
|
std.debug.assert(index >= 1 and index <= data.len);
|
||||||
|
|
||||||
|
var node_index: u16 = 0;
|
||||||
|
var count: u16 = index;
|
||||||
|
var w = std.Io.Writer.fixed(buf);
|
||||||
|
|
||||||
|
while (true) {
|
||||||
|
var sibling_index = dafsa[node_index].child_index;
|
||||||
|
while (true) {
|
||||||
|
if (dafsa[sibling_index].number > 0 and dafsa[sibling_index].number < count) {
|
||||||
|
count -= dafsa[sibling_index].number;
|
||||||
|
} else {
|
||||||
|
w.writeByte(dafsa[sibling_index].char) catch unreachable;
|
||||||
|
node_index = sibling_index;
|
||||||
|
if (dafsa[node_index].end_of_word) {
|
||||||
|
count -= 1;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (dafsa[sibling_index].end_of_list) break;
|
||||||
|
sibling_index += 1;
|
||||||
|
}
|
||||||
|
if (count == 0) break;
|
||||||
|
}
|
||||||
|
|
||||||
|
return w.buffered();
|
||||||
|
}
|
||||||
|
|
||||||
|
const Node = packed struct {
|
||||||
|
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
|
||||||
|
/// allows calculating "a one-to-one correspondence between the integers 1 to L
|
||||||
|
/// (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: std.math.IntFittingRange(0, data.len),
|
||||||
|
/// If true, this node is the end of a valid builtin.
|
||||||
|
/// 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,
|
||||||
|
/// Index of the first child of this node.
|
||||||
|
child_index: u16,
|
||||||
|
};
|
||||||
|
|
||||||
|
const dafsa = [_]Node{
|
||||||
|
.{ .char = 0, .end_of_word = false, .end_of_list = true, .number = 0, .child_index = 1 },
|
||||||
|
.{ .char = '_', .end_of_word = false, .end_of_list = true, .number = 4, .child_index = 2 },
|
||||||
|
.{ .char = '_', .end_of_word = false, .end_of_list = true, .number = 4, .child_index = 3 },
|
||||||
|
.{ .char = 'b', .end_of_word = false, .end_of_list = true, .number = 4, .child_index = 4 },
|
||||||
|
.{ .char = 'u', .end_of_word = false, .end_of_list = true, .number = 4, .child_index = 5 },
|
||||||
|
.{ .char = 'i', .end_of_word = false, .end_of_list = true, .number = 4, .child_index = 6 },
|
||||||
|
.{ .char = 'l', .end_of_word = false, .end_of_list = true, .number = 4, .child_index = 7 },
|
||||||
|
.{ .char = 't', .end_of_word = false, .end_of_list = true, .number = 4, .child_index = 8 },
|
||||||
|
.{ .char = 'i', .end_of_word = false, .end_of_list = true, .number = 4, .child_index = 9 },
|
||||||
|
.{ .char = 'n', .end_of_word = false, .end_of_list = true, .number = 4, .child_index = 10 },
|
||||||
|
.{ .char = '_', .end_of_word = false, .end_of_list = true, .number = 4, .child_index = 11 },
|
||||||
|
.{ .char = 'b', .end_of_word = false, .end_of_list = false, .number = 1, .child_index = 14 },
|
||||||
|
.{ .char = 'g', .end_of_word = false, .end_of_list = false, .number = 2, .child_index = 15 },
|
||||||
|
.{ .char = 's', .end_of_word = false, .end_of_list = true, .number = 1, .child_index = 16 },
|
||||||
|
.{ .char = 'i', .end_of_word = false, .end_of_list = true, .number = 1, .child_index = 17 },
|
||||||
|
.{ .char = 'e', .end_of_word = false, .end_of_list = true, .number = 2, .child_index = 18 },
|
||||||
|
.{ .char = 'e', .end_of_word = false, .end_of_list = true, .number = 1, .child_index = 19 },
|
||||||
|
.{ .char = 't', .end_of_word = false, .end_of_list = true, .number = 1, .child_index = 20 },
|
||||||
|
.{ .char = 't', .end_of_word = false, .end_of_list = true, .number = 2, .child_index = 21 },
|
||||||
|
.{ .char = 't', .end_of_word = false, .end_of_list = true, .number = 1, .child_index = 23 },
|
||||||
|
.{ .char = 'r', .end_of_word = false, .end_of_list = true, .number = 1, .child_index = 24 },
|
||||||
|
.{ .char = 'i', .end_of_word = false, .end_of_list = false, .number = 1, .child_index = 25 },
|
||||||
|
.{ .char = 'p', .end_of_word = false, .end_of_list = true, .number = 1, .child_index = 26 },
|
||||||
|
.{ .char = 'p', .end_of_word = false, .end_of_list = true, .number = 1, .child_index = 26 },
|
||||||
|
.{ .char = 'e', .end_of_word = false, .end_of_list = true, .number = 1, .child_index = 27 },
|
||||||
|
.{ .char = 'd', .end_of_word = true, .end_of_list = true, .number = 1, .child_index = 0 },
|
||||||
|
.{ .char = 's', .end_of_word = true, .end_of_list = true, .number = 1, .child_index = 0 },
|
||||||
|
.{ .char = 'v', .end_of_word = true, .end_of_list = true, .number = 1, .child_index = 0 },
|
||||||
|
};
|
||||||
|
pub const data = blk: {
|
||||||
|
@setEvalBranchQuota(36);
|
||||||
|
break :blk [_]Properties{
|
||||||
|
.{ .param_str = "UiUi", .attributes = .{ .@"const" = true } },
|
||||||
|
.{ .param_str = "Si", .attributes = .{ .@"const" = true } },
|
||||||
|
.{ .param_str = "UiUi" },
|
||||||
|
.{ .param_str = "vUiUi" },
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
}
|
||||||
13
lib/compiler/aro/aro/CodeGen.zig
vendored
13
lib/compiler/aro/aro/CodeGen.zig
vendored
@ -2,13 +2,12 @@ const std = @import("std");
|
|||||||
const Allocator = std.mem.Allocator;
|
const Allocator = std.mem.Allocator;
|
||||||
const assert = std.debug.assert;
|
const assert = std.debug.assert;
|
||||||
|
|
||||||
const backend = @import("../backend.zig");
|
const backend = @import("backend");
|
||||||
const Interner = backend.Interner;
|
const Interner = backend.Interner;
|
||||||
const Ir = backend.Ir;
|
const Ir = backend.Ir;
|
||||||
const Builder = Ir.Builder;
|
const Builder = Ir.Builder;
|
||||||
|
|
||||||
const Builtins = @import("Builtins.zig");
|
const Builtins = @import("Builtins.zig");
|
||||||
const Builtin = Builtins.Builtin;
|
|
||||||
const Compilation = @import("Compilation.zig");
|
const Compilation = @import("Compilation.zig");
|
||||||
const StringId = @import("StringInterner.zig").StringId;
|
const StringId = @import("StringInterner.zig").StringId;
|
||||||
const Tree = @import("Tree.zig");
|
const Tree = @import("Tree.zig");
|
||||||
@ -111,6 +110,9 @@ pub fn genIr(tree: *const Tree) Compilation.Error!Ir {
|
|||||||
error.FatalError => return error.FatalError,
|
error.FatalError => return error.FatalError,
|
||||||
error.OutOfMemory => return error.OutOfMemory,
|
error.OutOfMemory => return error.OutOfMemory,
|
||||||
},
|
},
|
||||||
|
.global_asm => {
|
||||||
|
return c.fail("TODO global assembly", .{});
|
||||||
|
},
|
||||||
else => unreachable,
|
else => unreachable,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -497,6 +499,7 @@ fn genExpr(c: *CodeGen, node_index: Node.Index) Error!Ir.Ref {
|
|||||||
.goto_stmt,
|
.goto_stmt,
|
||||||
.computed_goto_stmt,
|
.computed_goto_stmt,
|
||||||
.nullptr_literal,
|
.nullptr_literal,
|
||||||
|
.asm_stmt,
|
||||||
=> return c.fail("TODO CodeGen.genStmt {s}\n", .{@tagName(node)}),
|
=> return c.fail("TODO CodeGen.genStmt {s}\n", .{@tagName(node)}),
|
||||||
.comma_expr => |bin| {
|
.comma_expr => |bin| {
|
||||||
_ = try c.genExpr(bin.lhs);
|
_ = try c.genExpr(bin.lhs);
|
||||||
@ -857,7 +860,7 @@ fn genExpr(c: *CodeGen, node_index: Node.Index) Error!Ir.Ref {
|
|||||||
},
|
},
|
||||||
.builtin_call_expr => |call| {
|
.builtin_call_expr => |call| {
|
||||||
const name = c.tree.tokSlice(call.builtin_tok);
|
const name = c.tree.tokSlice(call.builtin_tok);
|
||||||
const builtin = c.comp.builtins.lookup(name).builtin;
|
const builtin = c.comp.builtins.lookup(name);
|
||||||
return c.genBuiltinCall(builtin, call.args, call.qt);
|
return c.genBuiltinCall(builtin, call.args, call.qt);
|
||||||
},
|
},
|
||||||
.addr_of_label,
|
.addr_of_label,
|
||||||
@ -1074,10 +1077,10 @@ fn genBoolExpr(c: *CodeGen, base: Node.Index, true_label: Ir.Ref, false_label: I
|
|||||||
try c.addBranch(cmp, true_label, false_label);
|
try c.addBranch(cmp, true_label, false_label);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn genBuiltinCall(c: *CodeGen, builtin: Builtin, arg_nodes: []const Node.Index, qt: QualType) Error!Ir.Ref {
|
fn genBuiltinCall(c: *CodeGen, builtin: Builtins.Expanded, arg_nodes: []const Node.Index, qt: QualType) Error!Ir.Ref {
|
||||||
_ = arg_nodes;
|
_ = arg_nodes;
|
||||||
_ = qt;
|
_ = qt;
|
||||||
return c.fail("TODO CodeGen.genBuiltinCall {s}\n", .{Builtin.nameFromTag(builtin.tag).span()});
|
return c.fail("TODO CodeGen.genBuiltinCall {t}\n", .{builtin.tag});
|
||||||
}
|
}
|
||||||
|
|
||||||
fn genCall(c: *CodeGen, call: Node.Call) Error!Ir.Ref {
|
fn genCall(c: *CodeGen, call: Node.Call) Error!Ir.Ref {
|
||||||
|
|||||||
535
lib/compiler/aro/aro/Compilation.zig
vendored
535
lib/compiler/aro/aro/Compilation.zig
vendored
File diff suppressed because it is too large
Load Diff
4
lib/compiler/aro/aro/Diagnostics.zig
vendored
4
lib/compiler/aro/aro/Diagnostics.zig
vendored
@ -195,7 +195,9 @@ pub const Option = enum {
|
|||||||
@"out-of-scope-function",
|
@"out-of-scope-function",
|
||||||
@"date-time",
|
@"date-time",
|
||||||
@"variadic-macro-arguments-omitted",
|
@"variadic-macro-arguments-omitted",
|
||||||
@"attribute-todo",
|
@"pragma-once-outside-header",
|
||||||
|
@"underlying-atomic-qualifier-ignored",
|
||||||
|
@"underlying-cv-qualifier-ignored",
|
||||||
|
|
||||||
/// GNU extensions
|
/// GNU extensions
|
||||||
pub const gnu = [_]Option{
|
pub const gnu = [_]Option{
|
||||||
|
|||||||
295
lib/compiler/aro/aro/Driver.zig
vendored
295
lib/compiler/aro/aro/Driver.zig
vendored
@ -15,7 +15,7 @@ const GCCVersion = @import("Driver/GCCVersion.zig");
|
|||||||
const LangOpts = @import("LangOpts.zig");
|
const LangOpts = @import("LangOpts.zig");
|
||||||
const Preprocessor = @import("Preprocessor.zig");
|
const Preprocessor = @import("Preprocessor.zig");
|
||||||
const Source = @import("Source.zig");
|
const Source = @import("Source.zig");
|
||||||
const target_util = @import("target.zig");
|
const Target = @import("Target.zig");
|
||||||
const Toolchain = @import("Toolchain.zig");
|
const Toolchain = @import("Toolchain.zig");
|
||||||
const Tree = @import("Tree.zig");
|
const Tree = @import("Tree.zig");
|
||||||
|
|
||||||
@ -46,6 +46,10 @@ comp: *Compilation,
|
|||||||
diagnostics: *Diagnostics,
|
diagnostics: *Diagnostics,
|
||||||
|
|
||||||
inputs: std.ArrayList(Source) = .empty,
|
inputs: std.ArrayList(Source) = .empty,
|
||||||
|
imacros: std.ArrayList(Source) = .empty,
|
||||||
|
implicit_includes: std.ArrayList(Source) = .empty,
|
||||||
|
/// List of includes that will be used to construct the compilation's search path
|
||||||
|
includes: std.ArrayList(Compilation.Include) = .empty,
|
||||||
link_objects: std.ArrayList([]const u8) = .empty,
|
link_objects: std.ArrayList([]const u8) = .empty,
|
||||||
output_name: ?[]const u8 = null,
|
output_name: ?[]const u8 = null,
|
||||||
sysroot: ?[]const u8 = null,
|
sysroot: ?[]const u8 = null,
|
||||||
@ -64,6 +68,7 @@ verbose_ast: bool = false,
|
|||||||
verbose_pp: bool = false,
|
verbose_pp: bool = false,
|
||||||
verbose_ir: bool = false,
|
verbose_ir: bool = false,
|
||||||
verbose_linker_args: bool = false,
|
verbose_linker_args: bool = false,
|
||||||
|
verbose_search_path: bool = false,
|
||||||
nobuiltininc: bool = false,
|
nobuiltininc: bool = false,
|
||||||
nostdinc: bool = false,
|
nostdinc: bool = false,
|
||||||
nostdlibinc: bool = false,
|
nostdlibinc: bool = false,
|
||||||
@ -99,6 +104,8 @@ aro_name: []const u8 = "",
|
|||||||
|
|
||||||
/// Value of -target passed via CLI
|
/// Value of -target passed via CLI
|
||||||
raw_target_triple: ?[]const u8 = null,
|
raw_target_triple: ?[]const u8 = null,
|
||||||
|
/// Value of -darwin-target-variant-triple passed via CLI
|
||||||
|
raw_darwin_variant_target_triple: ?[]const u8 = null,
|
||||||
|
|
||||||
/// Value of -mcpu passed via CLI
|
/// Value of -mcpu passed via CLI
|
||||||
raw_cpu: ?[]const u8 = null,
|
raw_cpu: ?[]const u8 = null,
|
||||||
@ -107,6 +114,7 @@ raw_cpu: ?[]const u8 = null,
|
|||||||
use_assembly_backend: bool = false,
|
use_assembly_backend: bool = false,
|
||||||
|
|
||||||
// linker options
|
// linker options
|
||||||
|
use_linker: ?[]const u8 = null,
|
||||||
linker_path: ?[]const u8 = null,
|
linker_path: ?[]const u8 = null,
|
||||||
nodefaultlibs: bool = false,
|
nodefaultlibs: bool = false,
|
||||||
nolibc: bool = false,
|
nolibc: bool = false,
|
||||||
@ -130,6 +138,9 @@ pub fn deinit(d: *Driver) void {
|
|||||||
d.comp.gpa.free(obj);
|
d.comp.gpa.free(obj);
|
||||||
}
|
}
|
||||||
d.inputs.deinit(d.comp.gpa);
|
d.inputs.deinit(d.comp.gpa);
|
||||||
|
d.imacros.deinit(d.comp.gpa);
|
||||||
|
d.implicit_includes.deinit(d.comp.gpa);
|
||||||
|
d.includes.deinit(d.comp.gpa);
|
||||||
d.link_objects.deinit(d.comp.gpa);
|
d.link_objects.deinit(d.comp.gpa);
|
||||||
d.* = undefined;
|
d.* = undefined;
|
||||||
}
|
}
|
||||||
@ -161,6 +172,8 @@ pub const usage =
|
|||||||
\\
|
\\
|
||||||
\\Compile options:
|
\\Compile options:
|
||||||
\\ -c, --compile Only run preprocess, compile, and assemble steps
|
\\ -c, --compile Only run preprocess, compile, and assemble steps
|
||||||
|
\\ -darwin-target-variant-triple
|
||||||
|
\\ Specify the darwin target variant triple
|
||||||
\\ -fapple-kext Use Apple's kernel extensions ABI
|
\\ -fapple-kext Use Apple's kernel extensions ABI
|
||||||
\\ -fchar8_t Enable char8_t (enabled by default in C23 and later)
|
\\ -fchar8_t Enable char8_t (enabled by default in C23 and later)
|
||||||
\\ -fno-char8_t Disable char8_t (disabled by default for pre-C23)
|
\\ -fno-char8_t Disable char8_t (disabled by default for pre-C23)
|
||||||
@ -212,6 +225,8 @@ pub const usage =
|
|||||||
\\ --embed-dir=<dir> Add directory to `#embed` search path
|
\\ --embed-dir=<dir> Add directory to `#embed` search path
|
||||||
\\ --emulate=[clang|gcc|msvc]
|
\\ --emulate=[clang|gcc|msvc]
|
||||||
\\ Select which C compiler to emulate (default clang)
|
\\ Select which C compiler to emulate (default clang)
|
||||||
|
\\ -imacros <file> Include macros from <file> before parsing
|
||||||
|
\\ -include <file> Process <file> as if `#include "file"` appeared as the first line of the primary source file.
|
||||||
\\ -mabicalls Enable SVR4-style position-independent code (Mips only)
|
\\ -mabicalls Enable SVR4-style position-independent code (Mips only)
|
||||||
\\ -mno-abicalls Disable SVR4-style position-independent code (Mips only)
|
\\ -mno-abicalls Disable SVR4-style position-independent code (Mips only)
|
||||||
\\ -mcmodel=<code-model> Generate code for the given code model
|
\\ -mcmodel=<code-model> Generate code for the given code model
|
||||||
@ -273,7 +288,8 @@ pub fn parseArgs(
|
|||||||
macro_buf: *std.ArrayList(u8),
|
macro_buf: *std.ArrayList(u8),
|
||||||
args: []const []const u8,
|
args: []const []const u8,
|
||||||
) (Compilation.Error || std.Io.Writer.Error)!bool {
|
) (Compilation.Error || std.Io.Writer.Error)!bool {
|
||||||
const io = d.comp.io;
|
const gpa = d.comp.gpa;
|
||||||
|
|
||||||
var i: usize = 1;
|
var i: usize = 1;
|
||||||
var comment_arg: []const u8 = "";
|
var comment_arg: []const u8 = "";
|
||||||
var hosted: ?bool = null;
|
var hosted: ?bool = null;
|
||||||
@ -310,7 +326,7 @@ pub fn parseArgs(
|
|||||||
value = macro[some + 1 ..];
|
value = macro[some + 1 ..];
|
||||||
macro = macro[0..some];
|
macro = macro[0..some];
|
||||||
}
|
}
|
||||||
try macro_buf.print(d.comp.gpa, "#define {s} {s}\n", .{ macro, value });
|
try macro_buf.print(gpa, "#define {s} {s}\n", .{ macro, value });
|
||||||
} else if (mem.startsWith(u8, arg, "-U")) {
|
} else if (mem.startsWith(u8, arg, "-U")) {
|
||||||
var macro = arg["-U".len..];
|
var macro = arg["-U".len..];
|
||||||
if (macro.len == 0) {
|
if (macro.len == 0) {
|
||||||
@ -321,7 +337,7 @@ pub fn parseArgs(
|
|||||||
}
|
}
|
||||||
macro = args[i];
|
macro = args[i];
|
||||||
}
|
}
|
||||||
try macro_buf.print(d.comp.gpa, "#undef {s}\n", .{macro});
|
try macro_buf.print(gpa, "#undef {s}\n", .{macro});
|
||||||
} else if (mem.eql(u8, arg, "-O")) {
|
} else if (mem.eql(u8, arg, "-O")) {
|
||||||
d.comp.code_gen_options.optimization_level = .@"1";
|
d.comp.code_gen_options.optimization_level = .@"1";
|
||||||
} else if (mem.startsWith(u8, arg, "-O")) {
|
} else if (mem.startsWith(u8, arg, "-O")) {
|
||||||
@ -334,6 +350,13 @@ pub fn parseArgs(
|
|||||||
d.system_defines = .no_system_defines;
|
d.system_defines = .no_system_defines;
|
||||||
} else if (mem.eql(u8, arg, "-c") or mem.eql(u8, arg, "--compile")) {
|
} else if (mem.eql(u8, arg, "-c") or mem.eql(u8, arg, "--compile")) {
|
||||||
d.only_compile = true;
|
d.only_compile = true;
|
||||||
|
} else if (mem.eql(u8, arg, "-darwin-target-variant-triple")) {
|
||||||
|
i += 1;
|
||||||
|
if (i >= args.len) {
|
||||||
|
try d.err("expected argument after -darwin-target-variant-triple", .{});
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
d.raw_darwin_variant_target_triple = args[i];
|
||||||
} else if (mem.eql(u8, arg, "-dD")) {
|
} else if (mem.eql(u8, arg, "-dD")) {
|
||||||
d.debug_dump_letters.d = true;
|
d.debug_dump_letters.d = true;
|
||||||
} else if (mem.eql(u8, arg, "-dM")) {
|
} else if (mem.eql(u8, arg, "-dM")) {
|
||||||
@ -508,7 +531,7 @@ pub fn parseArgs(
|
|||||||
}
|
}
|
||||||
path = args[i];
|
path = args[i];
|
||||||
}
|
}
|
||||||
try d.comp.include_dirs.append(d.comp.gpa, path);
|
try d.includes.append(gpa, .{ .kind = .normal, .path = path });
|
||||||
} else if (mem.startsWith(u8, arg, "-idirafter")) {
|
} else if (mem.startsWith(u8, arg, "-idirafter")) {
|
||||||
var path = arg["-idirafter".len..];
|
var path = arg["-idirafter".len..];
|
||||||
if (path.len == 0) {
|
if (path.len == 0) {
|
||||||
@ -519,7 +542,7 @@ pub fn parseArgs(
|
|||||||
}
|
}
|
||||||
path = args[i];
|
path = args[i];
|
||||||
}
|
}
|
||||||
try d.comp.after_include_dirs.append(d.comp.gpa, path);
|
try d.includes.append(gpa, .{ .kind = .after, .path = path });
|
||||||
} else if (mem.startsWith(u8, arg, "-isystem")) {
|
} else if (mem.startsWith(u8, arg, "-isystem")) {
|
||||||
var path = arg["-isystem".len..];
|
var path = arg["-isystem".len..];
|
||||||
if (path.len == 0) {
|
if (path.len == 0) {
|
||||||
@ -530,7 +553,7 @@ pub fn parseArgs(
|
|||||||
}
|
}
|
||||||
path = args[i];
|
path = args[i];
|
||||||
}
|
}
|
||||||
try d.comp.system_include_dirs.append(d.comp.gpa, path);
|
try d.includes.append(gpa, .{ .kind = .system, .path = path });
|
||||||
} else if (mem.startsWith(u8, arg, "-iquote")) {
|
} else if (mem.startsWith(u8, arg, "-iquote")) {
|
||||||
var path = arg["-iquote".len..];
|
var path = arg["-iquote".len..];
|
||||||
if (path.len == 0) {
|
if (path.len == 0) {
|
||||||
@ -541,7 +564,7 @@ pub fn parseArgs(
|
|||||||
}
|
}
|
||||||
path = args[i];
|
path = args[i];
|
||||||
}
|
}
|
||||||
try d.comp.iquote_include_dirs.append(d.comp.gpa, path);
|
try d.includes.append(gpa, .{ .kind = .quote, .path = path });
|
||||||
} else if (mem.startsWith(u8, arg, "-F")) {
|
} else if (mem.startsWith(u8, arg, "-F")) {
|
||||||
var path = arg["-F".len..];
|
var path = arg["-F".len..];
|
||||||
if (path.len == 0) {
|
if (path.len == 0) {
|
||||||
@ -552,7 +575,7 @@ pub fn parseArgs(
|
|||||||
}
|
}
|
||||||
path = args[i];
|
path = args[i];
|
||||||
}
|
}
|
||||||
try d.comp.framework_dirs.append(d.comp.gpa, path);
|
try d.includes.append(gpa, .{ .kind = .framework, .path = path });
|
||||||
} else if (mem.startsWith(u8, arg, "-iframework")) {
|
} else if (mem.startsWith(u8, arg, "-iframework")) {
|
||||||
var path = arg["-iframework".len..];
|
var path = arg["-iframework".len..];
|
||||||
if (path.len == 0) {
|
if (path.len == 0) {
|
||||||
@ -563,9 +586,27 @@ pub fn parseArgs(
|
|||||||
}
|
}
|
||||||
path = args[i];
|
path = args[i];
|
||||||
}
|
}
|
||||||
try d.comp.system_framework_dirs.append(d.comp.gpa, path);
|
try d.includes.append(gpa, .{ .kind = .system_framework, .path = path });
|
||||||
|
} else if (option(arg, "-include") orelse option(arg, "--include")) |implicit_include| {
|
||||||
|
try d.addImplicitInclude(implicit_include);
|
||||||
|
} else if (mem.eql(u8, arg, "-include") or mem.eql(u8, arg, "--include")) {
|
||||||
|
i += 1;
|
||||||
|
if (i >= args.len) {
|
||||||
|
try d.err("expected argument after {s}", .{arg});
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
try d.addImplicitInclude(args[i]);
|
||||||
|
} else if (option(arg, "-imacros") orelse option(arg, "--imacros")) |imacro_path| {
|
||||||
|
try d.addImacros(imacro_path);
|
||||||
|
} else if (mem.eql(u8, arg, "-imacros") or mem.eql(u8, arg, "--imacros")) {
|
||||||
|
i += 1;
|
||||||
|
if (i >= args.len) {
|
||||||
|
try d.err("expected argument after {s}", .{arg});
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
try d.addImacros(args[i]);
|
||||||
} else if (option(arg, "--embed-dir=")) |path| {
|
} else if (option(arg, "--embed-dir=")) |path| {
|
||||||
try d.comp.embed_dirs.append(d.comp.gpa, path);
|
try d.comp.embed_dirs.append(gpa, path);
|
||||||
} else if (option(arg, "--emulate=")) |compiler_str| {
|
} else if (option(arg, "--emulate=")) |compiler_str| {
|
||||||
const compiler = std.meta.stringToEnum(LangOpts.Compiler, compiler_str) orelse {
|
const compiler = std.meta.stringToEnum(LangOpts.Compiler, compiler_str) orelse {
|
||||||
try d.err("invalid compiler '{s}'", .{arg});
|
try d.err("invalid compiler '{s}'", .{arg});
|
||||||
@ -592,6 +633,9 @@ pub fn parseArgs(
|
|||||||
d.output_name = file;
|
d.output_name = file;
|
||||||
} else if (option(arg, "--sysroot=")) |sysroot| {
|
} else if (option(arg, "--sysroot=")) |sysroot| {
|
||||||
d.sysroot = sysroot;
|
d.sysroot = sysroot;
|
||||||
|
} else if (mem.eql(u8, arg, "-Wp,-v")) {
|
||||||
|
// TODO this is not how this argument should work
|
||||||
|
d.verbose_search_path = true;
|
||||||
} else if (mem.eql(u8, arg, "-pedantic")) {
|
} else if (mem.eql(u8, arg, "-pedantic")) {
|
||||||
d.diagnostics.state.extensions = .warning;
|
d.diagnostics.state.extensions = .warning;
|
||||||
} else if (mem.eql(u8, arg, "-pedantic-errors")) {
|
} else if (mem.eql(u8, arg, "-pedantic-errors")) {
|
||||||
@ -744,41 +788,22 @@ pub fn parseArgs(
|
|||||||
try d.warn("unknown argument '{s}'", .{arg});
|
try d.warn("unknown argument '{s}'", .{arg});
|
||||||
}
|
}
|
||||||
} else if (std.mem.endsWith(u8, arg, ".o") or std.mem.endsWith(u8, arg, ".obj")) {
|
} else if (std.mem.endsWith(u8, arg, ".o") or std.mem.endsWith(u8, arg, ".obj")) {
|
||||||
try d.link_objects.append(d.comp.gpa, arg);
|
try d.link_objects.append(gpa, arg);
|
||||||
} else {
|
} else {
|
||||||
const source = d.addSource(arg) catch |er| {
|
const source = d.addSource(arg) catch |er| {
|
||||||
return d.fatal("unable to add source file '{s}': {s}", .{ arg, errorDescription(er) });
|
return d.fatal("unable to add source file '{s}': {s}", .{ arg, errorDescription(er) });
|
||||||
};
|
};
|
||||||
try d.inputs.append(d.comp.gpa, source);
|
try d.inputs.append(gpa, source);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
var diags: std.Target.Query.ParseOptions.Diagnostics = .{};
|
d.comp.target = try d.parseTarget(d.raw_target_triple orelse "native", d.raw_cpu);
|
||||||
const opts: std.Target.Query.ParseOptions = .{
|
if (d.raw_darwin_variant_target_triple) |darwin_triple| {
|
||||||
.arch_os_abi = d.raw_target_triple orelse "native",
|
d.comp.darwin_target_variant = try d.parseTarget(darwin_triple, null);
|
||||||
.cpu_features = d.raw_cpu,
|
}
|
||||||
.diagnostics = &diags,
|
|
||||||
};
|
|
||||||
const query = std.Target.Query.parse(opts) catch |er| switch (er) {
|
|
||||||
error.UnknownCpuModel => {
|
|
||||||
return d.fatal("unknown CPU: '{s}'", .{diags.cpu_name.?});
|
|
||||||
},
|
|
||||||
error.UnknownCpuFeature => {
|
|
||||||
return d.fatal("unknown CPU feature: '{s}'", .{diags.unknown_feature_name.?});
|
|
||||||
},
|
|
||||||
error.UnknownArchitecture => {
|
|
||||||
return d.fatal("unknown architecture: '{s}'", .{diags.unknown_architecture_name.?});
|
|
||||||
},
|
|
||||||
else => |e| return d.fatal("unable to parse target query '{s}': {s}", .{
|
|
||||||
opts.arch_os_abi, @errorName(e),
|
|
||||||
}),
|
|
||||||
};
|
|
||||||
d.comp.target = std.zig.system.resolveTargetQuery(io, query) catch |e| {
|
|
||||||
return d.fatal("unable to resolve target: {s}", .{errorDescription(e)});
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
if (emulate != null or d.raw_target_triple != null) {
|
if (emulate != null or d.raw_target_triple != null) {
|
||||||
d.comp.langopts.setEmulatedCompiler(emulate orelse target_util.systemCompiler(d.comp.target));
|
d.comp.langopts.setEmulatedCompiler(emulate orelse d.comp.target.systemCompiler());
|
||||||
switch (d.comp.langopts.emulate) {
|
switch (d.comp.langopts.emulate) {
|
||||||
.clang => try d.diagnostics.set("clang", .off),
|
.clang => try d.diagnostics.set("clang", .off),
|
||||||
.gcc => try d.diagnostics.set("gnu", .off),
|
.gcc => try d.diagnostics.set("gnu", .off),
|
||||||
@ -839,6 +864,23 @@ fn addSource(d: *Driver, path: []const u8) !Source {
|
|||||||
return d.comp.addSourceFromPath(path);
|
return d.comp.addSourceFromPath(path);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn findIncludeCLI(d: *Driver, path: []const u8, kind: []const u8) !Source {
|
||||||
|
const source = (d.comp.findInclude(path, .{ .id = .keyword_include, .source = .generated }, .cli, .first) catch |er|
|
||||||
|
return d.fatal("unable to add {s} file '{s}': {s}", .{ kind, path, errorDescription(er) })) orelse
|
||||||
|
return d.fatal("unable to add {s} file '{s}': NotFound", .{ kind, path });
|
||||||
|
return source;
|
||||||
|
}
|
||||||
|
|
||||||
|
fn addImplicitInclude(d: *Driver, path: []const u8) !void {
|
||||||
|
const source = try d.findIncludeCLI(path, "implicit include");
|
||||||
|
try d.implicit_includes.append(d.comp.gpa, source);
|
||||||
|
}
|
||||||
|
|
||||||
|
fn addImacros(d: *Driver, path: []const u8) !void {
|
||||||
|
const source = try d.findIncludeCLI(path, "imacros");
|
||||||
|
try d.imacros.append(d.comp.gpa, source);
|
||||||
|
}
|
||||||
|
|
||||||
pub fn err(d: *Driver, fmt: []const u8, args: anytype) Compilation.Error!void {
|
pub fn err(d: *Driver, fmt: []const u8, args: anytype) Compilation.Error!void {
|
||||||
var sf = std.heap.stackFallback(1024, d.comp.gpa);
|
var sf = std.heap.stackFallback(1024, d.comp.gpa);
|
||||||
var allocating: std.Io.Writer.Allocating = .init(sf.get());
|
var allocating: std.Io.Writer.Allocating = .init(sf.get());
|
||||||
@ -857,13 +899,142 @@ pub fn warn(d: *Driver, fmt: []const u8, args: anytype) Compilation.Error!void {
|
|||||||
try d.diagnostics.add(.{ .kind = .warning, .text = allocating.written(), .location = null });
|
try d.diagnostics.add(.{ .kind = .warning, .text = allocating.written(), .location = null });
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn unsupportedOptionForTarget(d: *Driver, target: std.Target, opt: []const u8) Compilation.Error!void {
|
fn unsupportedOptionForTarget(d: *Driver, target: *const Target, opt: []const u8) Compilation.Error!void {
|
||||||
try d.err(
|
try d.err(
|
||||||
"unsupported option '{s}' for target '{s}-{s}-{s}'",
|
"unsupported option '{s}' for target '{s}-{s}-{s}'",
|
||||||
.{ opt, @tagName(target.cpu.arch), @tagName(target.os.tag), @tagName(target.abi) },
|
.{ opt, @tagName(target.cpu.arch), @tagName(target.os.tag), @tagName(target.abi) },
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn parseTarget(d: *Driver, arch_os_abi: []const u8, opt_cpu_features: ?[]const u8) Compilation.Error!Target {
|
||||||
|
var query: std.Target.Query = .{
|
||||||
|
.dynamic_linker = .init(null),
|
||||||
|
};
|
||||||
|
var vendor: Target.Vendor = .unknown;
|
||||||
|
var opt_sub_arch: ?Target.SubArch = null;
|
||||||
|
|
||||||
|
var it = mem.splitScalar(u8, arch_os_abi, '-');
|
||||||
|
const arch_name = it.first();
|
||||||
|
const arch_is_native = mem.eql(u8, arch_name, "native");
|
||||||
|
if (!arch_is_native) {
|
||||||
|
query.cpu_arch, opt_sub_arch = Target.parseArchName(arch_name) orelse {
|
||||||
|
return d.fatal("unknown architecture: '{s}'", .{arch_name});
|
||||||
|
};
|
||||||
|
}
|
||||||
|
const arch = query.cpu_arch orelse @import("builtin").cpu.arch;
|
||||||
|
|
||||||
|
const opt_os_text = blk: {
|
||||||
|
const opt_os_or_vendor = it.next();
|
||||||
|
if (opt_os_or_vendor) |os_or_vendor| {
|
||||||
|
if (Target.parseVendorName(os_or_vendor)) |parsed_vendor| {
|
||||||
|
vendor = parsed_vendor;
|
||||||
|
break :blk it.next();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break :blk opt_os_or_vendor;
|
||||||
|
};
|
||||||
|
|
||||||
|
if (opt_os_text) |os_text| {
|
||||||
|
var version_str: []const u8 = undefined;
|
||||||
|
Target.parseOs(&query, os_text, &version_str) catch |er| switch (er) {
|
||||||
|
error.UnknownOs => return d.fatal("unknown operating system '{s}'", .{os_text}),
|
||||||
|
error.InvalidOsVersion => return d.fatal("invalid operating system version '{s}'", .{version_str}),
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
const opt_abi_text = it.next();
|
||||||
|
if (opt_abi_text) |abi_text| {
|
||||||
|
var version_str: []const u8 = undefined;
|
||||||
|
Target.parseAbi(&query, abi_text, &version_str) catch |er| switch (er) {
|
||||||
|
error.UnknownAbi => return d.fatal("unknown ABI '{s}'", .{abi_text}),
|
||||||
|
error.InvalidAbiVersion => return d.fatal("invalid ABI version '{s}'", .{version_str}),
|
||||||
|
error.InvalidApiVersion => return d.fatal("invalid Android API version '{s}'", .{version_str}),
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
if (it.next() != null) {
|
||||||
|
return d.fatal("unexpected extra field in target: '{s}'", .{arch_os_abi});
|
||||||
|
}
|
||||||
|
|
||||||
|
if (opt_cpu_features) |cpu_features| {
|
||||||
|
const all_features = arch.allFeaturesList();
|
||||||
|
var index: usize = 0;
|
||||||
|
while (index < cpu_features.len and
|
||||||
|
cpu_features[index] != '+' and
|
||||||
|
cpu_features[index] != '-')
|
||||||
|
{
|
||||||
|
index += 1;
|
||||||
|
}
|
||||||
|
const cpu_name = cpu_features[0..index];
|
||||||
|
|
||||||
|
const add_set = &query.cpu_features_add;
|
||||||
|
const sub_set = &query.cpu_features_sub;
|
||||||
|
if (mem.eql(u8, cpu_name, "native")) {
|
||||||
|
query.cpu_model = .native;
|
||||||
|
} else if (mem.eql(u8, cpu_name, "baseline")) {
|
||||||
|
query.cpu_model = .baseline;
|
||||||
|
} else {
|
||||||
|
query.cpu_model = .{ .explicit = arch.parseCpuModel(cpu_name) catch |er| switch (er) {
|
||||||
|
error.UnknownCpuModel => return d.fatal("unknown CPU model: '{s}'", .{cpu_name}),
|
||||||
|
} };
|
||||||
|
}
|
||||||
|
|
||||||
|
if (opt_sub_arch) |sub_arch| {
|
||||||
|
if (sub_arch.toFeature(arch)) |feature| {
|
||||||
|
add_set.addFeature(feature);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
while (index < cpu_features.len) {
|
||||||
|
const op = cpu_features[index];
|
||||||
|
const set = switch (op) {
|
||||||
|
'+' => add_set,
|
||||||
|
'-' => sub_set,
|
||||||
|
else => unreachable,
|
||||||
|
};
|
||||||
|
index += 1;
|
||||||
|
const start = index;
|
||||||
|
while (index < cpu_features.len and
|
||||||
|
cpu_features[index] != '+' and
|
||||||
|
cpu_features[index] != '-')
|
||||||
|
{
|
||||||
|
index += 1;
|
||||||
|
}
|
||||||
|
const feature_name = cpu_features[start..index];
|
||||||
|
for (all_features, 0..) |feature, feat_index_usize| {
|
||||||
|
const feat_index: std.Target.Cpu.Feature.Set.Index = @intCast(feat_index_usize);
|
||||||
|
if (mem.eql(u8, feature_name, feature.name)) {
|
||||||
|
set.addFeature(feat_index);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
return d.fatal("unknown CPU feature: '{s}'", .{feature_name});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else if (opt_sub_arch) |sub_arch| {
|
||||||
|
if (sub_arch.toFeature(arch)) |feature| {
|
||||||
|
query.cpu_features_add.addFeature(feature);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const zig_target = std.zig.system.resolveTargetQuery(d.comp.io, query) catch |e|
|
||||||
|
return d.fatal("unable to resolve target: {s}", .{errorDescription(e)});
|
||||||
|
|
||||||
|
if (query.isNative()) {
|
||||||
|
if (zig_target.os.tag.isDarwin()) {
|
||||||
|
vendor = .apple;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return .{
|
||||||
|
.cpu = zig_target.cpu,
|
||||||
|
.vendor = vendor,
|
||||||
|
.os = zig_target.os,
|
||||||
|
.abi = zig_target.abi,
|
||||||
|
.ofmt = zig_target.ofmt,
|
||||||
|
.dynamic_linker = zig_target.dynamic_linker,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
pub fn fatal(d: *Driver, comptime fmt: []const u8, args: anytype) error{ FatalError, OutOfMemory } {
|
pub fn fatal(d: *Driver, comptime fmt: []const u8, args: anytype) error{ FatalError, OutOfMemory } {
|
||||||
var sf = std.heap.stackFallback(1024, d.comp.gpa);
|
var sf = std.heap.stackFallback(1024, d.comp.gpa);
|
||||||
var allocating: std.Io.Writer.Allocating = .init(sf.get());
|
var allocating: std.Io.Writer.Allocating = .init(sf.get());
|
||||||
@ -971,8 +1142,9 @@ pub fn main(d: *Driver, tc: *Toolchain, args: []const []const u8, comptime fast_
|
|||||||
};
|
};
|
||||||
tc.defineSystemIncludes() catch |er| switch (er) {
|
tc.defineSystemIncludes() catch |er| switch (er) {
|
||||||
error.OutOfMemory => return error.OutOfMemory,
|
error.OutOfMemory => return error.OutOfMemory,
|
||||||
error.AroIncludeNotFound => return d.fatal("unable to find Aro builtin headers", .{}),
|
error.FatalError => return error.FatalError,
|
||||||
};
|
};
|
||||||
|
try d.comp.initSearchPath(d.includes.items, d.verbose_search_path);
|
||||||
|
|
||||||
const builtin_macros = d.comp.generateBuiltinMacros(d.system_defines) catch |er| switch (er) {
|
const builtin_macros = d.comp.generateBuiltinMacros(d.system_defines) catch |er| switch (er) {
|
||||||
error.FileTooBig => return d.fatal("builtin macro source exceeded max size", .{}),
|
error.FileTooBig => return d.fatal("builtin macro source exceeded max size", .{}),
|
||||||
@ -1110,6 +1282,7 @@ fn processSource(
|
|||||||
comptime fast_exit: bool,
|
comptime fast_exit: bool,
|
||||||
asm_gen_fn: ?AsmCodeGenFn,
|
asm_gen_fn: ?AsmCodeGenFn,
|
||||||
) !void {
|
) !void {
|
||||||
|
const gpa = d.comp.gpa;
|
||||||
d.comp.generated_buf.items.len = 0;
|
d.comp.generated_buf.items.len = 0;
|
||||||
const prev_total = d.diagnostics.errors;
|
const prev_total = d.diagnostics.errors;
|
||||||
|
|
||||||
@ -1118,7 +1291,7 @@ fn processSource(
|
|||||||
|
|
||||||
var name_buf: [std.fs.max_name_bytes]u8 = undefined;
|
var name_buf: [std.fs.max_name_bytes]u8 = undefined;
|
||||||
var opt_dep_file = try d.initDepFile(source, &name_buf, false);
|
var opt_dep_file = try d.initDepFile(source, &name_buf, false);
|
||||||
defer if (opt_dep_file) |*dep_file| dep_file.deinit(d.comp.gpa);
|
defer if (opt_dep_file) |*dep_file| dep_file.deinit(gpa);
|
||||||
|
|
||||||
if (opt_dep_file) |*dep_file| pp.dep_file = dep_file;
|
if (opt_dep_file) |*dep_file| pp.dep_file = dep_file;
|
||||||
|
|
||||||
@ -1138,7 +1311,13 @@ fn processSource(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
try pp.preprocessSources(&.{ source, builtin, user_macros });
|
try pp.preprocessSources(.{
|
||||||
|
.main = source,
|
||||||
|
.builtin = builtin,
|
||||||
|
.command_line = user_macros,
|
||||||
|
.imacros = d.imacros.items,
|
||||||
|
.implicit_includes = d.implicit_includes.items,
|
||||||
|
});
|
||||||
|
|
||||||
var writer_buf: [4096]u8 = undefined;
|
var writer_buf: [4096]u8 = undefined;
|
||||||
if (opt_dep_file) |dep_file| {
|
if (opt_dep_file) |dep_file| {
|
||||||
@ -1219,8 +1398,8 @@ fn processSource(
|
|||||||
.{},
|
.{},
|
||||||
);
|
);
|
||||||
|
|
||||||
const assembly = try asm_fn(d.comp.target, &tree);
|
const assembly = try asm_fn(d.comp.target.toZigTarget(), &tree);
|
||||||
defer assembly.deinit(d.comp.gpa);
|
defer assembly.deinit(gpa);
|
||||||
|
|
||||||
if (d.only_preprocess_and_compile) {
|
if (d.only_preprocess_and_compile) {
|
||||||
const out_file = d.comp.cwd.createFile(out_file_name, .{}) catch |er|
|
const out_file = d.comp.cwd.createFile(out_file_name, .{}) catch |er|
|
||||||
@ -1249,20 +1428,20 @@ fn processSource(
|
|||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
var ir = try tree.genIr();
|
var ir = try tree.genIr();
|
||||||
defer ir.deinit(d.comp.gpa);
|
defer ir.deinit(gpa);
|
||||||
|
|
||||||
if (d.verbose_ir) {
|
if (d.verbose_ir) {
|
||||||
var stdout = std.fs.File.stdout().writer(&writer_buf);
|
var stdout = std.fs.File.stdout().writer(&writer_buf);
|
||||||
ir.dump(d.comp.gpa, d.detectConfig(stdout.file), &stdout.interface) catch {};
|
ir.dump(gpa, d.detectConfig(stdout.file), &stdout.interface) catch {};
|
||||||
}
|
}
|
||||||
|
|
||||||
var render_errors: Ir.Renderer.ErrorList = .{};
|
var render_errors: Ir.Renderer.ErrorList = .{};
|
||||||
defer {
|
defer {
|
||||||
for (render_errors.values()) |msg| d.comp.gpa.free(msg);
|
for (render_errors.values()) |msg| gpa.free(msg);
|
||||||
render_errors.deinit(d.comp.gpa);
|
render_errors.deinit(gpa);
|
||||||
}
|
}
|
||||||
|
|
||||||
var obj = ir.render(d.comp.gpa, d.comp.target, &render_errors) catch |e| switch (e) {
|
var obj = ir.render(gpa, d.comp.target.toZigTarget(), &render_errors) catch |e| switch (e) {
|
||||||
error.OutOfMemory => return error.OutOfMemory,
|
error.OutOfMemory => return error.OutOfMemory,
|
||||||
error.LowerFail => {
|
error.LowerFail => {
|
||||||
return d.fatal(
|
return d.fatal(
|
||||||
@ -1286,8 +1465,8 @@ fn processSource(
|
|||||||
if (fast_exit) std.process.exit(0); // Not linking, no need for cleanup.
|
if (fast_exit) std.process.exit(0); // Not linking, no need for cleanup.
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
try d.link_objects.ensureUnusedCapacity(d.comp.gpa, 1);
|
try d.link_objects.ensureUnusedCapacity(gpa, 1);
|
||||||
d.link_objects.appendAssumeCapacity(try d.comp.gpa.dupe(u8, out_file_name));
|
d.link_objects.appendAssumeCapacity(try gpa.dupe(u8, out_file_name));
|
||||||
d.temp_file_count += 1;
|
d.temp_file_count += 1;
|
||||||
if (fast_exit) {
|
if (fast_exit) {
|
||||||
try d.invokeLinker(tc, fast_exit);
|
try d.invokeLinker(tc, fast_exit);
|
||||||
@ -1357,17 +1536,17 @@ fn exitWithCleanup(d: *Driver, code: u8) noreturn {
|
|||||||
/// Parses the various -fpic/-fPIC/-fpie/-fPIE arguments.
|
/// Parses the various -fpic/-fPIC/-fpie/-fPIE arguments.
|
||||||
/// Then, smooshes them together with platform defaults, to decide whether
|
/// Then, smooshes them together with platform defaults, to decide whether
|
||||||
/// this compile should be using PIC mode or not.
|
/// this compile should be using PIC mode or not.
|
||||||
|
/// Returns a tuple of ( backend.CodeGenOptions.PicLevel, IsPIE).
|
||||||
pub fn getPICMode(d: *Driver, lastpic: []const u8) Compilation.Error!struct { backend.CodeGenOptions.PicLevel, bool } {
|
pub fn getPICMode(d: *Driver, lastpic: []const u8) Compilation.Error!struct { backend.CodeGenOptions.PicLevel, bool } {
|
||||||
const eqlIgnoreCase = std.ascii.eqlIgnoreCase;
|
const eqlIgnoreCase = std.ascii.eqlIgnoreCase;
|
||||||
|
|
||||||
const target = d.comp.target;
|
const target = &d.comp.target;
|
||||||
|
const is_pie_default = switch (target.isPIEDefault()) {
|
||||||
const is_pie_default = switch (target_util.isPIEDefault(target)) {
|
|
||||||
.yes => true,
|
.yes => true,
|
||||||
.no => false,
|
.no => false,
|
||||||
.depends_on_linker => false,
|
.depends_on_linker => false,
|
||||||
};
|
};
|
||||||
const is_pic_default = switch (target_util.isPICdefault(target)) {
|
const is_pic_default = switch (target.isPICdefault()) {
|
||||||
.yes => true,
|
.yes => true,
|
||||||
.no => false,
|
.no => false,
|
||||||
.depends_on_linker => false,
|
.depends_on_linker => false,
|
||||||
@ -1423,7 +1602,7 @@ pub fn getPICMode(d: *Driver, lastpic: []const u8) Compilation.Error!struct { ba
|
|||||||
// '-fno-...' arguments, both PIC and PIE are disabled. Any PIE
|
// '-fno-...' arguments, both PIC and PIE are disabled. Any PIE
|
||||||
// option implicitly enables PIC at the same level.
|
// option implicitly enables PIC at the same level.
|
||||||
if (target.os.tag == .windows and
|
if (target.os.tag == .windows and
|
||||||
!target_util.isCygwinMinGW(target) and
|
!target.isMinGW() and
|
||||||
(eqlIgnoreCase(lastpic, "-fpic") or eqlIgnoreCase(lastpic, "-fpie"))) // -fpic/-fPIC, -fpie/-fPIE
|
(eqlIgnoreCase(lastpic, "-fpic") or eqlIgnoreCase(lastpic, "-fpie"))) // -fpic/-fPIC, -fpie/-fPIE
|
||||||
{
|
{
|
||||||
try d.unsupportedOptionForTarget(target, lastpic);
|
try d.unsupportedOptionForTarget(target, lastpic);
|
||||||
@ -1434,7 +1613,7 @@ pub fn getPICMode(d: *Driver, lastpic: []const u8) Compilation.Error!struct { ba
|
|||||||
|
|
||||||
// Check whether the tool chain trumps the PIC-ness decision. If the PIC-ness
|
// Check whether the tool chain trumps the PIC-ness decision. If the PIC-ness
|
||||||
// is forced, then neither PIC nor PIE flags will have no effect.
|
// is forced, then neither PIC nor PIE flags will have no effect.
|
||||||
const forced = switch (target_util.isPICDefaultForced(target)) {
|
const forced = switch (target.isPICDefaultForced()) {
|
||||||
.yes => true,
|
.yes => true,
|
||||||
.no => false,
|
.no => false,
|
||||||
.depends_on_linker => false,
|
.depends_on_linker => false,
|
||||||
@ -1447,7 +1626,7 @@ pub fn getPICMode(d: *Driver, lastpic: []const u8) Compilation.Error!struct { ba
|
|||||||
is_piclevel_two = mem.eql(u8, lastpic, "-fPIE") or mem.eql(u8, lastpic, "-fPIC");
|
is_piclevel_two = mem.eql(u8, lastpic, "-fPIE") or mem.eql(u8, lastpic, "-fPIC");
|
||||||
} else {
|
} else {
|
||||||
pic, pie = .{ false, false };
|
pic, pie = .{ false, false };
|
||||||
if (target_util.isPS(target)) {
|
if (target.isPS()) {
|
||||||
if (d.comp.cmodel != .kernel) {
|
if (d.comp.cmodel != .kernel) {
|
||||||
pic = true;
|
pic = true;
|
||||||
try d.warn(
|
try d.warn(
|
||||||
@ -1459,7 +1638,7 @@ pub fn getPICMode(d: *Driver, lastpic: []const u8) Compilation.Error!struct { ba
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (pic and (target.os.tag.isDarwin() or target_util.isPS(target))) {
|
if (pic and (target.os.tag.isDarwin() or target.isPS())) {
|
||||||
is_piclevel_two = is_piclevel_two or is_pic_default;
|
is_piclevel_two = is_piclevel_two or is_pic_default;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
31
lib/compiler/aro/aro/Driver/Distro.zig
vendored
31
lib/compiler/aro/aro/Driver/Distro.zig
vendored
@ -2,7 +2,8 @@
|
|||||||
|
|
||||||
const std = @import("std");
|
const std = @import("std");
|
||||||
const mem = std.mem;
|
const mem = std.mem;
|
||||||
const Filesystem = @import("Filesystem.zig").Filesystem;
|
const Target = @import("../Target.zig");
|
||||||
|
const Toolchain = @import("../Toolchain.zig");
|
||||||
|
|
||||||
const MAX_BYTES = 1024; // TODO: Can we assume 1024 bytes enough for the info we need?
|
const MAX_BYTES = 1024; // TODO: Can we assume 1024 bytes enough for the info we need?
|
||||||
|
|
||||||
@ -168,9 +169,9 @@ fn scanForOsRelease(buf: []const u8) ?Tag {
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
fn detectOsRelease(fs: Filesystem) ?Tag {
|
fn detectOsRelease(tc: *const Toolchain) ?Tag {
|
||||||
var buf: [MAX_BYTES]u8 = undefined;
|
var buf: [MAX_BYTES]u8 = undefined;
|
||||||
const data = fs.readFile("/etc/os-release", &buf) orelse fs.readFile("/usr/lib/os-release", &buf) orelse return null;
|
const data = tc.readFile("/etc/os-release", &buf) orelse tc.readFile("/usr/lib/os-release", &buf) orelse return null;
|
||||||
return scanForOsRelease(data);
|
return scanForOsRelease(data);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -215,9 +216,9 @@ fn scanForLSBRelease(buf: []const u8) ?Tag {
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
fn detectLSBRelease(fs: Filesystem) ?Tag {
|
fn detectLSBRelease(tc: *const Toolchain) ?Tag {
|
||||||
var buf: [MAX_BYTES]u8 = undefined;
|
var buf: [MAX_BYTES]u8 = undefined;
|
||||||
const data = fs.readFile("/etc/lsb-release", &buf) orelse return null;
|
const data = tc.readFile("/etc/lsb-release", &buf) orelse return null;
|
||||||
|
|
||||||
return scanForLSBRelease(data);
|
return scanForLSBRelease(data);
|
||||||
}
|
}
|
||||||
@ -233,9 +234,9 @@ fn scanForRedHat(buf: []const u8) Tag {
|
|||||||
return .unknown;
|
return .unknown;
|
||||||
}
|
}
|
||||||
|
|
||||||
fn detectRedhat(fs: Filesystem) ?Tag {
|
fn detectRedhat(tc: *const Toolchain) ?Tag {
|
||||||
var buf: [MAX_BYTES]u8 = undefined;
|
var buf: [MAX_BYTES]u8 = undefined;
|
||||||
const data = fs.readFile("/etc/redhat-release", &buf) orelse return null;
|
const data = tc.readFile("/etc/redhat-release", &buf) orelse return null;
|
||||||
return scanForRedHat(data);
|
return scanForRedHat(data);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -269,21 +270,21 @@ fn scanForDebian(buf: []const u8) Tag {
|
|||||||
return .unknown;
|
return .unknown;
|
||||||
}
|
}
|
||||||
|
|
||||||
fn detectDebian(fs: Filesystem) ?Tag {
|
fn detectDebian(tc: *const Toolchain) ?Tag {
|
||||||
var buf: [MAX_BYTES]u8 = undefined;
|
var buf: [MAX_BYTES]u8 = undefined;
|
||||||
const data = fs.readFile("/etc/debian_version", &buf) orelse return null;
|
const data = tc.readFile("/etc/debian_version", &buf) orelse return null;
|
||||||
return scanForDebian(data);
|
return scanForDebian(data);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn detect(target: std.Target, fs: Filesystem) Tag {
|
pub fn detect(target: *const Target, tc: *const Toolchain) Tag {
|
||||||
if (target.os.tag != .linux) return .unknown;
|
if (target.os.tag != .linux) return .unknown;
|
||||||
|
|
||||||
if (detectOsRelease(fs)) |tag| return tag;
|
if (detectOsRelease(tc)) |tag| return tag;
|
||||||
if (detectLSBRelease(fs)) |tag| return tag;
|
if (detectLSBRelease(tc)) |tag| return tag;
|
||||||
if (detectRedhat(fs)) |tag| return tag;
|
if (detectRedhat(tc)) |tag| return tag;
|
||||||
if (detectDebian(fs)) |tag| return tag;
|
if (detectDebian(tc)) |tag| return tag;
|
||||||
|
|
||||||
if (fs.exists("/etc/gentoo-release")) return .gentoo;
|
if (tc.exists("/etc/gentoo-release")) return .gentoo;
|
||||||
|
|
||||||
return .unknown;
|
return .unknown;
|
||||||
}
|
}
|
||||||
|
|||||||
10
lib/compiler/aro/aro/Driver/Multilib.zig
vendored
10
lib/compiler/aro/aro/Driver/Multilib.zig
vendored
@ -1,5 +1,5 @@
|
|||||||
const std = @import("std");
|
const std = @import("std");
|
||||||
const Filesystem = @import("Filesystem.zig").Filesystem;
|
const Toolchain = @import("../Toolchain.zig");
|
||||||
|
|
||||||
/// Large enough for GCCDetector for Linux; may need to be increased to support other toolchains.
|
/// Large enough for GCCDetector for Linux; may need to be increased to support other toolchains.
|
||||||
const max_multilibs = 4;
|
const max_multilibs = 4;
|
||||||
@ -10,10 +10,10 @@ pub const Detected = struct {
|
|||||||
selected: Multilib = .{},
|
selected: Multilib = .{},
|
||||||
biarch_sibling: ?Multilib = null,
|
biarch_sibling: ?Multilib = null,
|
||||||
|
|
||||||
pub fn filter(d: *Detected, multilib_filter: Filter, fs: Filesystem) void {
|
pub fn filter(d: *Detected, multilib_filter: Filter, tc: *const Toolchain) void {
|
||||||
var found_count: u8 = 0;
|
var found_count: u8 = 0;
|
||||||
for (d.multilibs()) |multilib| {
|
for (d.multilibs()) |multilib| {
|
||||||
if (multilib_filter.exists(multilib, fs)) {
|
if (multilib_filter.exists(multilib, tc)) {
|
||||||
d.multilib_buf[found_count] = multilib;
|
d.multilib_buf[found_count] = multilib;
|
||||||
found_count += 1;
|
found_count += 1;
|
||||||
}
|
}
|
||||||
@ -51,8 +51,8 @@ pub const Detected = struct {
|
|||||||
pub const Filter = struct {
|
pub const Filter = struct {
|
||||||
base: [2][]const u8,
|
base: [2][]const u8,
|
||||||
file: []const u8,
|
file: []const u8,
|
||||||
pub fn exists(self: Filter, m: Multilib, fs: Filesystem) bool {
|
pub fn exists(self: Filter, m: Multilib, tc: *const Toolchain) bool {
|
||||||
return fs.joinedExists(&.{ self.base[0], self.base[1], m.gcc_suffix, self.file });
|
return tc.joinedExists(&.{ self.base[0], self.base[1], m.gcc_suffix, self.file });
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
3
lib/compiler/aro/aro/Hideset.zig
vendored
3
lib/compiler/aro/aro/Hideset.zig
vendored
@ -22,11 +22,12 @@ const Identifier = struct {
|
|||||||
byte_offset: u32 = 0,
|
byte_offset: u32 = 0,
|
||||||
|
|
||||||
fn slice(self: Identifier, comp: *const Compilation) []const u8 {
|
fn slice(self: Identifier, comp: *const Compilation) []const u8 {
|
||||||
var tmp_tokenizer = Tokenizer{
|
var tmp_tokenizer: Tokenizer = .{
|
||||||
.buf = comp.getSource(self.id).buf,
|
.buf = comp.getSource(self.id).buf,
|
||||||
.langopts = comp.langopts,
|
.langopts = comp.langopts,
|
||||||
.index = self.byte_offset,
|
.index = self.byte_offset,
|
||||||
.source = .generated,
|
.source = .generated,
|
||||||
|
.splice_locs = &.{},
|
||||||
};
|
};
|
||||||
const res = tmp_tokenizer.next();
|
const res = tmp_tokenizer.next();
|
||||||
return tmp_tokenizer.buf[res.start..res.end];
|
return tmp_tokenizer.buf[res.start..res.end];
|
||||||
|
|||||||
728
lib/compiler/aro/aro/Parser.zig
vendored
728
lib/compiler/aro/aro/Parser.zig
vendored
File diff suppressed because it is too large
Load Diff
70
lib/compiler/aro/aro/Parser/Diagnostic.zig
vendored
70
lib/compiler/aro/aro/Parser/Diagnostic.zig
vendored
@ -1348,6 +1348,11 @@ pub const invalid_asm_str: Diagnostic = .{
|
|||||||
.kind = .@"error",
|
.kind = .@"error",
|
||||||
};
|
};
|
||||||
|
|
||||||
|
pub const invalid_asm_output: Diagnostic = .{
|
||||||
|
.fmt = "invalid lvalue in asm output",
|
||||||
|
.kind = .@"error",
|
||||||
|
};
|
||||||
|
|
||||||
pub const dollar_in_identifier_extension: Diagnostic = .{
|
pub const dollar_in_identifier_extension: Diagnostic = .{
|
||||||
.fmt = "'$' in identifier",
|
.fmt = "'$' in identifier",
|
||||||
.opt = .@"dollar-in-identifier-extension",
|
.opt = .@"dollar-in-identifier-extension",
|
||||||
@ -1744,6 +1749,7 @@ pub const enum_fixed: Diagnostic = .{
|
|||||||
.fmt = "enumeration types with a fixed underlying type are a Clang extension",
|
.fmt = "enumeration types with a fixed underlying type are a Clang extension",
|
||||||
.kind = .off,
|
.kind = .off,
|
||||||
.opt = .@"fixed-enum-extension",
|
.opt = .@"fixed-enum-extension",
|
||||||
|
.suppress_version = .c23,
|
||||||
.extension = true,
|
.extension = true,
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -1767,6 +1773,29 @@ pub const enum_not_representable_fixed: Diagnostic = .{
|
|||||||
.kind = .@"error",
|
.kind = .@"error",
|
||||||
};
|
};
|
||||||
|
|
||||||
|
pub const enum_forward_declaration: Diagnostic = .{
|
||||||
|
.fmt = "ISO C forbids forward references to 'enum' types",
|
||||||
|
.kind = .off,
|
||||||
|
.extension = true,
|
||||||
|
};
|
||||||
|
|
||||||
|
pub const enum_atomic_ignored: Diagnostic = .{
|
||||||
|
.fmt = "'_Atomic' qualifier ignored; operations involving the enumeration type will be non-atomic",
|
||||||
|
.kind = .@"error",
|
||||||
|
.opt = .@"underlying-atomic-qualifier-ignored",
|
||||||
|
};
|
||||||
|
|
||||||
|
pub const enum_qualifiers_ignored: Diagnostic = .{
|
||||||
|
.fmt = "qualifiers in enumeration underlying type ignored",
|
||||||
|
.kind = .warning,
|
||||||
|
.opt = .@"underlying-cv-qualifier-ignored",
|
||||||
|
};
|
||||||
|
|
||||||
|
pub const enum_invalid_underlying_type: Diagnostic = .{
|
||||||
|
.fmt = "non-integral type {qt} is an invalid underlying type",
|
||||||
|
.kind = .@"error",
|
||||||
|
};
|
||||||
|
|
||||||
pub const transparent_union_wrong_type: Diagnostic = .{
|
pub const transparent_union_wrong_type: Diagnostic = .{
|
||||||
.fmt = "'transparent_union' attribute only applies to unions",
|
.fmt = "'transparent_union' attribute only applies to unions",
|
||||||
.opt = .@"ignored-attributes",
|
.opt = .@"ignored-attributes",
|
||||||
@ -2184,6 +2213,31 @@ pub const not_floating_type: Diagnostic = .{
|
|||||||
.kind = .@"error",
|
.kind = .@"error",
|
||||||
};
|
};
|
||||||
|
|
||||||
|
pub const elementwise_type: Diagnostic = .{
|
||||||
|
.fmt = "argument must be a vector{s} (was '{qt}')",
|
||||||
|
.kind = .@"error",
|
||||||
|
};
|
||||||
|
|
||||||
|
pub const nontemporal_address_pointer: Diagnostic = .{
|
||||||
|
.fmt = "address argument to nontemporal builtin must be a pointer ('{qt}' invalid)",
|
||||||
|
.kind = .@"error",
|
||||||
|
};
|
||||||
|
|
||||||
|
pub const nontemporal_address_type: Diagnostic = .{
|
||||||
|
.fmt = "address argument to nontemporal builtin must be a pointer to integer, float, pointer, or a vector of such types ('{qt}' invalid)",
|
||||||
|
.kind = .@"error",
|
||||||
|
};
|
||||||
|
|
||||||
|
pub const atomic_address_pointer: Diagnostic = .{
|
||||||
|
.fmt = "address argument to atomic builtin must be a pointer ('{qt}' invalid)",
|
||||||
|
.kind = .@"error",
|
||||||
|
};
|
||||||
|
|
||||||
|
pub const atomic_address_type: Diagnostic = .{
|
||||||
|
.fmt = "address argument to atomic builtin must be a pointer to an integer or a pointer types ('{qt}' invalid)",
|
||||||
|
.kind = .@"error",
|
||||||
|
};
|
||||||
|
|
||||||
pub const argument_types_differ: Diagnostic = .{
|
pub const argument_types_differ: Diagnostic = .{
|
||||||
.fmt = "arguments are of different types ({qt} vs {qt})",
|
.fmt = "arguments are of different types ({qt} vs {qt})",
|
||||||
.kind = .@"error",
|
.kind = .@"error",
|
||||||
@ -2304,12 +2358,6 @@ pub const overflow_result_requires_ptr: Diagnostic = .{
|
|||||||
pub const attribute_todo: Diagnostic = .{
|
pub const attribute_todo: Diagnostic = .{
|
||||||
.fmt = "TODO: implement '{s}' attribute for {s}",
|
.fmt = "TODO: implement '{s}' attribute for {s}",
|
||||||
.kind = .warning,
|
.kind = .warning,
|
||||||
.opt = .@"attribute-todo",
|
|
||||||
};
|
|
||||||
|
|
||||||
pub const invalid_type_underlying_enum: Diagnostic = .{
|
|
||||||
.fmt = "non-integral type {qt} is an invalid underlying type",
|
|
||||||
.kind = .@"error",
|
|
||||||
};
|
};
|
||||||
|
|
||||||
pub const auto_type_self_initialized: Diagnostic = .{
|
pub const auto_type_self_initialized: Diagnostic = .{
|
||||||
@ -2422,3 +2470,13 @@ pub const nonnull_not_applicable: Diagnostic = .{
|
|||||||
.kind = .warning,
|
.kind = .warning,
|
||||||
.opt = .@"ignored-attributes",
|
.opt = .@"ignored-attributes",
|
||||||
};
|
};
|
||||||
|
|
||||||
|
pub const mixing_decimal_floats: Diagnostic = .{
|
||||||
|
.fmt = "cannot mix operands of decimal floating and other floating types",
|
||||||
|
.kind = .@"error",
|
||||||
|
};
|
||||||
|
|
||||||
|
pub const invalid_attribute_location: Diagnostic = .{
|
||||||
|
.fmt = "{s} cannot appear here",
|
||||||
|
.kind = .@"error",
|
||||||
|
};
|
||||||
|
|||||||
18
lib/compiler/aro/aro/Pragma.zig
vendored
18
lib/compiler/aro/aro/Pragma.zig
vendored
@ -10,6 +10,13 @@ pub const Error = Compilation.Error || error{ UnknownPragma, StopPreprocessing }
|
|||||||
|
|
||||||
const Pragma = @This();
|
const Pragma = @This();
|
||||||
|
|
||||||
|
/// A do-nothing pragma; useful for unwrapping an optional pragma into a pragma that does nothing in the null case.
|
||||||
|
pub const do_nothing: Pragma = .{
|
||||||
|
.deinit = deinit_nothing,
|
||||||
|
};
|
||||||
|
|
||||||
|
fn deinit_nothing(_: *Pragma, _: *Compilation) void {}
|
||||||
|
|
||||||
/// Called during Preprocessor.init
|
/// Called during Preprocessor.init
|
||||||
beforePreprocess: ?*const fn (*Pragma, *Compilation) void = null,
|
beforePreprocess: ?*const fn (*Pragma, *Compilation) void = null,
|
||||||
|
|
||||||
@ -40,6 +47,12 @@ preserveTokens: ?*const fn (*Pragma, *Preprocessor, start_idx: TokenIndex) bool
|
|||||||
/// The parser's `p.tok_i` field must not be changed
|
/// The parser's `p.tok_i` field must not be changed
|
||||||
parserHandler: ?*const fn (*Pragma, *Parser, start_idx: TokenIndex) Compilation.Error!void = null,
|
parserHandler: ?*const fn (*Pragma, *Parser, start_idx: TokenIndex) Compilation.Error!void = null,
|
||||||
|
|
||||||
|
/// Whether to perform preprocessor token expansion on the token at index `i`. 0 is the index of the first
|
||||||
|
/// token after the name token (the name token is never expanded). Whitespace tokens are always skipped when calculating
|
||||||
|
/// token indices. For example, in `#pragma GCC warning "A warning"` token 0 is `warning` and token 1 is `"A warning"`
|
||||||
|
/// By default, all tokens are expanded; use this to override that behavior.
|
||||||
|
shouldExpandTokenAtIndexHandler: ?*const fn (*const Pragma, i: TokenIndex) bool = null,
|
||||||
|
|
||||||
pub fn pasteTokens(pp: *Preprocessor, start_idx: TokenIndex) ![]const u8 {
|
pub fn pasteTokens(pp: *Preprocessor, start_idx: TokenIndex) ![]const u8 {
|
||||||
if (pp.tokens.get(start_idx).id == .nl) return error.ExpectedStringLiteral;
|
if (pp.tokens.get(start_idx).id == .nl) return error.ExpectedStringLiteral;
|
||||||
|
|
||||||
@ -84,6 +97,11 @@ pub fn parserCB(self: *Pragma, p: *Parser, start_idx: TokenIndex) Compilation.Er
|
|||||||
if (self.parserHandler) |func| return func(self, p, start_idx);
|
if (self.parserHandler) |func| return func(self, p, start_idx);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn shouldExpandTokenAtIndex(self: *const Pragma, idx: TokenIndex) bool {
|
||||||
|
if (self.shouldExpandTokenAtIndexHandler) |func| return func(self, idx);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
pub const Diagnostic = struct {
|
pub const Diagnostic = struct {
|
||||||
fmt: []const u8,
|
fmt: []const u8,
|
||||||
kind: Diagnostics.Message.Kind,
|
kind: Diagnostics.Message.Kind,
|
||||||
|
|||||||
661
lib/compiler/aro/aro/Preprocessor.zig
vendored
661
lib/compiler/aro/aro/Preprocessor.zig
vendored
File diff suppressed because it is too large
Load Diff
16
lib/compiler/aro/aro/Preprocessor/Diagnostic.zig
vendored
16
lib/compiler/aro/aro/Preprocessor/Diagnostic.zig
vendored
@ -73,6 +73,16 @@ pub const line_invalid_filename: Diagnostic = .{
|
|||||||
.kind = .@"error",
|
.kind = .@"error",
|
||||||
};
|
};
|
||||||
|
|
||||||
|
pub const line_invalid_number: Diagnostic = .{
|
||||||
|
.fmt = "{s} directive requires a positive integer argument",
|
||||||
|
.kind = .@"error",
|
||||||
|
};
|
||||||
|
|
||||||
|
pub const line_invalid_flag: Diagnostic = .{
|
||||||
|
.fmt = "invalid flag '{s}' in line marker directive",
|
||||||
|
.kind = .@"error",
|
||||||
|
};
|
||||||
|
|
||||||
pub const unterminated_conditional_directive: Diagnostic = .{
|
pub const unterminated_conditional_directive: Diagnostic = .{
|
||||||
.fmt = "unterminated conditional directive",
|
.fmt = "unterminated conditional directive",
|
||||||
.kind = .@"error",
|
.kind = .@"error",
|
||||||
@ -456,3 +466,9 @@ pub const no_argument_variadic_macro: Diagnostic = .{
|
|||||||
.kind = .off,
|
.kind = .off,
|
||||||
.extension = true,
|
.extension = true,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
pub const pragma_once_in_main_file: Diagnostic = .{
|
||||||
|
.fmt = "#pragma once in main file",
|
||||||
|
.kind = .warning,
|
||||||
|
.opt = .@"pragma-once-outside-header",
|
||||||
|
};
|
||||||
|
|||||||
28
lib/compiler/aro/aro/Source.zig
vendored
28
lib/compiler/aro/aro/Source.zig
vendored
@ -1,9 +1,15 @@
|
|||||||
const std = @import("std");
|
const std = @import("std");
|
||||||
|
|
||||||
pub const Id = enum(u32) {
|
pub const Id = packed struct(u32) {
|
||||||
unused = 0,
|
index: enum(u31) {
|
||||||
generated = 1,
|
unused = std.math.maxInt(u31) - 0,
|
||||||
|
generated = std.math.maxInt(u31) - 1,
|
||||||
_,
|
_,
|
||||||
|
},
|
||||||
|
alias: bool = false,
|
||||||
|
|
||||||
|
pub const unused: Id = .{ .index = .unused };
|
||||||
|
pub const generated: Id = .{ .index = .generated };
|
||||||
};
|
};
|
||||||
|
|
||||||
/// Classifies the file for line marker output in -E mode
|
/// Classifies the file for line marker output in -E mode
|
||||||
@ -52,20 +58,6 @@ id: Id,
|
|||||||
splice_locs: []const u32,
|
splice_locs: []const u32,
|
||||||
kind: Kind,
|
kind: Kind,
|
||||||
|
|
||||||
/// Todo: binary search instead of scanning entire `splice_locs`.
|
|
||||||
pub fn numSplicesBefore(source: Source, byte_offset: u32) u32 {
|
|
||||||
for (source.splice_locs, 0..) |splice_offset, i| {
|
|
||||||
if (splice_offset > byte_offset) return @intCast(i);
|
|
||||||
}
|
|
||||||
return @intCast(source.splice_locs.len);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Returns the actual line number (before newline splicing) of a Location
|
|
||||||
/// This corresponds to what the user would actually see in their text editor
|
|
||||||
pub fn physicalLine(source: Source, loc: Location) u32 {
|
|
||||||
return loc.line + source.numSplicesBefore(loc.byte_offset);
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn lineCol(source: Source, loc: Location) ExpandedLocation {
|
pub fn lineCol(source: Source, loc: Location) ExpandedLocation {
|
||||||
var start: usize = 0;
|
var start: usize = 0;
|
||||||
// find the start of the line which is either a newline or a splice
|
// find the start of the line which is either a newline or a splice
|
||||||
@ -117,7 +109,7 @@ pub fn lineCol(source: Source, loc: Location) ExpandedLocation {
|
|||||||
return .{
|
return .{
|
||||||
.path = source.path,
|
.path = source.path,
|
||||||
.line = source.buf[start..nl],
|
.line = source.buf[start..nl],
|
||||||
.line_no = loc.line + splice_index,
|
.line_no = loc.line,
|
||||||
.col = col,
|
.col = col,
|
||||||
.width = width,
|
.width = width,
|
||||||
.end_with_splice = end_with_splice,
|
.end_with_splice = end_with_splice,
|
||||||
|
|||||||
1744
lib/compiler/aro/aro/Target.zig
vendored
Normal file
1744
lib/compiler/aro/aro/Target.zig
vendored
Normal file
File diff suppressed because it is too large
Load Diff
151
lib/compiler/aro/aro/Tokenizer.zig
vendored
151
lib/compiler/aro/aro/Tokenizer.zig
vendored
@ -144,6 +144,11 @@ pub const Token = struct {
|
|||||||
hash,
|
hash,
|
||||||
hash_hash,
|
hash_hash,
|
||||||
|
|
||||||
|
/// Special token for handling expansion of parameters to builtin preprocessor functions
|
||||||
|
macro_param_builtin_func,
|
||||||
|
/// Special token for implementing builtin object macros
|
||||||
|
macro_builtin_obj,
|
||||||
|
|
||||||
/// Special token to speed up preprocessing, `loc.end` will be an index to the param list.
|
/// Special token to speed up preprocessing, `loc.end` will be an index to the param list.
|
||||||
macro_param,
|
macro_param,
|
||||||
/// Special token to signal that the argument must be replaced without expansion (e.g. in concatenation)
|
/// Special token to signal that the argument must be replaced without expansion (e.g. in concatenation)
|
||||||
@ -154,40 +159,6 @@ pub const Token = struct {
|
|||||||
stringify_va_args,
|
stringify_va_args,
|
||||||
/// Special macro whitespace, always equal to a single space
|
/// Special macro whitespace, always equal to a single space
|
||||||
macro_ws,
|
macro_ws,
|
||||||
/// Special token for implementing __has_attribute
|
|
||||||
macro_param_has_attribute,
|
|
||||||
/// Special token for implementing __has_c_attribute
|
|
||||||
macro_param_has_c_attribute,
|
|
||||||
/// Special token for implementing __has_declspec_attribute
|
|
||||||
macro_param_has_declspec_attribute,
|
|
||||||
/// Special token for implementing __has_warning
|
|
||||||
macro_param_has_warning,
|
|
||||||
/// Special token for implementing __has_feature
|
|
||||||
macro_param_has_feature,
|
|
||||||
/// Special token for implementing __has_extension
|
|
||||||
macro_param_has_extension,
|
|
||||||
/// Special token for implementing __has_builtin
|
|
||||||
macro_param_has_builtin,
|
|
||||||
/// Special token for implementing __has_include
|
|
||||||
macro_param_has_include,
|
|
||||||
/// Special token for implementing __has_include_next
|
|
||||||
macro_param_has_include_next,
|
|
||||||
/// Special token for implementing __has_embed
|
|
||||||
macro_param_has_embed,
|
|
||||||
/// Special token for implementing __is_identifier
|
|
||||||
macro_param_is_identifier,
|
|
||||||
/// Special token for implementing __FILE__
|
|
||||||
macro_file,
|
|
||||||
/// Special token for implementing __LINE__
|
|
||||||
macro_line,
|
|
||||||
/// Special token for implementing __COUNTER__
|
|
||||||
macro_counter,
|
|
||||||
/// Special token for implementing _Pragma
|
|
||||||
macro_param_pragma_operator,
|
|
||||||
/// Special token for implementing __identifier (MS extension)
|
|
||||||
macro_param_ms_identifier,
|
|
||||||
/// Special token for implementing __pragma (MS extension)
|
|
||||||
macro_param_ms_pragma,
|
|
||||||
|
|
||||||
/// Special identifier for implementing __func__
|
/// Special identifier for implementing __func__
|
||||||
macro_func,
|
macro_func,
|
||||||
@ -195,12 +166,6 @@ pub const Token = struct {
|
|||||||
macro_function,
|
macro_function,
|
||||||
/// Special identifier for implementing __PRETTY_FUNCTION__
|
/// Special identifier for implementing __PRETTY_FUNCTION__
|
||||||
macro_pretty_func,
|
macro_pretty_func,
|
||||||
/// Special identifier for implementing __DATE__
|
|
||||||
macro_date,
|
|
||||||
/// Special identifier for implementing __TIME__
|
|
||||||
macro_time,
|
|
||||||
/// Special identifier for implementing __TIMESTAMP__
|
|
||||||
macro_timestamp,
|
|
||||||
|
|
||||||
keyword_auto,
|
keyword_auto,
|
||||||
keyword_auto_type,
|
keyword_auto_type,
|
||||||
@ -268,6 +233,17 @@ pub const Token = struct {
|
|||||||
keyword_false,
|
keyword_false,
|
||||||
keyword_nullptr,
|
keyword_nullptr,
|
||||||
keyword_typeof_unqual,
|
keyword_typeof_unqual,
|
||||||
|
keyword_float16,
|
||||||
|
keyword_float32,
|
||||||
|
keyword_float64,
|
||||||
|
keyword_float128,
|
||||||
|
keyword_float32x,
|
||||||
|
keyword_float64x,
|
||||||
|
keyword_float128x,
|
||||||
|
keyword_dfloat32,
|
||||||
|
keyword_dfloat64,
|
||||||
|
keyword_dfloat128,
|
||||||
|
keyword_dfloat64x,
|
||||||
|
|
||||||
// Preprocessor directives
|
// Preprocessor directives
|
||||||
keyword_include,
|
keyword_include,
|
||||||
@ -307,19 +283,17 @@ pub const Token = struct {
|
|||||||
keyword_asm,
|
keyword_asm,
|
||||||
keyword_asm1,
|
keyword_asm1,
|
||||||
keyword_asm2,
|
keyword_asm2,
|
||||||
/// _Float128
|
|
||||||
keyword_float128_1,
|
|
||||||
/// __float128
|
/// __float128
|
||||||
keyword_float128_2,
|
keyword_float128_1,
|
||||||
keyword_int128,
|
keyword_int128,
|
||||||
keyword_imag1,
|
keyword_imag1,
|
||||||
keyword_imag2,
|
keyword_imag2,
|
||||||
keyword_real1,
|
keyword_real1,
|
||||||
keyword_real2,
|
keyword_real2,
|
||||||
keyword_float16,
|
|
||||||
|
|
||||||
// clang keywords
|
// clang keywords
|
||||||
keyword_fp16,
|
keyword_fp16,
|
||||||
|
keyword_bf16,
|
||||||
|
|
||||||
// ms keywords
|
// ms keywords
|
||||||
keyword_declspec,
|
keyword_declspec,
|
||||||
@ -375,6 +349,9 @@ pub const Token = struct {
|
|||||||
/// completion of the preceding #include
|
/// completion of the preceding #include
|
||||||
include_resume,
|
include_resume,
|
||||||
|
|
||||||
|
/// Virtual linemarker token output from preprocessor to represent actual linemarker in the source file
|
||||||
|
linemarker,
|
||||||
|
|
||||||
/// A comment token if asked to preserve comments.
|
/// A comment token if asked to preserve comments.
|
||||||
comment,
|
comment,
|
||||||
|
|
||||||
@ -408,9 +385,6 @@ pub const Token = struct {
|
|||||||
.macro_func,
|
.macro_func,
|
||||||
.macro_function,
|
.macro_function,
|
||||||
.macro_pretty_func,
|
.macro_pretty_func,
|
||||||
.macro_date,
|
|
||||||
.macro_time,
|
|
||||||
.macro_timestamp,
|
|
||||||
.keyword_auto,
|
.keyword_auto,
|
||||||
.keyword_auto_type,
|
.keyword_auto_type,
|
||||||
.keyword_break,
|
.keyword_break,
|
||||||
@ -480,7 +454,6 @@ pub const Token = struct {
|
|||||||
.keyword_asm1,
|
.keyword_asm1,
|
||||||
.keyword_asm2,
|
.keyword_asm2,
|
||||||
.keyword_float128_1,
|
.keyword_float128_1,
|
||||||
.keyword_float128_2,
|
|
||||||
.keyword_int128,
|
.keyword_int128,
|
||||||
.keyword_imag1,
|
.keyword_imag1,
|
||||||
.keyword_imag2,
|
.keyword_imag2,
|
||||||
@ -488,6 +461,7 @@ pub const Token = struct {
|
|||||||
.keyword_real2,
|
.keyword_real2,
|
||||||
.keyword_float16,
|
.keyword_float16,
|
||||||
.keyword_fp16,
|
.keyword_fp16,
|
||||||
|
.keyword_bf16,
|
||||||
.keyword_declspec,
|
.keyword_declspec,
|
||||||
.keyword_int64,
|
.keyword_int64,
|
||||||
.keyword_int64_2,
|
.keyword_int64_2,
|
||||||
@ -527,6 +501,16 @@ pub const Token = struct {
|
|||||||
.keyword_false,
|
.keyword_false,
|
||||||
.keyword_nullptr,
|
.keyword_nullptr,
|
||||||
.keyword_typeof_unqual,
|
.keyword_typeof_unqual,
|
||||||
|
.keyword_float32,
|
||||||
|
.keyword_float64,
|
||||||
|
.keyword_float128,
|
||||||
|
.keyword_float32x,
|
||||||
|
.keyword_float64x,
|
||||||
|
.keyword_float128x,
|
||||||
|
.keyword_dfloat32,
|
||||||
|
.keyword_dfloat64,
|
||||||
|
.keyword_dfloat128,
|
||||||
|
.keyword_dfloat64x,
|
||||||
=> return true,
|
=> return true,
|
||||||
else => return false,
|
else => return false,
|
||||||
}
|
}
|
||||||
@ -570,6 +554,7 @@ pub const Token = struct {
|
|||||||
return switch (id) {
|
return switch (id) {
|
||||||
.include_start,
|
.include_start,
|
||||||
.include_resume,
|
.include_resume,
|
||||||
|
.linemarker,
|
||||||
=> unreachable,
|
=> unreachable,
|
||||||
|
|
||||||
.unterminated_comment,
|
.unterminated_comment,
|
||||||
@ -605,27 +590,9 @@ pub const Token = struct {
|
|||||||
.macro_param_no_expand,
|
.macro_param_no_expand,
|
||||||
.stringify_param,
|
.stringify_param,
|
||||||
.stringify_va_args,
|
.stringify_va_args,
|
||||||
.macro_param_has_attribute,
|
|
||||||
.macro_param_has_c_attribute,
|
|
||||||
.macro_param_has_declspec_attribute,
|
|
||||||
.macro_param_has_warning,
|
|
||||||
.macro_param_has_feature,
|
|
||||||
.macro_param_has_extension,
|
|
||||||
.macro_param_has_builtin,
|
|
||||||
.macro_param_has_include,
|
|
||||||
.macro_param_has_include_next,
|
|
||||||
.macro_param_has_embed,
|
|
||||||
.macro_param_is_identifier,
|
|
||||||
.macro_file,
|
|
||||||
.macro_line,
|
|
||||||
.macro_counter,
|
|
||||||
.macro_time,
|
|
||||||
.macro_date,
|
|
||||||
.macro_timestamp,
|
|
||||||
.macro_param_pragma_operator,
|
|
||||||
.macro_param_ms_identifier,
|
|
||||||
.macro_param_ms_pragma,
|
|
||||||
.placemarker,
|
.placemarker,
|
||||||
|
.macro_param_builtin_func,
|
||||||
|
.macro_builtin_obj,
|
||||||
=> "",
|
=> "",
|
||||||
.macro_ws => " ",
|
.macro_ws => " ",
|
||||||
|
|
||||||
@ -744,6 +711,17 @@ pub const Token = struct {
|
|||||||
.keyword_false => "false",
|
.keyword_false => "false",
|
||||||
.keyword_nullptr => "nullptr",
|
.keyword_nullptr => "nullptr",
|
||||||
.keyword_typeof_unqual => "typeof_unqual",
|
.keyword_typeof_unqual => "typeof_unqual",
|
||||||
|
.keyword_float16 => "_Float16",
|
||||||
|
.keyword_float32 => "_Float32",
|
||||||
|
.keyword_float64 => "_Float64",
|
||||||
|
.keyword_float128 => "_Float128",
|
||||||
|
.keyword_float32x => "_Float32x",
|
||||||
|
.keyword_float64x => "_Float64x",
|
||||||
|
.keyword_float128x => "_Float128x",
|
||||||
|
.keyword_dfloat32 => "_Decimal32",
|
||||||
|
.keyword_dfloat64 => "_Decimal64",
|
||||||
|
.keyword_dfloat128 => "_Decimal128",
|
||||||
|
.keyword_dfloat64x => "_Decimal64x",
|
||||||
.keyword_include => "include",
|
.keyword_include => "include",
|
||||||
.keyword_include_next => "include_next",
|
.keyword_include_next => "include_next",
|
||||||
.keyword_embed => "embed",
|
.keyword_embed => "embed",
|
||||||
@ -780,15 +758,14 @@ pub const Token = struct {
|
|||||||
.keyword_asm => "asm",
|
.keyword_asm => "asm",
|
||||||
.keyword_asm1 => "__asm",
|
.keyword_asm1 => "__asm",
|
||||||
.keyword_asm2 => "__asm__",
|
.keyword_asm2 => "__asm__",
|
||||||
.keyword_float128_1 => "_Float128",
|
.keyword_float128_1 => "__float128",
|
||||||
.keyword_float128_2 => "__float128",
|
|
||||||
.keyword_int128 => "__int128",
|
.keyword_int128 => "__int128",
|
||||||
.keyword_imag1 => "__imag",
|
.keyword_imag1 => "__imag",
|
||||||
.keyword_imag2 => "__imag__",
|
.keyword_imag2 => "__imag__",
|
||||||
.keyword_real1 => "__real",
|
.keyword_real1 => "__real",
|
||||||
.keyword_real2 => "__real__",
|
.keyword_real2 => "__real__",
|
||||||
.keyword_float16 => "_Float16",
|
|
||||||
.keyword_fp16 => "__fp16",
|
.keyword_fp16 => "__fp16",
|
||||||
|
.keyword_bf16 => "__bf16",
|
||||||
.keyword_declspec => "__declspec",
|
.keyword_declspec => "__declspec",
|
||||||
.keyword_int64 => "__int64",
|
.keyword_int64 => "__int64",
|
||||||
.keyword_int64_2 => "_int64",
|
.keyword_int64_2 => "_int64",
|
||||||
@ -1030,6 +1007,17 @@ pub const Token = struct {
|
|||||||
.{ "false", .keyword_false },
|
.{ "false", .keyword_false },
|
||||||
.{ "nullptr", .keyword_nullptr },
|
.{ "nullptr", .keyword_nullptr },
|
||||||
.{ "typeof_unqual", .keyword_typeof_unqual },
|
.{ "typeof_unqual", .keyword_typeof_unqual },
|
||||||
|
.{ "_Float16", .keyword_float16 },
|
||||||
|
.{ "_Float32", .keyword_float32 },
|
||||||
|
.{ "_Float64", .keyword_float64 },
|
||||||
|
.{ "_Float128", .keyword_float128 },
|
||||||
|
.{ "_Float32x", .keyword_float32x },
|
||||||
|
.{ "_Float64x", .keyword_float64x },
|
||||||
|
.{ "_Float128x", .keyword_float128x },
|
||||||
|
.{ "_Decimal32", .keyword_dfloat32 },
|
||||||
|
.{ "_Decimal64", .keyword_dfloat64 },
|
||||||
|
.{ "_Decimal128", .keyword_dfloat128 },
|
||||||
|
.{ "_Decimal64x", .keyword_dfloat64x },
|
||||||
|
|
||||||
// Preprocessor directives
|
// Preprocessor directives
|
||||||
.{ "include", .keyword_include },
|
.{ "include", .keyword_include },
|
||||||
@ -1073,17 +1061,16 @@ pub const Token = struct {
|
|||||||
.{ "asm", .keyword_asm },
|
.{ "asm", .keyword_asm },
|
||||||
.{ "__asm", .keyword_asm1 },
|
.{ "__asm", .keyword_asm1 },
|
||||||
.{ "__asm__", .keyword_asm2 },
|
.{ "__asm__", .keyword_asm2 },
|
||||||
.{ "_Float128", .keyword_float128_1 },
|
.{ "__float128", .keyword_float128_1 },
|
||||||
.{ "__float128", .keyword_float128_2 },
|
|
||||||
.{ "__int128", .keyword_int128 },
|
.{ "__int128", .keyword_int128 },
|
||||||
.{ "__imag", .keyword_imag1 },
|
.{ "__imag", .keyword_imag1 },
|
||||||
.{ "__imag__", .keyword_imag2 },
|
.{ "__imag__", .keyword_imag2 },
|
||||||
.{ "__real", .keyword_real1 },
|
.{ "__real", .keyword_real1 },
|
||||||
.{ "__real__", .keyword_real2 },
|
.{ "__real__", .keyword_real2 },
|
||||||
.{ "_Float16", .keyword_float16 },
|
|
||||||
|
|
||||||
// clang keywords
|
// clang keywords
|
||||||
.{ "__fp16", .keyword_fp16 },
|
.{ "__fp16", .keyword_fp16 },
|
||||||
|
.{ "__bf16", .keyword_bf16 },
|
||||||
|
|
||||||
// ms keywords
|
// ms keywords
|
||||||
.{ "__declspec", .keyword_declspec },
|
.{ "__declspec", .keyword_declspec },
|
||||||
@ -1126,6 +1113,8 @@ index: u32 = 0,
|
|||||||
source: Source.Id,
|
source: Source.Id,
|
||||||
langopts: LangOpts,
|
langopts: LangOpts,
|
||||||
line: u32 = 1,
|
line: u32 = 1,
|
||||||
|
splice_index: u32 = 0,
|
||||||
|
splice_locs: []const u32,
|
||||||
|
|
||||||
pub fn next(self: *Tokenizer) Token {
|
pub fn next(self: *Tokenizer) Token {
|
||||||
var state: enum {
|
var state: enum {
|
||||||
@ -1909,6 +1898,12 @@ pub fn next(self: *Tokenizer) Token {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
for (self.splice_locs[self.splice_index..]) |splice_offset| {
|
||||||
|
if (splice_offset > start) break;
|
||||||
|
self.line += 1;
|
||||||
|
self.splice_index += 1;
|
||||||
|
}
|
||||||
|
|
||||||
return .{
|
return .{
|
||||||
.id = id,
|
.id = id,
|
||||||
.start = start,
|
.start = start,
|
||||||
@ -2331,7 +2326,7 @@ test "Tokenizer fuzz test" {
|
|||||||
fn testOne(_: @This(), input_bytes: []const u8) anyerror!void {
|
fn testOne(_: @This(), input_bytes: []const u8) anyerror!void {
|
||||||
var arena: std.heap.ArenaAllocator = .init(std.testing.allocator);
|
var arena: std.heap.ArenaAllocator = .init(std.testing.allocator);
|
||||||
defer arena.deinit();
|
defer arena.deinit();
|
||||||
var comp = Compilation.init(std.testing.allocator, arena.allocator(), undefined, std.fs.cwd());
|
var comp = Compilation.init(std.testing.allocator, arena.allocator(), std.testing.io, undefined, std.fs.cwd());
|
||||||
defer comp.deinit();
|
defer comp.deinit();
|
||||||
|
|
||||||
const source = try comp.addSourceFromBuffer("fuzz.c", input_bytes);
|
const source = try comp.addSourceFromBuffer("fuzz.c", input_bytes);
|
||||||
@ -2340,6 +2335,7 @@ test "Tokenizer fuzz test" {
|
|||||||
.buf = source.buf,
|
.buf = source.buf,
|
||||||
.source = source.id,
|
.source = source.id,
|
||||||
.langopts = comp.langopts,
|
.langopts = comp.langopts,
|
||||||
|
.splice_locs = &.{},
|
||||||
};
|
};
|
||||||
while (true) {
|
while (true) {
|
||||||
const prev_index = tokenizer.index;
|
const prev_index = tokenizer.index;
|
||||||
@ -2355,16 +2351,17 @@ test "Tokenizer fuzz test" {
|
|||||||
fn expectTokensExtra(contents: []const u8, expected_tokens: []const Token.Id, langopts: ?LangOpts) !void {
|
fn expectTokensExtra(contents: []const u8, expected_tokens: []const Token.Id, langopts: ?LangOpts) !void {
|
||||||
var arena: std.heap.ArenaAllocator = .init(std.testing.allocator);
|
var arena: std.heap.ArenaAllocator = .init(std.testing.allocator);
|
||||||
defer arena.deinit();
|
defer arena.deinit();
|
||||||
var comp = Compilation.init(std.testing.allocator, arena.allocator(), undefined, std.fs.cwd());
|
var comp = Compilation.init(std.testing.allocator, arena.allocator(), std.testing.io, undefined, std.fs.cwd());
|
||||||
defer comp.deinit();
|
defer comp.deinit();
|
||||||
if (langopts) |provided| {
|
if (langopts) |provided| {
|
||||||
comp.langopts = provided;
|
comp.langopts = provided;
|
||||||
}
|
}
|
||||||
const source = try comp.addSourceFromBuffer("path", contents);
|
const source = try comp.addSourceFromBuffer("path", contents);
|
||||||
var tokenizer = Tokenizer{
|
var tokenizer: Tokenizer = .{
|
||||||
.buf = source.buf,
|
.buf = source.buf,
|
||||||
.source = source.id,
|
.source = source.id,
|
||||||
.langopts = comp.langopts,
|
.langopts = comp.langopts,
|
||||||
|
.splice_locs = &.{},
|
||||||
};
|
};
|
||||||
var i: usize = 0;
|
var i: usize = 0;
|
||||||
while (i < expected_tokens.len) {
|
while (i < expected_tokens.len) {
|
||||||
|
|||||||
131
lib/compiler/aro/aro/Toolchain.zig
vendored
131
lib/compiler/aro/aro/Toolchain.zig
vendored
@ -5,9 +5,8 @@ const system_defaults = @import("system_defaults");
|
|||||||
|
|
||||||
const Compilation = @import("Compilation.zig");
|
const Compilation = @import("Compilation.zig");
|
||||||
const Driver = @import("Driver.zig");
|
const Driver = @import("Driver.zig");
|
||||||
const Filesystem = @import("Driver/Filesystem.zig").Filesystem;
|
|
||||||
const Multilib = @import("Driver/Multilib.zig");
|
const Multilib = @import("Driver/Multilib.zig");
|
||||||
const target_util = @import("target.zig");
|
const Target = @import("Target.zig");
|
||||||
|
|
||||||
pub const PathList = std.ArrayList([]const u8);
|
pub const PathList = std.ArrayList([]const u8);
|
||||||
|
|
||||||
@ -41,7 +40,6 @@ const Inner = union(enum) {
|
|||||||
|
|
||||||
const Toolchain = @This();
|
const Toolchain = @This();
|
||||||
|
|
||||||
filesystem: Filesystem,
|
|
||||||
driver: *Driver,
|
driver: *Driver,
|
||||||
|
|
||||||
/// The list of toolchain specific path prefixes to search for libraries.
|
/// The list of toolchain specific path prefixes to search for libraries.
|
||||||
@ -57,8 +55,8 @@ selected_multilib: Multilib = .{},
|
|||||||
|
|
||||||
inner: Inner = .{ .uninitialized = {} },
|
inner: Inner = .{ .uninitialized = {} },
|
||||||
|
|
||||||
pub fn getTarget(tc: *const Toolchain) std.Target {
|
pub fn getTarget(tc: *const Toolchain) *const Target {
|
||||||
return tc.driver.comp.target;
|
return &tc.driver.comp.target;
|
||||||
}
|
}
|
||||||
|
|
||||||
fn getDefaultLinker(tc: *const Toolchain) []const u8 {
|
fn getDefaultLinker(tc: *const Toolchain) []const u8 {
|
||||||
@ -107,7 +105,7 @@ pub fn getLinkerPath(tc: *const Toolchain, buf: []u8) ![]const u8 {
|
|||||||
if (std.fs.path.dirname(path) == null) {
|
if (std.fs.path.dirname(path) == null) {
|
||||||
path = tc.getProgramPath(path, buf);
|
path = tc.getProgramPath(path, buf);
|
||||||
}
|
}
|
||||||
if (tc.filesystem.canExecute(path)) {
|
if (tc.canExecute(path)) {
|
||||||
return path;
|
return path;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -139,7 +137,7 @@ pub fn getLinkerPath(tc: *const Toolchain, buf: []u8) ![]const u8 {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (std.fs.path.isAbsolute(use_linker)) {
|
if (std.fs.path.isAbsolute(use_linker)) {
|
||||||
if (tc.filesystem.canExecute(use_linker)) {
|
if (tc.canExecute(use_linker)) {
|
||||||
return use_linker;
|
return use_linker;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
@ -155,7 +153,7 @@ pub fn getLinkerPath(tc: *const Toolchain, buf: []u8) ![]const u8 {
|
|||||||
}
|
}
|
||||||
linker_name.appendSliceAssumeCapacity(use_linker);
|
linker_name.appendSliceAssumeCapacity(use_linker);
|
||||||
const linker_path = tc.getProgramPath(linker_name.items, buf);
|
const linker_path = tc.getProgramPath(linker_name.items, buf);
|
||||||
if (tc.filesystem.canExecute(linker_path)) {
|
if (tc.canExecute(linker_path)) {
|
||||||
return linker_path;
|
return linker_path;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -227,12 +225,12 @@ fn getProgramPath(tc: *const Toolchain, name: []const u8, buf: []u8) []const u8
|
|||||||
|
|
||||||
const candidate = std.fs.path.join(fib.allocator(), &.{ program_path, tool_name }) catch continue;
|
const candidate = std.fs.path.join(fib.allocator(), &.{ program_path, tool_name }) catch continue;
|
||||||
|
|
||||||
if (tc.filesystem.canExecute(candidate) and candidate.len <= buf.len) {
|
if (tc.canExecute(candidate) and candidate.len <= buf.len) {
|
||||||
@memcpy(buf[0..candidate.len], candidate);
|
@memcpy(buf[0..candidate.len], candidate);
|
||||||
return buf[0..candidate.len];
|
return buf[0..candidate.len];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return tc.filesystem.findProgramByName(tc.driver.comp.gpa, name, tc.driver.comp.environment.path, buf) orelse continue;
|
return tc.findProgramByName(name, buf) orelse continue;
|
||||||
}
|
}
|
||||||
@memcpy(buf[0..name.len], name);
|
@memcpy(buf[0..name.len], name);
|
||||||
return buf[0..name.len];
|
return buf[0..name.len];
|
||||||
@ -256,7 +254,7 @@ pub fn getFilePath(tc: *const Toolchain, name: []const u8) ![]const u8 {
|
|||||||
// todo check compiler RT path
|
// todo check compiler RT path
|
||||||
const aro_dir = std.fs.path.dirname(tc.driver.aro_name) orelse "";
|
const aro_dir = std.fs.path.dirname(tc.driver.aro_name) orelse "";
|
||||||
const candidate = try std.fs.path.join(allocator, &.{ aro_dir, "..", name });
|
const candidate = try std.fs.path.join(allocator, &.{ aro_dir, "..", name });
|
||||||
if (tc.filesystem.exists(candidate)) {
|
if (tc.exists(candidate)) {
|
||||||
return arena.dupe(u8, candidate);
|
return arena.dupe(u8, candidate);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -283,7 +281,7 @@ fn searchPaths(tc: *const Toolchain, fib: *std.heap.FixedBufferAllocator, sysroo
|
|||||||
else
|
else
|
||||||
std.fs.path.join(fib.allocator(), &.{ path, name }) catch continue;
|
std.fs.path.join(fib.allocator(), &.{ path, name }) catch continue;
|
||||||
|
|
||||||
if (tc.filesystem.exists(candidate)) {
|
if (tc.exists(candidate)) {
|
||||||
return candidate;
|
return candidate;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -304,7 +302,7 @@ pub fn addPathIfExists(tc: *Toolchain, components: []const []const u8, dest_kind
|
|||||||
|
|
||||||
const candidate = try std.fs.path.join(fib.allocator(), components);
|
const candidate = try std.fs.path.join(fib.allocator(), components);
|
||||||
|
|
||||||
if (tc.filesystem.exists(candidate)) {
|
if (tc.exists(candidate)) {
|
||||||
const duped = try tc.driver.comp.arena.dupe(u8, candidate);
|
const duped = try tc.driver.comp.arena.dupe(u8, candidate);
|
||||||
const dest = switch (dest_kind) {
|
const dest = switch (dest_kind) {
|
||||||
.library => &tc.library_paths,
|
.library => &tc.library_paths,
|
||||||
@ -404,11 +402,11 @@ fn addUnwindLibrary(tc: *const Toolchain, argv: *std.ArrayList([]const u8)) !voi
|
|||||||
const target = tc.getTarget();
|
const target = tc.getTarget();
|
||||||
if ((target.abi.isAndroid() and unw == .libgcc) or
|
if ((target.abi.isAndroid() and unw == .libgcc) or
|
||||||
target.ofmt == .wasm or
|
target.ofmt == .wasm or
|
||||||
target_util.isWindowsMSVCEnvironment(target) or
|
target.isWindowsMSVCEnvironment() or
|
||||||
unw == .none) return;
|
unw == .none) return;
|
||||||
|
|
||||||
const lgk = tc.getLibGCCKind();
|
const lgk = tc.getLibGCCKind();
|
||||||
const as_needed = lgk == .unspecified and !target.abi.isAndroid() and !target_util.isCygwinMinGW(target);
|
const as_needed = lgk == .unspecified and !target.abi.isAndroid() and !target.isMinGW();
|
||||||
|
|
||||||
try argv.ensureUnusedCapacity(tc.driver.comp.gpa, 3);
|
try argv.ensureUnusedCapacity(tc.driver.comp.gpa, 3);
|
||||||
if (as_needed) {
|
if (as_needed) {
|
||||||
@ -420,7 +418,7 @@ fn addUnwindLibrary(tc: *const Toolchain, argv: *std.ArrayList([]const u8)) !voi
|
|||||||
.compiler_rt => if (lgk == .static) {
|
.compiler_rt => if (lgk == .static) {
|
||||||
argv.appendAssumeCapacity("-l:libunwind.a");
|
argv.appendAssumeCapacity("-l:libunwind.a");
|
||||||
} else if (lgk == .shared) {
|
} else if (lgk == .shared) {
|
||||||
if (target_util.isCygwinMinGW(target)) {
|
if (target.isMinGW()) {
|
||||||
argv.appendAssumeCapacity("-l:libunwind.dll.a");
|
argv.appendAssumeCapacity("-l:libunwind.dll.a");
|
||||||
} else {
|
} else {
|
||||||
argv.appendAssumeCapacity("-l:libunwind.so");
|
argv.appendAssumeCapacity("-l:libunwind.so");
|
||||||
@ -455,7 +453,7 @@ pub fn addRuntimeLibs(tc: *const Toolchain, argv: *std.ArrayList([]const u8)) !v
|
|||||||
// TODO
|
// TODO
|
||||||
},
|
},
|
||||||
.libgcc => {
|
.libgcc => {
|
||||||
if (target_util.isKnownWindowsMSVCEnvironment(target)) {
|
if (target.isKnownWindowsMSVCEnvironment()) {
|
||||||
const rtlib_str = tc.driver.rtlib orelse system_defaults.rtlib;
|
const rtlib_str = tc.driver.rtlib orelse system_defaults.rtlib;
|
||||||
if (!mem.eql(u8, rtlib_str, "platform")) {
|
if (!mem.eql(u8, rtlib_str, "platform")) {
|
||||||
try tc.driver.err("unsupported runtime library 'libgcc' for platform 'MSVC'", .{});
|
try tc.driver.err("unsupported runtime library 'libgcc' for platform 'MSVC'", .{});
|
||||||
@ -477,14 +475,107 @@ pub fn defineSystemIncludes(tc: *Toolchain) !void {
|
|||||||
.unknown => {
|
.unknown => {
|
||||||
if (tc.driver.nostdinc) return;
|
if (tc.driver.nostdinc) return;
|
||||||
|
|
||||||
const comp = tc.driver.comp;
|
|
||||||
if (!tc.driver.nobuiltininc) {
|
if (!tc.driver.nobuiltininc) {
|
||||||
try comp.addBuiltinIncludeDir(tc.driver.aro_name, tc.driver.resource_dir);
|
try tc.addBuiltinIncludeDir();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!tc.driver.nostdlibinc) {
|
if (!tc.driver.nostdlibinc) {
|
||||||
try comp.addSystemIncludeDir("/usr/include");
|
try tc.addSystemIncludeDir("/usr/include");
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn addSystemIncludeDir(tc: *const Toolchain, path: []const u8) !void {
|
||||||
|
const d = tc.driver;
|
||||||
|
_ = try d.includes.append(d.comp.gpa, .{ .kind = .system, .path = try d.comp.arena.dupe(u8, path) });
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Add built-in aro headers directory to system include paths
|
||||||
|
pub fn addBuiltinIncludeDir(tc: *const Toolchain) !void {
|
||||||
|
const d = tc.driver;
|
||||||
|
const comp = d.comp;
|
||||||
|
const gpa = comp.gpa;
|
||||||
|
const arena = comp.arena;
|
||||||
|
try d.includes.ensureUnusedCapacity(gpa, 1);
|
||||||
|
if (d.resource_dir) |resource_dir| {
|
||||||
|
const path = try std.fs.path.join(arena, &.{ resource_dir, "include" });
|
||||||
|
comp.cwd.access(path, .{}) catch {
|
||||||
|
return d.fatal("Aro builtin headers not found in provided -resource-dir", .{});
|
||||||
|
};
|
||||||
|
d.includes.appendAssumeCapacity(.{ .kind = .system, .path = path });
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
var search_path = d.aro_name;
|
||||||
|
while (std.fs.path.dirname(search_path)) |dirname| : (search_path = dirname) {
|
||||||
|
var base_dir = d.comp.cwd.openDir(dirname, .{}) catch continue;
|
||||||
|
defer base_dir.close();
|
||||||
|
|
||||||
|
base_dir.access("include/stddef.h", .{}) catch continue;
|
||||||
|
const path = try std.fs.path.join(arena, &.{ dirname, "include" });
|
||||||
|
d.includes.appendAssumeCapacity(.{ .kind = .system, .path = path });
|
||||||
|
break;
|
||||||
|
} else return d.fatal("unable to find Aro builtin headers", .{});
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Read the file at `path` into `buf`.
|
||||||
|
/// Returns null if any errors are encountered
|
||||||
|
/// Otherwise returns a slice of `buf`. If the file is larger than `buf` partial contents are returned
|
||||||
|
pub fn readFile(tc: *const Toolchain, path: []const u8, buf: []u8) ?[]const u8 {
|
||||||
|
const comp = tc.driver.comp;
|
||||||
|
return comp.cwd.adaptToNewApi().readFile(comp.io, path, buf) catch null;
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn exists(tc: *const Toolchain, path: []const u8) bool {
|
||||||
|
const comp = tc.driver.comp;
|
||||||
|
comp.cwd.adaptToNewApi().access(comp.io, path, .{}) catch return false;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn joinedExists(tc: *const Toolchain, parts: []const []const u8) bool {
|
||||||
|
var buf: [std.fs.max_path_bytes]u8 = undefined;
|
||||||
|
var fib = std.heap.FixedBufferAllocator.init(&buf);
|
||||||
|
const joined = std.fs.path.join(fib.allocator(), parts) catch return false;
|
||||||
|
return tc.exists(joined);
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn canExecute(tc: *const Toolchain, path: []const u8) bool {
|
||||||
|
if (@import("builtin").os.tag == .windows) {
|
||||||
|
// TODO
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
const comp = tc.driver.comp;
|
||||||
|
comp.cwd.adaptToNewApi().access(comp.io, path, .{ .execute = true }) catch return false;
|
||||||
|
// Todo: ensure path is not a directory
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Search for an executable named `name` using platform-specific logic
|
||||||
|
/// If it's found, write the full path to `buf` and return a slice of it
|
||||||
|
/// Otherwise retun null
|
||||||
|
pub fn findProgramByName(tc: *const Toolchain, name: []const u8, buf: []u8) ?[]const u8 {
|
||||||
|
std.debug.assert(name.len > 0);
|
||||||
|
if (@import("builtin").os.tag == .windows) {
|
||||||
|
// TODO
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
const comp = tc.driver.comp;
|
||||||
|
|
||||||
|
// TODO: does WASI need special handling?
|
||||||
|
if (mem.indexOfScalar(u8, name, '/') != null) {
|
||||||
|
@memcpy(buf[0..name.len], name);
|
||||||
|
return buf[0..name.len];
|
||||||
|
}
|
||||||
|
const path_env = comp.environment.path orelse return null;
|
||||||
|
var fib = std.heap.FixedBufferAllocator.init(buf);
|
||||||
|
|
||||||
|
var it = mem.tokenizeScalar(u8, path_env, std.fs.path.delimiter);
|
||||||
|
while (it.next()) |path_dir| {
|
||||||
|
defer fib.reset();
|
||||||
|
const full_path = std.fs.path.join(fib.allocator(), &.{ path_dir, name }) catch continue;
|
||||||
|
if (tc.canExecute(full_path)) return full_path;
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|||||||
232
lib/compiler/aro/aro/Tree.zig
vendored
232
lib/compiler/aro/aro/Tree.zig
vendored
@ -36,7 +36,7 @@ pub const TokenWithExpansionLocs = struct {
|
|||||||
pub fn expansionSlice(tok: TokenWithExpansionLocs) []const Source.Location {
|
pub fn expansionSlice(tok: TokenWithExpansionLocs) []const Source.Location {
|
||||||
const locs = tok.expansion_locs orelse return &[0]Source.Location{};
|
const locs = tok.expansion_locs orelse return &[0]Source.Location{};
|
||||||
var i: usize = 0;
|
var i: usize = 0;
|
||||||
while (locs[i].id != .unused) : (i += 1) {}
|
while (locs[i].id.index != .unused) : (i += 1) {}
|
||||||
return locs[0..i];
|
return locs[0..i];
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -56,7 +56,7 @@ pub const TokenWithExpansionLocs = struct {
|
|||||||
|
|
||||||
if (tok.expansion_locs) |locs| {
|
if (tok.expansion_locs) |locs| {
|
||||||
var i: usize = 0;
|
var i: usize = 0;
|
||||||
while (locs[i].id != .unused) : (i += 1) {}
|
while (locs[i].id.index != .unused) : (i += 1) {}
|
||||||
list.items = locs[0..i];
|
list.items = locs[0..i];
|
||||||
while (locs[i].byte_offset != 1) : (i += 1) {}
|
while (locs[i].byte_offset != 1) : (i += 1) {}
|
||||||
list.capacity = i + 1;
|
list.capacity = i + 1;
|
||||||
@ -68,7 +68,7 @@ pub const TokenWithExpansionLocs = struct {
|
|||||||
try list.ensureTotalCapacity(gpa, wanted_len);
|
try list.ensureTotalCapacity(gpa, wanted_len);
|
||||||
|
|
||||||
for (new) |new_loc| {
|
for (new) |new_loc| {
|
||||||
if (new_loc.id == .generated) continue;
|
if (new_loc.id.index == .generated) continue;
|
||||||
list.appendAssumeCapacity(new_loc);
|
list.appendAssumeCapacity(new_loc);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -76,7 +76,7 @@ pub const TokenWithExpansionLocs = struct {
|
|||||||
pub fn free(expansion_locs: ?[*]Source.Location, gpa: std.mem.Allocator) void {
|
pub fn free(expansion_locs: ?[*]Source.Location, gpa: std.mem.Allocator) void {
|
||||||
const locs = expansion_locs orelse return;
|
const locs = expansion_locs orelse return;
|
||||||
var i: usize = 0;
|
var i: usize = 0;
|
||||||
while (locs[i].id != .unused) : (i += 1) {}
|
while (locs[i].id.index != .unused) : (i += 1) {}
|
||||||
while (locs[i].byte_offset != 1) : (i += 1) {}
|
while (locs[i].byte_offset != 1) : (i += 1) {}
|
||||||
gpa.free(locs[0 .. i + 1]);
|
gpa.free(locs[0 .. i + 1]);
|
||||||
}
|
}
|
||||||
@ -133,10 +133,11 @@ pub fn deinit(tree: *Tree) void {
|
|||||||
tree.* = undefined;
|
tree.* = undefined;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub const GNUAssemblyQualifiers = struct {
|
pub const GNUAssemblyQualifiers = packed struct(u32) {
|
||||||
@"volatile": bool = false,
|
@"volatile": bool = false,
|
||||||
@"inline": bool = false,
|
@"inline": bool = false,
|
||||||
goto: bool = false,
|
goto: bool = false,
|
||||||
|
_: u29 = 0,
|
||||||
};
|
};
|
||||||
|
|
||||||
pub const Node = union(enum) {
|
pub const Node = union(enum) {
|
||||||
@ -146,7 +147,7 @@ pub const Node = union(enum) {
|
|||||||
param: Param,
|
param: Param,
|
||||||
variable: Variable,
|
variable: Variable,
|
||||||
typedef: Typedef,
|
typedef: Typedef,
|
||||||
global_asm: SimpleAsm,
|
global_asm: GlobalAsm,
|
||||||
|
|
||||||
struct_decl: ContainerDecl,
|
struct_decl: ContainerDecl,
|
||||||
union_decl: ContainerDecl,
|
union_decl: ContainerDecl,
|
||||||
@ -173,7 +174,7 @@ pub const Node = union(enum) {
|
|||||||
break_stmt: BreakStmt,
|
break_stmt: BreakStmt,
|
||||||
null_stmt: NullStmt,
|
null_stmt: NullStmt,
|
||||||
return_stmt: ReturnStmt,
|
return_stmt: ReturnStmt,
|
||||||
gnu_asm_simple: SimpleAsm,
|
asm_stmt: AsmStmt,
|
||||||
|
|
||||||
assign_expr: Binary,
|
assign_expr: Binary,
|
||||||
mul_assign_expr: Binary,
|
mul_assign_expr: Binary,
|
||||||
@ -333,7 +334,7 @@ pub const Node = union(enum) {
|
|||||||
implicit: bool,
|
implicit: bool,
|
||||||
};
|
};
|
||||||
|
|
||||||
pub const SimpleAsm = struct {
|
pub const GlobalAsm = struct {
|
||||||
asm_tok: TokenIndex,
|
asm_tok: TokenIndex,
|
||||||
asm_str: Node.Index,
|
asm_str: Node.Index,
|
||||||
};
|
};
|
||||||
@ -455,6 +456,22 @@ pub const Node = union(enum) {
|
|||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
pub const AsmStmt = struct {
|
||||||
|
asm_tok: TokenIndex,
|
||||||
|
asm_str: Node.Index,
|
||||||
|
outputs: []const Operand,
|
||||||
|
inputs: []const Operand,
|
||||||
|
clobbers: []const Node.Index,
|
||||||
|
labels: []const Node.Index,
|
||||||
|
quals: GNUAssemblyQualifiers,
|
||||||
|
|
||||||
|
pub const Operand = struct {
|
||||||
|
name: TokenIndex,
|
||||||
|
constraint: Node.Index,
|
||||||
|
expr: Node.Index,
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
pub const Binary = struct {
|
pub const Binary = struct {
|
||||||
qt: QualType,
|
qt: QualType,
|
||||||
lhs: Node.Index,
|
lhs: Node.Index,
|
||||||
@ -1027,10 +1044,56 @@ pub const Node = union(enum) {
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
.gnu_asm_simple => .{
|
.asm_stmt, .asm_stmt_volatile, .asm_stmt_inline, .asm_stmt_inline_volatile => |tag| {
|
||||||
.gnu_asm_simple = .{
|
const extra = tree.extra.items;
|
||||||
|
var extra_index = node_data[2];
|
||||||
|
|
||||||
|
const operand_size = @sizeOf(AsmStmt.Operand) / @sizeOf(u32);
|
||||||
|
|
||||||
|
const outputs_len = extra[extra_index] * operand_size;
|
||||||
|
extra_index += 1;
|
||||||
|
const inputs_len = extra[extra_index] * operand_size;
|
||||||
|
extra_index += 1;
|
||||||
|
const clobbers_len = extra[extra_index];
|
||||||
|
extra_index += 1;
|
||||||
|
|
||||||
|
const labels_len = node_data[1];
|
||||||
|
const quals: GNUAssemblyQualifiers = .{
|
||||||
|
.@"inline" = tag == .asm_stmt_inline or tag == .asm_stmt_inline_volatile,
|
||||||
|
.@"volatile" = tag == .asm_stmt_volatile or tag == .asm_stmt_inline_volatile,
|
||||||
|
.goto = labels_len > 0,
|
||||||
|
};
|
||||||
|
|
||||||
|
const outputs = extra[extra_index..][0..outputs_len];
|
||||||
|
extra_index += outputs_len;
|
||||||
|
const inputs = extra[extra_index..][0..inputs_len];
|
||||||
|
extra_index += inputs_len;
|
||||||
|
const clobbers = extra[extra_index..][0..clobbers_len];
|
||||||
|
extra_index += clobbers_len;
|
||||||
|
const labels = extra[extra_index..][0..labels_len];
|
||||||
|
extra_index += labels_len;
|
||||||
|
|
||||||
|
return .{
|
||||||
|
.asm_stmt = .{
|
||||||
.asm_tok = node_tok,
|
.asm_tok = node_tok,
|
||||||
.asm_str = @enumFromInt(node_data[0]),
|
.asm_str = @enumFromInt(node_data[0]),
|
||||||
|
.outputs = @ptrCast(outputs),
|
||||||
|
.inputs = @ptrCast(inputs),
|
||||||
|
.clobbers = @ptrCast(clobbers),
|
||||||
|
.labels = @ptrCast(labels),
|
||||||
|
.quals = quals,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
},
|
||||||
|
.asm_stmt_simple => .{
|
||||||
|
.asm_stmt = .{
|
||||||
|
.asm_tok = node_tok,
|
||||||
|
.asm_str = @enumFromInt(node_data[0]),
|
||||||
|
.outputs = &.{},
|
||||||
|
.inputs = &.{},
|
||||||
|
.clobbers = &.{},
|
||||||
|
.labels = &.{},
|
||||||
|
.quals = @bitCast(node_data[1]),
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
.assign_expr => .{
|
.assign_expr => .{
|
||||||
@ -1726,7 +1789,11 @@ pub const Node = union(enum) {
|
|||||||
.computed_goto_stmt,
|
.computed_goto_stmt,
|
||||||
.continue_stmt,
|
.continue_stmt,
|
||||||
.break_stmt,
|
.break_stmt,
|
||||||
.gnu_asm_simple,
|
.asm_stmt,
|
||||||
|
.asm_stmt_volatile,
|
||||||
|
.asm_stmt_inline,
|
||||||
|
.asm_stmt_inline_volatile,
|
||||||
|
.asm_stmt_simple,
|
||||||
.global_asm,
|
.global_asm,
|
||||||
.generic_association_expr,
|
.generic_association_expr,
|
||||||
.generic_default_expr,
|
.generic_default_expr,
|
||||||
@ -1813,7 +1880,11 @@ pub const Node = union(enum) {
|
|||||||
return_stmt,
|
return_stmt,
|
||||||
return_none_stmt,
|
return_none_stmt,
|
||||||
implicit_return,
|
implicit_return,
|
||||||
gnu_asm_simple,
|
asm_stmt,
|
||||||
|
asm_stmt_inline,
|
||||||
|
asm_stmt_volatile,
|
||||||
|
asm_stmt_inline_volatile,
|
||||||
|
asm_stmt_simple,
|
||||||
comma_expr,
|
comma_expr,
|
||||||
assign_expr,
|
assign_expr,
|
||||||
mul_assign_expr,
|
mul_assign_expr,
|
||||||
@ -2174,10 +2245,39 @@ pub fn setNode(tree: *Tree, node: Node, index: usize) !void {
|
|||||||
}
|
}
|
||||||
repr.tok = @"return".return_tok;
|
repr.tok = @"return".return_tok;
|
||||||
},
|
},
|
||||||
.gnu_asm_simple => |gnu_asm_simple| {
|
.asm_stmt => |asm_stmt| {
|
||||||
repr.tag = .gnu_asm_simple;
|
repr.tok = asm_stmt.asm_tok;
|
||||||
repr.data[0] = @intFromEnum(gnu_asm_simple.asm_str);
|
repr.data[0] = @intFromEnum(asm_stmt.asm_str);
|
||||||
repr.tok = gnu_asm_simple.asm_tok;
|
if (asm_stmt.outputs.len == 0 and asm_stmt.inputs.len == 0 and asm_stmt.clobbers.len == 0 and asm_stmt.labels.len == 0) {
|
||||||
|
repr.tag = .asm_stmt_simple;
|
||||||
|
repr.data[1] = @bitCast(asm_stmt.quals);
|
||||||
|
} else {
|
||||||
|
if (asm_stmt.quals.@"inline" and asm_stmt.quals.@"volatile") {
|
||||||
|
repr.tag = .asm_stmt_inline_volatile;
|
||||||
|
} else if (asm_stmt.quals.@"inline") {
|
||||||
|
repr.tag = .asm_stmt_inline;
|
||||||
|
} else if (asm_stmt.quals.@"volatile") {
|
||||||
|
repr.tag = .asm_stmt_volatile;
|
||||||
|
} else {
|
||||||
|
repr.tag = .asm_stmt;
|
||||||
|
}
|
||||||
|
repr.data[1] = @intCast(asm_stmt.labels.len);
|
||||||
|
repr.data[2] = @intCast(tree.extra.items.len);
|
||||||
|
|
||||||
|
const operand_size = @sizeOf(Node.AsmStmt.Operand) / @sizeOf(u32);
|
||||||
|
try tree.extra.ensureUnusedCapacity(tree.comp.gpa, 3 // lens
|
||||||
|
+ (asm_stmt.outputs.len + asm_stmt.inputs.len) * operand_size // outputs inputs
|
||||||
|
+ asm_stmt.clobbers.len + asm_stmt.labels.len);
|
||||||
|
|
||||||
|
tree.extra.appendAssumeCapacity(@intCast(asm_stmt.outputs.len));
|
||||||
|
tree.extra.appendAssumeCapacity(@intCast(asm_stmt.inputs.len));
|
||||||
|
tree.extra.appendAssumeCapacity(@intCast(asm_stmt.clobbers.len));
|
||||||
|
|
||||||
|
tree.extra.appendSliceAssumeCapacity(@ptrCast(asm_stmt.outputs));
|
||||||
|
tree.extra.appendSliceAssumeCapacity(@ptrCast(asm_stmt.inputs));
|
||||||
|
tree.extra.appendSliceAssumeCapacity(@ptrCast(asm_stmt.clobbers));
|
||||||
|
tree.extra.appendSliceAssumeCapacity(@ptrCast(asm_stmt.labels));
|
||||||
|
}
|
||||||
},
|
},
|
||||||
.assign_expr => |bin| {
|
.assign_expr => |bin| {
|
||||||
repr.tag = .assign_expr;
|
repr.tag = .assign_expr;
|
||||||
@ -2804,18 +2904,17 @@ const CallableResultUsage = struct {
|
|||||||
};
|
};
|
||||||
|
|
||||||
pub fn callableResultUsage(tree: *const Tree, node: Node.Index) ?CallableResultUsage {
|
pub fn callableResultUsage(tree: *const Tree, node: Node.Index) ?CallableResultUsage {
|
||||||
var cur_node = node;
|
loop: switch (node.get(tree)) {
|
||||||
while (true) switch (cur_node.get(tree)) {
|
|
||||||
.decl_ref_expr => |decl_ref| return .{
|
.decl_ref_expr => |decl_ref| return .{
|
||||||
.tok = decl_ref.name_tok,
|
.tok = decl_ref.name_tok,
|
||||||
.nodiscard = decl_ref.qt.hasAttribute(tree.comp, .nodiscard),
|
.nodiscard = decl_ref.qt.hasAttribute(tree.comp, .nodiscard),
|
||||||
.warn_unused_result = decl_ref.qt.hasAttribute(tree.comp, .warn_unused_result),
|
.warn_unused_result = decl_ref.qt.hasAttribute(tree.comp, .warn_unused_result),
|
||||||
},
|
},
|
||||||
|
|
||||||
.paren_expr, .addr_of_expr, .deref_expr => |un| cur_node = un.operand,
|
.paren_expr, .addr_of_expr, .deref_expr => |un| continue :loop un.operand.get(tree),
|
||||||
.comma_expr => |bin| cur_node = bin.rhs,
|
.comma_expr => |bin| continue :loop bin.rhs.get(tree),
|
||||||
.cast => |cast| cur_node = cast.operand,
|
.cast => |cast| continue :loop cast.operand.get(tree),
|
||||||
.call_expr => |call| cur_node = call.callee,
|
.call_expr => |call| continue :loop call.callee.get(tree),
|
||||||
.member_access_expr, .member_access_ptr_expr => |access| {
|
.member_access_expr, .member_access_ptr_expr => |access| {
|
||||||
var qt = access.base.qt(tree);
|
var qt = access.base.qt(tree);
|
||||||
if (qt.get(tree.comp, .pointer)) |pointer| qt = pointer.child;
|
if (qt.get(tree.comp, .pointer)) |pointer| qt = pointer.child;
|
||||||
@ -2825,19 +2924,14 @@ pub fn callableResultUsage(tree: *const Tree, node: Node.Index) ?CallableResultU
|
|||||||
};
|
};
|
||||||
|
|
||||||
const field = record_ty.fields[access.member_index];
|
const field = record_ty.fields[access.member_index];
|
||||||
const attributes = field.attributes(tree.comp);
|
|
||||||
return .{
|
return .{
|
||||||
.tok = field.name_tok,
|
.tok = field.name_tok,
|
||||||
.nodiscard = for (attributes) |attr| {
|
.nodiscard = field.qt.hasAttribute(tree.comp, .nodiscard),
|
||||||
if (attr.tag == .nodiscard) break true;
|
.warn_unused_result = field.qt.hasAttribute(tree.comp, .warn_unused_result),
|
||||||
} else false,
|
|
||||||
.warn_unused_result = for (attributes) |attr| {
|
|
||||||
if (attr.tag == .warn_unused_result) break true;
|
|
||||||
} else false,
|
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
else => return null,
|
else => return null,
|
||||||
};
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn isLval(tree: *const Tree, node: Node.Index) bool {
|
pub fn isLval(tree: *const Tree, node: Node.Index) bool {
|
||||||
@ -3004,6 +3098,13 @@ fn dumpNode(
|
|||||||
try config.setColor(w, ATTRIBUTE);
|
try config.setColor(w, ATTRIBUTE);
|
||||||
try w.writeAll(" bitfield");
|
try w.writeAll(" bitfield");
|
||||||
}
|
}
|
||||||
|
if (node == .asm_stmt) {
|
||||||
|
const quals = node.asm_stmt.quals;
|
||||||
|
try config.setColor(w, ATTRIBUTE);
|
||||||
|
if (quals.@"inline") try w.writeAll(" inline");
|
||||||
|
if (quals.@"volatile") try w.writeAll(" volatile");
|
||||||
|
if (quals.goto) try w.writeAll(" goto");
|
||||||
|
}
|
||||||
|
|
||||||
if (tree.value_map.get(node_index)) |val| {
|
if (tree.value_map.get(node_index)) |val| {
|
||||||
try config.setColor(w, LITERAL);
|
try config.setColor(w, LITERAL);
|
||||||
@ -3028,7 +3129,6 @@ fn dumpNode(
|
|||||||
if (node == .return_stmt and node.return_stmt.operand == .implicit and node.return_stmt.operand.implicit) {
|
if (node == .return_stmt and node.return_stmt.operand == .implicit and node.return_stmt.operand.implicit) {
|
||||||
try config.setColor(w, IMPLICIT);
|
try config.setColor(w, IMPLICIT);
|
||||||
try w.writeAll(" (value: 0)");
|
try w.writeAll(" (value: 0)");
|
||||||
try config.setColor(w, .reset);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
try w.writeAll("\n");
|
try w.writeAll("\n");
|
||||||
@ -3048,8 +3148,7 @@ fn dumpNode(
|
|||||||
|
|
||||||
switch (node) {
|
switch (node) {
|
||||||
.empty_decl => {},
|
.empty_decl => {},
|
||||||
.global_asm, .gnu_asm_simple => |@"asm"| {
|
.global_asm => |@"asm"| {
|
||||||
try w.splatByteAll(' ', level + 1);
|
|
||||||
try tree.dumpNode(@"asm".asm_str, level + delta, config, w);
|
try tree.dumpNode(@"asm".asm_str, level + delta, config, w);
|
||||||
},
|
},
|
||||||
.static_assert => |assert| {
|
.static_assert => |assert| {
|
||||||
@ -3428,6 +3527,73 @@ fn dumpNode(
|
|||||||
.none => {},
|
.none => {},
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
.asm_stmt => |@"asm"| {
|
||||||
|
try tree.dumpNode(@"asm".asm_str, level + delta, config, w);
|
||||||
|
|
||||||
|
const write_operand = struct {
|
||||||
|
fn write_operand(
|
||||||
|
_w: *std.Io.Writer,
|
||||||
|
_level: u32,
|
||||||
|
_config: std.Io.tty.Config,
|
||||||
|
_tree: *const Tree,
|
||||||
|
operands: []const Node.AsmStmt.Operand,
|
||||||
|
) std.Io.tty.Config.SetColorError!void {
|
||||||
|
for (operands) |operand| {
|
||||||
|
if (operand.name != 0) {
|
||||||
|
try _w.splatByteAll(' ', _level + delta);
|
||||||
|
try _w.writeAll("asm name: ");
|
||||||
|
try _config.setColor(_w, NAME);
|
||||||
|
try _w.writeAll(_tree.tokSlice(operand.name));
|
||||||
|
try _w.writeByte('\n');
|
||||||
|
try _config.setColor(_w, .reset);
|
||||||
|
}
|
||||||
|
|
||||||
|
try _w.splatByteAll(' ', _level + delta);
|
||||||
|
try _w.writeAll("constraint: ");
|
||||||
|
const constraint_val = _tree.value_map.get(operand.constraint).?;
|
||||||
|
try _config.setColor(_w, LITERAL);
|
||||||
|
_ = try constraint_val.print(operand.constraint.qt(_tree), _tree.comp, _w);
|
||||||
|
try _w.writeByte('\n');
|
||||||
|
|
||||||
|
try _tree.dumpNode(operand.expr, _level + delta, _config, _w);
|
||||||
|
}
|
||||||
|
try _config.setColor(_w, .reset);
|
||||||
|
}
|
||||||
|
}.write_operand;
|
||||||
|
|
||||||
|
if (@"asm".outputs.len > 0) {
|
||||||
|
try w.splatByteAll(' ', level + half);
|
||||||
|
try w.writeAll("ouputs:\n");
|
||||||
|
|
||||||
|
try write_operand(w, level, config, tree, @"asm".outputs);
|
||||||
|
}
|
||||||
|
if (@"asm".inputs.len > 0) {
|
||||||
|
try w.splatByteAll(' ', level + half);
|
||||||
|
try w.writeAll("inputs:\n");
|
||||||
|
|
||||||
|
try write_operand(w, level, config, tree, @"asm".inputs);
|
||||||
|
}
|
||||||
|
if (@"asm".clobbers.len > 0) {
|
||||||
|
try w.splatByteAll(' ', level + half);
|
||||||
|
try w.writeAll("clobbers:\n");
|
||||||
|
try config.setColor(w, LITERAL);
|
||||||
|
for (@"asm".clobbers) |clobber| {
|
||||||
|
const clobber_val = tree.value_map.get(clobber).?;
|
||||||
|
|
||||||
|
try w.splatByteAll(' ', level + delta);
|
||||||
|
_ = try clobber_val.print(clobber.qt(tree), tree.comp, w);
|
||||||
|
try w.writeByte('\n');
|
||||||
|
}
|
||||||
|
try config.setColor(w, .reset);
|
||||||
|
}
|
||||||
|
if (@"asm".labels.len > 0) {
|
||||||
|
try w.splatByteAll(' ', level + half);
|
||||||
|
try w.writeAll("labels:\n");
|
||||||
|
for (@"asm".labels) |label| {
|
||||||
|
try tree.dumpNode(label, level + delta, config, w);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
.call_expr => |call| {
|
.call_expr => |call| {
|
||||||
try w.splatByteAll(' ', level + half);
|
try w.splatByteAll(' ', level + half);
|
||||||
try w.writeAll("callee:\n");
|
try w.writeAll("callee:\n");
|
||||||
|
|||||||
46
lib/compiler/aro/aro/Tree/number_affixes.zig
vendored
46
lib/compiler/aro/aro/Tree/number_affixes.zig
vendored
@ -95,6 +95,33 @@ pub const Suffix = enum {
|
|||||||
// _Bitint
|
// _Bitint
|
||||||
WB, UWB,
|
WB, UWB,
|
||||||
|
|
||||||
|
// __bf16
|
||||||
|
BF16,
|
||||||
|
|
||||||
|
// _Float32 and imaginary _Float32
|
||||||
|
F32, IF32,
|
||||||
|
|
||||||
|
// _Float64 and imaginary _Float64
|
||||||
|
F64, IF64,
|
||||||
|
|
||||||
|
// _Float32x and imaginary _Float32x
|
||||||
|
F32x, IF32x,
|
||||||
|
|
||||||
|
// _Float64x and imaginary _Float64x
|
||||||
|
F64x, IF64x,
|
||||||
|
|
||||||
|
// _Decimal32
|
||||||
|
D32,
|
||||||
|
|
||||||
|
// _Decimal64
|
||||||
|
D64,
|
||||||
|
|
||||||
|
// _Decimal128
|
||||||
|
D128,
|
||||||
|
|
||||||
|
// _Decimal64x
|
||||||
|
D64x,
|
||||||
|
|
||||||
// zig fmt: on
|
// zig fmt: on
|
||||||
|
|
||||||
const Tuple = struct { Suffix, []const []const u8 };
|
const Tuple = struct { Suffix, []const []const u8 };
|
||||||
@ -126,6 +153,15 @@ pub const Suffix = enum {
|
|||||||
.{ .W, &.{"W"} },
|
.{ .W, &.{"W"} },
|
||||||
.{ .F128, &.{"F128"} },
|
.{ .F128, &.{"F128"} },
|
||||||
.{ .Q, &.{"Q"} },
|
.{ .Q, &.{"Q"} },
|
||||||
|
.{ .BF16, &.{"BF16"} },
|
||||||
|
.{ .F32, &.{"F32"} },
|
||||||
|
.{ .F64, &.{"F64"} },
|
||||||
|
.{ .F32x, &.{"F32x"} },
|
||||||
|
.{ .F64x, &.{"F64x"} },
|
||||||
|
.{ .D32, &.{"D32"} },
|
||||||
|
.{ .D64, &.{"D64"} },
|
||||||
|
.{ .D128, &.{"D128"} },
|
||||||
|
.{ .D64x, &.{"D64x"} },
|
||||||
|
|
||||||
.{ .I, &.{"I"} },
|
.{ .I, &.{"I"} },
|
||||||
.{ .IL, &.{ "I", "L" } },
|
.{ .IL, &.{ "I", "L" } },
|
||||||
@ -134,6 +170,10 @@ pub const Suffix = enum {
|
|||||||
.{ .IW, &.{ "I", "W" } },
|
.{ .IW, &.{ "I", "W" } },
|
||||||
.{ .IF128, &.{ "I", "F128" } },
|
.{ .IF128, &.{ "I", "F128" } },
|
||||||
.{ .IQ, &.{ "I", "Q" } },
|
.{ .IQ, &.{ "I", "Q" } },
|
||||||
|
.{ .IF32, &.{ "I", "F32" } },
|
||||||
|
.{ .IF64, &.{ "I", "F64" } },
|
||||||
|
.{ .IF32x, &.{ "I", "F32x" } },
|
||||||
|
.{ .IF64x, &.{ "I", "F64x" } },
|
||||||
};
|
};
|
||||||
|
|
||||||
pub fn fromString(buf: []const u8, suffix_kind: enum { int, float }) ?Suffix {
|
pub fn fromString(buf: []const u8, suffix_kind: enum { int, float }) ?Suffix {
|
||||||
@ -162,8 +202,8 @@ pub const Suffix = enum {
|
|||||||
|
|
||||||
pub fn isImaginary(suffix: Suffix) bool {
|
pub fn isImaginary(suffix: Suffix) bool {
|
||||||
return switch (suffix) {
|
return switch (suffix) {
|
||||||
.I, .IL, .IF, .IU, .IUL, .ILL, .IULL, .IWB, .IUWB, .IF128, .IQ, .IW, .IF16 => true,
|
.I, .IL, .IF, .IU, .IUL, .ILL, .IULL, .IWB, .IUWB, .IF128, .IQ, .IW, .IF16, .IF32, .IF64, .IF32x, .IF64x => true,
|
||||||
.None, .L, .F16, .F, .U, .UL, .LL, .ULL, .WB, .UWB, .F128, .Q, .W => false,
|
.None, .L, .F16, .F, .U, .UL, .LL, .ULL, .WB, .UWB, .F128, .Q, .W, .F32, .F64, .F32x, .F64x, .D32, .D64, .D128, .D64x, .BF16 => false,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -171,7 +211,7 @@ pub const Suffix = enum {
|
|||||||
return switch (suffix) {
|
return switch (suffix) {
|
||||||
.None, .L, .LL, .I, .IL, .ILL, .WB, .IWB => true,
|
.None, .L, .LL, .I, .IL, .ILL, .WB, .IWB => true,
|
||||||
.U, .UL, .ULL, .IU, .IUL, .IULL, .UWB, .IUWB => false,
|
.U, .UL, .ULL, .IU, .IUL, .IULL, .UWB, .IUWB => false,
|
||||||
.F, .IF, .F16, .F128, .IF128, .Q, .IQ, .W, .IW, .IF16 => unreachable,
|
.F, .IF, .F16, .F128, .IF128, .Q, .IQ, .W, .IW, .IF16, .F32, .IF32, .F64, .IF64, .F32x, .IF32x, .F64x, .IF64x, .D32, .D64, .D128, .D64x, .BF16 => unreachable,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
234
lib/compiler/aro/aro/TypeStore.zig
vendored
234
lib/compiler/aro/aro/TypeStore.zig
vendored
@ -7,7 +7,6 @@ const record_layout = @import("record_layout.zig");
|
|||||||
const Parser = @import("Parser.zig");
|
const Parser = @import("Parser.zig");
|
||||||
const StringInterner = @import("StringInterner.zig");
|
const StringInterner = @import("StringInterner.zig");
|
||||||
const StringId = StringInterner.StringId;
|
const StringId = StringInterner.StringId;
|
||||||
const target_util = @import("target.zig");
|
|
||||||
const Tree = @import("Tree.zig");
|
const Tree = @import("Tree.zig");
|
||||||
const Node = Tree.Node;
|
const Node = Tree.Node;
|
||||||
const TokenIndex = Tree.TokenIndex;
|
const TokenIndex = Tree.TokenIndex;
|
||||||
@ -92,6 +91,16 @@ const Index = enum(u29) {
|
|||||||
int_pointer = std.math.maxInt(u29) - 27,
|
int_pointer = std.math.maxInt(u29) - 27,
|
||||||
/// Special type used when combining declarators.
|
/// Special type used when combining declarators.
|
||||||
declarator_combine = std.math.maxInt(u29) - 28,
|
declarator_combine = std.math.maxInt(u29) - 28,
|
||||||
|
float_bf16 = std.math.maxInt(u29) - 29,
|
||||||
|
float_float32 = std.math.maxInt(u29) - 30,
|
||||||
|
float_float64 = std.math.maxInt(u29) - 31,
|
||||||
|
float_float32x = std.math.maxInt(u29) - 32,
|
||||||
|
float_float64x = std.math.maxInt(u29) - 33,
|
||||||
|
float_float128x = std.math.maxInt(u29) - 34,
|
||||||
|
float_dfloat32 = std.math.maxInt(u29) - 35,
|
||||||
|
float_dfloat64 = std.math.maxInt(u29) - 36,
|
||||||
|
float_dfloat128 = std.math.maxInt(u29) - 37,
|
||||||
|
float_dfloat64x = std.math.maxInt(u29) - 38,
|
||||||
_,
|
_,
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -123,12 +132,22 @@ pub const QualType = packed struct(u32) {
|
|||||||
pub const ulong_long: QualType = .{ ._index = .int_ulong_long };
|
pub const ulong_long: QualType = .{ ._index = .int_ulong_long };
|
||||||
pub const int128: QualType = .{ ._index = .int_int128 };
|
pub const int128: QualType = .{ ._index = .int_int128 };
|
||||||
pub const uint128: QualType = .{ ._index = .int_uint128 };
|
pub const uint128: QualType = .{ ._index = .int_uint128 };
|
||||||
|
pub const bf16: QualType = .{ ._index = .float_bf16 };
|
||||||
pub const fp16: QualType = .{ ._index = .float_fp16 };
|
pub const fp16: QualType = .{ ._index = .float_fp16 };
|
||||||
pub const float16: QualType = .{ ._index = .float_float16 };
|
pub const float16: QualType = .{ ._index = .float_float16 };
|
||||||
pub const float: QualType = .{ ._index = .float_float };
|
pub const float: QualType = .{ ._index = .float_float };
|
||||||
pub const double: QualType = .{ ._index = .float_double };
|
pub const double: QualType = .{ ._index = .float_double };
|
||||||
pub const long_double: QualType = .{ ._index = .float_long_double };
|
pub const long_double: QualType = .{ ._index = .float_long_double };
|
||||||
pub const float128: QualType = .{ ._index = .float_float128 };
|
pub const float128: QualType = .{ ._index = .float_float128 };
|
||||||
|
pub const float32: QualType = .{ ._index = .float_float32 };
|
||||||
|
pub const float64: QualType = .{ ._index = .float_float64 };
|
||||||
|
pub const float32x: QualType = .{ ._index = .float_float32x };
|
||||||
|
pub const float64x: QualType = .{ ._index = .float_float64x };
|
||||||
|
pub const float128x: QualType = .{ ._index = .float_float128x };
|
||||||
|
pub const dfloat32: QualType = .{ ._index = .float_dfloat32 };
|
||||||
|
pub const dfloat64: QualType = .{ ._index = .float_dfloat64 };
|
||||||
|
pub const dfloat128: QualType = .{ ._index = .float_dfloat128 };
|
||||||
|
pub const dfloat64x: QualType = .{ ._index = .float_dfloat64x };
|
||||||
pub const void_pointer: QualType = .{ ._index = .void_pointer };
|
pub const void_pointer: QualType = .{ ._index = .void_pointer };
|
||||||
pub const char_pointer: QualType = .{ ._index = .char_pointer };
|
pub const char_pointer: QualType = .{ ._index = .char_pointer };
|
||||||
pub const int_pointer: QualType = .{ ._index = .int_pointer };
|
pub const int_pointer: QualType = .{ ._index = .int_pointer };
|
||||||
@ -184,12 +203,22 @@ pub const QualType = packed struct(u32) {
|
|||||||
.int_ulong_long => return .{ .int = .ulong_long },
|
.int_ulong_long => return .{ .int = .ulong_long },
|
||||||
.int_int128 => return .{ .int = .int128 },
|
.int_int128 => return .{ .int = .int128 },
|
||||||
.int_uint128 => return .{ .int = .uint128 },
|
.int_uint128 => return .{ .int = .uint128 },
|
||||||
|
.float_bf16 => return .{ .float = .bf16 },
|
||||||
.float_fp16 => return .{ .float = .fp16 },
|
.float_fp16 => return .{ .float = .fp16 },
|
||||||
.float_float16 => return .{ .float = .float16 },
|
.float_float16 => return .{ .float = .float16 },
|
||||||
.float_float => return .{ .float = .float },
|
.float_float => return .{ .float = .float },
|
||||||
.float_double => return .{ .float = .double },
|
.float_double => return .{ .float = .double },
|
||||||
.float_long_double => return .{ .float = .long_double },
|
.float_long_double => return .{ .float = .long_double },
|
||||||
.float_float128 => return .{ .float = .float128 },
|
.float_float128 => return .{ .float = .float128 },
|
||||||
|
.float_float32 => return .{ .float = .float32 },
|
||||||
|
.float_float64 => return .{ .float = .float64 },
|
||||||
|
.float_float32x => return .{ .float = .float32x },
|
||||||
|
.float_float64x => return .{ .float = .float64x },
|
||||||
|
.float_float128x => return .{ .float = .float128x },
|
||||||
|
.float_dfloat32 => return .{ .float = .dfloat32 },
|
||||||
|
.float_dfloat64 => return .{ .float = .dfloat64 },
|
||||||
|
.float_dfloat128 => return .{ .float = .dfloat128 },
|
||||||
|
.float_dfloat64x => return .{ .float = .dfloat64x },
|
||||||
.void_pointer => return .{ .pointer = .{ .child = .void, .decayed = null } },
|
.void_pointer => return .{ .pointer = .{ .child = .void, .decayed = null } },
|
||||||
.char_pointer => return .{ .pointer = .{ .child = .char, .decayed = null } },
|
.char_pointer => return .{ .pointer = .{ .child = .char, .decayed = null } },
|
||||||
.int_pointer => return .{ .pointer = .{ .child = .int, .decayed = null } },
|
.int_pointer => return .{ .pointer = .{ .child = .int, .decayed = null } },
|
||||||
@ -608,8 +637,17 @@ pub const QualType = packed struct(u32) {
|
|||||||
.float => comp.target.cTypeAlignment(.float),
|
.float => comp.target.cTypeAlignment(.float),
|
||||||
.double => comp.target.cTypeAlignment(.double),
|
.double => comp.target.cTypeAlignment(.double),
|
||||||
.long_double => comp.target.cTypeAlignment(.longdouble),
|
.long_double => comp.target.cTypeAlignment(.longdouble),
|
||||||
.fp16, .float16 => 2,
|
.bf16, .fp16, .float16 => 2,
|
||||||
.float128 => 16,
|
.float128 => 16,
|
||||||
|
.float32 => comp.target.cTypeAlignment(.float),
|
||||||
|
.float64 => comp.target.cTypeAlignment(.double),
|
||||||
|
.float32x => 8,
|
||||||
|
.float64x => 16,
|
||||||
|
.float128x => unreachable, // Not supported
|
||||||
|
.dfloat32 => 4,
|
||||||
|
.dfloat64 => 8,
|
||||||
|
.dfloat128 => 16,
|
||||||
|
.dfloat64x => 16,
|
||||||
},
|
},
|
||||||
.bit_int => |bit_int| {
|
.bit_int => |bit_int| {
|
||||||
// https://www.open-std.org/jtc1/sc22/wg14/www/docs/n2709.pdf
|
// https://www.open-std.org/jtc1/sc22/wg14/www/docs/n2709.pdf
|
||||||
@ -628,7 +666,7 @@ pub const QualType = packed struct(u32) {
|
|||||||
else => comp.target.ptrBitWidth() / 8,
|
else => comp.target.ptrBitWidth() / 8,
|
||||||
},
|
},
|
||||||
|
|
||||||
.func => target_util.defaultFunctionAlignment(comp.target),
|
.func => comp.target.defaultFunctionAlignment(),
|
||||||
|
|
||||||
.array => |array| continue :loop array.elem.base(comp).type,
|
.array => |array| continue :loop array.elem.base(comp).type,
|
||||||
.vector => |vector| continue :loop vector.elem.base(comp).type,
|
.vector => |vector| continue :loop vector.elem.base(comp).type,
|
||||||
@ -774,14 +812,23 @@ pub const QualType = packed struct(u32) {
|
|||||||
pub fn floatRank(qt: QualType, comp: *const Compilation) usize {
|
pub fn floatRank(qt: QualType, comp: *const Compilation) usize {
|
||||||
return loop: switch (qt.base(comp).type) {
|
return loop: switch (qt.base(comp).type) {
|
||||||
.float => |float_ty| switch (float_ty) {
|
.float => |float_ty| switch (float_ty) {
|
||||||
// TODO: bfloat16 => 0
|
.bf16 => 0,
|
||||||
.float16 => 1,
|
.float16 => 1,
|
||||||
.fp16 => 2,
|
.fp16 => 2,
|
||||||
.float => 3,
|
.float => 3,
|
||||||
.double => 4,
|
.float32 => 4,
|
||||||
.long_double => 5,
|
.float32x => 5,
|
||||||
.float128 => 6,
|
.double => 6,
|
||||||
|
.float64 => 7,
|
||||||
|
.float64x => 8,
|
||||||
|
.long_double => 9,
|
||||||
|
.float128 => 10,
|
||||||
// TODO: ibm128 => 7
|
// TODO: ibm128 => 7
|
||||||
|
.float128x => unreachable, // Not supported
|
||||||
|
.dfloat32 => decimal_float_rank + 0,
|
||||||
|
.dfloat64 => decimal_float_rank + 1,
|
||||||
|
.dfloat64x => decimal_float_rank + 2,
|
||||||
|
.dfloat128 => decimal_float_rank + 3,
|
||||||
},
|
},
|
||||||
.complex => |complex| continue :loop complex.base(comp).type,
|
.complex => |complex| continue :loop complex.base(comp).type,
|
||||||
.atomic => |atomic| continue :loop atomic.base(comp).type,
|
.atomic => |atomic| continue :loop atomic.base(comp).type,
|
||||||
@ -789,6 +836,8 @@ pub const QualType = packed struct(u32) {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub const decimal_float_rank = 90;
|
||||||
|
|
||||||
/// Rank for integer conversions, ignoring domain (complex vs real)
|
/// Rank for integer conversions, ignoring domain (complex vs real)
|
||||||
/// Asserts that ty is an integer type
|
/// Asserts that ty is an integer type
|
||||||
pub fn intRank(qt: QualType, comp: *const Compilation) usize {
|
pub fn intRank(qt: QualType, comp: *const Compilation) usize {
|
||||||
@ -1135,7 +1184,7 @@ pub const QualType = packed struct(u32) {
|
|||||||
if (index <= aligned_index) break;
|
if (index <= aligned_index) break;
|
||||||
}
|
}
|
||||||
last_aligned_index = index;
|
last_aligned_index = index;
|
||||||
const requested = if (attribute.args.aligned.alignment) |alignment| alignment.requested else target_util.defaultAlignment(comp.target);
|
const requested = if (attribute.args.aligned.alignment) |alignment| alignment.requested else comp.target.defaultAlignment();
|
||||||
if (max_requested == null or max_requested.? < requested) {
|
if (max_requested == null or max_requested.? < requested) {
|
||||||
max_requested = requested;
|
max_requested = requested;
|
||||||
}
|
}
|
||||||
@ -1143,9 +1192,16 @@ pub const QualType = packed struct(u32) {
|
|||||||
return max_requested;
|
return max_requested;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn linkage(qt: QualType, comp: *const Compilation) std.builtin.GlobalLinkage {
|
||||||
|
if (qt.hasAttribute(comp, .internal_linkage)) return .internal;
|
||||||
|
if (qt.hasAttribute(comp, .weak)) return .weak;
|
||||||
|
if (qt.hasAttribute(comp, .selectany)) return .link_once;
|
||||||
|
return .strong;
|
||||||
|
}
|
||||||
|
|
||||||
pub fn enumIsPacked(qt: QualType, comp: *const Compilation) bool {
|
pub fn enumIsPacked(qt: QualType, comp: *const Compilation) bool {
|
||||||
std.debug.assert(qt.is(comp, .@"enum"));
|
std.debug.assert(qt.is(comp, .@"enum"));
|
||||||
return comp.langopts.short_enums or target_util.packAllEnums(comp.target) or qt.hasAttribute(comp, .@"packed");
|
return comp.langopts.short_enums or comp.target.packAllEnums() or qt.hasAttribute(comp, .@"packed");
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn shouldDesugar(qt: QualType, comp: *const Compilation) bool {
|
pub fn shouldDesugar(qt: QualType, comp: *const Compilation) bool {
|
||||||
@ -1275,12 +1331,22 @@ pub const QualType = packed struct(u32) {
|
|||||||
},
|
},
|
||||||
.bit_int => |bit_int| try w.print("{s} _BitInt({d})", .{ @tagName(bit_int.signedness), bit_int.bits }),
|
.bit_int => |bit_int| try w.print("{s} _BitInt({d})", .{ @tagName(bit_int.signedness), bit_int.bits }),
|
||||||
.float => |float_ty| switch (float_ty) {
|
.float => |float_ty| switch (float_ty) {
|
||||||
|
.bf16 => try w.writeAll("__bf16"),
|
||||||
.fp16 => try w.writeAll("__fp16"),
|
.fp16 => try w.writeAll("__fp16"),
|
||||||
.float16 => try w.writeAll("_Float16"),
|
.float16 => try w.writeAll("_Float16"),
|
||||||
.float => try w.writeAll("float"),
|
.float => try w.writeAll("float"),
|
||||||
.double => try w.writeAll("double"),
|
.double => try w.writeAll("double"),
|
||||||
.long_double => try w.writeAll("long double"),
|
.long_double => try w.writeAll("long double"),
|
||||||
.float128 => try w.writeAll("__float128"),
|
.float128 => try w.writeAll("__float128"),
|
||||||
|
.float32 => try w.writeAll("_Float32"),
|
||||||
|
.float64 => try w.writeAll("_Float64"),
|
||||||
|
.float32x => try w.writeAll("_Float32x"),
|
||||||
|
.float64x => try w.writeAll("_Float64x"),
|
||||||
|
.float128x => try w.writeAll("_Float128x"),
|
||||||
|
.dfloat32 => try w.writeAll("_Decimal32"),
|
||||||
|
.dfloat64 => try w.writeAll("_Decimal64"),
|
||||||
|
.dfloat128 => try w.writeAll("_Decimal128"),
|
||||||
|
.dfloat64x => try w.writeAll("_Decimal64x"),
|
||||||
},
|
},
|
||||||
.complex => |complex| {
|
.complex => |complex| {
|
||||||
try w.writeAll("_Complex ");
|
try w.writeAll("_Complex ");
|
||||||
@ -1498,21 +1564,41 @@ pub const Type = union(enum) {
|
|||||||
};
|
};
|
||||||
|
|
||||||
pub const Float = enum {
|
pub const Float = enum {
|
||||||
|
bf16,
|
||||||
fp16,
|
fp16,
|
||||||
float16,
|
float16,
|
||||||
float,
|
float,
|
||||||
double,
|
double,
|
||||||
long_double,
|
long_double,
|
||||||
float128,
|
float128,
|
||||||
|
float32,
|
||||||
|
float64,
|
||||||
|
float32x,
|
||||||
|
float64x,
|
||||||
|
float128x,
|
||||||
|
dfloat32,
|
||||||
|
dfloat64,
|
||||||
|
dfloat128,
|
||||||
|
dfloat64x,
|
||||||
|
|
||||||
pub fn bits(float: Float, comp: *const Compilation) u16 {
|
pub fn bits(float: Float, comp: *const Compilation) u16 {
|
||||||
return switch (float) {
|
return switch (float) {
|
||||||
|
.bf16 => 16,
|
||||||
.fp16 => 16,
|
.fp16 => 16,
|
||||||
.float16 => 16,
|
.float16 => 16,
|
||||||
.float => comp.target.cTypeBitSize(.float),
|
.float => comp.target.cTypeBitSize(.float),
|
||||||
.double => comp.target.cTypeBitSize(.double),
|
.double => comp.target.cTypeBitSize(.double),
|
||||||
.long_double => comp.target.cTypeBitSize(.longdouble),
|
.long_double => comp.target.cTypeBitSize(.longdouble),
|
||||||
.float128 => 128,
|
.float128 => 128,
|
||||||
|
.float32 => 32,
|
||||||
|
.float64 => 64,
|
||||||
|
.float32x => 32 * 2,
|
||||||
|
.float64x => 64 * 2,
|
||||||
|
.float128x => unreachable, // Not supported
|
||||||
|
.dfloat32 => 32,
|
||||||
|
.dfloat64 => 64,
|
||||||
|
.dfloat128 => 128,
|
||||||
|
.dfloat64x => 64 * 2,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@ -1747,12 +1833,22 @@ pub fn putExtra(ts: *TypeStore, gpa: std.mem.Allocator, ty: Type) !Index {
|
|||||||
.uint128 => return .int_uint128,
|
.uint128 => return .int_uint128,
|
||||||
},
|
},
|
||||||
.float => |float| switch (float) {
|
.float => |float| switch (float) {
|
||||||
|
.bf16 => return .float_bf16,
|
||||||
.fp16 => return .float_fp16,
|
.fp16 => return .float_fp16,
|
||||||
.float16 => return .float_float16,
|
.float16 => return .float_float16,
|
||||||
.float => return .float_float,
|
.float => return .float_float,
|
||||||
.double => return .float_double,
|
.double => return .float_double,
|
||||||
.long_double => return .float_long_double,
|
.long_double => return .float_long_double,
|
||||||
.float128 => return .float_float128,
|
.float128 => return .float_float128,
|
||||||
|
.float32 => return .float_float32,
|
||||||
|
.float64 => return .float_float64,
|
||||||
|
.float32x => return .float_float32x,
|
||||||
|
.float64x => return .float_float64x,
|
||||||
|
.float128x => return .float_float128x,
|
||||||
|
.dfloat32 => return .float_dfloat32,
|
||||||
|
.dfloat64 => return .float_dfloat64,
|
||||||
|
.dfloat128 => return .float_dfloat128,
|
||||||
|
.dfloat64x => return .float_dfloat64x,
|
||||||
},
|
},
|
||||||
else => {},
|
else => {},
|
||||||
}
|
}
|
||||||
@ -2009,10 +2105,10 @@ pub fn initNamedTypes(ts: *TypeStore, comp: *Compilation) !void {
|
|||||||
else => .int,
|
else => .int,
|
||||||
};
|
};
|
||||||
|
|
||||||
ts.intmax = target_util.intMaxType(comp.target);
|
ts.intmax = comp.target.intMaxType();
|
||||||
ts.intptr = target_util.intPtrType(comp.target);
|
ts.intptr = comp.target.intPtrType();
|
||||||
ts.int16 = target_util.int16Type(comp.target);
|
ts.int16 = comp.target.int16Type();
|
||||||
ts.int64 = target_util.int64Type(comp.target);
|
ts.int64 = comp.target.int64Type();
|
||||||
ts.uint_least16_t = comp.intLeastN(16, .unsigned);
|
ts.uint_least16_t = comp.intLeastN(16, .unsigned);
|
||||||
ts.uint_least32_t = comp.intLeastN(32, .unsigned);
|
ts.uint_least32_t = comp.intLeastN(32, .unsigned);
|
||||||
|
|
||||||
@ -2100,7 +2196,6 @@ fn generateVaListType(ts: *TypeStore, comp: *Compilation) !QualType {
|
|||||||
else
|
else
|
||||||
return .char_pointer,
|
return .char_pointer,
|
||||||
.powerpc, .powerpcle => .powerpc_va_list,
|
.powerpc, .powerpcle => .powerpc_va_list,
|
||||||
.s390x => .s390x_va_list,
|
|
||||||
.x86_64 => switch (comp.target.os.tag) {
|
.x86_64 => switch (comp.target.os.tag) {
|
||||||
.uefi, .windows => return .char_pointer,
|
.uefi, .windows => return .char_pointer,
|
||||||
else => .x86_64_va_list,
|
else => .x86_64_va_list,
|
||||||
@ -2367,18 +2462,33 @@ pub const Builder = struct {
|
|||||||
complex_sbit_int: u64,
|
complex_sbit_int: u64,
|
||||||
complex_ubit_int: u64,
|
complex_ubit_int: u64,
|
||||||
|
|
||||||
|
bf16,
|
||||||
fp16,
|
fp16,
|
||||||
float16,
|
float16,
|
||||||
float,
|
float,
|
||||||
double,
|
double,
|
||||||
long_double,
|
long_double,
|
||||||
float128,
|
float128,
|
||||||
|
float32,
|
||||||
|
float64,
|
||||||
|
float32x,
|
||||||
|
float64x,
|
||||||
|
float128x,
|
||||||
|
dfloat32,
|
||||||
|
dfloat64,
|
||||||
|
dfloat128,
|
||||||
|
dfloat64x,
|
||||||
complex,
|
complex,
|
||||||
complex_float16,
|
complex_float16,
|
||||||
complex_float,
|
complex_float,
|
||||||
complex_double,
|
complex_double,
|
||||||
complex_long_double,
|
complex_long_double,
|
||||||
complex_float128,
|
complex_float128,
|
||||||
|
complex_float32,
|
||||||
|
complex_float64,
|
||||||
|
complex_float32x,
|
||||||
|
complex_float64x,
|
||||||
|
complex_float128x,
|
||||||
|
|
||||||
// Any not simply constructed from specifier keywords.
|
// Any not simply constructed from specifier keywords.
|
||||||
other: QualType,
|
other: QualType,
|
||||||
@ -2450,6 +2560,7 @@ pub const Builder = struct {
|
|||||||
.complex_sint128 => "_Complex signed __int128",
|
.complex_sint128 => "_Complex signed __int128",
|
||||||
.complex_uint128 => "_Complex unsigned __int128",
|
.complex_uint128 => "_Complex unsigned __int128",
|
||||||
|
|
||||||
|
.bf16 => "__bf16",
|
||||||
.fp16 => "__fp16",
|
.fp16 => "__fp16",
|
||||||
.float16 => "_Float16",
|
.float16 => "_Float16",
|
||||||
.float => "float",
|
.float => "float",
|
||||||
@ -2581,18 +2692,33 @@ pub const Builder = struct {
|
|||||||
break :blk if (complex) try qt.toComplex(b.parser.comp) else qt;
|
break :blk if (complex) try qt.toComplex(b.parser.comp) else qt;
|
||||||
},
|
},
|
||||||
|
|
||||||
|
.bf16 => .bf16,
|
||||||
.fp16 => .fp16,
|
.fp16 => .fp16,
|
||||||
.float16 => .float16,
|
.float16 => .float16,
|
||||||
.float => .float,
|
.float => .float,
|
||||||
.double => .double,
|
.double => .double,
|
||||||
.long_double => .long_double,
|
.long_double => .long_double,
|
||||||
.float128 => .float128,
|
.float128 => .float128,
|
||||||
|
.float32 => .float32,
|
||||||
|
.float64 => .float64,
|
||||||
|
.float32x => .float32x,
|
||||||
|
.float64x => .float64x,
|
||||||
|
.float128x => .float128x,
|
||||||
|
.dfloat32 => .dfloat32,
|
||||||
|
.dfloat64 => .dfloat64,
|
||||||
|
.dfloat128 => .dfloat128,
|
||||||
|
.dfloat64x => .dfloat64x,
|
||||||
|
|
||||||
.complex_float16,
|
.complex_float16,
|
||||||
.complex_float,
|
.complex_float,
|
||||||
.complex_double,
|
.complex_double,
|
||||||
.complex_long_double,
|
.complex_long_double,
|
||||||
.complex_float128,
|
.complex_float128,
|
||||||
|
.complex_float32,
|
||||||
|
.complex_float64,
|
||||||
|
.complex_float32x,
|
||||||
|
.complex_float64x,
|
||||||
|
.complex_float128x,
|
||||||
.complex,
|
.complex,
|
||||||
=> blk: {
|
=> blk: {
|
||||||
const base_qt: QualType = switch (b.type) {
|
const base_qt: QualType = switch (b.type) {
|
||||||
@ -2601,6 +2727,11 @@ pub const Builder = struct {
|
|||||||
.complex_double => .double,
|
.complex_double => .double,
|
||||||
.complex_long_double => .long_double,
|
.complex_long_double => .long_double,
|
||||||
.complex_float128 => .float128,
|
.complex_float128 => .float128,
|
||||||
|
.complex_float32 => .float32,
|
||||||
|
.complex_float64 => .float64,
|
||||||
|
.complex_float32x => .float32x,
|
||||||
|
.complex_float64x => .float64x,
|
||||||
|
.complex_float128x => .float128x,
|
||||||
.complex => .double,
|
.complex => .double,
|
||||||
else => unreachable,
|
else => unreachable,
|
||||||
};
|
};
|
||||||
@ -2749,7 +2880,7 @@ pub const Builder = struct {
|
|||||||
else => {},
|
else => {},
|
||||||
}
|
}
|
||||||
|
|
||||||
if (new == .int128 and !target_util.hasInt128(b.parser.comp.target)) {
|
if (new == .int128 and !b.parser.comp.target.hasInt128()) {
|
||||||
try b.parser.err(source_tok, .type_not_supported_on_target, .{"__int128"});
|
try b.parser.err(source_tok, .type_not_supported_on_target, .{"__int128"});
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2996,13 +3127,59 @@ pub const Builder = struct {
|
|||||||
.complex => .complex_float128,
|
.complex => .complex_float128,
|
||||||
else => return b.cannotCombine(source_tok),
|
else => return b.cannotCombine(source_tok),
|
||||||
},
|
},
|
||||||
.complex => switch (b.type) {
|
.float32 => switch (b.type) {
|
||||||
|
.none => .float32,
|
||||||
|
.complex => .complex_float32,
|
||||||
|
else => return b.cannotCombine(source_tok),
|
||||||
|
},
|
||||||
|
.float64 => switch (b.type) {
|
||||||
|
.none => .float64,
|
||||||
|
.complex => .complex_float64,
|
||||||
|
else => return b.cannotCombine(source_tok),
|
||||||
|
},
|
||||||
|
.float32x => switch (b.type) {
|
||||||
|
.none => .float32x,
|
||||||
|
.complex => .complex_float32x,
|
||||||
|
else => return b.cannotCombine(source_tok),
|
||||||
|
},
|
||||||
|
.float64x => switch (b.type) {
|
||||||
|
.none => .float64x,
|
||||||
|
.complex => .complex_float64x,
|
||||||
|
else => return b.cannotCombine(source_tok),
|
||||||
|
},
|
||||||
|
.float128x => switch (b.type) {
|
||||||
|
.none => .float128x,
|
||||||
|
.complex => .complex_float128x,
|
||||||
|
else => return b.cannotCombine(source_tok),
|
||||||
|
},
|
||||||
|
.dfloat32 => switch (b.type) {
|
||||||
|
.none => .dfloat32,
|
||||||
|
else => return b.cannotCombine(source_tok),
|
||||||
|
},
|
||||||
|
.dfloat64 => switch (b.type) {
|
||||||
|
.none => .dfloat64,
|
||||||
|
else => return b.cannotCombine(source_tok),
|
||||||
|
},
|
||||||
|
.dfloat128 => switch (b.type) {
|
||||||
|
.none => .dfloat128,
|
||||||
|
else => return b.cannotCombine(source_tok),
|
||||||
|
},
|
||||||
|
.dfloat64x => switch (b.type) {
|
||||||
|
.none => .dfloat64x,
|
||||||
|
else => return b.cannotCombine(source_tok),
|
||||||
|
},
|
||||||
|
.complex => switch (b.type) { //
|
||||||
.none => .complex,
|
.none => .complex,
|
||||||
.float16 => .complex_float16,
|
.float16 => .complex_float16,
|
||||||
.float => .complex_float,
|
.float => .complex_float,
|
||||||
.double => .complex_double,
|
.double => .complex_double,
|
||||||
.long_double => .complex_long_double,
|
.long_double => .complex_long_double,
|
||||||
.float128 => .complex_float128,
|
.float128 => .complex_float128,
|
||||||
|
.float32 => .complex_float32,
|
||||||
|
.float64 => .complex_float64,
|
||||||
|
.float32x => .complex_float32x,
|
||||||
|
.float64x => .complex_float64x,
|
||||||
|
.float128x => .complex_float128x,
|
||||||
.char => .complex_char,
|
.char => .complex_char,
|
||||||
.schar => .complex_schar,
|
.schar => .complex_schar,
|
||||||
.uchar => .complex_uchar,
|
.uchar => .complex_uchar,
|
||||||
@ -3072,6 +3249,11 @@ pub const Builder = struct {
|
|||||||
.complex_bit_int,
|
.complex_bit_int,
|
||||||
.complex_sbit_int,
|
.complex_sbit_int,
|
||||||
.complex_ubit_int,
|
.complex_ubit_int,
|
||||||
|
.complex_float32,
|
||||||
|
.complex_float64,
|
||||||
|
.complex_float32x,
|
||||||
|
.complex_float64x,
|
||||||
|
.complex_float128x,
|
||||||
=> return b.duplicateSpec(source_tok, "_Complex"),
|
=> return b.duplicateSpec(source_tok, "_Complex"),
|
||||||
else => return b.cannotCombine(source_tok),
|
else => return b.cannotCombine(source_tok),
|
||||||
},
|
},
|
||||||
@ -3104,12 +3286,22 @@ pub const Builder = struct {
|
|||||||
return .{ .bit_int = bit_int.bits };
|
return .{ .bit_int = bit_int.bits };
|
||||||
},
|
},
|
||||||
.float => |float| switch (float) {
|
.float => |float| switch (float) {
|
||||||
|
.bf16 => .bf16,
|
||||||
.fp16 => .fp16,
|
.fp16 => .fp16,
|
||||||
.float16 => .float16,
|
.float16 => .float16,
|
||||||
.float => .float,
|
.float => .float,
|
||||||
.double => .double,
|
.double => .double,
|
||||||
.long_double => .long_double,
|
.long_double => .long_double,
|
||||||
.float128 => .float128,
|
.float128 => .float128,
|
||||||
|
.float32 => .float32,
|
||||||
|
.float64 => .float64,
|
||||||
|
.float32x => .float32x,
|
||||||
|
.float64x => .float64x,
|
||||||
|
.float128x => .float128x,
|
||||||
|
.dfloat32 => .dfloat32,
|
||||||
|
.dfloat64 => .dfloat64,
|
||||||
|
.dfloat128 => .dfloat128,
|
||||||
|
.dfloat64x => .dfloat64x,
|
||||||
},
|
},
|
||||||
.complex => |complex| switch (complex.base(comp).type) {
|
.complex => |complex| switch (complex.base(comp).type) {
|
||||||
.int => |int| switch (int) {
|
.int => |int| switch (int) {
|
||||||
@ -3134,11 +3326,21 @@ pub const Builder = struct {
|
|||||||
},
|
},
|
||||||
.float => |float| switch (float) {
|
.float => |float| switch (float) {
|
||||||
.fp16 => unreachable,
|
.fp16 => unreachable,
|
||||||
|
.bf16 => unreachable,
|
||||||
.float16 => .complex_float16,
|
.float16 => .complex_float16,
|
||||||
.float => .complex_float,
|
.float => .complex_float,
|
||||||
.double => .complex_double,
|
.double => .complex_double,
|
||||||
.long_double => .complex_long_double,
|
.long_double => .complex_long_double,
|
||||||
.float128 => .complex_float128,
|
.float128 => .complex_float128,
|
||||||
|
.float32 => .complex_float32,
|
||||||
|
.float64 => .complex_float64,
|
||||||
|
.float32x => .complex_float32x,
|
||||||
|
.float64x => .complex_float64x,
|
||||||
|
.float128x => .complex_float128x,
|
||||||
|
.dfloat32 => unreachable,
|
||||||
|
.dfloat64 => unreachable,
|
||||||
|
.dfloat128 => unreachable,
|
||||||
|
.dfloat64x => unreachable,
|
||||||
},
|
},
|
||||||
else => unreachable,
|
else => unreachable,
|
||||||
},
|
},
|
||||||
|
|||||||
12
lib/compiler/aro/aro/Value.zig
vendored
12
lib/compiler/aro/aro/Value.zig
vendored
@ -8,7 +8,7 @@ const BigIntSpace = Interner.Tag.Int.BigIntSpace;
|
|||||||
|
|
||||||
const annex_g = @import("annex_g.zig");
|
const annex_g = @import("annex_g.zig");
|
||||||
const Compilation = @import("Compilation.zig");
|
const Compilation = @import("Compilation.zig");
|
||||||
const target_util = @import("target.zig");
|
const Target = @import("Target.zig");
|
||||||
const QualType = @import("TypeStore.zig").QualType;
|
const QualType = @import("TypeStore.zig").QualType;
|
||||||
|
|
||||||
const Value = @This();
|
const Value = @This();
|
||||||
@ -80,10 +80,10 @@ test "minUnsignedBits" {
|
|||||||
defer arena_state.deinit();
|
defer arena_state.deinit();
|
||||||
const arena = arena_state.allocator();
|
const arena = arena_state.allocator();
|
||||||
|
|
||||||
var comp = Compilation.init(std.testing.allocator, arena, undefined, std.fs.cwd());
|
var comp = Compilation.init(std.testing.allocator, arena, std.testing.io, undefined, std.fs.cwd());
|
||||||
defer comp.deinit();
|
defer comp.deinit();
|
||||||
const target_query = try std.Target.Query.parse(.{ .arch_os_abi = "x86_64-linux-gnu" });
|
const target_query = try std.Target.Query.parse(.{ .arch_os_abi = "x86_64-linux-gnu" });
|
||||||
comp.target = try std.zig.system.resolveTargetQuery(target_query);
|
comp.target = .fromZigTarget(try std.zig.system.resolveTargetQuery(std.testing.io, target_query));
|
||||||
|
|
||||||
try Test.checkIntBits(&comp, 0, 0);
|
try Test.checkIntBits(&comp, 0, 0);
|
||||||
try Test.checkIntBits(&comp, 1, 1);
|
try Test.checkIntBits(&comp, 1, 1);
|
||||||
@ -119,10 +119,10 @@ test "minSignedBits" {
|
|||||||
defer arena_state.deinit();
|
defer arena_state.deinit();
|
||||||
const arena = arena_state.allocator();
|
const arena = arena_state.allocator();
|
||||||
|
|
||||||
var comp = Compilation.init(std.testing.allocator, arena, undefined, std.fs.cwd());
|
var comp = Compilation.init(std.testing.allocator, arena, std.testing.io, undefined, std.fs.cwd());
|
||||||
defer comp.deinit();
|
defer comp.deinit();
|
||||||
const target_query = try std.Target.Query.parse(.{ .arch_os_abi = "x86_64-linux-gnu" });
|
const target_query = try std.Target.Query.parse(.{ .arch_os_abi = "x86_64-linux-gnu" });
|
||||||
comp.target = try std.zig.system.resolveTargetQuery(target_query);
|
comp.target = .fromZigTarget(try std.zig.system.resolveTargetQuery(std.testing.io, target_query));
|
||||||
|
|
||||||
try Test.checkIntBits(&comp, -1, 1);
|
try Test.checkIntBits(&comp, -1, 1);
|
||||||
try Test.checkIntBits(&comp, -2, 2);
|
try Test.checkIntBits(&comp, -2, 2);
|
||||||
@ -401,7 +401,7 @@ pub fn isZero(v: Value, comp: *const Compilation) bool {
|
|||||||
switch (v.ref()) {
|
switch (v.ref()) {
|
||||||
.zero => return true,
|
.zero => return true,
|
||||||
.one => return false,
|
.one => return false,
|
||||||
.null => return target_util.nullRepr(comp.target) == 0,
|
.null => return comp.target.nullRepr() == 0,
|
||||||
else => {},
|
else => {},
|
||||||
}
|
}
|
||||||
const key = comp.interner.get(v.ref());
|
const key = comp.interner.get(v.ref());
|
||||||
|
|||||||
6
lib/compiler/aro/aro/features.zig
vendored
6
lib/compiler/aro/aro/features.zig
vendored
@ -1,6 +1,6 @@
|
|||||||
const std = @import("std");
|
const std = @import("std");
|
||||||
const Compilation = @import("Compilation.zig");
|
const Compilation = @import("Compilation.zig");
|
||||||
const target_util = @import("target.zig");
|
const Target = @import("Target.zig");
|
||||||
|
|
||||||
/// Used to implement the __has_feature macro.
|
/// Used to implement the __has_feature macro.
|
||||||
pub fn hasFeature(comp: *Compilation, ext: []const u8) bool {
|
pub fn hasFeature(comp: *Compilation, ext: []const u8) bool {
|
||||||
@ -43,7 +43,7 @@ pub fn hasFeature(comp: *Compilation, ext: []const u8) bool {
|
|||||||
.c_atomic = comp.langopts.standard.atLeast(.c11),
|
.c_atomic = comp.langopts.standard.atLeast(.c11),
|
||||||
.c_generic_selections = comp.langopts.standard.atLeast(.c11),
|
.c_generic_selections = comp.langopts.standard.atLeast(.c11),
|
||||||
.c_static_assert = comp.langopts.standard.atLeast(.c11),
|
.c_static_assert = comp.langopts.standard.atLeast(.c11),
|
||||||
.c_thread_local = comp.langopts.standard.atLeast(.c11) and target_util.isTlsSupported(comp.target),
|
.c_thread_local = comp.langopts.standard.atLeast(.c11) and comp.target.isTlsSupported(),
|
||||||
};
|
};
|
||||||
inline for (@typeInfo(@TypeOf(list)).@"struct".fields) |f| {
|
inline for (@typeInfo(@TypeOf(list)).@"struct".fields) |f| {
|
||||||
if (std.mem.eql(u8, f.name, ext)) return @field(list, f.name);
|
if (std.mem.eql(u8, f.name, ext)) return @field(list, f.name);
|
||||||
@ -60,7 +60,7 @@ pub fn hasExtension(comp: *Compilation, ext: []const u8) bool {
|
|||||||
.c_atomic = true,
|
.c_atomic = true,
|
||||||
.c_generic_selections = true,
|
.c_generic_selections = true,
|
||||||
.c_static_assert = true,
|
.c_static_assert = true,
|
||||||
.c_thread_local = target_util.isTlsSupported(comp.target),
|
.c_thread_local = comp.target.isTlsSupported(),
|
||||||
// misc
|
// misc
|
||||||
.overloadable_unmarked = false, // TODO
|
.overloadable_unmarked = false, // TODO
|
||||||
.statement_attributes_with_gnu_syntax = true,
|
.statement_attributes_with_gnu_syntax = true,
|
||||||
|
|||||||
5
lib/compiler/aro/aro/pragmas/gcc.zig
vendored
5
lib/compiler/aro/aro/pragmas/gcc.zig
vendored
@ -18,6 +18,7 @@ pragma: Pragma = .{
|
|||||||
.preprocessorHandler = preprocessorHandler,
|
.preprocessorHandler = preprocessorHandler,
|
||||||
.parserHandler = parserHandler,
|
.parserHandler = parserHandler,
|
||||||
.preserveTokens = preserveTokens,
|
.preserveTokens = preserveTokens,
|
||||||
|
.shouldExpandTokenAtIndexHandler = shouldExpandTokenAtIndex,
|
||||||
},
|
},
|
||||||
original_state: Diagnostics.State = .{},
|
original_state: Diagnostics.State = .{},
|
||||||
state_stack: std.ArrayList(Diagnostics.State) = .empty,
|
state_stack: std.ArrayList(Diagnostics.State) = .empty,
|
||||||
@ -169,3 +170,7 @@ fn preserveTokens(_: *Pragma, pp: *Preprocessor, start_idx: TokenIndex) bool {
|
|||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn shouldExpandTokenAtIndex(_: *const Pragma, _: TokenIndex) bool {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|||||||
9
lib/compiler/aro/aro/pragmas/once.zig
vendored
9
lib/compiler/aro/aro/pragmas/once.zig
vendored
@ -51,6 +51,15 @@ fn preprocessorHandler(pragma: *Pragma, pp: *Preprocessor, start_idx: TokenIndex
|
|||||||
.location = name_tok.loc.expand(pp.comp),
|
.location = name_tok.loc.expand(pp.comp),
|
||||||
}, pp.expansionSlice(start_idx + 1), true);
|
}, pp.expansionSlice(start_idx + 1), true);
|
||||||
}
|
}
|
||||||
|
if (pp.include_depth == 0) {
|
||||||
|
const diagnostic: Preprocessor.Diagnostic = .pragma_once_in_main_file;
|
||||||
|
return pp.diagnostics.addWithLocation(pp.comp, .{
|
||||||
|
.text = diagnostic.fmt,
|
||||||
|
.kind = diagnostic.kind,
|
||||||
|
.opt = diagnostic.opt,
|
||||||
|
.location = name_tok.loc.expand(pp.comp),
|
||||||
|
}, pp.expansionSlice(start_idx + 1), true);
|
||||||
|
}
|
||||||
const seen = self.preprocess_count == pp.preprocess_count;
|
const seen = self.preprocess_count == pp.preprocess_count;
|
||||||
const prev = try self.pragma_once.fetchPut(pp.comp.gpa, name_tok.loc.id, {});
|
const prev = try self.pragma_once.fetchPut(pp.comp.gpa, name_tok.loc.id, {});
|
||||||
if (prev != null and !seen) {
|
if (prev != null and !seen) {
|
||||||
|
|||||||
17
lib/compiler/aro/aro/pragmas/pack.zig
vendored
17
lib/compiler/aro/aro/pragmas/pack.zig
vendored
@ -84,10 +84,10 @@ fn parserHandler(pragma: *Pragma, p: *Parser, start_idx: TokenIndex) Compilation
|
|||||||
if (action == .push) {
|
if (action == .push) {
|
||||||
try pack.stack.append(p.comp.gpa, .{ .label = label orelse "", .val = p.pragma_pack orelse 8 });
|
try pack.stack.append(p.comp.gpa, .{ .label = label orelse "", .val = p.pragma_pack orelse 8 });
|
||||||
} else {
|
} else {
|
||||||
pack.pop(p, label);
|
const pop_success = pack.pop(p, label);
|
||||||
if (new_val != null) {
|
if (new_val != null) {
|
||||||
try Pragma.err(p.pp, arg, .pragma_pack_undefined_pop, .{});
|
try Pragma.err(p.pp, arg, .pragma_pack_undefined_pop, .{});
|
||||||
} else if (pack.stack.items.len == 0) {
|
} else if (!pop_success) {
|
||||||
try Pragma.err(p.pp, arg, .pragma_pack_empty_stack, .{});
|
try Pragma.err(p.pp, arg, .pragma_pack_empty_stack, .{});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -136,22 +136,25 @@ fn packInt(p: *Parser, tok_i: TokenIndex) Compilation.Error!?u8 {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn pop(pack: *Pack, p: *Parser, maybe_label: ?[]const u8) void {
|
/// Returns true if an item was successfully popped.
|
||||||
|
fn pop(pack: *Pack, p: *Parser, maybe_label: ?[]const u8) bool {
|
||||||
if (maybe_label) |label| {
|
if (maybe_label) |label| {
|
||||||
var i = pack.stack.items.len;
|
var i = pack.stack.items.len;
|
||||||
while (i > 0) {
|
while (i > 0) {
|
||||||
i -= 1;
|
i -= 1;
|
||||||
if (std.mem.eql(u8, pack.stack.items[i].label, label)) {
|
if (std.mem.eql(u8, pack.stack.items[i].label, label)) {
|
||||||
const prev = pack.stack.orderedRemove(i);
|
p.pragma_pack = pack.stack.items[i].val;
|
||||||
p.pragma_pack = prev.val;
|
pack.stack.items.len = i;
|
||||||
return;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
return false;
|
||||||
} else {
|
} else {
|
||||||
const prev = pack.stack.pop() orelse {
|
const prev = pack.stack.pop() orelse {
|
||||||
p.pragma_pack = 2;
|
p.pragma_pack = 2;
|
||||||
return;
|
return false;
|
||||||
};
|
};
|
||||||
p.pragma_pack = prev.val;
|
p.pragma_pack = prev.val;
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
10
lib/compiler/aro/aro/record_layout.zig
vendored
10
lib/compiler/aro/aro/record_layout.zig
vendored
@ -6,7 +6,7 @@ const std = @import("std");
|
|||||||
const Attribute = @import("Attribute.zig");
|
const Attribute = @import("Attribute.zig");
|
||||||
const Compilation = @import("Compilation.zig");
|
const Compilation = @import("Compilation.zig");
|
||||||
const Parser = @import("Parser.zig");
|
const Parser = @import("Parser.zig");
|
||||||
const target_util = @import("target.zig");
|
const Target = @import("Target.zig");
|
||||||
const TypeStore = @import("TypeStore.zig");
|
const TypeStore = @import("TypeStore.zig");
|
||||||
const QualType = TypeStore.QualType;
|
const QualType = TypeStore.QualType;
|
||||||
const Type = TypeStore.Type;
|
const Type = TypeStore.Type;
|
||||||
@ -281,18 +281,18 @@ const SysVContext = struct {
|
|||||||
// Some targets ignore the alignment of the underlying type when laying out
|
// Some targets ignore the alignment of the underlying type when laying out
|
||||||
// non-zero-sized bit-fields. See test case 0072. On such targets, bit-fields never
|
// non-zero-sized bit-fields. See test case 0072. On such targets, bit-fields never
|
||||||
// cross a storage boundary. See test case 0081.
|
// cross a storage boundary. See test case 0081.
|
||||||
if (target_util.ignoreNonZeroSizedBitfieldTypeAlignment(self.comp.target)) {
|
if (self.comp.target.ignoreNonZeroSizedBitfieldTypeAlignment()) {
|
||||||
ty_fld_algn_bits = 1;
|
ty_fld_algn_bits = 1;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// Some targets ignore the alignment of the underlying type when laying out
|
// Some targets ignore the alignment of the underlying type when laying out
|
||||||
// zero-sized bit-fields. See test case 0073.
|
// zero-sized bit-fields. See test case 0073.
|
||||||
if (target_util.ignoreZeroSizedBitfieldTypeAlignment(self.comp.target)) {
|
if (self.comp.target.ignoreZeroSizedBitfieldTypeAlignment()) {
|
||||||
ty_fld_algn_bits = 1;
|
ty_fld_algn_bits = 1;
|
||||||
}
|
}
|
||||||
// Some targets have a minimum alignment of zero-sized bit-fields. See test case
|
// Some targets have a minimum alignment of zero-sized bit-fields. See test case
|
||||||
// 0074.
|
// 0074.
|
||||||
if (target_util.minZeroWidthBitfieldAlignment(self.comp.target)) |target_align| {
|
if (self.comp.target.minZeroWidthBitfieldAlignment()) |target_align| {
|
||||||
ty_fld_algn_bits = @max(ty_fld_algn_bits, target_align);
|
ty_fld_algn_bits = @max(ty_fld_algn_bits, target_align);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -355,7 +355,7 @@ const SysVContext = struct {
|
|||||||
|
|
||||||
// Unnamed fields do not contribute to the record alignment except on a few targets.
|
// Unnamed fields do not contribute to the record alignment except on a few targets.
|
||||||
// See test case 0079.
|
// See test case 0079.
|
||||||
if (is_named or target_util.unnamedFieldAffectsAlignment(self.comp.target)) {
|
if (is_named or self.comp.target.unnamedFieldAffectsAlignment()) {
|
||||||
var inherited_align_bits: u32 = undefined;
|
var inherited_align_bits: u32 = undefined;
|
||||||
|
|
||||||
if (bit_width == 0) {
|
if (bit_width == 0) {
|
||||||
|
|||||||
998
lib/compiler/aro/aro/target.zig
vendored
998
lib/compiler/aro/aro/target.zig
vendored
@ -1,998 +0,0 @@
|
|||||||
const std = @import("std");
|
|
||||||
|
|
||||||
const backend = @import("../backend.zig");
|
|
||||||
|
|
||||||
const LangOpts = @import("LangOpts.zig");
|
|
||||||
const TargetSet = @import("Builtins/Properties.zig").TargetSet;
|
|
||||||
const QualType = @import("TypeStore.zig").QualType;
|
|
||||||
|
|
||||||
/// intmax_t for this target
|
|
||||||
pub fn intMaxType(target: std.Target) QualType {
|
|
||||||
switch (target.cpu.arch) {
|
|
||||||
.aarch64,
|
|
||||||
.aarch64_be,
|
|
||||||
.sparc64,
|
|
||||||
=> if (target.os.tag != .openbsd) return .long,
|
|
||||||
|
|
||||||
.bpfel,
|
|
||||||
.bpfeb,
|
|
||||||
.loongarch64,
|
|
||||||
.riscv64,
|
|
||||||
.riscv64be,
|
|
||||||
.powerpc64,
|
|
||||||
.powerpc64le,
|
|
||||||
.ve,
|
|
||||||
=> return .long,
|
|
||||||
|
|
||||||
.x86_64 => switch (target.os.tag) {
|
|
||||||
.windows, .openbsd => {},
|
|
||||||
else => switch (target.abi) {
|
|
||||||
.gnux32, .muslx32 => {},
|
|
||||||
else => return .long,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
|
|
||||||
else => {},
|
|
||||||
}
|
|
||||||
return .long_long;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// intptr_t for this target
|
|
||||||
pub fn intPtrType(target: std.Target) QualType {
|
|
||||||
if (target.os.tag == .haiku) return .long;
|
|
||||||
|
|
||||||
switch (target.cpu.arch) {
|
|
||||||
.aarch64, .aarch64_be => switch (target.os.tag) {
|
|
||||||
.windows => return .long_long,
|
|
||||||
else => {},
|
|
||||||
},
|
|
||||||
|
|
||||||
.msp430,
|
|
||||||
.csky,
|
|
||||||
.loongarch32,
|
|
||||||
.riscv32,
|
|
||||||
.riscv32be,
|
|
||||||
.xcore,
|
|
||||||
.hexagon,
|
|
||||||
.m68k,
|
|
||||||
.spirv32,
|
|
||||||
.arc,
|
|
||||||
.avr,
|
|
||||||
=> return .int,
|
|
||||||
|
|
||||||
.sparc => switch (target.os.tag) {
|
|
||||||
.netbsd, .openbsd => {},
|
|
||||||
else => return .int,
|
|
||||||
},
|
|
||||||
|
|
||||||
.powerpc, .powerpcle => switch (target.os.tag) {
|
|
||||||
.linux, .freebsd, .netbsd => return .int,
|
|
||||||
else => {},
|
|
||||||
},
|
|
||||||
|
|
||||||
// 32-bit x86 Darwin, OpenBSD, and RTEMS use long (the default); others use int
|
|
||||||
.x86 => switch (target.os.tag) {
|
|
||||||
.openbsd, .rtems => {},
|
|
||||||
else => if (!target.os.tag.isDarwin()) return .int,
|
|
||||||
},
|
|
||||||
|
|
||||||
.x86_64 => switch (target.os.tag) {
|
|
||||||
.windows => return .long_long,
|
|
||||||
else => switch (target.abi) {
|
|
||||||
.gnux32, .muslx32 => return .int,
|
|
||||||
else => {},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
|
|
||||||
else => {},
|
|
||||||
}
|
|
||||||
|
|
||||||
return .long;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// int16_t for this target
|
|
||||||
pub fn int16Type(target: std.Target) QualType {
|
|
||||||
return switch (target.cpu.arch) {
|
|
||||||
.avr => .int,
|
|
||||||
else => .short,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
/// sig_atomic_t for this target
|
|
||||||
pub fn sigAtomicType(target: std.Target) QualType {
|
|
||||||
if (target.cpu.arch.isWasm()) return .long;
|
|
||||||
return switch (target.cpu.arch) {
|
|
||||||
.avr => .schar,
|
|
||||||
.msp430 => .long,
|
|
||||||
else => .int,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
/// int64_t for this target
|
|
||||||
pub fn int64Type(target: std.Target) QualType {
|
|
||||||
switch (target.cpu.arch) {
|
|
||||||
.loongarch64,
|
|
||||||
.ve,
|
|
||||||
.riscv64,
|
|
||||||
.riscv64be,
|
|
||||||
.powerpc64,
|
|
||||||
.powerpc64le,
|
|
||||||
.bpfel,
|
|
||||||
.bpfeb,
|
|
||||||
=> return .long,
|
|
||||||
|
|
||||||
.sparc64 => return intMaxType(target),
|
|
||||||
|
|
||||||
.x86, .x86_64 => if (!target.os.tag.isDarwin()) return intMaxType(target),
|
|
||||||
.aarch64, .aarch64_be => if (!target.os.tag.isDarwin() and target.os.tag != .openbsd and target.os.tag != .windows) return .long,
|
|
||||||
else => {},
|
|
||||||
}
|
|
||||||
return .long_long;
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn float80Type(target: std.Target) ?QualType {
|
|
||||||
switch (target.cpu.arch) {
|
|
||||||
.x86, .x86_64 => return .long_double,
|
|
||||||
else => {},
|
|
||||||
}
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// This function returns 1 if function alignment is not observable or settable.
|
|
||||||
pub fn defaultFunctionAlignment(target: std.Target) u8 {
|
|
||||||
return switch (target.cpu.arch) {
|
|
||||||
.arm, .armeb => 4,
|
|
||||||
.aarch64, .aarch64_be => 4,
|
|
||||||
.sparc, .sparc64 => 4,
|
|
||||||
.riscv64, .riscv64be => 2,
|
|
||||||
else => 1,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn isTlsSupported(target: std.Target) bool {
|
|
||||||
if (target.os.tag.isDarwin()) {
|
|
||||||
var supported = false;
|
|
||||||
switch (target.os.tag) {
|
|
||||||
.macos => supported = !(target.os.isAtLeast(.macos, .{ .major = 10, .minor = 7, .patch = 0 }) orelse false),
|
|
||||||
else => {},
|
|
||||||
}
|
|
||||||
return supported;
|
|
||||||
}
|
|
||||||
return switch (target.cpu.arch) {
|
|
||||||
.bpfel, .bpfeb, .msp430, .nvptx, .nvptx64, .x86, .arm, .armeb, .thumb, .thumbeb => false,
|
|
||||||
else => true,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn ignoreNonZeroSizedBitfieldTypeAlignment(target: std.Target) bool {
|
|
||||||
switch (target.cpu.arch) {
|
|
||||||
.avr => return true,
|
|
||||||
.arm => {
|
|
||||||
if (std.Target.arm.featureSetHas(target.cpu.features, .has_v7)) {
|
|
||||||
switch (target.os.tag) {
|
|
||||||
.ios => return true,
|
|
||||||
else => return false,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
else => return false,
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn ignoreZeroSizedBitfieldTypeAlignment(target: std.Target) bool {
|
|
||||||
switch (target.cpu.arch) {
|
|
||||||
.avr => return true,
|
|
||||||
else => return false,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn minZeroWidthBitfieldAlignment(target: std.Target) ?u29 {
|
|
||||||
switch (target.cpu.arch) {
|
|
||||||
.avr => return 8,
|
|
||||||
.arm => {
|
|
||||||
if (std.Target.arm.featureSetHas(target.cpu.features, .has_v7)) {
|
|
||||||
switch (target.os.tag) {
|
|
||||||
.ios => return 32,
|
|
||||||
else => return null,
|
|
||||||
}
|
|
||||||
} else return null;
|
|
||||||
},
|
|
||||||
else => return null,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn unnamedFieldAffectsAlignment(target: std.Target) bool {
|
|
||||||
switch (target.cpu.arch) {
|
|
||||||
.aarch64 => {
|
|
||||||
if (target.os.tag.isDarwin() or target.os.tag == .windows) return false;
|
|
||||||
return true;
|
|
||||||
},
|
|
||||||
.armeb => {
|
|
||||||
if (std.Target.arm.featureSetHas(target.cpu.features, .has_v7)) {
|
|
||||||
if (std.Target.Abi.default(target.cpu.arch, target.os.tag) == .eabi) return true;
|
|
||||||
}
|
|
||||||
},
|
|
||||||
.arm => return true,
|
|
||||||
.avr => return true,
|
|
||||||
.thumb => {
|
|
||||||
if (target.os.tag == .windows) return false;
|
|
||||||
return true;
|
|
||||||
},
|
|
||||||
else => return false,
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn packAllEnums(target: std.Target) bool {
|
|
||||||
return switch (target.cpu.arch) {
|
|
||||||
.hexagon => true,
|
|
||||||
else => false,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Default alignment (in bytes) for __attribute__((aligned)) when no alignment is specified
|
|
||||||
pub fn defaultAlignment(target: std.Target) u29 {
|
|
||||||
switch (target.cpu.arch) {
|
|
||||||
.avr => return 1,
|
|
||||||
.arm => if (target.abi.isAndroid() or target.os.tag == .ios) return 16 else return 8,
|
|
||||||
.sparc => if (std.Target.sparc.featureSetHas(target.cpu.features, .v9)) return 16 else return 8,
|
|
||||||
.mips, .mipsel => switch (target.abi) {
|
|
||||||
.none, .gnuabi64 => return 16,
|
|
||||||
else => return 8,
|
|
||||||
},
|
|
||||||
.s390x, .armeb, .thumbeb, .thumb => return 8,
|
|
||||||
else => return 16,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
pub fn systemCompiler(target: std.Target) LangOpts.Compiler {
|
|
||||||
// Android is linux but not gcc, so these checks go first
|
|
||||||
// the rest for documentation as fn returns .clang
|
|
||||||
if (target.os.tag.isDarwin() or
|
|
||||||
target.abi.isAndroid() or
|
|
||||||
target.os.tag.isBSD() or
|
|
||||||
target.os.tag == .fuchsia or
|
|
||||||
target.os.tag == .illumos or
|
|
||||||
target.os.tag == .haiku or
|
|
||||||
target.cpu.arch == .hexagon)
|
|
||||||
{
|
|
||||||
return .clang;
|
|
||||||
}
|
|
||||||
if (target.os.tag == .uefi) return .msvc;
|
|
||||||
// this is before windows to grab WindowsGnu
|
|
||||||
if (target.abi.isGnu() or
|
|
||||||
target.os.tag == .linux)
|
|
||||||
{
|
|
||||||
return .gcc;
|
|
||||||
}
|
|
||||||
if (target.os.tag == .windows) {
|
|
||||||
return .msvc;
|
|
||||||
}
|
|
||||||
if (target.cpu.arch == .avr) return .gcc;
|
|
||||||
return .clang;
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn hasFloat128(target: std.Target) bool {
|
|
||||||
if (target.cpu.arch.isWasm()) return true;
|
|
||||||
if (target.os.tag.isDarwin()) return false;
|
|
||||||
if (target.cpu.arch.isPowerPC()) return std.Target.powerpc.featureSetHas(target.cpu.features, .float128);
|
|
||||||
return switch (target.os.tag) {
|
|
||||||
.dragonfly,
|
|
||||||
.haiku,
|
|
||||||
.linux,
|
|
||||||
.openbsd,
|
|
||||||
.illumos,
|
|
||||||
=> target.cpu.arch.isX86(),
|
|
||||||
else => false,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn hasInt128(target: std.Target) bool {
|
|
||||||
if (target.cpu.arch == .wasm32) return true;
|
|
||||||
if (target.cpu.arch == .x86_64) return true;
|
|
||||||
return target.ptrBitWidth() >= 64;
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn hasHalfPrecisionFloatABI(target: std.Target) bool {
|
|
||||||
return switch (target.cpu.arch) {
|
|
||||||
.thumb, .thumbeb, .arm, .aarch64 => true,
|
|
||||||
else => false,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
pub const FPSemantics = enum {
|
|
||||||
None,
|
|
||||||
IEEEHalf,
|
|
||||||
BFloat,
|
|
||||||
IEEESingle,
|
|
||||||
IEEEDouble,
|
|
||||||
IEEEQuad,
|
|
||||||
/// Minifloat 5-bit exponent 2-bit mantissa
|
|
||||||
E5M2,
|
|
||||||
/// Minifloat 4-bit exponent 3-bit mantissa
|
|
||||||
E4M3,
|
|
||||||
x87ExtendedDouble,
|
|
||||||
IBMExtendedDouble,
|
|
||||||
|
|
||||||
/// Only intended for generating float.h macros for the preprocessor
|
|
||||||
pub fn forType(ty: std.Target.CType, target: std.Target) FPSemantics {
|
|
||||||
std.debug.assert(ty == .float or ty == .double or ty == .longdouble);
|
|
||||||
return switch (target.cTypeBitSize(ty)) {
|
|
||||||
32 => .IEEESingle,
|
|
||||||
64 => .IEEEDouble,
|
|
||||||
80 => .x87ExtendedDouble,
|
|
||||||
128 => switch (target.cpu.arch) {
|
|
||||||
.powerpc, .powerpcle, .powerpc64, .powerpc64le => .IBMExtendedDouble,
|
|
||||||
else => .IEEEQuad,
|
|
||||||
},
|
|
||||||
else => unreachable,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn halfPrecisionType(target: std.Target) ?FPSemantics {
|
|
||||||
switch (target.cpu.arch) {
|
|
||||||
.aarch64,
|
|
||||||
.aarch64_be,
|
|
||||||
.arm,
|
|
||||||
.armeb,
|
|
||||||
.hexagon,
|
|
||||||
.riscv32,
|
|
||||||
.riscv32be,
|
|
||||||
.riscv64,
|
|
||||||
.riscv64be,
|
|
||||||
.spirv32,
|
|
||||||
.spirv64,
|
|
||||||
=> return .IEEEHalf,
|
|
||||||
.x86, .x86_64 => if (std.Target.x86.featureSetHas(target.cpu.features, .sse2)) return .IEEEHalf,
|
|
||||||
else => {},
|
|
||||||
}
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn chooseValue(self: FPSemantics, comptime T: type, values: [6]T) T {
|
|
||||||
return switch (self) {
|
|
||||||
.IEEEHalf => values[0],
|
|
||||||
.IEEESingle => values[1],
|
|
||||||
.IEEEDouble => values[2],
|
|
||||||
.x87ExtendedDouble => values[3],
|
|
||||||
.IBMExtendedDouble => values[4],
|
|
||||||
.IEEEQuad => values[5],
|
|
||||||
else => unreachable,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
pub fn isLP64(target: std.Target) bool {
|
|
||||||
return target.cTypeBitSize(.int) == 32 and target.ptrBitWidth() == 64;
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn isKnownWindowsMSVCEnvironment(target: std.Target) bool {
|
|
||||||
return target.os.tag == .windows and target.abi == .msvc;
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn isWindowsMSVCEnvironment(target: std.Target) bool {
|
|
||||||
return target.os.tag == .windows and (target.abi == .msvc or target.abi == .none);
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn isCygwinMinGW(target: std.Target) bool {
|
|
||||||
return target.os.tag == .windows and (target.abi == .gnu);
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn isPS(target: std.Target) bool {
|
|
||||||
return (target.os.tag == .ps4 or target.os.tag == .ps5) and target.cpu.arch == .x86_64;
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn builtinEnabled(target: std.Target, enabled_for: TargetSet) bool {
|
|
||||||
var it = enabled_for.iterator();
|
|
||||||
while (it.next()) |val| {
|
|
||||||
switch (val) {
|
|
||||||
.basic => return true,
|
|
||||||
.x86_64 => if (target.cpu.arch == .x86_64) return true,
|
|
||||||
.aarch64 => if (target.cpu.arch == .aarch64) return true,
|
|
||||||
.arm => if (target.cpu.arch == .arm) return true,
|
|
||||||
.ppc => switch (target.cpu.arch) {
|
|
||||||
.powerpc, .powerpc64, .powerpc64le => return true,
|
|
||||||
else => {},
|
|
||||||
},
|
|
||||||
else => {
|
|
||||||
// Todo: handle other target predicates
|
|
||||||
},
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn defaultFpEvalMethod(target: std.Target) LangOpts.FPEvalMethod {
|
|
||||||
switch (target.cpu.arch) {
|
|
||||||
.x86, .x86_64 => {
|
|
||||||
if (target.ptrBitWidth() == 32 and target.os.tag == .netbsd) {
|
|
||||||
if (target.os.version_range.semver.min.order(.{ .major = 6, .minor = 99, .patch = 26 }) != .gt) {
|
|
||||||
// NETBSD <= 6.99.26 on 32-bit x86 defaults to double
|
|
||||||
return .double;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (std.Target.x86.featureSetHas(target.cpu.features, .sse)) {
|
|
||||||
return .source;
|
|
||||||
}
|
|
||||||
return .extended;
|
|
||||||
},
|
|
||||||
else => {},
|
|
||||||
}
|
|
||||||
return .source;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Value of the `-m` flag for `ld` for this target
|
|
||||||
pub fn ldEmulationOption(target: std.Target, arm_endianness: ?std.builtin.Endian) ?[]const u8 {
|
|
||||||
return switch (target.cpu.arch) {
|
|
||||||
.x86 => "elf_i386",
|
|
||||||
.arm,
|
|
||||||
.armeb,
|
|
||||||
.thumb,
|
|
||||||
.thumbeb,
|
|
||||||
=> switch (arm_endianness orelse target.cpu.arch.endian()) {
|
|
||||||
.little => "armelf_linux_eabi",
|
|
||||||
.big => "armelfb_linux_eabi",
|
|
||||||
},
|
|
||||||
.aarch64 => "aarch64linux",
|
|
||||||
.aarch64_be => "aarch64linuxb",
|
|
||||||
.m68k => "m68kelf",
|
|
||||||
.powerpc => if (target.os.tag == .linux) "elf32ppclinux" else "elf32ppc",
|
|
||||||
.powerpcle => if (target.os.tag == .linux) "elf32lppclinux" else "elf32lppc",
|
|
||||||
.powerpc64 => "elf64ppc",
|
|
||||||
.powerpc64le => "elf64lppc",
|
|
||||||
.riscv32 => "elf32lriscv",
|
|
||||||
.riscv32be => "elf32briscv",
|
|
||||||
.riscv64 => "elf64lriscv",
|
|
||||||
.riscv64be => "elf64briscv",
|
|
||||||
.sparc => "elf32_sparc",
|
|
||||||
.sparc64 => "elf64_sparc",
|
|
||||||
.loongarch32 => "elf32loongarch",
|
|
||||||
.loongarch64 => "elf64loongarch",
|
|
||||||
.mips => "elf32btsmip",
|
|
||||||
.mipsel => "elf32ltsmip",
|
|
||||||
.mips64 => switch (target.abi) {
|
|
||||||
.gnuabin32, .muslabin32 => "elf32btsmipn32",
|
|
||||||
else => "elf64btsmip",
|
|
||||||
},
|
|
||||||
.mips64el => switch (target.abi) {
|
|
||||||
.gnuabin32, .muslabin32 => "elf32ltsmipn32",
|
|
||||||
else => "elf64ltsmip",
|
|
||||||
},
|
|
||||||
.x86_64 => switch (target.abi) {
|
|
||||||
.gnux32, .muslx32 => "elf32_x86_64",
|
|
||||||
else => "elf_x86_64",
|
|
||||||
},
|
|
||||||
.ve => "elf64ve",
|
|
||||||
.csky => "cskyelf_linux",
|
|
||||||
else => null,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn get32BitArchVariant(target: std.Target) ?std.Target {
|
|
||||||
var copy = target;
|
|
||||||
switch (target.cpu.arch) {
|
|
||||||
.amdgcn,
|
|
||||||
.avr,
|
|
||||||
.msp430,
|
|
||||||
.ve,
|
|
||||||
.bpfel,
|
|
||||||
.bpfeb,
|
|
||||||
.kvx,
|
|
||||||
.s390x,
|
|
||||||
=> return null,
|
|
||||||
|
|
||||||
.arc,
|
|
||||||
.arm,
|
|
||||||
.armeb,
|
|
||||||
.csky,
|
|
||||||
.hexagon,
|
|
||||||
.m68k,
|
|
||||||
.mips,
|
|
||||||
.mipsel,
|
|
||||||
.powerpc,
|
|
||||||
.powerpcle,
|
|
||||||
.riscv32,
|
|
||||||
.riscv32be,
|
|
||||||
.sparc,
|
|
||||||
.thumb,
|
|
||||||
.thumbeb,
|
|
||||||
.x86,
|
|
||||||
.xcore,
|
|
||||||
.nvptx,
|
|
||||||
.kalimba,
|
|
||||||
.lanai,
|
|
||||||
.wasm32,
|
|
||||||
.spirv32,
|
|
||||||
.loongarch32,
|
|
||||||
.xtensa,
|
|
||||||
.propeller,
|
|
||||||
.or1k,
|
|
||||||
=> {}, // Already 32 bit
|
|
||||||
|
|
||||||
.aarch64 => copy.cpu.arch = .arm,
|
|
||||||
.aarch64_be => copy.cpu.arch = .armeb,
|
|
||||||
.nvptx64 => copy.cpu.arch = .nvptx,
|
|
||||||
.wasm64 => copy.cpu.arch = .wasm32,
|
|
||||||
.spirv64 => copy.cpu.arch = .spirv32,
|
|
||||||
.loongarch64 => copy.cpu.arch = .loongarch32,
|
|
||||||
.mips64 => copy.cpu.arch = .mips,
|
|
||||||
.mips64el => copy.cpu.arch = .mipsel,
|
|
||||||
.powerpc64 => copy.cpu.arch = .powerpc,
|
|
||||||
.powerpc64le => copy.cpu.arch = .powerpcle,
|
|
||||||
.riscv64 => copy.cpu.arch = .riscv32,
|
|
||||||
.riscv64be => copy.cpu.arch = .riscv32be,
|
|
||||||
.sparc64 => copy.cpu.arch = .sparc,
|
|
||||||
.x86_64 => copy.cpu.arch = .x86,
|
|
||||||
}
|
|
||||||
return copy;
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn get64BitArchVariant(target: std.Target) ?std.Target {
|
|
||||||
var copy = target;
|
|
||||||
switch (target.cpu.arch) {
|
|
||||||
.arc,
|
|
||||||
.avr,
|
|
||||||
.csky,
|
|
||||||
.hexagon,
|
|
||||||
.kalimba,
|
|
||||||
.lanai,
|
|
||||||
.m68k,
|
|
||||||
.msp430,
|
|
||||||
.xcore,
|
|
||||||
.xtensa,
|
|
||||||
.propeller,
|
|
||||||
.or1k,
|
|
||||||
=> return null,
|
|
||||||
|
|
||||||
.aarch64,
|
|
||||||
.aarch64_be,
|
|
||||||
.amdgcn,
|
|
||||||
.bpfeb,
|
|
||||||
.bpfel,
|
|
||||||
.nvptx64,
|
|
||||||
.wasm64,
|
|
||||||
.spirv64,
|
|
||||||
.kvx,
|
|
||||||
.loongarch64,
|
|
||||||
.mips64,
|
|
||||||
.mips64el,
|
|
||||||
.powerpc64,
|
|
||||||
.powerpc64le,
|
|
||||||
.riscv64,
|
|
||||||
.riscv64be,
|
|
||||||
.s390x,
|
|
||||||
.sparc64,
|
|
||||||
.ve,
|
|
||||||
.x86_64,
|
|
||||||
=> {}, // Already 64 bit
|
|
||||||
|
|
||||||
.arm => copy.cpu.arch = .aarch64,
|
|
||||||
.armeb => copy.cpu.arch = .aarch64_be,
|
|
||||||
.loongarch32 => copy.cpu.arch = .loongarch64,
|
|
||||||
.mips => copy.cpu.arch = .mips64,
|
|
||||||
.mipsel => copy.cpu.arch = .mips64el,
|
|
||||||
.nvptx => copy.cpu.arch = .nvptx64,
|
|
||||||
.powerpc => copy.cpu.arch = .powerpc64,
|
|
||||||
.powerpcle => copy.cpu.arch = .powerpc64le,
|
|
||||||
.riscv32 => copy.cpu.arch = .riscv64,
|
|
||||||
.riscv32be => copy.cpu.arch = .riscv64be,
|
|
||||||
.sparc => copy.cpu.arch = .sparc64,
|
|
||||||
.spirv32 => copy.cpu.arch = .spirv64,
|
|
||||||
.thumb => copy.cpu.arch = .aarch64,
|
|
||||||
.thumbeb => copy.cpu.arch = .aarch64_be,
|
|
||||||
.wasm32 => copy.cpu.arch = .wasm64,
|
|
||||||
.x86 => copy.cpu.arch = .x86_64,
|
|
||||||
}
|
|
||||||
return copy;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Adapted from Zig's src/codegen/llvm.zig
|
|
||||||
pub fn toLLVMTriple(target: std.Target, buf: []u8) []const u8 {
|
|
||||||
// 64 bytes is assumed to be large enough to hold any target triple; increase if necessary
|
|
||||||
std.debug.assert(buf.len >= 64);
|
|
||||||
|
|
||||||
var writer: std.Io.Writer = .fixed(buf);
|
|
||||||
|
|
||||||
const llvm_arch = switch (target.cpu.arch) {
|
|
||||||
.arm => "arm",
|
|
||||||
.armeb => "armeb",
|
|
||||||
.aarch64 => if (target.abi == .ilp32) "aarch64_32" else "aarch64",
|
|
||||||
.aarch64_be => "aarch64_be",
|
|
||||||
.arc => "arc",
|
|
||||||
.avr => "avr",
|
|
||||||
.bpfel => "bpfel",
|
|
||||||
.bpfeb => "bpfeb",
|
|
||||||
.csky => "csky",
|
|
||||||
.hexagon => "hexagon",
|
|
||||||
.loongarch32 => "loongarch32",
|
|
||||||
.loongarch64 => "loongarch64",
|
|
||||||
.m68k => "m68k",
|
|
||||||
.mips => "mips",
|
|
||||||
.mipsel => "mipsel",
|
|
||||||
.mips64 => "mips64",
|
|
||||||
.mips64el => "mips64el",
|
|
||||||
.msp430 => "msp430",
|
|
||||||
.powerpc => "powerpc",
|
|
||||||
.powerpcle => "powerpcle",
|
|
||||||
.powerpc64 => "powerpc64",
|
|
||||||
.powerpc64le => "powerpc64le",
|
|
||||||
.amdgcn => "amdgcn",
|
|
||||||
.riscv32 => "riscv32",
|
|
||||||
.riscv32be => "riscv32be",
|
|
||||||
.riscv64 => "riscv64",
|
|
||||||
.riscv64be => "riscv64be",
|
|
||||||
.sparc => "sparc",
|
|
||||||
.sparc64 => "sparc64",
|
|
||||||
.s390x => "s390x",
|
|
||||||
.thumb => "thumb",
|
|
||||||
.thumbeb => "thumbeb",
|
|
||||||
.x86 => "i386",
|
|
||||||
.x86_64 => "x86_64",
|
|
||||||
.xcore => "xcore",
|
|
||||||
.xtensa => "xtensa",
|
|
||||||
.nvptx => "nvptx",
|
|
||||||
.nvptx64 => "nvptx64",
|
|
||||||
.spirv32 => "spirv32",
|
|
||||||
.spirv64 => "spirv64",
|
|
||||||
.lanai => "lanai",
|
|
||||||
.wasm32 => "wasm32",
|
|
||||||
.wasm64 => "wasm64",
|
|
||||||
.ve => "ve",
|
|
||||||
// Note: propeller1, kalimba, kvx, and or1k are not supported in LLVM; this is the Zig arch name
|
|
||||||
.kalimba => "kalimba",
|
|
||||||
.kvx => "kvx",
|
|
||||||
.propeller => "propeller",
|
|
||||||
.or1k => "or1k",
|
|
||||||
};
|
|
||||||
writer.writeAll(llvm_arch) catch unreachable;
|
|
||||||
writer.writeByte('-') catch unreachable;
|
|
||||||
|
|
||||||
const llvm_os = switch (target.os.tag) {
|
|
||||||
.freestanding => "unknown",
|
|
||||||
.dragonfly => "dragonfly",
|
|
||||||
.freebsd => "freebsd",
|
|
||||||
.fuchsia => "fuchsia",
|
|
||||||
.linux => "linux",
|
|
||||||
.ps3 => "lv2",
|
|
||||||
.netbsd => "netbsd",
|
|
||||||
.openbsd => "openbsd",
|
|
||||||
.illumos => "solaris",
|
|
||||||
.windows => "windows",
|
|
||||||
.haiku => "haiku",
|
|
||||||
.rtems => "rtems",
|
|
||||||
.cuda => "cuda",
|
|
||||||
.nvcl => "nvcl",
|
|
||||||
.amdhsa => "amdhsa",
|
|
||||||
.ps4 => "ps4",
|
|
||||||
.ps5 => "ps5",
|
|
||||||
.mesa3d => "mesa3d",
|
|
||||||
.contiki => "contiki",
|
|
||||||
.amdpal => "amdpal",
|
|
||||||
.hermit => "hermit",
|
|
||||||
.hurd => "hurd",
|
|
||||||
.wasi => "wasi",
|
|
||||||
.emscripten => "emscripten",
|
|
||||||
.uefi => "windows",
|
|
||||||
.macos => "macosx",
|
|
||||||
.ios, .maccatalyst => "ios",
|
|
||||||
.tvos => "tvos",
|
|
||||||
.watchos => "watchos",
|
|
||||||
.driverkit => "driverkit",
|
|
||||||
.visionos => "xros",
|
|
||||||
.serenity => "serenity",
|
|
||||||
.vulkan => "vulkan",
|
|
||||||
.managarm => "managarm",
|
|
||||||
.@"3ds",
|
|
||||||
.vita,
|
|
||||||
.opencl,
|
|
||||||
.opengl,
|
|
||||||
.plan9,
|
|
||||||
.other,
|
|
||||||
=> "unknown",
|
|
||||||
};
|
|
||||||
writer.writeAll(llvm_os) catch unreachable;
|
|
||||||
|
|
||||||
if (target.os.tag.isDarwin()) {
|
|
||||||
const min_version = target.os.version_range.semver.min;
|
|
||||||
writer.print("{d}.{d}.{d}", .{
|
|
||||||
min_version.major,
|
|
||||||
min_version.minor,
|
|
||||||
min_version.patch,
|
|
||||||
}) catch unreachable;
|
|
||||||
}
|
|
||||||
writer.writeByte('-') catch unreachable;
|
|
||||||
|
|
||||||
const llvm_abi = switch (target.abi) {
|
|
||||||
.none => if (target.os.tag == .maccatalyst) "macabi" else "unknown",
|
|
||||||
.ilp32 => "unknown",
|
|
||||||
.gnu => "gnu",
|
|
||||||
.gnuabin32 => "gnuabin32",
|
|
||||||
.gnuabi64 => "gnuabi64",
|
|
||||||
.gnueabi => "gnueabi",
|
|
||||||
.gnueabihf => "gnueabihf",
|
|
||||||
.gnuf32 => "gnuf32",
|
|
||||||
.gnusf => "gnusf",
|
|
||||||
.gnux32 => "gnux32",
|
|
||||||
.code16 => "code16",
|
|
||||||
.eabi => "eabi",
|
|
||||||
.eabihf => "eabihf",
|
|
||||||
.android => "android",
|
|
||||||
.androideabi => "androideabi",
|
|
||||||
.musl => "musl",
|
|
||||||
.muslabin32 => "muslabin32",
|
|
||||||
.muslabi64 => "muslabi64",
|
|
||||||
.musleabi => "musleabi",
|
|
||||||
.musleabihf => "musleabihf",
|
|
||||||
.muslf32 => "muslf32",
|
|
||||||
.muslsf => "muslsf",
|
|
||||||
.muslx32 => "muslx32",
|
|
||||||
.msvc => "msvc",
|
|
||||||
.itanium => "itanium",
|
|
||||||
.simulator => "simulator",
|
|
||||||
.ohos => "ohos",
|
|
||||||
.ohoseabi => "ohoseabi",
|
|
||||||
};
|
|
||||||
writer.writeAll(llvm_abi) catch unreachable;
|
|
||||||
return writer.buffered();
|
|
||||||
}
|
|
||||||
|
|
||||||
pub const DefaultPIStatus = enum { yes, no, depends_on_linker };
|
|
||||||
|
|
||||||
pub fn isPIEDefault(target: std.Target) DefaultPIStatus {
|
|
||||||
return switch (target.os.tag) {
|
|
||||||
.haiku,
|
|
||||||
|
|
||||||
.maccatalyst,
|
|
||||||
.macos,
|
|
||||||
.ios,
|
|
||||||
.tvos,
|
|
||||||
.watchos,
|
|
||||||
.visionos,
|
|
||||||
.driverkit,
|
|
||||||
|
|
||||||
.dragonfly,
|
|
||||||
.netbsd,
|
|
||||||
.freebsd,
|
|
||||||
.illumos,
|
|
||||||
|
|
||||||
.cuda,
|
|
||||||
.amdhsa,
|
|
||||||
.amdpal,
|
|
||||||
.mesa3d,
|
|
||||||
|
|
||||||
.ps4,
|
|
||||||
.ps5,
|
|
||||||
|
|
||||||
.hurd,
|
|
||||||
=> .no,
|
|
||||||
|
|
||||||
.openbsd,
|
|
||||||
.fuchsia,
|
|
||||||
=> .yes,
|
|
||||||
|
|
||||||
.linux => {
|
|
||||||
if (target.abi == .ohos)
|
|
||||||
return .yes;
|
|
||||||
|
|
||||||
switch (target.cpu.arch) {
|
|
||||||
.ve => return .no,
|
|
||||||
else => return if (target.os.tag == .linux or target.abi.isAndroid() or target.abi.isMusl()) .yes else .no,
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
.windows => {
|
|
||||||
if (target.isMinGW())
|
|
||||||
return .no;
|
|
||||||
|
|
||||||
if (target.abi == .itanium)
|
|
||||||
return if (target.cpu.arch == .x86_64) .yes else .no;
|
|
||||||
|
|
||||||
if (target.abi == .msvc or target.abi == .none)
|
|
||||||
return .depends_on_linker;
|
|
||||||
|
|
||||||
return .no;
|
|
||||||
},
|
|
||||||
|
|
||||||
else => {
|
|
||||||
switch (target.cpu.arch) {
|
|
||||||
.hexagon => {
|
|
||||||
// CLANG_DEFAULT_PIE_ON_LINUX
|
|
||||||
return if (target.os.tag == .linux or target.abi.isAndroid() or target.abi.isMusl()) .yes else .no;
|
|
||||||
},
|
|
||||||
|
|
||||||
else => return .no,
|
|
||||||
}
|
|
||||||
},
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn isPICdefault(target: std.Target) DefaultPIStatus {
|
|
||||||
return switch (target.os.tag) {
|
|
||||||
.haiku,
|
|
||||||
|
|
||||||
.maccatalyst,
|
|
||||||
.macos,
|
|
||||||
.ios,
|
|
||||||
.tvos,
|
|
||||||
.watchos,
|
|
||||||
.visionos,
|
|
||||||
.driverkit,
|
|
||||||
|
|
||||||
.amdhsa,
|
|
||||||
.amdpal,
|
|
||||||
.mesa3d,
|
|
||||||
|
|
||||||
.ps4,
|
|
||||||
.ps5,
|
|
||||||
=> .yes,
|
|
||||||
|
|
||||||
.fuchsia,
|
|
||||||
.cuda,
|
|
||||||
=> .no,
|
|
||||||
|
|
||||||
.dragonfly,
|
|
||||||
.openbsd,
|
|
||||||
.netbsd,
|
|
||||||
.freebsd,
|
|
||||||
.illumos,
|
|
||||||
.hurd,
|
|
||||||
=> {
|
|
||||||
return switch (target.cpu.arch) {
|
|
||||||
.mips64, .mips64el => .yes,
|
|
||||||
else => .no,
|
|
||||||
};
|
|
||||||
},
|
|
||||||
|
|
||||||
.linux => {
|
|
||||||
if (target.abi == .ohos)
|
|
||||||
return .no;
|
|
||||||
|
|
||||||
return switch (target.cpu.arch) {
|
|
||||||
.mips64, .mips64el => .yes,
|
|
||||||
else => .no,
|
|
||||||
};
|
|
||||||
},
|
|
||||||
|
|
||||||
.windows => {
|
|
||||||
if (target.isMinGW())
|
|
||||||
return if (target.cpu.arch == .x86_64 or target.cpu.arch == .aarch64) .yes else .no;
|
|
||||||
|
|
||||||
if (target.abi == .itanium)
|
|
||||||
return if (target.cpu.arch == .x86_64) .yes else .no;
|
|
||||||
|
|
||||||
if (target.abi == .msvc or target.abi == .none)
|
|
||||||
return .depends_on_linker;
|
|
||||||
|
|
||||||
if (target.ofmt == .macho)
|
|
||||||
return .yes;
|
|
||||||
|
|
||||||
return switch (target.cpu.arch) {
|
|
||||||
.x86_64, .mips64, .mips64el => .yes,
|
|
||||||
else => .no,
|
|
||||||
};
|
|
||||||
},
|
|
||||||
|
|
||||||
else => {
|
|
||||||
if (target.ofmt == .macho)
|
|
||||||
return .yes;
|
|
||||||
|
|
||||||
return switch (target.cpu.arch) {
|
|
||||||
.mips64, .mips64el => .yes,
|
|
||||||
else => .no,
|
|
||||||
};
|
|
||||||
},
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn isPICDefaultForced(target: std.Target) DefaultPIStatus {
|
|
||||||
return switch (target.os.tag) {
|
|
||||||
.amdhsa, .amdpal, .mesa3d => .yes,
|
|
||||||
|
|
||||||
.haiku,
|
|
||||||
.dragonfly,
|
|
||||||
.openbsd,
|
|
||||||
.netbsd,
|
|
||||||
.freebsd,
|
|
||||||
.illumos,
|
|
||||||
.cuda,
|
|
||||||
.ps4,
|
|
||||||
.ps5,
|
|
||||||
.hurd,
|
|
||||||
.linux,
|
|
||||||
.fuchsia,
|
|
||||||
=> .no,
|
|
||||||
|
|
||||||
.windows => {
|
|
||||||
if (target.isMinGW())
|
|
||||||
return .yes;
|
|
||||||
|
|
||||||
if (target.abi == .itanium)
|
|
||||||
return if (target.cpu.arch == .x86_64) .yes else .no;
|
|
||||||
|
|
||||||
// if (bfd) return target.cpu.arch == .x86_64 else target.cpu.arch == .x86_64 or target.cpu.arch == .aarch64;
|
|
||||||
if (target.abi == .msvc or target.abi == .none)
|
|
||||||
return .depends_on_linker;
|
|
||||||
|
|
||||||
if (target.ofmt == .macho)
|
|
||||||
return if (target.cpu.arch == .aarch64 or target.cpu.arch == .x86_64) .yes else .no;
|
|
||||||
|
|
||||||
return if (target.cpu.arch == .x86_64) .yes else .no;
|
|
||||||
},
|
|
||||||
|
|
||||||
.maccatalyst,
|
|
||||||
.macos,
|
|
||||||
.ios,
|
|
||||||
.tvos,
|
|
||||||
.watchos,
|
|
||||||
.visionos,
|
|
||||||
.driverkit,
|
|
||||||
=> if (target.cpu.arch == .x86_64 or target.cpu.arch == .aarch64) .yes else .no,
|
|
||||||
|
|
||||||
else => {
|
|
||||||
return switch (target.cpu.arch) {
|
|
||||||
.hexagon,
|
|
||||||
.lanai,
|
|
||||||
.avr,
|
|
||||||
.riscv32,
|
|
||||||
.riscv64,
|
|
||||||
.csky,
|
|
||||||
.xcore,
|
|
||||||
.wasm32,
|
|
||||||
.wasm64,
|
|
||||||
.ve,
|
|
||||||
.spirv32,
|
|
||||||
.spirv64,
|
|
||||||
=> .no,
|
|
||||||
|
|
||||||
.msp430 => .yes,
|
|
||||||
|
|
||||||
else => {
|
|
||||||
if (target.ofmt == .macho)
|
|
||||||
return if (target.cpu.arch == .aarch64 or target.cpu.arch == .x86_64) .yes else .no;
|
|
||||||
return .no;
|
|
||||||
},
|
|
||||||
};
|
|
||||||
},
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
test "alignment functions - smoke test" {
|
|
||||||
const linux: std.Target.Os = .{ .tag = .linux, .version_range = .{ .none = {} } };
|
|
||||||
const x86_64_target: std.Target = .{
|
|
||||||
.abi = std.Target.Abi.default(.x86_64, linux.tag),
|
|
||||||
.cpu = std.Target.Cpu.Model.generic(.x86_64).toCpu(.x86_64),
|
|
||||||
.os = linux,
|
|
||||||
.ofmt = .elf,
|
|
||||||
};
|
|
||||||
|
|
||||||
try std.testing.expect(isTlsSupported(x86_64_target));
|
|
||||||
try std.testing.expect(!ignoreNonZeroSizedBitfieldTypeAlignment(x86_64_target));
|
|
||||||
try std.testing.expect(minZeroWidthBitfieldAlignment(x86_64_target) == null);
|
|
||||||
try std.testing.expect(!unnamedFieldAffectsAlignment(x86_64_target));
|
|
||||||
try std.testing.expect(defaultAlignment(x86_64_target) == 16);
|
|
||||||
try std.testing.expect(!packAllEnums(x86_64_target));
|
|
||||||
try std.testing.expect(systemCompiler(x86_64_target) == .gcc);
|
|
||||||
}
|
|
||||||
|
|
||||||
test "target size/align tests" {
|
|
||||||
var comp: @import("Compilation.zig") = undefined;
|
|
||||||
|
|
||||||
const linux: std.Target.Os = .{ .tag = .linux, .version_range = .{ .none = {} } };
|
|
||||||
const x86_target: std.Target = .{
|
|
||||||
.abi = std.Target.Abi.default(.x86, linux.tag),
|
|
||||||
.cpu = std.Target.Cpu.Model.generic(.x86).toCpu(.x86),
|
|
||||||
.os = linux,
|
|
||||||
.ofmt = .elf,
|
|
||||||
};
|
|
||||||
comp.target = x86_target;
|
|
||||||
|
|
||||||
const tt: QualType = .long_long;
|
|
||||||
|
|
||||||
try std.testing.expectEqual(@as(u64, 8), tt.sizeof(&comp));
|
|
||||||
try std.testing.expectEqual(@as(u64, 4), tt.alignof(&comp));
|
|
||||||
}
|
|
||||||
|
|
||||||
/// The canonical integer representation of nullptr_t.
|
|
||||||
pub fn nullRepr(_: std.Target) u64 {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
2
lib/compiler/aro/assembly_backend/x86_64.zig
vendored
2
lib/compiler/aro/assembly_backend/x86_64.zig
vendored
@ -167,7 +167,7 @@ fn genDecls(c: *AsmCodeGen) !void {
|
|||||||
if (c.tree.comp.code_gen_options.debug != .strip) {
|
if (c.tree.comp.code_gen_options.debug != .strip) {
|
||||||
const sources = c.tree.comp.sources.values();
|
const sources = c.tree.comp.sources.values();
|
||||||
for (sources) |source| {
|
for (sources) |source| {
|
||||||
try c.data.print(" .file {d} \"{s}\"\n", .{ @intFromEnum(source.id) - 1, source.path });
|
try c.data.print(" .file {d} \"{s}\"\n", .{ @intFromEnum(source.id.index) + 1, source.path });
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
9
lib/compiler/aro/backend/Assembly.zig
vendored
9
lib/compiler/aro/backend/Assembly.zig
vendored
@ -12,9 +12,8 @@ pub fn deinit(self: *const Assembly, gpa: Allocator) void {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn writeToFile(self: Assembly, file: std.fs.File) !void {
|
pub fn writeToFile(self: Assembly, file: std.fs.File) !void {
|
||||||
var vec: [2]std.posix.iovec_const = .{
|
var file_writer = file.writer(&.{});
|
||||||
.{ .base = self.data.ptr, .len = self.data.len },
|
|
||||||
.{ .base = self.text.ptr, .len = self.text.len },
|
var buffers = [_][]const u8{ self.data, self.text };
|
||||||
};
|
try file_writer.interface.writeSplatAll(&buffers, 1);
|
||||||
return file.writevAll(&vec);
|
|
||||||
}
|
}
|
||||||
|
|||||||
20
lib/compiler/aro/main.zig
vendored
20
lib/compiler/aro/main.zig
vendored
@ -9,21 +9,31 @@ const Driver = aro.Driver;
|
|||||||
const Toolchain = aro.Toolchain;
|
const Toolchain = aro.Toolchain;
|
||||||
const assembly_backend = @import("assembly_backend");
|
const assembly_backend = @import("assembly_backend");
|
||||||
|
|
||||||
var general_purpose_allocator = std.heap.GeneralPurposeAllocator(.{}){};
|
var debug_allocator: std.heap.DebugAllocator(.{
|
||||||
|
.stack_trace_frames = 0,
|
||||||
|
// A unique value so that when a default-constructed
|
||||||
|
// GeneralPurposeAllocator is incorrectly passed to testing allocator, or
|
||||||
|
// vice versa, panic occurs.
|
||||||
|
.canary = @truncate(0xc647026dc6875134),
|
||||||
|
}) = .{};
|
||||||
|
|
||||||
pub fn main() u8 {
|
pub fn main() u8 {
|
||||||
const gpa = if (@import("builtin").link_libc)
|
const gpa = if (@import("builtin").link_libc)
|
||||||
std.heap.raw_c_allocator
|
std.heap.raw_c_allocator
|
||||||
else
|
else
|
||||||
general_purpose_allocator.allocator();
|
debug_allocator.allocator();
|
||||||
defer if (!@import("builtin").link_libc) {
|
defer if (!@import("builtin").link_libc) {
|
||||||
_ = general_purpose_allocator.deinit();
|
_ = debug_allocator.deinit();
|
||||||
};
|
};
|
||||||
|
|
||||||
var arena_instance = std.heap.ArenaAllocator.init(gpa);
|
var arena_instance = std.heap.ArenaAllocator.init(gpa);
|
||||||
defer arena_instance.deinit();
|
defer arena_instance.deinit();
|
||||||
const arena = arena_instance.allocator();
|
const arena = arena_instance.allocator();
|
||||||
|
|
||||||
|
var threaded: std.Io.Threaded = .init(gpa);
|
||||||
|
defer threaded.deinit();
|
||||||
|
const io = threaded.io();
|
||||||
|
|
||||||
const fast_exit = @import("builtin").mode != .Debug;
|
const fast_exit = @import("builtin").mode != .Debug;
|
||||||
|
|
||||||
const args = process.argsAlloc(arena) catch {
|
const args = process.argsAlloc(arena) catch {
|
||||||
@ -48,7 +58,7 @@ pub fn main() u8 {
|
|||||||
} },
|
} },
|
||||||
};
|
};
|
||||||
|
|
||||||
var comp = Compilation.initDefault(gpa, arena, &diagnostics, std.fs.cwd()) catch |er| switch (er) {
|
var comp = Compilation.initDefault(gpa, arena, io, &diagnostics, std.fs.cwd()) catch |er| switch (er) {
|
||||||
error.OutOfMemory => {
|
error.OutOfMemory => {
|
||||||
std.debug.print("out of memory\n", .{});
|
std.debug.print("out of memory\n", .{});
|
||||||
if (fast_exit) process.exit(1);
|
if (fast_exit) process.exit(1);
|
||||||
@ -60,7 +70,7 @@ pub fn main() u8 {
|
|||||||
var driver: Driver = .{ .comp = &comp, .aro_name = aro_name, .diagnostics = &diagnostics };
|
var driver: Driver = .{ .comp = &comp, .aro_name = aro_name, .diagnostics = &diagnostics };
|
||||||
defer driver.deinit();
|
defer driver.deinit();
|
||||||
|
|
||||||
var toolchain: Toolchain = .{ .driver = &driver, .filesystem = .{ .real = comp.cwd } };
|
var toolchain: Toolchain = .{ .driver = &driver };
|
||||||
defer toolchain.deinit();
|
defer toolchain.deinit();
|
||||||
|
|
||||||
driver.main(&toolchain, args, fast_exit, assembly_backend.genAsm) catch |er| switch (er) {
|
driver.main(&toolchain, args, fast_exit, assembly_backend.genAsm) catch |er| switch (er) {
|
||||||
|
|||||||
@ -29,6 +29,7 @@ pub fn preprocess(
|
|||||||
error.OutOfMemory => |e| return e,
|
error.OutOfMemory => |e| return e,
|
||||||
error.WriteFailed => unreachable,
|
error.WriteFailed => unreachable,
|
||||||
};
|
};
|
||||||
|
try comp.initSearchPath(driver.includes.items, false);
|
||||||
|
|
||||||
if (hasAnyErrors(comp)) return error.ArgError;
|
if (hasAnyErrors(comp)) return error.ArgError;
|
||||||
|
|
||||||
@ -59,7 +60,7 @@ pub fn preprocess(
|
|||||||
pp.preserve_whitespace = true;
|
pp.preserve_whitespace = true;
|
||||||
pp.linemarkers = .line_directives;
|
pp.linemarkers = .line_directives;
|
||||||
|
|
||||||
pp.preprocessSources(&.{ source, builtin_macros, user_macros }) catch |err| switch (err) {
|
pp.preprocessSources(.{ .main = source, .builtin = builtin_macros, .command_line = user_macros }) catch |err| switch (err) {
|
||||||
error.FatalError => return error.PreprocessError,
|
error.FatalError => return error.PreprocessError,
|
||||||
else => |e| return e,
|
else => |e| return e,
|
||||||
};
|
};
|
||||||
@ -71,7 +72,7 @@ pub fn preprocess(
|
|||||||
if (maybe_dependencies) |dependencies| {
|
if (maybe_dependencies) |dependencies| {
|
||||||
for (comp.sources.values()) |comp_source| {
|
for (comp.sources.values()) |comp_source| {
|
||||||
if (comp_source.id == builtin_macros.id or comp_source.id == user_macros.id) continue;
|
if (comp_source.id == builtin_macros.id or comp_source.id == user_macros.id) continue;
|
||||||
if (comp_source.id == .unused or comp_source.id == .generated) continue;
|
if (comp_source.id.index == .unused or comp_source.id.index == .generated) continue;
|
||||||
const duped_path = try dependencies.allocator.dupe(u8, comp_source.path);
|
const duped_path = try dependencies.allocator.dupe(u8, comp_source.path);
|
||||||
errdefer dependencies.allocator.free(duped_path);
|
errdefer dependencies.allocator.free(duped_path);
|
||||||
try dependencies.list.append(dependencies.allocator, duped_path);
|
try dependencies.list.append(dependencies.allocator, duped_path);
|
||||||
|
|||||||
@ -79,6 +79,20 @@ pub fn transFnMacro(mt: *MacroTranslator) ParseError!void {
|
|||||||
try block_scope.discardVariable(mangled_name);
|
try block_scope.discardVariable(mangled_name);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// #define FOO(x)
|
||||||
|
if (mt.peek() == .eof) {
|
||||||
|
try block_scope.statements.append(mt.t.gpa, ZigTag.return_void.init());
|
||||||
|
|
||||||
|
const fn_decl = try ZigTag.pub_inline_fn.create(mt.t.arena, .{
|
||||||
|
.name = mt.name,
|
||||||
|
.params = fn_params,
|
||||||
|
.return_type = ZigTag.void_type.init(),
|
||||||
|
.body = try block_scope.complete(),
|
||||||
|
});
|
||||||
|
try mt.t.addTopLevelDecl(mt.name, fn_decl);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
const expr = try mt.parseCExpr(scope);
|
const expr = try mt.parseCExpr(scope);
|
||||||
const last = mt.peek();
|
const last = mt.peek();
|
||||||
if (last != .eof)
|
if (last != .eof)
|
||||||
@ -252,7 +266,7 @@ fn parseCNumLit(mt: *MacroTranslator) ParseError!ZigNode {
|
|||||||
const lit_bytes = mt.tokSlice();
|
const lit_bytes = mt.tokSlice();
|
||||||
mt.i += 1;
|
mt.i += 1;
|
||||||
|
|
||||||
var bytes = try std.ArrayListUnmanaged(u8).initCapacity(arena, lit_bytes.len + 3);
|
var bytes = try std.ArrayList(u8).initCapacity(arena, lit_bytes.len + 3);
|
||||||
|
|
||||||
const prefix = aro.Tree.Token.NumberPrefix.fromString(lit_bytes);
|
const prefix = aro.Tree.Token.NumberPrefix.fromString(lit_bytes);
|
||||||
switch (prefix) {
|
switch (prefix) {
|
||||||
@ -637,7 +651,7 @@ fn parseCPrimaryExpr(mt: *MacroTranslator, scope: *Scope) ParseError!ZigNode {
|
|||||||
|
|
||||||
// for handling type macros (EVIL)
|
// for handling type macros (EVIL)
|
||||||
// TODO maybe detect and treat type macros as typedefs in parseCSpecifierQualifierList?
|
// TODO maybe detect and treat type macros as typedefs in parseCSpecifierQualifierList?
|
||||||
if (try mt.parseCTypeName(scope, true)) |type_name| {
|
if (try mt.parseCTypeName(scope)) |type_name| {
|
||||||
return type_name;
|
return type_name;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -825,6 +839,18 @@ fn parseCMulExpr(mt: *MacroTranslator, scope: *Scope) ParseError!ZigNode {
|
|||||||
switch (mt.peek()) {
|
switch (mt.peek()) {
|
||||||
.asterisk => {
|
.asterisk => {
|
||||||
mt.i += 1;
|
mt.i += 1;
|
||||||
|
switch (mt.peek()) {
|
||||||
|
.comma, .r_paren, .eof => {
|
||||||
|
// This is probably a pointer type
|
||||||
|
return ZigTag.c_pointer.create(mt.t.arena, .{
|
||||||
|
.is_const = false,
|
||||||
|
.is_volatile = false,
|
||||||
|
.is_allowzero = false,
|
||||||
|
.elem_type = node,
|
||||||
|
});
|
||||||
|
},
|
||||||
|
else => {},
|
||||||
|
}
|
||||||
const lhs = try mt.macroIntFromBool(node);
|
const lhs = try mt.macroIntFromBool(node);
|
||||||
const rhs = try mt.macroIntFromBool(try mt.parseCCastExpr(scope));
|
const rhs = try mt.macroIntFromBool(try mt.parseCCastExpr(scope));
|
||||||
node = try ZigTag.mul.create(mt.t.arena, .{ .lhs = lhs, .rhs = rhs });
|
node = try ZigTag.mul.create(mt.t.arena, .{ .lhs = lhs, .rhs = rhs });
|
||||||
@ -848,7 +874,7 @@ fn parseCMulExpr(mt: *MacroTranslator, scope: *Scope) ParseError!ZigNode {
|
|||||||
|
|
||||||
fn parseCCastExpr(mt: *MacroTranslator, scope: *Scope) ParseError!ZigNode {
|
fn parseCCastExpr(mt: *MacroTranslator, scope: *Scope) ParseError!ZigNode {
|
||||||
if (mt.eat(.l_paren)) {
|
if (mt.eat(.l_paren)) {
|
||||||
if (try mt.parseCTypeName(scope, true)) |type_name| {
|
if (try mt.parseCTypeName(scope)) |type_name| {
|
||||||
while (true) {
|
while (true) {
|
||||||
const next_tok = mt.peek();
|
const next_tok = mt.peek();
|
||||||
if (next_tok == .r_paren) {
|
if (next_tok == .r_paren) {
|
||||||
@ -882,14 +908,14 @@ fn parseCCastExpr(mt: *MacroTranslator, scope: *Scope) ParseError!ZigNode {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// allow_fail is set when unsure if we are parsing a type-name
|
// allow_fail is set when unsure if we are parsing a type-name
|
||||||
fn parseCTypeName(mt: *MacroTranslator, scope: *Scope, allow_fail: bool) ParseError!?ZigNode {
|
fn parseCTypeName(mt: *MacroTranslator, scope: *Scope) ParseError!?ZigNode {
|
||||||
if (try mt.parseCSpecifierQualifierList(scope, allow_fail)) |node| {
|
if (try mt.parseCSpecifierQualifierList(scope)) |node| {
|
||||||
return try mt.parseCAbstractDeclarator(node);
|
return try mt.parseCAbstractDeclarator(node);
|
||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
fn parseCSpecifierQualifierList(mt: *MacroTranslator, scope: *Scope, allow_fail: bool) ParseError!?ZigNode {
|
fn parseCSpecifierQualifierList(mt: *MacroTranslator, scope: *Scope) ParseError!?ZigNode {
|
||||||
const tok = mt.peek();
|
const tok = mt.peek();
|
||||||
switch (tok) {
|
switch (tok) {
|
||||||
.macro_param, .macro_param_no_expand => {
|
.macro_param, .macro_param_no_expand => {
|
||||||
@ -897,9 +923,9 @@ fn parseCSpecifierQualifierList(mt: *MacroTranslator, scope: *Scope, allow_fail:
|
|||||||
|
|
||||||
// Assume that this is only a cast if the next token is ')'
|
// Assume that this is only a cast if the next token is ')'
|
||||||
// e.g. param)identifier
|
// e.g. param)identifier
|
||||||
if (allow_fail and (mt.macro.tokens.len < mt.i + 3 or
|
if (mt.macro.tokens.len < mt.i + 3 or
|
||||||
mt.macro.tokens[mt.i + 1].id != .r_paren or
|
mt.macro.tokens[mt.i + 1].id != .r_paren or
|
||||||
mt.macro.tokens[mt.i + 2].id != .identifier))
|
mt.macro.tokens[mt.i + 2].id != .identifier)
|
||||||
return null;
|
return null;
|
||||||
|
|
||||||
mt.i += 1;
|
mt.i += 1;
|
||||||
@ -912,10 +938,10 @@ fn parseCSpecifierQualifierList(mt: *MacroTranslator, scope: *Scope, allow_fail:
|
|||||||
|
|
||||||
if (mt.t.global_scope.blank_macros.contains(slice)) {
|
if (mt.t.global_scope.blank_macros.contains(slice)) {
|
||||||
mt.i += 1;
|
mt.i += 1;
|
||||||
return try mt.parseCSpecifierQualifierList(scope, allow_fail);
|
return try mt.parseCSpecifierQualifierList(scope);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!allow_fail or mt.t.typedefs.contains(mangled_name)) {
|
if (mt.t.typedefs.contains(mangled_name)) {
|
||||||
mt.i += 1;
|
mt.i += 1;
|
||||||
if (Translator.builtin_typedef_map.get(mangled_name)) |ty| {
|
if (Translator.builtin_typedef_map.get(mangled_name)) |ty| {
|
||||||
return try ZigTag.type.create(mt.t.arena, ty);
|
return try ZigTag.type.create(mt.t.arena, ty);
|
||||||
@ -952,21 +978,27 @@ fn parseCSpecifierQualifierList(mt: *MacroTranslator, scope: *Scope, allow_fail:
|
|||||||
.keyword_enum, .keyword_struct, .keyword_union => {
|
.keyword_enum, .keyword_struct, .keyword_union => {
|
||||||
const tag_name = mt.tokSlice();
|
const tag_name = mt.tokSlice();
|
||||||
mt.i += 1;
|
mt.i += 1;
|
||||||
|
if (mt.peek() != .identifier) {
|
||||||
|
mt.i -= 1;
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
// struct Foo will be declared as struct_Foo by transRecordDecl
|
// struct Foo will be declared as struct_Foo by transRecordDecl
|
||||||
const identifier = mt.tokSlice();
|
const identifier = mt.tokSlice();
|
||||||
try mt.expect(.identifier);
|
try mt.expect(.identifier);
|
||||||
|
|
||||||
const name = try std.fmt.allocPrint(mt.t.arena, "{s}_{s}", .{ tag_name, identifier });
|
const name = try std.fmt.allocPrint(mt.t.arena, "{s}_{s}", .{ tag_name, identifier });
|
||||||
|
if (!mt.t.global_scope.contains(name)) {
|
||||||
|
try mt.fail("unable to translate C expr: '{s}' not found", .{name});
|
||||||
|
return error.ParseError;
|
||||||
|
}
|
||||||
|
|
||||||
return try ZigTag.identifier.create(mt.t.arena, name);
|
return try ZigTag.identifier.create(mt.t.arena, name);
|
||||||
},
|
},
|
||||||
else => {},
|
else => {},
|
||||||
}
|
}
|
||||||
|
|
||||||
if (allow_fail) return null;
|
return null;
|
||||||
|
|
||||||
try mt.fail("unable to translate C expr: unexpected token '{s}'", .{tok.symbol()});
|
|
||||||
return error.ParseError;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn parseCNumericType(mt: *MacroTranslator) ParseError!ZigNode {
|
fn parseCNumericType(mt: *MacroTranslator) ParseError!ZigNode {
|
||||||
@ -1126,6 +1158,11 @@ fn parseCPostfixExprInner(mt: *MacroTranslator, scope: *Scope, type_name: ?ZigNo
|
|||||||
switch (mt.peek()) {
|
switch (mt.peek()) {
|
||||||
.period => {
|
.period => {
|
||||||
mt.i += 1;
|
mt.i += 1;
|
||||||
|
const tok = mt.tokens[mt.i];
|
||||||
|
if (tok.id == .macro_param or tok.id == .macro_param_no_expand) {
|
||||||
|
try mt.fail("unable to translate C expr: field access using macro parameter", .{});
|
||||||
|
return error.ParseError;
|
||||||
|
}
|
||||||
const field_name = mt.tokSlice();
|
const field_name = mt.tokSlice();
|
||||||
try mt.expect(.identifier);
|
try mt.expect(.identifier);
|
||||||
|
|
||||||
@ -1133,6 +1170,11 @@ fn parseCPostfixExprInner(mt: *MacroTranslator, scope: *Scope, type_name: ?ZigNo
|
|||||||
},
|
},
|
||||||
.arrow => {
|
.arrow => {
|
||||||
mt.i += 1;
|
mt.i += 1;
|
||||||
|
const tok = mt.tokens[mt.i];
|
||||||
|
if (tok.id == .macro_param or tok.id == .macro_param_no_expand) {
|
||||||
|
try mt.fail("unable to translate C expr: field access using macro parameter", .{});
|
||||||
|
return error.ParseError;
|
||||||
|
}
|
||||||
const field_name = mt.tokSlice();
|
const field_name = mt.tokSlice();
|
||||||
try mt.expect(.identifier);
|
try mt.expect(.identifier);
|
||||||
|
|
||||||
@ -1286,7 +1328,7 @@ fn parseCUnaryExpr(mt: *MacroTranslator, scope: *Scope) ParseError!ZigNode {
|
|||||||
.keyword_sizeof => {
|
.keyword_sizeof => {
|
||||||
mt.i += 1;
|
mt.i += 1;
|
||||||
const operand = if (mt.eat(.l_paren)) blk: {
|
const operand = if (mt.eat(.l_paren)) blk: {
|
||||||
const inner = (try mt.parseCTypeName(scope, false)).?;
|
const inner = (try mt.parseCTypeName(scope)) orelse try mt.parseCUnaryExpr(scope);
|
||||||
try mt.expect(.r_paren);
|
try mt.expect(.r_paren);
|
||||||
break :blk inner;
|
break :blk inner;
|
||||||
} else try mt.parseCUnaryExpr(scope);
|
} else try mt.parseCUnaryExpr(scope);
|
||||||
@ -1298,7 +1340,7 @@ fn parseCUnaryExpr(mt: *MacroTranslator, scope: *Scope) ParseError!ZigNode {
|
|||||||
// TODO this won't work if using <stdalign.h>'s
|
// TODO this won't work if using <stdalign.h>'s
|
||||||
// #define alignof _Alignof
|
// #define alignof _Alignof
|
||||||
try mt.expect(.l_paren);
|
try mt.expect(.l_paren);
|
||||||
const operand = (try mt.parseCTypeName(scope, false)).?;
|
const operand = (try mt.parseCTypeName(scope)) orelse try mt.parseCUnaryExpr(scope);
|
||||||
try mt.expect(.r_paren);
|
try mt.expect(.r_paren);
|
||||||
|
|
||||||
return ZigTag.alignof.create(mt.t.arena, operand);
|
return ZigTag.alignof.create(mt.t.arena, operand);
|
||||||
|
|||||||
@ -178,6 +178,7 @@ fn tokenizeMacro(allocator: mem.Allocator, source: []const u8, tok_list: *std.Ar
|
|||||||
.buf = source,
|
.buf = source,
|
||||||
.source = .unused,
|
.source = .unused,
|
||||||
.langopts = .{},
|
.langopts = .{},
|
||||||
|
.splice_locs = &.{},
|
||||||
};
|
};
|
||||||
{
|
{
|
||||||
const name_tok = tokenizer.nextNoWS();
|
const name_tok = tokenizer.nextNoWS();
|
||||||
|
|||||||
@ -8,7 +8,7 @@ const Translator = @import("Translator.zig");
|
|||||||
const Scope = @This();
|
const Scope = @This();
|
||||||
|
|
||||||
pub const SymbolTable = std.StringArrayHashMapUnmanaged(ast.Node);
|
pub const SymbolTable = std.StringArrayHashMapUnmanaged(ast.Node);
|
||||||
pub const AliasList = std.ArrayListUnmanaged(struct {
|
pub const AliasList = std.ArrayList(struct {
|
||||||
alias: []const u8,
|
alias: []const u8,
|
||||||
name: []const u8,
|
name: []const u8,
|
||||||
});
|
});
|
||||||
@ -16,7 +16,7 @@ pub const AliasList = std.ArrayListUnmanaged(struct {
|
|||||||
/// Associates a container (structure or union) with its relevant member functions.
|
/// Associates a container (structure or union) with its relevant member functions.
|
||||||
pub const ContainerMemberFns = struct {
|
pub const ContainerMemberFns = struct {
|
||||||
container_decl_ptr: *ast.Node,
|
container_decl_ptr: *ast.Node,
|
||||||
member_fns: std.ArrayListUnmanaged(*ast.Payload.Func) = .empty,
|
member_fns: std.ArrayList(*ast.Payload.Func) = .empty,
|
||||||
};
|
};
|
||||||
pub const ContainerMemberFnsHashMap = std.AutoArrayHashMapUnmanaged(aro.QualType, ContainerMemberFns);
|
pub const ContainerMemberFnsHashMap = std.AutoArrayHashMapUnmanaged(aro.QualType, ContainerMemberFns);
|
||||||
|
|
||||||
@ -55,7 +55,7 @@ pub const Condition = struct {
|
|||||||
pub const Block = struct {
|
pub const Block = struct {
|
||||||
base: Scope,
|
base: Scope,
|
||||||
translator: *Translator,
|
translator: *Translator,
|
||||||
statements: std.ArrayListUnmanaged(ast.Node),
|
statements: std.ArrayList(ast.Node),
|
||||||
variables: AliasList,
|
variables: AliasList,
|
||||||
mangle_count: u32 = 0,
|
mangle_count: u32 = 0,
|
||||||
label: ?[]const u8 = null,
|
label: ?[]const u8 = null,
|
||||||
@ -195,7 +195,7 @@ pub const Root = struct {
|
|||||||
translator: *Translator,
|
translator: *Translator,
|
||||||
sym_table: SymbolTable,
|
sym_table: SymbolTable,
|
||||||
blank_macros: std.StringArrayHashMapUnmanaged(void),
|
blank_macros: std.StringArrayHashMapUnmanaged(void),
|
||||||
nodes: std.ArrayListUnmanaged(ast.Node),
|
nodes: std.ArrayList(ast.Node),
|
||||||
container_member_fns_map: ContainerMemberFnsHashMap,
|
container_member_fns_map: ContainerMemberFnsHashMap,
|
||||||
|
|
||||||
pub fn init(t: *Translator) Root {
|
pub fn init(t: *Translator) Root {
|
||||||
@ -252,7 +252,7 @@ pub const Root = struct {
|
|||||||
const gpa = root.translator.gpa;
|
const gpa = root.translator.gpa;
|
||||||
const arena = root.translator.arena;
|
const arena = root.translator.arena;
|
||||||
|
|
||||||
var member_names: std.StringArrayHashMapUnmanaged(u32) = .empty;
|
var member_names: std.StringArrayHashMapUnmanaged(void) = .empty;
|
||||||
defer member_names.deinit(gpa);
|
defer member_names.deinit(gpa);
|
||||||
for (root.container_member_fns_map.values()) |members| {
|
for (root.container_member_fns_map.values()) |members| {
|
||||||
member_names.clearRetainingCapacity();
|
member_names.clearRetainingCapacity();
|
||||||
@ -261,7 +261,7 @@ pub const Root = struct {
|
|||||||
const payload: *ast.Payload.Container = @alignCast(@fieldParentPtr("base", members.container_decl_ptr.ptr_otherwise));
|
const payload: *ast.Payload.Container = @alignCast(@fieldParentPtr("base", members.container_decl_ptr.ptr_otherwise));
|
||||||
// Avoid duplication with field names
|
// Avoid duplication with field names
|
||||||
for (payload.data.fields) |field| {
|
for (payload.data.fields) |field| {
|
||||||
try member_names.put(gpa, field.name, 0);
|
try member_names.put(gpa, field.name, {});
|
||||||
}
|
}
|
||||||
break :blk_record &payload.data.decls;
|
break :blk_record &payload.data.decls;
|
||||||
},
|
},
|
||||||
@ -278,34 +278,39 @@ pub const Root = struct {
|
|||||||
};
|
};
|
||||||
|
|
||||||
const old_decls = decls_ptr.*;
|
const old_decls = decls_ptr.*;
|
||||||
const new_decls = try arena.alloc(ast.Node, old_decls.len + members.member_fns.items.len);
|
const new_decls = try arena.alloc(ast.Node, old_decls.len + members.member_fns.items.len * 2);
|
||||||
@memcpy(new_decls[0..old_decls.len], old_decls);
|
@memcpy(new_decls[0..old_decls.len], old_decls);
|
||||||
// Assume the allocator of payload.data.decls is arena,
|
// Assume the allocator of payload.data.decls is arena,
|
||||||
// so don't add arena.free(old_variables).
|
// so don't add arena.free(old_variables).
|
||||||
const func_ref_vars = new_decls[old_decls.len..];
|
const func_ref_vars = new_decls[old_decls.len..];
|
||||||
var count: u32 = 0;
|
var count: u32 = 0;
|
||||||
|
|
||||||
|
// Add members without mangling them - only fields may cause name conflicts
|
||||||
for (members.member_fns.items) |func| {
|
for (members.member_fns.items) |func| {
|
||||||
const func_name = func.data.name.?;
|
const func_name = func.data.name.?;
|
||||||
|
const member_name_slot = try member_names.getOrPutValue(gpa, func_name, {});
|
||||||
const last_index = std.mem.lastIndexOf(u8, func_name, "_");
|
if (member_name_slot.found_existing) continue;
|
||||||
const last_name = if (last_index) |index| func_name[index + 1 ..] else continue;
|
|
||||||
var same_count: u32 = 0;
|
|
||||||
const gop = try member_names.getOrPutValue(gpa, last_name, same_count);
|
|
||||||
if (gop.found_existing) {
|
|
||||||
gop.value_ptr.* += 1;
|
|
||||||
same_count = gop.value_ptr.*;
|
|
||||||
}
|
|
||||||
const var_name = if (same_count == 0)
|
|
||||||
last_name
|
|
||||||
else
|
|
||||||
try std.fmt.allocPrint(arena, "{s}{d}", .{ last_name, same_count });
|
|
||||||
|
|
||||||
func_ref_vars[count] = try ast.Node.Tag.pub_var_simple.create(arena, .{
|
func_ref_vars[count] = try ast.Node.Tag.pub_var_simple.create(arena, .{
|
||||||
.name = var_name,
|
.name = func_name,
|
||||||
.init = try ast.Node.Tag.identifier.create(arena, func_name),
|
.init = try ast.Node.Tag.root_ref.create(arena, func_name),
|
||||||
});
|
});
|
||||||
count += 1;
|
count += 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
for (members.member_fns.items) |func| {
|
||||||
|
const func_name = func.data.name.?;
|
||||||
|
const func_name_trimmed = std.mem.trimEnd(u8, func_name, "_");
|
||||||
|
const last_idx = std.mem.findLast(u8, func_name_trimmed, "_") orelse continue;
|
||||||
|
const func_name_alias = func_name[last_idx + 1 ..];
|
||||||
|
const member_name_slot = try member_names.getOrPutValue(gpa, func_name_alias, {});
|
||||||
|
if (member_name_slot.found_existing) continue;
|
||||||
|
func_ref_vars[count] = try ast.Node.Tag.pub_var_simple.create(arena, .{
|
||||||
|
.name = func_name_alias,
|
||||||
|
.init = try ast.Node.Tag.root_ref.create(arena, func_name),
|
||||||
|
});
|
||||||
|
count += 1;
|
||||||
|
}
|
||||||
|
|
||||||
decls_ptr.* = new_decls[0 .. old_decls.len + count];
|
decls_ptr.* = new_decls[0 .. old_decls.len + count];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -82,12 +82,11 @@ pub fn getMangle(t: *Translator) u32 {
|
|||||||
|
|
||||||
/// Convert an `aro.Source.Location` to a 'file:line:column' string.
|
/// Convert an `aro.Source.Location` to a 'file:line:column' string.
|
||||||
pub fn locStr(t: *Translator, loc: aro.Source.Location) ![]const u8 {
|
pub fn locStr(t: *Translator, loc: aro.Source.Location) ![]const u8 {
|
||||||
const source = t.comp.getSource(loc.id);
|
const expanded = loc.expand(t.comp);
|
||||||
const line_col = source.lineCol(loc);
|
const filename = expanded.path;
|
||||||
const filename = source.path;
|
|
||||||
|
|
||||||
const line = source.physicalLine(loc);
|
const line = expanded.line_no;
|
||||||
const col = line_col.col;
|
const col = expanded.col;
|
||||||
|
|
||||||
return std.fmt.allocPrint(t.arena, "{s}:{d}:{d}", .{ filename, line, col });
|
return std.fmt.allocPrint(t.arena, "{s}:{d}:{d}", .{ filename, line, col });
|
||||||
}
|
}
|
||||||
@ -139,7 +138,11 @@ pub fn failDeclExtra(
|
|||||||
// location
|
// location
|
||||||
// pub const name = @compileError(msg);
|
// pub const name = @compileError(msg);
|
||||||
const fail_msg = try std.fmt.allocPrint(t.arena, format, args);
|
const fail_msg = try std.fmt.allocPrint(t.arena, format, args);
|
||||||
const fail_decl = try ZigTag.fail_decl.create(t.arena, .{ .actual = name, .mangled = fail_msg });
|
const fail_decl = try ZigTag.fail_decl.create(t.arena, .{
|
||||||
|
.actual = name,
|
||||||
|
.mangled = fail_msg,
|
||||||
|
.local = scope.id != .root,
|
||||||
|
});
|
||||||
|
|
||||||
const str = try t.locStr(loc);
|
const str = try t.locStr(loc);
|
||||||
const location_comment = try std.fmt.allocPrint(t.arena, "// {s}", .{str});
|
const location_comment = try std.fmt.allocPrint(t.arena, "// {s}", .{str});
|
||||||
@ -220,6 +223,7 @@ pub fn translate(options: Options) mem.Allocator.Error![]u8 {
|
|||||||
defer allocating.deinit();
|
defer allocating.deinit();
|
||||||
|
|
||||||
allocating.writer.writeAll(
|
allocating.writer.writeAll(
|
||||||
|
\\const __root = @This();
|
||||||
\\pub const __builtin = @import("std").zig.c_translation.builtins;
|
\\pub const __builtin = @import("std").zig.c_translation.builtins;
|
||||||
\\pub const __helpers = @import("std").zig.c_translation.helpers;
|
\\pub const __helpers = @import("std").zig.c_translation.helpers;
|
||||||
\\
|
\\
|
||||||
@ -297,7 +301,7 @@ fn prepopulateGlobalNameTable(t: *Translator) !void {
|
|||||||
}
|
}
|
||||||
|
|
||||||
for (t.pp.defines.keys(), t.pp.defines.values()) |name, macro| {
|
for (t.pp.defines.keys(), t.pp.defines.values()) |name, macro| {
|
||||||
if (macro.is_builtin) continue;
|
if (macro.isBuiltin()) continue;
|
||||||
if (!t.isSelfDefinedMacro(name, macro)) {
|
if (!t.isSelfDefinedMacro(name, macro)) {
|
||||||
try t.global_names.put(t.gpa, name, {});
|
try t.global_names.put(t.gpa, name, {});
|
||||||
}
|
}
|
||||||
@ -527,6 +531,13 @@ fn transRecordDecl(t: *Translator, scope: *Scope, record_qt: QualType) Error!voi
|
|||||||
break :init ZigTag.opaque_literal.init();
|
break :init ZigTag.opaque_literal.init();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Demote record to opaque if it contains an opaque field
|
||||||
|
if (t.typeWasDemotedToOpaque(field.qt)) {
|
||||||
|
try t.opaque_demotes.put(t.gpa, base.qt, {});
|
||||||
|
try t.warn(scope, field_loc, "{s} demoted to opaque type - has opaque field", .{container_kind_name});
|
||||||
|
break :init ZigTag.opaque_literal.init();
|
||||||
|
}
|
||||||
|
|
||||||
var field_name = field.name.lookup(t.comp);
|
var field_name = field.name.lookup(t.comp);
|
||||||
if (field.name_tok == 0) {
|
if (field.name_tok == 0) {
|
||||||
field_name = try std.fmt.allocPrint(t.arena, "unnamed_{d}", .{unnamed_field_count});
|
field_name = try std.fmt.allocPrint(t.arena, "unnamed_{d}", .{unnamed_field_count});
|
||||||
@ -856,12 +867,18 @@ fn transVarDecl(t: *Translator, scope: *Scope, variable: Node.Variable) Error!vo
|
|||||||
break :blk null;
|
break :blk null;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// TODO actually set with @export/@extern
|
||||||
|
const linkage = variable.qt.linkage(t.comp);
|
||||||
|
if (linkage != .strong) {
|
||||||
|
try t.warn(scope, variable.name_tok, "TODO {s} linkage ignored", .{@tagName(linkage)});
|
||||||
|
}
|
||||||
|
|
||||||
const alignment: ?c_uint = variable.qt.requestedAlignment(t.comp) orelse null;
|
const alignment: ?c_uint = variable.qt.requestedAlignment(t.comp) orelse null;
|
||||||
var node = try ZigTag.var_decl.create(t.arena, .{
|
var node = try ZigTag.var_decl.create(t.arena, .{
|
||||||
.is_pub = toplevel,
|
.is_pub = toplevel,
|
||||||
.is_const = is_const,
|
.is_const = is_const,
|
||||||
.is_extern = is_extern,
|
.is_extern = is_extern,
|
||||||
.is_export = toplevel and variable.storage_class == .auto,
|
.is_export = toplevel and variable.storage_class == .auto and linkage == .strong,
|
||||||
.is_threadlocal = variable.thread_local,
|
.is_threadlocal = variable.thread_local,
|
||||||
.linksection_string = linksection_string,
|
.linksection_string = linksection_string,
|
||||||
.alignment = alignment,
|
.alignment = alignment,
|
||||||
@ -1013,7 +1030,7 @@ fn transStaticAssert(t: *Translator, scope: *Scope, static_assert: Node.StaticAs
|
|||||||
try scope.appendNode(assert_node);
|
try scope.appendNode(assert_node);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn transGlobalAsm(t: *Translator, scope: *Scope, global_asm: Node.SimpleAsm) Error!void {
|
fn transGlobalAsm(t: *Translator, scope: *Scope, global_asm: Node.GlobalAsm) Error!void {
|
||||||
const asm_string = t.tree.value_map.get(global_asm.asm_str).?;
|
const asm_string = t.tree.value_map.get(global_asm.asm_str).?;
|
||||||
const bytes = t.comp.interner.get(asm_string.ref()).bytes;
|
const bytes = t.comp.interner.get(asm_string.ref()).bytes;
|
||||||
|
|
||||||
@ -1071,6 +1088,17 @@ fn transType(t: *Translator, scope: *Scope, qt: QualType, source_loc: TokenIndex
|
|||||||
.double => return ZigTag.type.create(t.arena, "f64"),
|
.double => return ZigTag.type.create(t.arena, "f64"),
|
||||||
.long_double => return ZigTag.type.create(t.arena, "c_longdouble"),
|
.long_double => return ZigTag.type.create(t.arena, "c_longdouble"),
|
||||||
.float128 => return ZigTag.type.create(t.arena, "f128"),
|
.float128 => return ZigTag.type.create(t.arena, "f128"),
|
||||||
|
.bf16,
|
||||||
|
.float32,
|
||||||
|
.float64,
|
||||||
|
.float32x,
|
||||||
|
.float64x,
|
||||||
|
.float128x,
|
||||||
|
.dfloat32,
|
||||||
|
.dfloat64,
|
||||||
|
.dfloat128,
|
||||||
|
.dfloat64x,
|
||||||
|
=> return t.fail(error.UnsupportedType, source_loc, "TODO support float type: '{s}'", .{try t.getTypeStr(qt)}),
|
||||||
},
|
},
|
||||||
.pointer => |pointer_ty| {
|
.pointer => |pointer_ty| {
|
||||||
const child_qt = pointer_ty.child;
|
const child_qt = pointer_ty.child;
|
||||||
@ -1165,17 +1193,8 @@ fn headFieldAlignment(t: *Translator, record_decl: aro.Type.Record) ?c_uint {
|
|||||||
const parent_ptr_alignment_bits = record_decl.layout.?.pointer_alignment_bits;
|
const parent_ptr_alignment_bits = record_decl.layout.?.pointer_alignment_bits;
|
||||||
const parent_ptr_alignment = parent_ptr_alignment_bits / bits_per_byte;
|
const parent_ptr_alignment = parent_ptr_alignment_bits / bits_per_byte;
|
||||||
var max_field_alignment_bits: u64 = 0;
|
var max_field_alignment_bits: u64 = 0;
|
||||||
for (record_decl.fields) |field| {
|
for (record_decl.fields) |field|
|
||||||
if (field.qt.getRecord(t.comp)) |field_record_decl| {
|
max_field_alignment_bits = @max(max_field_alignment_bits, bits_per_byte * field.qt.alignof(t.comp));
|
||||||
const child_record_alignment = field_record_decl.layout.?.field_alignment_bits;
|
|
||||||
if (child_record_alignment > max_field_alignment_bits)
|
|
||||||
max_field_alignment_bits = child_record_alignment;
|
|
||||||
} else {
|
|
||||||
const field_size = field.layout.size_bits;
|
|
||||||
if (field_size > max_field_alignment_bits)
|
|
||||||
max_field_alignment_bits = field_size;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (max_field_alignment_bits != parent_ptr_alignment_bits) {
|
if (max_field_alignment_bits != parent_ptr_alignment_bits) {
|
||||||
return parent_ptr_alignment;
|
return parent_ptr_alignment;
|
||||||
} else {
|
} else {
|
||||||
@ -1227,10 +1246,7 @@ fn alignmentForField(
|
|||||||
// Records have a natural alignment when used as a field, and their size is
|
// Records have a natural alignment when used as a field, and their size is
|
||||||
// a multiple of this alignment value. For all other types, the natural alignment
|
// a multiple of this alignment value. For all other types, the natural alignment
|
||||||
// is their size.
|
// is their size.
|
||||||
const field_natural_alignment_bits: u64 = if (field.qt.getRecord(t.comp)) |record|
|
const field_natural_alignment_bits: u64 = bits_per_byte * field.qt.alignof(t.comp);
|
||||||
record.layout.?.field_alignment_bits
|
|
||||||
else
|
|
||||||
field_size_bits;
|
|
||||||
const rem_bits = field_offset_bits % field_natural_alignment_bits;
|
const rem_bits = field_offset_bits % field_natural_alignment_bits;
|
||||||
|
|
||||||
// If there's a remainder, then the alignment is smaller than the field's
|
// If there's a remainder, then the alignment is smaller than the field's
|
||||||
@ -1351,13 +1367,19 @@ fn transFnType(
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// TODO actually set with @export/@extern
|
||||||
|
const linkage = func_qt.linkage(t.comp);
|
||||||
|
if (linkage != .strong) {
|
||||||
|
try t.warn(scope, source_loc, "TODO {s} linkage ignored", .{@tagName(linkage)});
|
||||||
|
}
|
||||||
|
|
||||||
const payload = try t.arena.create(ast.Payload.Func);
|
const payload = try t.arena.create(ast.Payload.Func);
|
||||||
payload.* = .{
|
payload.* = .{
|
||||||
.base = .{ .tag = .func },
|
.base = .{ .tag = .func },
|
||||||
.data = .{
|
.data = .{
|
||||||
.is_pub = ctx.is_pub,
|
.is_pub = ctx.is_pub,
|
||||||
.is_extern = ctx.is_extern,
|
.is_extern = ctx.is_extern,
|
||||||
.is_export = ctx.is_export,
|
.is_export = ctx.is_export and linkage == .strong,
|
||||||
.is_inline = ctx.is_always_inline,
|
.is_inline = ctx.is_always_inline,
|
||||||
.is_var_args = switch (func_ty.kind) {
|
.is_var_args = switch (func_ty.kind) {
|
||||||
.normal => false,
|
.normal => false,
|
||||||
@ -1446,18 +1468,7 @@ fn typeIsOpaque(t: *Translator, qt: QualType) bool {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn typeWasDemotedToOpaque(t: *Translator, qt: QualType) bool {
|
fn typeWasDemotedToOpaque(t: *Translator, qt: QualType) bool {
|
||||||
const base = qt.base(t.comp);
|
return t.opaque_demotes.contains(qt);
|
||||||
switch (base.type) {
|
|
||||||
.@"struct", .@"union" => |record_ty| {
|
|
||||||
if (t.opaque_demotes.contains(base.qt)) return true;
|
|
||||||
for (record_ty.fields) |field| {
|
|
||||||
if (t.typeWasDemotedToOpaque(field.qt)) return true;
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
},
|
|
||||||
.@"enum" => return t.opaque_demotes.contains(base.qt),
|
|
||||||
else => return false,
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn typeHasWrappingOverflow(t: *Translator, qt: QualType) bool {
|
fn typeHasWrappingOverflow(t: *Translator, qt: QualType) bool {
|
||||||
@ -1539,6 +1550,9 @@ fn transStmt(t: *Translator, scope: *Scope, stmt: Node.Index) TransError!ZigNode
|
|||||||
.goto_stmt, .computed_goto_stmt, .labeled_stmt => {
|
.goto_stmt, .computed_goto_stmt, .labeled_stmt => {
|
||||||
return t.fail(error.UnsupportedTranslation, stmt.tok(t.tree), "TODO goto", .{});
|
return t.fail(error.UnsupportedTranslation, stmt.tok(t.tree), "TODO goto", .{});
|
||||||
},
|
},
|
||||||
|
.asm_stmt => {
|
||||||
|
return t.fail(error.UnsupportedTranslation, stmt.tok(t.tree), "TODO asm stmt", .{});
|
||||||
|
},
|
||||||
else => return t.transExprCoercing(scope, stmt, .unused),
|
else => return t.transExprCoercing(scope, stmt, .unused),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -2197,7 +2211,7 @@ fn transExpr(t: *Translator, scope: *Scope, expr: Node.Index, used: ResultUsed)
|
|||||||
.default_stmt,
|
.default_stmt,
|
||||||
.goto_stmt,
|
.goto_stmt,
|
||||||
.computed_goto_stmt,
|
.computed_goto_stmt,
|
||||||
.gnu_asm_simple,
|
.asm_stmt,
|
||||||
.global_asm,
|
.global_asm,
|
||||||
.typedef,
|
.typedef,
|
||||||
.struct_decl,
|
.struct_decl,
|
||||||
@ -3031,6 +3045,10 @@ fn transMemberAccess(
|
|||||||
.normal => member_access.base.qt(t.tree),
|
.normal => member_access.base.qt(t.tree),
|
||||||
.ptr => member_access.base.qt(t.tree).childType(t.comp),
|
.ptr => member_access.base.qt(t.tree).childType(t.comp),
|
||||||
};
|
};
|
||||||
|
if (t.typeWasDemotedToOpaque(base_info)) {
|
||||||
|
return t.fail(error.UnsupportedTranslation, member_access.access_tok, "member access of demoted record", .{});
|
||||||
|
}
|
||||||
|
|
||||||
const record = base_info.getRecord(t.comp).?;
|
const record = base_info.getRecord(t.comp).?;
|
||||||
const field = record.fields[member_access.member_index];
|
const field = record.fields[member_access.member_index];
|
||||||
const field_name = if (field.name_tok == 0) t.anonymous_record_field_names.get(.{
|
const field_name = if (field.name_tok == 0) t.anonymous_record_field_names.get(.{
|
||||||
@ -3551,7 +3569,7 @@ fn transArrayInit(
|
|||||||
const array_item_qt = array_init.container_qt.childType(t.comp);
|
const array_item_qt = array_init.container_qt.childType(t.comp);
|
||||||
const array_item_type = try t.transType(scope, array_item_qt, array_init.l_brace_tok);
|
const array_item_type = try t.transType(scope, array_item_qt, array_init.l_brace_tok);
|
||||||
var maybe_lhs: ?ZigNode = null;
|
var maybe_lhs: ?ZigNode = null;
|
||||||
var val_list: std.ArrayListUnmanaged(ZigNode) = .empty;
|
var val_list: std.ArrayList(ZigNode) = .empty;
|
||||||
defer val_list.deinit(t.gpa);
|
defer val_list.deinit(t.gpa);
|
||||||
var i: usize = 0;
|
var i: usize = 0;
|
||||||
while (i < array_init.items.len) {
|
while (i < array_init.items.len) {
|
||||||
@ -3671,6 +3689,10 @@ fn transTypeInfo(
|
|||||||
const operand = operand: {
|
const operand = operand: {
|
||||||
if (typeinfo.expr) |expr| {
|
if (typeinfo.expr) |expr| {
|
||||||
const operand = try t.transExpr(scope, expr, .used);
|
const operand = try t.transExpr(scope, expr, .used);
|
||||||
|
if (operand.tag() == .string_literal) {
|
||||||
|
const deref = try ZigTag.deref.create(t.arena, operand);
|
||||||
|
break :operand try ZigTag.typeof.create(t.arena, deref);
|
||||||
|
}
|
||||||
break :operand try ZigTag.typeof.create(t.arena, operand);
|
break :operand try ZigTag.typeof.create(t.arena, operand);
|
||||||
}
|
}
|
||||||
break :operand try t.transType(scope, typeinfo.operand_qt, typeinfo.op_tok);
|
break :operand try t.transType(scope, typeinfo.operand_qt, typeinfo.op_tok);
|
||||||
@ -3962,7 +3984,8 @@ fn createFlexibleMemberFn(
|
|||||||
|
|
||||||
// return @ptrCast(&self.*.<field_name>);
|
// return @ptrCast(&self.*.<field_name>);
|
||||||
const address_of = try ZigTag.address_of.create(t.arena, field_access);
|
const address_of = try ZigTag.address_of.create(t.arena, field_access);
|
||||||
const casted = try ZigTag.ptr_cast.create(t.arena, address_of);
|
const aligned = try ZigTag.align_cast.create(t.arena, address_of);
|
||||||
|
const casted = try ZigTag.ptr_cast.create(t.arena, aligned);
|
||||||
const return_stmt = try ZigTag.@"return".create(t.arena, casted);
|
const return_stmt = try ZigTag.@"return".create(t.arena, casted);
|
||||||
const body = try ZigTag.block_single.create(t.arena, return_stmt);
|
const body = try ZigTag.block_single.create(t.arena, return_stmt);
|
||||||
|
|
||||||
@ -3994,7 +4017,7 @@ fn transMacros(t: *Translator) !void {
|
|||||||
defer pattern_list.deinit(t.gpa);
|
defer pattern_list.deinit(t.gpa);
|
||||||
|
|
||||||
for (t.pp.defines.keys(), t.pp.defines.values()) |name, macro| {
|
for (t.pp.defines.keys(), t.pp.defines.values()) |name, macro| {
|
||||||
if (macro.is_builtin) continue;
|
if (macro.isBuiltin()) continue;
|
||||||
if (t.global_scope.containsNow(name)) {
|
if (t.global_scope.containsNow(name)) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -247,6 +247,9 @@ pub const Node = extern union {
|
|||||||
/// comptime { if (!(lhs)) @compileError(rhs); }
|
/// comptime { if (!(lhs)) @compileError(rhs); }
|
||||||
static_assert,
|
static_assert,
|
||||||
|
|
||||||
|
/// __root.<name>
|
||||||
|
root_ref,
|
||||||
|
|
||||||
pub const last_no_payload_tag = Tag.@"break";
|
pub const last_no_payload_tag = Tag.@"break";
|
||||||
pub const no_payload_count = @intFromEnum(last_no_payload_tag) + 1;
|
pub const no_payload_count = @intFromEnum(last_no_payload_tag) + 1;
|
||||||
|
|
||||||
@ -394,7 +397,8 @@ pub const Node = extern union {
|
|||||||
.block => Payload.Block,
|
.block => Payload.Block,
|
||||||
.c_pointer, .single_pointer => Payload.Pointer,
|
.c_pointer, .single_pointer => Payload.Pointer,
|
||||||
.array_type, .null_sentinel_array_type => Payload.Array,
|
.array_type, .null_sentinel_array_type => Payload.Array,
|
||||||
.arg_redecl, .alias, .fail_decl => Payload.ArgRedecl,
|
.arg_redecl, .alias => Payload.ArgRedecl,
|
||||||
|
.fail_decl => Payload.FailDecl,
|
||||||
.var_simple, .pub_var_simple, .wrapped_local, .mut_str => Payload.SimpleVarDecl,
|
.var_simple, .pub_var_simple, .wrapped_local, .mut_str => Payload.SimpleVarDecl,
|
||||||
.enum_constant => Payload.EnumConstant,
|
.enum_constant => Payload.EnumConstant,
|
||||||
.array_filler => Payload.ArrayFiller,
|
.array_filler => Payload.ArrayFiller,
|
||||||
@ -405,6 +409,7 @@ pub const Node = extern union {
|
|||||||
.builtin_extern => Payload.Extern,
|
.builtin_extern => Payload.Extern,
|
||||||
.helper_call => Payload.HelperCall,
|
.helper_call => Payload.HelperCall,
|
||||||
.helper_ref => Payload.HelperRef,
|
.helper_ref => Payload.HelperRef,
|
||||||
|
.root_ref => Payload.RootRef,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -708,6 +713,15 @@ pub const Payload = struct {
|
|||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
pub const FailDecl = struct {
|
||||||
|
base: Payload,
|
||||||
|
data: struct {
|
||||||
|
actual: []const u8,
|
||||||
|
mangled: []const u8,
|
||||||
|
local: bool,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
pub const SimpleVarDecl = struct {
|
pub const SimpleVarDecl = struct {
|
||||||
base: Payload,
|
base: Payload,
|
||||||
data: struct {
|
data: struct {
|
||||||
@ -791,6 +805,11 @@ pub const Payload = struct {
|
|||||||
base: Payload,
|
base: Payload,
|
||||||
data: []const u8,
|
data: []const u8,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
pub const RootRef = struct {
|
||||||
|
base: Payload,
|
||||||
|
data: []const u8,
|
||||||
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
/// Converts the nodes into a Zig Ast.
|
/// Converts the nodes into a Zig Ast.
|
||||||
@ -860,7 +879,7 @@ const Context = struct {
|
|||||||
gpa: Allocator,
|
gpa: Allocator,
|
||||||
buf: std.ArrayList(u8) = .empty,
|
buf: std.ArrayList(u8) = .empty,
|
||||||
nodes: std.zig.Ast.NodeList = .empty,
|
nodes: std.zig.Ast.NodeList = .empty,
|
||||||
extra_data: std.ArrayListUnmanaged(u32) = .empty,
|
extra_data: std.ArrayList(u32) = .empty,
|
||||||
tokens: std.zig.Ast.TokenList = .empty,
|
tokens: std.zig.Ast.TokenList = .empty,
|
||||||
|
|
||||||
fn addTokenFmt(c: *Context, tag: TokenTag, comptime format: []const u8, args: anytype) Allocator.Error!TokenIndex {
|
fn addTokenFmt(c: *Context, tag: TokenTag, comptime format: []const u8, args: anytype) Allocator.Error!TokenIndex {
|
||||||
@ -1203,12 +1222,25 @@ fn renderNode(c: *Context, node: Node) Allocator.Error!NodeIndex {
|
|||||||
},
|
},
|
||||||
.fail_decl => {
|
.fail_decl => {
|
||||||
const payload = node.castTag(.fail_decl).?.data;
|
const payload = node.castTag(.fail_decl).?.data;
|
||||||
// pub const name = @compileError(msg);
|
// pub const name = (if (true))? @compileError(msg);
|
||||||
_ = try c.addToken(.keyword_pub, "pub");
|
if (!payload.local) _ = try c.addToken(.keyword_pub, "pub");
|
||||||
const const_tok = try c.addToken(.keyword_const, "const");
|
const const_tok = try c.addToken(.keyword_const, "const");
|
||||||
_ = try c.addIdentifier(payload.actual);
|
_ = try c.addIdentifier(payload.actual);
|
||||||
_ = try c.addToken(.equal, "=");
|
_ = try c.addToken(.equal, "=");
|
||||||
|
|
||||||
|
var if_tok: TokenIndex = undefined;
|
||||||
|
var true_node: NodeIndex = undefined;
|
||||||
|
if (payload.local) {
|
||||||
|
if_tok = try c.addToken(.keyword_if, "if");
|
||||||
|
_ = try c.addToken(.l_paren, "(");
|
||||||
|
true_node = try c.addNode(.{
|
||||||
|
.tag = .identifier,
|
||||||
|
.main_token = try c.addToken(.identifier, "true"),
|
||||||
|
.data = undefined,
|
||||||
|
});
|
||||||
|
_ = try c.addToken(.r_paren, ")");
|
||||||
|
}
|
||||||
|
|
||||||
const compile_error_tok = try c.addToken(.builtin, "@compileError");
|
const compile_error_tok = try c.addToken(.builtin, "@compileError");
|
||||||
_ = try c.addToken(.l_paren, "(");
|
_ = try c.addToken(.l_paren, "(");
|
||||||
const err_msg_tok = try c.addTokenFmt(.string_literal, "\"{f}\"", .{std.zig.fmtString(payload.mangled)});
|
const err_msg_tok = try c.addTokenFmt(.string_literal, "\"{f}\"", .{std.zig.fmtString(payload.mangled)});
|
||||||
@ -1233,7 +1265,16 @@ fn renderNode(c: *Context, node: Node) Allocator.Error!NodeIndex {
|
|||||||
.data = .{
|
.data = .{
|
||||||
.opt_node_and_opt_node = .{
|
.opt_node_and_opt_node = .{
|
||||||
.none, // Type expression
|
.none, // Type expression
|
||||||
compile_error.toOptional(), // Init expression
|
if (payload.local) // Init expression
|
||||||
|
(try c.addNode(.{
|
||||||
|
.tag = .if_simple,
|
||||||
|
.main_token = if_tok,
|
||||||
|
.data = .{ .node_and_node = .{
|
||||||
|
true_node, compile_error,
|
||||||
|
} },
|
||||||
|
})).toOptional()
|
||||||
|
else
|
||||||
|
compile_error.toOptional(),
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
@ -2158,6 +2199,15 @@ fn renderNode(c: *Context, node: Node) Allocator.Error!NodeIndex {
|
|||||||
});
|
});
|
||||||
},
|
},
|
||||||
.@"anytype" => unreachable, // Handled in renderParams
|
.@"anytype" => unreachable, // Handled in renderParams
|
||||||
|
.root_ref => {
|
||||||
|
const payload = node.castTag(.root_ref).?.data;
|
||||||
|
const root_tok = try c.addNode(.{
|
||||||
|
.tag = .identifier,
|
||||||
|
.main_token = try c.addIdentifier("__root"),
|
||||||
|
.data = undefined,
|
||||||
|
});
|
||||||
|
return renderFieldAccess(c, root_tok, payload);
|
||||||
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2480,6 +2530,7 @@ fn renderNodeGrouped(c: *Context, node: Node) !NodeIndex {
|
|||||||
.sqrt,
|
.sqrt,
|
||||||
.trunc,
|
.trunc,
|
||||||
.floor,
|
.floor,
|
||||||
|
.root_ref,
|
||||||
=> {
|
=> {
|
||||||
// no grouping needed
|
// no grouping needed
|
||||||
return renderNode(c, node);
|
return renderNode(c, node);
|
||||||
|
|||||||
@ -22,7 +22,7 @@ pub fn main() u8 {
|
|||||||
defer threaded.deinit();
|
defer threaded.deinit();
|
||||||
const io = threaded.io();
|
const io = threaded.io();
|
||||||
|
|
||||||
var args = process.argsAlloc(arena) catch {
|
const args = process.argsAlloc(arena) catch {
|
||||||
std.debug.print("ran out of memory allocating arguments\n", .{});
|
std.debug.print("ran out of memory allocating arguments\n", .{});
|
||||||
if (fast_exit) process.exit(1);
|
if (fast_exit) process.exit(1);
|
||||||
return 1;
|
return 1;
|
||||||
@ -58,7 +58,7 @@ pub fn main() u8 {
|
|||||||
var driver: aro.Driver = .{ .comp = &comp, .diagnostics = &diagnostics, .aro_name = "aro" };
|
var driver: aro.Driver = .{ .comp = &comp, .diagnostics = &diagnostics, .aro_name = "aro" };
|
||||||
defer driver.deinit();
|
defer driver.deinit();
|
||||||
|
|
||||||
var toolchain: aro.Toolchain = .{ .driver = &driver, .filesystem = .{ .real = comp.cwd } };
|
var toolchain: aro.Toolchain = .{ .driver = &driver };
|
||||||
defer toolchain.deinit();
|
defer toolchain.deinit();
|
||||||
|
|
||||||
translate(&driver, &toolchain, args, zig_integration) catch |err| switch (err) {
|
translate(&driver, &toolchain, args, zig_integration) catch |err| switch (err) {
|
||||||
@ -149,7 +149,7 @@ fn translate(d: *aro.Driver, tc: *aro.Toolchain, args: [][:0]u8, zig_integration
|
|||||||
break :args args[0..i];
|
break :args args[0..i];
|
||||||
};
|
};
|
||||||
const user_macros = macros: {
|
const user_macros = macros: {
|
||||||
var macro_buf: std.ArrayListUnmanaged(u8) = .empty;
|
var macro_buf: std.ArrayList(u8) = .empty;
|
||||||
defer macro_buf.deinit(gpa);
|
defer macro_buf.deinit(gpa);
|
||||||
|
|
||||||
var discard_buf: [256]u8 = undefined;
|
var discard_buf: [256]u8 = undefined;
|
||||||
@ -182,12 +182,10 @@ fn translate(d: *aro.Driver, tc: *aro.Toolchain, args: [][:0]u8, zig_integration
|
|||||||
error.OutOfMemory => return error.OutOfMemory,
|
error.OutOfMemory => return error.OutOfMemory,
|
||||||
error.TooManyMultilibs => return d.fatal("found more than one multilib with the same priority", .{}),
|
error.TooManyMultilibs => return d.fatal("found more than one multilib with the same priority", .{}),
|
||||||
};
|
};
|
||||||
tc.defineSystemIncludes() catch |er| switch (er) {
|
try tc.defineSystemIncludes();
|
||||||
error.OutOfMemory => return error.OutOfMemory,
|
try d.comp.initSearchPath(d.includes.items, d.verbose_search_path);
|
||||||
error.AroIncludeNotFound => return d.fatal("unable to find Aro builtin headers", .{}),
|
|
||||||
};
|
|
||||||
|
|
||||||
const builtin_macros = d.comp.generateBuiltinMacros(.include_system_defines) catch |err| switch (err) {
|
const builtin_macros = d.comp.generateBuiltinMacros(d.system_defines) catch |err| switch (err) {
|
||||||
error.FileTooBig => return d.fatal("builtin macro source exceeded max size", .{}),
|
error.FileTooBig => return d.fatal("builtin macro source exceeded max size", .{}),
|
||||||
else => |e| return e,
|
else => |e| return e,
|
||||||
};
|
};
|
||||||
@ -205,7 +203,13 @@ fn translate(d: *aro.Driver, tc: *aro.Toolchain, args: [][:0]u8, zig_integration
|
|||||||
|
|
||||||
if (opt_dep_file) |*dep_file| pp.dep_file = dep_file;
|
if (opt_dep_file) |*dep_file| pp.dep_file = dep_file;
|
||||||
|
|
||||||
try pp.preprocessSources(&.{ source, builtin_macros, user_macros });
|
try pp.preprocessSources(.{
|
||||||
|
.main = source,
|
||||||
|
.builtin = builtin_macros,
|
||||||
|
.command_line = user_macros,
|
||||||
|
.imacros = d.imacros.items,
|
||||||
|
.implicit_includes = d.implicit_includes.items,
|
||||||
|
});
|
||||||
|
|
||||||
var c_tree = try pp.parse();
|
var c_tree = try pp.parse();
|
||||||
defer c_tree.deinit();
|
defer c_tree.deinit();
|
||||||
|
|||||||
@ -5693,7 +5693,7 @@ pub fn translateC(
|
|||||||
const plus_or_minus = "-+"[@intFromBool(is_enabled)];
|
const plus_or_minus = "-+"[@intFromBool(is_enabled)];
|
||||||
try buf.print(gpa, "{c}{s}", .{ plus_or_minus, feature.name });
|
try buf.print(gpa, "{c}{s}", .{ plus_or_minus, feature.name });
|
||||||
}
|
}
|
||||||
break :mcpu try buf.toOwnedSlice(arena);
|
break :mcpu try arena.dupe(u8, buf.items);
|
||||||
};
|
};
|
||||||
try argv.append(mcpu);
|
try argv.append(mcpu);
|
||||||
|
|
||||||
|
|||||||
@ -307,7 +307,7 @@ pub fn buildImportLib(comp: *Compilation, lib_name: []const u8) !void {
|
|||||||
var aro_comp = aro.Compilation.init(gpa, arena, io, &diagnostics, std.fs.cwd());
|
var aro_comp = aro.Compilation.init(gpa, arena, io, &diagnostics, std.fs.cwd());
|
||||||
defer aro_comp.deinit();
|
defer aro_comp.deinit();
|
||||||
|
|
||||||
aro_comp.target = target.*;
|
aro_comp.target = .fromZigTarget(target.*);
|
||||||
|
|
||||||
const include_dir = try comp.dirs.zig_lib.join(arena, &.{ "libc", "mingw", "def-include" });
|
const include_dir = try comp.dirs.zig_lib.join(arena, &.{ "libc", "mingw", "def-include" });
|
||||||
|
|
||||||
@ -318,7 +318,7 @@ pub fn buildImportLib(comp: *Compilation, lib_name: []const u8) !void {
|
|||||||
nosuspend stderr.print("include dir: {s}\n", .{include_dir}) catch break :print;
|
nosuspend stderr.print("include dir: {s}\n", .{include_dir}) catch break :print;
|
||||||
}
|
}
|
||||||
|
|
||||||
try aro_comp.include_dirs.append(gpa, include_dir);
|
try aro_comp.search_path.append(gpa, .{ .path = include_dir, .kind = .normal });
|
||||||
|
|
||||||
const builtin_macros = try aro_comp.generateBuiltinMacros(.include_system_defines);
|
const builtin_macros = try aro_comp.generateBuiltinMacros(.include_system_defines);
|
||||||
const def_file_source = try aro_comp.addSourceFromPath(def_file_path);
|
const def_file_source = try aro_comp.addSourceFromPath(def_file_path);
|
||||||
@ -328,7 +328,7 @@ pub fn buildImportLib(comp: *Compilation, lib_name: []const u8) !void {
|
|||||||
pp.linemarkers = .none;
|
pp.linemarkers = .none;
|
||||||
pp.preserve_whitespace = true;
|
pp.preserve_whitespace = true;
|
||||||
|
|
||||||
try pp.preprocessSources(&.{ def_file_source, builtin_macros });
|
try pp.preprocessSources(.{ .main = def_file_source, .builtin = builtin_macros });
|
||||||
|
|
||||||
if (aro_comp.diagnostics.output.to_list.messages.items.len != 0) {
|
if (aro_comp.diagnostics.output.to_list.messages.items.len != 0) {
|
||||||
var buffer: [64]u8 = undefined;
|
var buffer: [64]u8 = undefined;
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user