authorgravatar for 14938807+xackus@users.noreply.github.comxackus <14938807+xackus@users.noreply.github.com> 2021-06-12 20:39:40+02:00
committergravatar for git@vexu.euVeikka Tuominen <git@vexu.eu> 2021-06-13 16:47:55+03:00
loge5750f8c7f65455589e2d4b45847a351ab7023d6
tree9afe4e14c46b7f8e401943ee05bd66751d6151c6
parentaa83cbb69737fbf8567c100340e476b5e38f0c84

translate-c: better numeric type parsing


1 files changed, 113 insertions(+), 37 deletions(-)

src/translate_c.zig+113-37
......@@ -5627,44 +5627,20 @@ fn parseCSpecifierQualifierList(c: *Context, m: *MacroCtx, scope: *Scope) ParseE
56275627 return try Tag.identifier.create(c.arena, builtin_typedef_map.get(mangled_name) orelse mangled_name);
56285628 }
56295629 },
5630 // eventually this will be replaced by std.c.parse which will handle these correctly
56315630 .Keyword_void => return try Tag.type.create(c.arena, "c_void"),
56325631 .Keyword_bool => return try Tag.type.create(c.arena, "bool"),
5633 .Keyword_double => return try Tag.type.create(c.arena, "f64"),
5634 .Keyword_long => return try Tag.type.create(c.arena, "c_long"),
5635 .Keyword_int => return try Tag.type.create(c.arena, "c_int"),
5636 .Keyword_float => return try Tag.type.create(c.arena, "f32"),
5637 .Keyword_short => return try Tag.type.create(c.arena, "c_short"),
5638 .Keyword_char => return try Tag.type.create(c.arena, "u8"),
5639 .Keyword_unsigned => if (m.next()) |t| switch (t) {
5640 .Keyword_char => return try Tag.type.create(c.arena, "u8"),
5641 .Keyword_short => return try Tag.type.create(c.arena, "c_ushort"),
5642 .Keyword_int => return try Tag.type.create(c.arena, "c_uint"),
5643 .Keyword_long => if (m.peek() != null and m.peek().? == .Keyword_long) {
5644 _ = m.next();
5645 return try Tag.type.create(c.arena, "c_ulonglong");
5646 } else return try Tag.type.create(c.arena, "c_ulong"),
5647 else => {
5648 m.i -= 1;
5649 return try Tag.type.create(c.arena, "c_uint");
5650 },
5651 } else {
5652 return try Tag.type.create(c.arena, "c_uint");
5653 },
5654 .Keyword_signed => if (m.next()) |t| switch (t) {
5655 .Keyword_char => return try Tag.type.create(c.arena, "i8"),
5656 .Keyword_short => return try Tag.type.create(c.arena, "c_short"),
5657 .Keyword_int => return try Tag.type.create(c.arena, "c_int"),
5658 .Keyword_long => if (m.peek() != null and m.peek().? == .Keyword_long) {
5659 _ = m.next();
5660 return try Tag.type.create(c.arena, "c_longlong");
5661 } else return try Tag.type.create(c.arena, "c_long"),
5662 else => {
5663 m.i -= 1;
5664 return try Tag.type.create(c.arena, "c_int");
5665 },
5666 } else {
5667 return try Tag.type.create(c.arena, "c_int");
5632 .Keyword_char,
5633 .Keyword_int,
5634 .Keyword_short,
5635 .Keyword_long,
5636 .Keyword_float,
5637 .Keyword_double,
5638 .Keyword_signed,
5639 .Keyword_unsigned,
5640 .Keyword_complex,
5641 => {
5642 m.i -= 1;
5643 return try parseCNumericType(c, m, scope);
56685644 },
56695645 .Keyword_enum, .Keyword_struct, .Keyword_union => {
56705646 // struct Foo will be declared as struct_Foo by transRecordDecl
......@@ -5678,7 +5654,6 @@ fn parseCSpecifierQualifierList(c: *Context, m: *MacroCtx, scope: *Scope) ParseE
56785654 const name = try std.fmt.allocPrint(c.arena, "{s}_{s}", .{ slice, m.slice() });
56795655 return try Tag.identifier.create(c.arena, name);
56805656 },
5681 .Keyword_complex => {}, // TODO
56825657 else => {},
56835658 }
56845659
......@@ -5686,6 +5661,107 @@ fn parseCSpecifierQualifierList(c: *Context, m: *MacroCtx, scope: *Scope) ParseE
56865661 return null;
56875662}
56885663
5664fn parseCNumericType(c: *Context, m: *MacroCtx, scope: *Scope) ParseError!Node {
5665 const KwCounter = struct {
5666 double: u8 = 0,
5667 long: u8 = 0,
5668 int: u8 = 0,
5669 float: u8 = 0,
5670 short: u8 = 0,
5671 char: u8 = 0,
5672 unsigned: u8 = 0,
5673 signed: u8 = 0,
5674 complex: u8 = 0,
5675
5676 fn eql(self: @This(), other: @This()) bool {
5677 return meta.eql(self, other);
5678 }
5679 };
5680
5681 // Yes, these can be in *any* order
5682 // This still doesn't cover cases where for example volatile is intermixed
5683
5684 var kw = KwCounter{};
5685 // prevent overflow
5686 var i: u8 = 0;
5687 while (i < math.maxInt(u8)) : (i += 1) {
5688 switch (m.next().?) {
5689 .Keyword_double => kw.double += 1,
5690 .Keyword_long => kw.long += 1,
5691 .Keyword_int => kw.int += 1,
5692 .Keyword_float => kw.float += 1,
5693 .Keyword_short => kw.short += 1,
5694 .Keyword_char => kw.char += 1,
5695 .Keyword_unsigned => kw.unsigned += 1,
5696 .Keyword_signed => kw.signed += 1,
5697 .Keyword_complex => kw.complex += 1,
5698 else => {
5699 m.i -= 1;
5700 break;
5701 },
5702 }
5703 }
5704
5705 if (kw.eql(.{ .int = 1 }) or kw.eql(.{ .signed = 1 }) or kw.eql(.{ .signed = 1, .int = 1 }))
5706 return Tag.type.create(c.arena, "c_int");
5707
5708 if (kw.eql(.{ .unsigned = 1 }) or kw.eql(.{ .unsigned = 1, .int = 1 }))
5709 return Tag.type.create(c.arena, "c_uint");
5710
5711 if (kw.eql(.{ .long = 1 }) or kw.eql(.{ .signed = 1, .long = 1 }) or kw.eql(.{ .long = 1, .int = 1 }) or kw.eql(.{ .signed = 1, .long = 1, .int = 1 }))
5712 return Tag.type.create(c.arena, "c_long");
5713
5714 if (kw.eql(.{ .unsigned = 1, .long = 1 }) or kw.eql(.{ .unsigned = 1, .long = 1, .int = 1 }))
5715 return Tag.type.create(c.arena, "c_ulong");
5716
5717 if (kw.eql(.{ .long = 2 }) or kw.eql(.{ .signed = 1, .long = 2 }) or kw.eql(.{ .long = 2, .int = 1 }) or kw.eql(.{ .signed = 1, .long = 2, .int = 1 }))
5718 return Tag.type.create(c.arena, "c_longlong");
5719
5720 if (kw.eql(.{ .unsigned = 1, .long = 2 }) or kw.eql(.{ .unsigned = 1, .long = 2, .int = 1 }))
5721 return Tag.type.create(c.arena, "c_ulonglong");
5722
5723 if (kw.eql(.{ .signed = 1, .char = 1 }))
5724 return Tag.type.create(c.arena, "i8");
5725
5726 if (kw.eql(.{ .char = 1 }) or kw.eql(.{ .unsigned = 1, .char = 1 }))
5727 return Tag.type.create(c.arena, "u8");
5728
5729 if (kw.eql(.{ .short = 1 }) or kw.eql(.{ .signed = 1, .short = 1 }) or kw.eql(.{ .short = 1, .int = 1 }) or kw.eql(.{ .signed = 1, .short = 1, .int = 1 }))
5730 return Tag.type.create(c.arena, "c_short");
5731
5732 if (kw.eql(.{ .unsigned = 1, .short = 1 }) or kw.eql(.{ .unsigned = 1, .short = 1, .int = 1 }))
5733 return Tag.type.create(c.arena, "c_ushort");
5734
5735 if (kw.eql(.{ .float = 1 }))
5736 return Tag.type.create(c.arena, "f32");
5737
5738 if (kw.eql(.{ .double = 1 }))
5739 return Tag.type.create(c.arena, "f64");
5740
5741 if (kw.eql(.{ .long = 1, .double = 1 })) {
5742 try m.fail(c, "unable to translate: TODO long double", .{});
5743 return error.ParseError;
5744 }
5745
5746 if (kw.eql(.{ .float = 1, .complex = 1 })) {
5747 try m.fail(c, "unable to translate: TODO _Complex", .{});
5748 return error.ParseError;
5749 }
5750
5751 if (kw.eql(.{ .double = 1, .complex = 1 })) {
5752 try m.fail(c, "unable to translate: TODO _Complex", .{});
5753 return error.ParseError;
5754 }
5755
5756 if (kw.eql(.{ .long = 1, .double = 1, .complex = 1 })) {
5757 try m.fail(c, "unable to translate: TODO _Complex", .{});
5758 return error.ParseError;
5759 }
5760
5761 try m.fail(c, "unable to translate: invalid numeric type", .{});
5762 return error.ParseError;
5763}
5764
56895765fn parseCAbstractDeclarator(c: *Context, m: *MacroCtx, scope: *Scope, node: Node) ParseError!Node {
56905766 switch (m.next().?) {
56915767 .Asterisk => {