Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Rework attributes a bit #765

Merged
merged 2 commits into from
Sep 5, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
78 changes: 55 additions & 23 deletions src/aro/Attribute.zig
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,57 @@ pub const Kind = enum {
}
};

pub const Iterator = struct {
source: union(enum) {
ty: Type,
slice: []const Attribute,
},
index: usize,

pub fn initSlice(slice: ?[]const Attribute) Iterator {
return .{ .source = .{ .slice = slice orelse &.{} }, .index = 0 };
}

pub fn initType(ty: Type) Iterator {
return .{ .source = .{ .ty = ty }, .index = 0 };
}

/// returns the next attribute as well as its index within the slice or current type
/// The index can be used to determine when a nested type has been recursed into
pub fn next(self: *Iterator) ?struct { Attribute, usize } {
switch (self.source) {
.slice => |slice| {
if (self.index < slice.len) {
defer self.index += 1;
return .{ slice[self.index], self.index };
}
},
.ty => |ty| {
switch (ty.specifier) {
.typeof_type => {
self.* = .{ .source = .{ .ty = ty.data.sub_type.* }, .index = 0 };
return self.next();
},
.typeof_expr => {
self.* = .{ .source = .{ .ty = ty.data.expr.ty }, .index = 0 };
return self.next();
},
.attributed => {
if (self.index < ty.data.attributed.attributes.len) {
defer self.index += 1;
return .{ ty.data.attributed.attributes[self.index], self.index };
}
self.* = .{ .source = .{ .ty = ty.data.attributed.base }, .index = 0 };
return self.next();
},
else => {},
}
},
}
return null;
}
};

pub const ArgumentType = enum {
string,
identifier,
Expand Down Expand Up @@ -740,7 +791,6 @@ pub fn applyVariableAttributes(p: *Parser, ty: Type, attr_buf_start: usize, tag:
const toks = p.attr_buf.items(.tok)[attr_buf_start..];
p.attr_application_buf.items.len = 0;
var base_ty = ty;
if (base_ty.specifier == .attributed) base_ty = base_ty.data.attributed.base;
var common = false;
var nocommon = false;
for (attrs, toks) |attr, tok| switch (attr.tag) {
Expand Down Expand Up @@ -785,12 +835,7 @@ pub fn applyVariableAttributes(p: *Parser, ty: Type, attr_buf_start: usize, tag:
=> |t| try p.errExtra(.attribute_todo, tok, .{ .attribute_todo = .{ .tag = t, .kind = .variables } }),
else => try ignoredAttrErr(p, tok, attr.tag, "variables"),
};
const existing = ty.getAttributes();
if (existing.len == 0 and p.attr_application_buf.items.len == 0) return base_ty;
if (existing.len == 0) return base_ty.withAttributes(p.arena, p.attr_application_buf.items);

const attributed_type = try Type.Attributed.create(p.arena, base_ty, existing, p.attr_application_buf.items);
return Type{ .specifier = .attributed, .data = .{ .attributed = attributed_type } };
return base_ty.withAttributes(p.arena, p.attr_application_buf.items);
}

pub fn applyFieldAttributes(p: *Parser, field_ty: *Type, attr_buf_start: usize) ![]const Attribute {
Expand All @@ -815,7 +860,6 @@ pub fn applyTypeAttributes(p: *Parser, ty: Type, attr_buf_start: usize, tag: ?Di
const toks = p.attr_buf.items(.tok)[attr_buf_start..];
p.attr_application_buf.items.len = 0;
var base_ty = ty;
if (base_ty.specifier == .attributed) base_ty = base_ty.data.attributed.base;
for (attrs, toks) |attr, tok| switch (attr.tag) {
// zig fmt: off
.@"packed", .may_alias, .deprecated, .unavailable, .unused, .warn_if_not_aligned, .mode,
Expand All @@ -836,27 +880,14 @@ pub fn applyTypeAttributes(p: *Parser, ty: Type, attr_buf_start: usize, tag: ?Di
=> |t| try p.errExtra(.attribute_todo, tok, .{ .attribute_todo = .{ .tag = t, .kind = .types } }),
else => try ignoredAttrErr(p, tok, attr.tag, "types"),
};

const existing = ty.getAttributes();
// TODO: the alignment annotation on a type should override
// the decl it refers to. This might not be true for others. Maybe bug.

// if there are annotations on this type def use those.
if (p.attr_application_buf.items.len > 0) {
return try base_ty.withAttributes(p.arena, p.attr_application_buf.items);
} else if (existing.len > 0) {
// else use the ones on the typedef decl we were refering to.
return try base_ty.withAttributes(p.arena, existing);
}
return base_ty;
return base_ty.withAttributes(p.arena, p.attr_application_buf.items);
}

pub fn applyFunctionAttributes(p: *Parser, ty: Type, attr_buf_start: usize) !Type {
const attrs = p.attr_buf.items(.attr)[attr_buf_start..];
const toks = p.attr_buf.items(.tok)[attr_buf_start..];
p.attr_application_buf.items.len = 0;
var base_ty = ty;
if (base_ty.specifier == .attributed) base_ty = base_ty.data.attributed.base;
var hot = false;
var cold = false;
var @"noinline" = false;
Expand Down Expand Up @@ -1059,6 +1090,7 @@ fn applyTransparentUnion(attr: Attribute, p: *Parser, tok: TokenIndex, ty: Type)
}

fn applyVectorSize(attr: Attribute, p: *Parser, tok: TokenIndex, ty: *Type) !void {
const base = ty.base();
const is_enum = ty.is(.@"enum");
if (!(ty.isInt() or ty.isFloat()) or !ty.isReal() or (is_enum and p.comp.langopts.emulate == .gcc)) {
try p.errStr(.invalid_vec_elem_ty, tok, try p.typeStr(ty.*));
Expand All @@ -1075,7 +1107,7 @@ fn applyVectorSize(attr: Attribute, p: *Parser, tok: TokenIndex, ty: *Type) !voi

const arr_ty = try p.arena.create(Type.Array);
arr_ty.* = .{ .elem = ty.*, .len = vec_size };
ty.* = Type{
base.* = .{
.specifier = .vector,
.data = .{ .array = arr_ty },
};
Expand Down
6 changes: 1 addition & 5 deletions src/aro/Parser.zig
Original file line number Diff line number Diff line change
Expand Up @@ -1037,10 +1037,8 @@ fn decl(p: *Parser) Error!bool {

// Collect old style parameter declarations.
if (init_d.d.old_style_func != null) {
const attrs = init_d.d.ty.getAttributes();
var base_ty = if (init_d.d.ty.specifier == .attributed) init_d.d.ty.data.attributed.base else init_d.d.ty;
var base_ty = init_d.d.ty.base();
base_ty.specifier = .func;
init_d.d.ty = try base_ty.withAttributes(p.arena, attrs);

const param_buf_top = p.param_buf.items.len;
defer p.param_buf.items.len = param_buf_top;
Expand Down Expand Up @@ -3901,8 +3899,6 @@ fn convertInitList(p: *Parser, il: InitList, init_ty: Type) Error!NodeIndex {
.specifier = .array,
.data = .{ .array = arr_ty },
};
const attrs = init_ty.getAttributes();
arr_init_node.ty = try arr_init_node.ty.withAttributes(p.arena, attrs);
} else if (start < max_items) {
const elem = try p.addNode(.{
.tag = .array_filler_expr,
Expand Down
4 changes: 3 additions & 1 deletion src/aro/Tree.zig
Original file line number Diff line number Diff line change
Expand Up @@ -909,7 +909,9 @@ fn dumpNode(

if (ty.specifier == .attributed) {
try config.setColor(w, ATTRIBUTE);
for (ty.data.attributed.attributes) |attr| {
var it = Attribute.Iterator.initType(ty);
while (it.next()) |item| {
const attr, _ = item;
try w.writeByteNTimes(' ', level + half);
try w.print("attr: {s}", .{@tagName(attr.tag)});
try tree.dumpAttribute(attr, w);
Expand Down
Loading
Loading